提交 32eec68d 编写于 作者: A Alex Elder

rbd: don't drop the rbd_id too early

Currently an rbd device's id is released when it is removed, but it
is done before the code is run to clean up sysfs-related files (such
as /sys/bus/rbd/devices/1).

It's possible that an rbd is still in use after the rbd_remove()
call has been made.  It's essentially the same as an active inode
that stays around after it has been removed--until its final close
operation.  This means that the id shows up as free for reuse at a
time it should not be.

The effect of this was seen by Jens Rehpoehler, who:
    - had a filesystem mounted on an rbd device
    - unmapped that filesystem (without unmounting)
    - found that the mount still worked properly
    - but hit a panic when he attempted to re-map a new rbd device

This re-map attempt found the previously-unmapped id available.
The subsequent attempt to reuse it was met with a panic while
attempting to (re-)install the sysfs entry for the new mapped
device.

Fix this by holding off "putting" the rbd id, until the rbd_device
release function is called--when the last reference is finally
dropped.

Note: This fixes: http://tracker.newdream.net/issues/1907Signed-off-by: NAlex Elder <elder@dreamhost.com>
Signed-off-by: NSage Weil <sage@newdream.net>
上级 593a9e7b
...@@ -2421,7 +2421,12 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2421,7 +2421,12 @@ static ssize_t rbd_add(struct bus_type *bus,
if (rc) if (rc)
goto err_out_blkdev; goto err_out_blkdev;
/* set up and announce blkdev mapping */ /*
* At this point cleanup in the event of an error is the job
* of the sysfs code (initiated by rbd_bus_del_dev()).
*
* Set up and announce blkdev mapping.
*/
rc = rbd_init_disk(rbd_dev); rc = rbd_init_disk(rbd_dev);
if (rc) if (rc)
goto err_out_bus; goto err_out_bus;
...@@ -2433,8 +2438,6 @@ static ssize_t rbd_add(struct bus_type *bus, ...@@ -2433,8 +2438,6 @@ static ssize_t rbd_add(struct bus_type *bus,
return count; return count;
err_out_bus: err_out_bus:
rbd_id_put(rbd_dev);
/* this will also clean up rest of rbd_dev stuff */ /* this will also clean up rest of rbd_dev stuff */
rbd_bus_del_dev(rbd_dev); rbd_bus_del_dev(rbd_dev);
...@@ -2492,6 +2495,9 @@ static void rbd_dev_release(struct device *dev) ...@@ -2492,6 +2495,9 @@ static void rbd_dev_release(struct device *dev)
/* clean up and free blkdev */ /* clean up and free blkdev */
rbd_free_disk(rbd_dev); rbd_free_disk(rbd_dev);
unregister_blkdev(rbd_dev->major, rbd_dev->name); unregister_blkdev(rbd_dev->major, rbd_dev->name);
/* done with the id, and with the rbd_dev */
rbd_id_put(rbd_dev);
kfree(rbd_dev); kfree(rbd_dev);
/* release module ref */ /* release module ref */
...@@ -2524,8 +2530,6 @@ static ssize_t rbd_remove(struct bus_type *bus, ...@@ -2524,8 +2530,6 @@ static ssize_t rbd_remove(struct bus_type *bus,
goto done; goto done;
} }
rbd_id_put(rbd_dev);
__rbd_remove_all_snaps(rbd_dev); __rbd_remove_all_snaps(rbd_dev);
rbd_bus_del_dev(rbd_dev); rbd_bus_del_dev(rbd_dev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册