Merge tag 'i3c/for-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/i3c/linux
[linux-2.6-microblaze.git] / fs / block_dev.c
index 92ed7d5..b8abccd 100644 (file)
@@ -79,7 +79,7 @@ static void kill_bdev(struct block_device *bdev)
 {
        struct address_space *mapping = bdev->bd_inode->i_mapping;
 
-       if (mapping->nrpages == 0 && mapping->nrexceptional == 0)
+       if (mapping_empty(mapping))
                return;
 
        invalidate_bh_lrus();
@@ -275,6 +275,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
                bio.bi_opf = dio_bio_write_op(iocb);
                task_io_account_write(ret);
        }
+       if (iocb->ki_flags & IOCB_NOWAIT)
+               bio.bi_opf |= REQ_NOWAIT;
        if (iocb->ki_flags & IOCB_HIPRI)
                bio_set_polled(&bio, iocb);
 
@@ -428,6 +430,8 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
                        bio->bi_opf = dio_bio_write_op(iocb);
                        task_io_account_write(bio->bi_iter.bi_size);
                }
+               if (iocb->ki_flags & IOCB_NOWAIT)
+                       bio->bi_opf |= REQ_NOWAIT;
 
                dio->size += bio->bi_iter.bi_size;
                pos += bio->bi_iter.bi_size;
@@ -1236,16 +1240,18 @@ static void __blkdev_put(struct block_device *bdev, fmode_t mode, int for_part);
 int bdev_disk_changed(struct block_device *bdev, bool invalidate)
 {
        struct gendisk *disk = bdev->bd_disk;
-       int ret;
+       int ret = 0;
 
        lockdep_assert_held(&bdev->bd_mutex);
 
-       clear_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state);
-
 rescan:
-       ret = blk_drop_partitions(bdev);
-       if (ret)
-               return ret;
+       if (bdev->bd_part_count)
+               return -EBUSY;
+       sync_blockdev(bdev);
+       invalidate_bdev(bdev);
+       blk_drop_partitions(disk);
+
+       clear_bit(GD_NEED_PART_SCAN, &disk->state);
 
        /*
         * Historically we only set the capacity to zero for devices that
@@ -1259,9 +1265,6 @@ rescan:
                if (disk_part_scan_enabled(disk) ||
                    !(disk->flags & GENHD_FL_REMOVABLE))
                        set_capacity(disk, 0);
-       } else {
-               if (disk->fops->revalidate_disk)
-                       disk->fops->revalidate_disk(disk);
        }
 
        if (get_capacity(disk)) {
@@ -1433,10 +1436,6 @@ struct block_device *blkdev_get_by_dev(dev_t dev, fmode_t mode, void *holder)
        if (ret)
                return ERR_PTR(ret);
 
-       /*
-        * If we lost a race with 'disk' being deleted, try again.  See md.c.
-        */
-retry:
        bdev = blkdev_get_no_open(dev);
        if (!bdev)
                return ERR_PTR(-ENXIO);
@@ -1483,8 +1482,6 @@ abort_claiming:
        disk_unblock_events(disk);
 put_blkdev:
        blkdev_put_no_open(bdev);
-       if (ret == -ERESTARTSYS)
-               goto retry;
        return ERR_PTR(ret);
 }
 EXPORT_SYMBOL(blkdev_get_by_dev);
@@ -1680,6 +1677,7 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct inode *bd_inode = bdev_file_inode(file);
        loff_t size = i_size_read(bd_inode);
        struct blk_plug plug;
+       size_t shorted = 0;
        ssize_t ret;
 
        if (bdev_read_only(I_BDEV(bd_inode)))
@@ -1697,12 +1695,17 @@ ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
                return -EOPNOTSUPP;
 
-       iov_iter_truncate(from, size - iocb->ki_pos);
+       size -= iocb->ki_pos;
+       if (iov_iter_count(from) > size) {
+               shorted = iov_iter_count(from) - size;
+               iov_iter_truncate(from, size);
+       }
 
        blk_start_plug(&plug);
        ret = __generic_file_write_iter(iocb, from);
        if (ret > 0)
                ret = generic_write_sync(iocb, ret);
+       iov_iter_reexpand(from, iov_iter_count(from) + shorted);
        blk_finish_plug(&plug);
        return ret;
 }
@@ -1714,13 +1717,21 @@ ssize_t blkdev_read_iter(struct kiocb *iocb, struct iov_iter *to)
        struct inode *bd_inode = bdev_file_inode(file);
        loff_t size = i_size_read(bd_inode);
        loff_t pos = iocb->ki_pos;
+       size_t shorted = 0;
+       ssize_t ret;
 
        if (pos >= size)
                return 0;
 
        size -= pos;
-       iov_iter_truncate(to, size);
-       return generic_file_read_iter(iocb, to);
+       if (iov_iter_count(to) > size) {
+               shorted = iov_iter_count(to) - size;
+               iov_iter_truncate(to, size);
+       }
+
+       ret = generic_file_read_iter(iocb, to);
+       iov_iter_reexpand(to, iov_iter_count(to) + shorted);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(blkdev_read_iter);