aboutsummaryrefslogtreecommitdiffstats
path: root/fs/block_dev.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2012-10-15 17:20:17 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-28 13:59:37 -0400
commit1a25b1c4ce189e3926f2981f3302352a930086db (patch)
tree8db002bfdbaec616392f563d96621bfd5fbcfcd5 /fs/block_dev.c
parent1bf11c53535ab87e3bf14ecdf6747bf46f601c5d (diff)
Lock splice_read and splice_write functions
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>
Diffstat (limited to 'fs/block_dev.c')
-rw-r--r--fs/block_dev.c37
1 files changed, 35 insertions, 2 deletions
diff --git a/fs/block_dev.c b/fs/block_dev.c
index b3c1d3dae77d..1a1e5e3b1eaf 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma)
1661 return ret; 1661 return ret;
1662} 1662}
1663 1663
1664static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos,
1665 struct pipe_inode_info *pipe, size_t len,
1666 unsigned int flags)
1667{
1668 ssize_t ret;
1669 struct block_device *bdev = I_BDEV(file->f_mapping->host);
1670
1671 percpu_down_read(&bdev->bd_block_size_semaphore);
1672
1673 ret = generic_file_splice_read(file, ppos, pipe, len, flags);
1674
1675 percpu_up_read(&bdev->bd_block_size_semaphore);
1676
1677 return ret;
1678}
1679
1680static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe,
1681 struct file *file, loff_t *ppos, size_t len,
1682 unsigned int flags)
1683{
1684 ssize_t ret;
1685 struct block_device *bdev = I_BDEV(file->f_mapping->host);
1686
1687 percpu_down_read(&bdev->bd_block_size_semaphore);
1688
1689 ret = generic_file_splice_write(pipe, file, ppos, len, flags);
1690
1691 percpu_up_read(&bdev->bd_block_size_semaphore);
1692
1693 return ret;
1694}
1695
1696
1664/* 1697/*
1665 * Try to release a page associated with block device when the system 1698 * Try to release a page associated with block device when the system
1666 * is under memory pressure. 1699 * is under memory pressure.
@@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = {
1699#ifdef CONFIG_COMPAT 1732#ifdef CONFIG_COMPAT
1700 .compat_ioctl = compat_blkdev_ioctl, 1733 .compat_ioctl = compat_blkdev_ioctl,
1701#endif 1734#endif
1702 .splice_read = generic_file_splice_read, 1735 .splice_read = blkdev_splice_read,
1703 .splice_write = generic_file_splice_write, 1736 .splice_write = blkdev_splice_write,
1704}; 1737};
1705 1738
1706int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) 1739int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg)