From 8e0180cadfa779390adc23eddb953c423fea109d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 18 Mar 2013 12:49:13 -0700 Subject: [PATCH] 3.8-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.8/loopdev-fix-a-deadlock.patch | 63 ++++++++++++++ ...pdev-remove-an-user-triggerable-oops.patch | 83 +++++++++++++++++++ queue-3.8/series | 3 + 4 files changed, 190 insertions(+) create mode 100644 queue-3.8/block-use-i_size_write-in-bd_set_size.patch create mode 100644 queue-3.8/loopdev-fix-a-deadlock.patch create mode 100644 queue-3.8/loopdev-remove-an-user-triggerable-oops.patch diff --git a/queue-3.8/block-use-i_size_write-in-bd_set_size.patch b/queue-3.8/block-use-i_size_write-in-bd_set_size.patch new file mode 100644 index 00000000000..ade0fb15a53 --- /dev/null +++ b/queue-3.8/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 +@@ -1033,7 +1033,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.8/loopdev-fix-a-deadlock.patch b/queue-3.8/loopdev-fix-a-deadlock.patch new file mode 100644 index 00000000000..e78b34dcad4 --- /dev/null +++ b/queue-3.8/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 +@@ -1285,11 +1285,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.8/loopdev-remove-an-user-triggerable-oops.patch b/queue-3.8/loopdev-remove-an-user-triggerable-oops.patch new file mode 100644 index 00000000000..5ade0da4822 --- /dev/null +++ b/queue-3.8/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 +@@ -1856,11 +1856,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. +@@ -1878,8 +1882,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); +@@ -1892,6 +1898,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.8/series b/queue-3.8/series index d158094792f..1a3c5ddb0f2 100644 --- a/queue-3.8/series +++ b/queue-3.8/series @@ -50,3 +50,6 @@ kbuild-fix-make-headers_check-with-make-3.80.patch atmel_lcdfb-fix-16-bpp-modes-on-older-socs.patch net-mlx4_en-initialize-rfs-filters-lock-and-list-in-init_netdev.patch net-mlx4_en-disable-rfs-when-running-in-sriov-mode.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