summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Elder <elder@inktank.com>2013-05-31 17:40:44 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-09 12:24:25 -0800
commit7aa73ee13251af1534de166ea5379f32a6bf7793 (patch)
treefbd0161f39acac30d75737a5c0e6aab2c080b75f
parentc4d00f5b3e1f48f99d99d813fe8071c719e1790b (diff)
rbd: protect against concurrent unmaps
commit 82a442d239695a242c4d584464c9606322cd02aa upstream. Make sure two concurrent unmap operations on the same rbd device won't collide, by only proceeding with the removal and cleanup of a device if is not already underway. Signed-off-by: Alex Elder <elder@inktank.com> Reviewed-by: Josh Durgin <josh.durgin@inktank.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/block/rbd.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index afdbd558485d..8326b39b0576 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -5108,6 +5108,7 @@ static ssize_t rbd_remove(struct bus_type *bus,
struct list_head *tmp;
int dev_id;
unsigned long ul;
+ bool already = false;
int ret;
ret = strict_strtoul(buf, 10, &ul);
@@ -5135,11 +5136,12 @@ static ssize_t rbd_remove(struct bus_type *bus,
if (rbd_dev->open_count)
ret = -EBUSY;
else
- set_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags);
+ already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
+ &rbd_dev->flags);
spin_unlock_irq(&rbd_dev->lock);
}
spin_unlock(&rbd_dev_list_lock);
- if (ret < 0)
+ if (ret < 0 || already)
goto done;
rbd_bus_del_dev(rbd_dev);