From 1dd86002ade8f7416d8f63c802aa6b55fb181fca Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 18 Mar 2013 12:48:31 -0700 Subject: [PATCH] 3.4-stable patches added patches: block-use-i_size_write-in-bd_set_size.patch loopdev-fix-a-deadlock.patch loopdev-remove-an-user-triggerable-oops.patch --- ...lock-use-i_size_write-in-bd_set_size.patch | 41 +++++++++ queue-3.4/loopdev-fix-a-deadlock.patch | 63 ++++++++++++++ ...pdev-remove-an-user-triggerable-oops.patch | 83 +++++++++++++++++++ queue-3.4/series | 3 + 4 files changed, 190 insertions(+) create mode 100644 queue-3.4/block-use-i_size_write-in-bd_set_size.patch create mode 100644 queue-3.4/loopdev-fix-a-deadlock.patch create mode 100644 queue-3.4/loopdev-remove-an-user-triggerable-oops.patch diff --git a/queue-3.4/block-use-i_size_write-in-bd_set_size.patch b/queue-3.4/block-use-i_size_write-in-bd_set_size.patch new file mode 100644 index 00000000000..471a9ee2f81 --- /dev/null +++ b/queue-3.4/block-use-i_size_write-in-bd_set_size.patch @@ -0,0 +1,41 @@ +From d646a02a9d44d1421f273ae3923d97b47b918176 Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Thu, 21 Feb 2013 15:16:42 -0800 +Subject: block: use i_size_write() in bd_set_size() + +From: Guo Chao + +commit d646a02a9d44d1421f273ae3923d97b47b918176 upstream. + +blkdev_ioctl(GETBLKSIZE) uses i_size_read() to read size of block device. +If we update block size directly, reader may see intermediate result in +some machines and configurations. Use i_size_write() instead. + +Signed-off-by: Guo Chao +Cc: Alexander Viro +Cc: Guo Chao +Cc: M. Hindess +Cc: Nikanth Karthikesan +Cc: Jens Axboe +Signed-off-by: Andrew Morton +Signed-off-by: Jens Axboe +Acked-by: Jeff Mahoney +Signed-off-by: Greg Kroah-Hartman + +--- + fs/block_dev.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/fs/block_dev.c ++++ b/fs/block_dev.c +@@ -1086,7 +1086,9 @@ void bd_set_size(struct block_device *bd + { + unsigned bsize = bdev_logical_block_size(bdev); + +- bdev->bd_inode->i_size = size; ++ mutex_lock(&bdev->bd_inode->i_mutex); ++ i_size_write(bdev->bd_inode, size); ++ mutex_unlock(&bdev->bd_inode->i_mutex); + while (bsize < PAGE_CACHE_SIZE) { + if (size & bsize) + break; diff --git a/queue-3.4/loopdev-fix-a-deadlock.patch b/queue-3.4/loopdev-fix-a-deadlock.patch new file mode 100644 index 00000000000..2bb355489d5 --- /dev/null +++ b/queue-3.4/loopdev-fix-a-deadlock.patch @@ -0,0 +1,63 @@ +From 5370019dc2d2c2ff90e95d181468071362934f3a Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Thu, 21 Feb 2013 15:16:45 -0800 +Subject: loopdev: fix a deadlock + +From: Guo Chao + +commit 5370019dc2d2c2ff90e95d181468071362934f3a upstream. + +bd_mutex and lo_ctl_mutex can be held in different order. + +Path #1: + +blkdev_open + blkdev_get + __blkdev_get (hold bd_mutex) + lo_open (hold lo_ctl_mutex) + +Path #2: + +blkdev_ioctl + lo_ioctl (hold lo_ctl_mutex) + lo_set_capacity (hold bd_mutex) + +Lockdep does not report it, because path #2 actually holds a subclass of +lo_ctl_mutex. This subclass seems creep into the code by mistake. The +patch author actually just mentioned it in the changelog, see commit +f028f3b2 ("loop: fix circular locking in loop_clr_fd()"), also see: + + http://marc.info/?l=linux-kernel&m=123806169129727&w=2 + +Path #2 hold bd_mutex to call bd_set_size(), I've protected it +with i_mutex in a previous patch, so drop bd_mutex at this site. + +Signed-off-by: Guo Chao +Cc: Alexander Viro +Cc: Guo Chao +Cc: M. Hindess +Cc: Nikanth Karthikesan +Cc: Jens Axboe +Signed-off-by: Andrew Morton +Signed-off-by: Jens Axboe +Acked-by: Jeff Mahoney +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 2 -- + 1 file changed, 2 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1263,11 +1263,9 @@ static int loop_set_capacity(struct loop + /* the width of sector_t may be narrow for bit-shift */ + sz = sec; + sz <<= 9; +- mutex_lock(&bdev->bd_mutex); + bd_set_size(bdev, sz); + /* let user-space know about the new size */ + kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, KOBJ_CHANGE); +- mutex_unlock(&bdev->bd_mutex); + + out: + return err; diff --git a/queue-3.4/loopdev-remove-an-user-triggerable-oops.patch b/queue-3.4/loopdev-remove-an-user-triggerable-oops.patch new file mode 100644 index 00000000000..aedcb59d33d --- /dev/null +++ b/queue-3.4/loopdev-remove-an-user-triggerable-oops.patch @@ -0,0 +1,83 @@ +From b1a6650406875b9097a032eed89af50682fe1160 Mon Sep 17 00:00:00 2001 +From: Guo Chao +Date: Thu, 21 Feb 2013 15:16:49 -0800 +Subject: loopdev: remove an user triggerable oops + +From: Guo Chao + +commit b1a6650406875b9097a032eed89af50682fe1160 upstream. + +When loopdev is built as module and we pass an invalid parameter, +loop_init() will return directly without deregister misc device, which +will cause an oops when insert loop module next time because we left some +garbage in the misc device list. + +Test case: +sudo modprobe loop max_part=1024 +(failed due to invalid parameter) +sudo modprobe loop +(oops) + +Clean up nicely to avoid such oops. + +Signed-off-by: Guo Chao +Cc: Alexander Viro +Cc: Guo Chao +Cc: M. Hindess +Cc: Nikanth Karthikesan +Cc: Jens Axboe +Signed-off-by: Andrew Morton +Signed-off-by: Jens Axboe +Acked-by: Jeff Mahoney +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/block/loop.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +--- a/drivers/block/loop.c ++++ b/drivers/block/loop.c +@@ -1835,11 +1835,15 @@ static int __init loop_init(void) + max_part = (1UL << part_shift) - 1; + } + +- if ((1UL << part_shift) > DISK_MAX_PARTS) +- return -EINVAL; ++ if ((1UL << part_shift) > DISK_MAX_PARTS) { ++ err = -EINVAL; ++ goto misc_out; ++ } + +- if (max_loop > 1UL << (MINORBITS - part_shift)) +- return -EINVAL; ++ if (max_loop > 1UL << (MINORBITS - part_shift)) { ++ err = -EINVAL; ++ goto misc_out; ++ } + + /* + * If max_loop is specified, create that many devices upfront. +@@ -1857,8 +1861,10 @@ static int __init loop_init(void) + range = 1UL << MINORBITS; + } + +- if (register_blkdev(LOOP_MAJOR, "loop")) +- return -EIO; ++ if (register_blkdev(LOOP_MAJOR, "loop")) { ++ err = -EIO; ++ goto misc_out; ++ } + + blk_register_region(MKDEV(LOOP_MAJOR, 0), range, + THIS_MODULE, loop_probe, NULL, NULL); +@@ -1871,6 +1877,10 @@ static int __init loop_init(void) + + printk(KERN_INFO "loop: module loaded\n"); + return 0; ++ ++misc_out: ++ misc_deregister(&loop_misc); ++ return err; + } + + static int loop_exit_cb(int id, void *ptr, void *data) diff --git a/queue-3.4/series b/queue-3.4/series index 383b67025ff..f987e849461 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -30,3 +30,6 @@ btrfs-use-rcu_barrier-to-wait-for-bdev-puts-at-unmount.patch atmel_lcdfb-fix-16-bpp-modes-on-older-socs.patch drm-i915-ebusy-status-handling-added-to-i915_gem_fault.patch hwmon-sht15-fix-memory-leak-if-regulator_enable-fails.patch +block-use-i_size_write-in-bd_set_size.patch +loopdev-fix-a-deadlock.patch +loopdev-remove-an-user-triggerable-oops.patch -- 2.47.3