Patchwork mtd: mtd_blkdevs: don't increase 'open' count on error path

login
register
mail settings
Submitter Brian Norris
Date Nov. 7, 2011, 11:51 p.m.
Message ID <1320709865-21903-1-git-send-email-computersforpeace@gmail.com>
Download mbox | patch
Permalink /patch/124219/
State Accepted
Commit 342ff28f5a2e5aa3236617bd2bddf6c749677ef2
Headers show

Comments

Brian Norris - Nov. 7, 2011, 11:51 p.m.
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

Cc: stable@kernel.org [3.0+]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
---
 drivers/mtd/mtd_blkdevs.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)
Artem Bityutskiy - Nov. 17, 2011, 9:35 p.m.
On Mon, 2011-11-07 at 15:51 -0800, Brian Norris wrote:
> 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.

Pushed to l2-mtd-2.6.git, thanks!

Artem.

Patch

diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c
index ed8b5e7..424ca5f 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;