aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2011-11-07 15:51:05 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2012-01-25 17:24:32 -0800
commit488e572df737befdfc783503642d70ea18b3a001 (patch)
treeda29858912525fbaa67c90223a5540bdae900a13 /drivers/mtd
parent13205eedda9d80daf129ddad54bd6ffe5df92dff (diff)
downloadkernel_samsung_smdk4412-488e572df737befdfc783503642d70ea18b3a001.zip
kernel_samsung_smdk4412-488e572df737befdfc783503642d70ea18b3a001.tar.gz
kernel_samsung_smdk4412-488e572df737befdfc783503642d70ea18b3a001.tar.bz2
mtd: mtd_blkdevs: don't increase 'open' count on error path
commit 342ff28f5a2e5aa3236617bd2bddf6c749677ef2 upstream. Some error paths in mtd_blkdevs were fixed in the following commit: commit 94735ec4044a6d318b83ad3c5794e931ed168d10 mtd: mtd_blkdevs: fix error path in blktrans_open But on these error paths, the block device's `dev->open' count is already incremented before we check for errors. This meant that, while the error path was handled correctly on the first time through blktrans_open(), the device is erroneously considered already open on the second time through. This problem can be seen, for instance, when a UBI volume is simultaneously mounted as a UBIFS partition and read through its corresponding gluebi mtdblockX device. This results in blktrans_open() passing its error checks (with `dev->open > 0') without actually having a handle on the device. Here's a summarized log of the actions and results with nandsim: # modprobe nandsim # modprobe mtdblock # modprobe gluebi # modprobe ubifs # ubiattach /dev/ubi_ctrl -m 0 ... # ubimkvol /dev/ubi0 -N test -s 16MiB ... # mount -t ubifs ubi0:test /mnt # ls /dev/mtdblock* /dev/mtdblock0 /dev/mtdblock1 # cat /dev/mtdblock1 > /dev/null cat: can't open '/dev/mtdblock4': Device or resource busy # cat /dev/mtdblock1 > /dev/null CPU 0 Unable to handle kernel paging request at virtual address fffffff0, epc == 8031536c, ra == 8031f280 Oops[#1]: ... Call Trace: [<8031536c>] ubi_leb_read+0x14/0x164 [<8031f280>] gluebi_read+0xf0/0x148 [<802edba8>] mtdblock_readsect+0x64/0x198 [<802ecfe4>] mtd_blktrans_thread+0x330/0x3f4 [<8005be98>] kthread+0x88/0x90 [<8000bc04>] kernel_thread_helper+0x10/0x18 Signed-off-by: Brian Norris <computersforpeace@gmail.com> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/mtd_blkdevs.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index ca38569..bff8d46 100644
--- a/drivers/mtd/mtd_blkdevs.c
+++ b/drivers/mtd/mtd_blkdevs.c
@@ -215,7 +215,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
mutex_lock(&dev->lock);
- if (dev->open++)
+ if (dev->open)
goto unlock;
kref_get(&dev->ref);
@@ -235,6 +235,7 @@ static int blktrans_open(struct block_device *bdev, fmode_t mode)
goto error_release;
unlock:
+ dev->open++;
mutex_unlock(&dev->lock);
blktrans_dev_put(dev);
return ret;