]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/block_dev.c
ext4: fix data corruption caused by unaligned direct AIO
[linux.git] / fs / block_dev.c
index 450be88cffef3a7e0b9d68973159ac1c2a2b00fc..58a4c1217fa87d60376771a2c315b8b02d0bff1c 100644 (file)
@@ -104,6 +104,20 @@ void invalidate_bdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
+static void set_init_blocksize(struct block_device *bdev)
+{
+       unsigned bsize = bdev_logical_block_size(bdev);
+       loff_t size = i_size_read(bdev->bd_inode);
+
+       while (bsize < PAGE_SIZE) {
+               if (size & bsize)
+                       break;
+               bsize <<= 1;
+       }
+       bdev->bd_block_size = bsize;
+       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+}
+
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
@@ -237,11 +251,9 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter,
 
        qc = submit_bio(&bio);
        for (;;) {
-               __set_current_state(TASK_UNINTERRUPTIBLE);
-
+               set_current_state(TASK_UNINTERRUPTIBLE);
                if (!READ_ONCE(bio.bi_private))
                        break;
-
                if (!(iocb->ki_flags & IOCB_HIPRI) ||
                    !blk_poll(bdev_get_queue(bdev), qc, true))
                        io_schedule();
@@ -426,8 +438,7 @@ __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, int nr_pages)
                return -EIOCBQUEUED;
 
        for (;;) {
-               __set_current_state(TASK_UNINTERRUPTIBLE);
-
+               set_current_state(TASK_UNINTERRUPTIBLE);
                if (!READ_ONCE(dio->waiter))
                        break;
 
@@ -1434,18 +1445,9 @@ EXPORT_SYMBOL(check_disk_change);
 
 void bd_set_size(struct block_device *bdev, loff_t size)
 {
-       unsigned bsize = bdev_logical_block_size(bdev);
-
        inode_lock(bdev->bd_inode);
        i_size_write(bdev->bd_inode, size);
        inode_unlock(bdev->bd_inode);
-       while (bsize < PAGE_SIZE) {
-               if (size & bsize)
-                       break;
-               bsize <<= 1;
-       }
-       bdev->bd_block_size = bsize;
-       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 }
 EXPORT_SYMBOL(bd_set_size);
 
@@ -1522,8 +1524,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                }
                        }
 
-                       if (!ret)
+                       if (!ret) {
                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+                               set_init_blocksize(bdev);
+                       }
 
                        /*
                         * If the device is invalidated, rescan partition
@@ -1558,6 +1562,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_clear;
                        }
                        bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
+                       set_init_blocksize(bdev);
                }
 
                if (bdev->bd_bdi == &noop_backing_dev_info)