]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
Lock splice_read and splice_write functions
authorMikulas Patocka <mpatocka@redhat.com>
Mon, 15 Oct 2012 21:20:17 +0000 (17:20 -0400)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 28 Oct 2012 17:59:37 +0000 (10:59 -0700)
Functions generic_file_splice_read and generic_file_splice_write access
the pagecache directly. For block devices these functions must be locked
so that block size is not changed while they are in progress.

This patch is an additional fix for commit b87570f5d349 ("Fix a crash
when block device is read and block size is changed at the same time")
that locked aio_read, aio_write and mmap against block size change.

Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
fs/block_dev.c

index b3c1d3dae77d06fcde3fa3ecf36b2af9e2b25d85..1a1e5e3b1eafc7f00454cb2d544b8761161d015e 100644 (file)
@@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
        return ret;
 }
 
        return ret;
 }
 
+static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
+                                 struct pipe_inode_info *pipe, size_t len,
+                                 unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_read(file, ppos, pipe, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
+                                  struct file *file, loff_t *ppos, size_t len,
+                                  unsigned int flags)
+{
+       ssize_t ret;
+       struct block_device *bdev = I_BDEV(file->f_mapping->host);
+
+       percpu_down_read(&bdev->bd_block_size_semaphore);
+
+       ret = generic_file_splice_write(pipe, file, ppos, len, flags);
+
+       percpu_up_read(&bdev->bd_block_size_semaphore);
+
+       return ret;
+}
+
+
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
 /*
  * Try to release a page associated with block device when the system
  * is under memory pressure.
@@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = compat_blkdev_ioctl,
 #endif
-       .splice_read    = generic_file_splice_read,
-       .splice_write   = generic_file_splice_write,
+       .splice_read    = blkdev_splice_read,
+       .splice_write   = blkdev_splice_write,
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)
 };
 
 int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)