Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 359646
b: refs/heads/master
c: b82d167
h: refs/heads/master
v: v3
  • Loading branch information
Alex Elder authored and Sage Weil committed Feb 14, 2013
1 parent bb7c508 commit c0a0bac
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 11 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 6d292906f80170f4647079dd503df18b737750af
refs/heads/master: b82d167be64b3e88d9434d8a98ce83c83a07aa48
43 changes: 33 additions & 10 deletions trunk/drivers/block/rbd.c
Original file line number Diff line number Diff line change
Expand Up @@ -261,10 +261,10 @@ struct rbd_device {

char name[DEV_NAME_LEN]; /* blkdev name, e.g. rbd3 */

spinlock_t lock; /* queue lock */
spinlock_t lock; /* queue, flags, open_count */

struct rbd_image_header header;
unsigned long flags;
unsigned long flags; /* possibly lock protected */
struct rbd_spec *spec;

char *header_name;
Expand All @@ -289,13 +289,19 @@ struct rbd_device {

/* sysfs related */
struct device dev;
unsigned long open_count;
unsigned long open_count; /* protected by lock */
};

/* Flag bits for rbd_dev->flags */

/*
* Flag bits for rbd_dev->flags. If atomicity is required,
* rbd_dev->lock is used to protect access.
*
* Currently, only the "removing" flag (which is coupled with the
* "open_count" field) requires atomic access.
*/
enum rbd_dev_flags {
RBD_DEV_FLAG_EXISTS, /* mapped snapshot has not been deleted */
RBD_DEV_FLAG_REMOVING, /* this mapping is being removed */
};

static DEFINE_MUTEX(ctl_mutex); /* Serialize open/close/setup/teardown */
Expand Down Expand Up @@ -383,14 +389,23 @@ static int rbd_dev_v2_refresh(struct rbd_device *rbd_dev, u64 *hver);
static int rbd_open(struct block_device *bdev, fmode_t mode)
{
struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
bool removing = false;

if ((mode & FMODE_WRITE) && rbd_dev->mapping.read_only)
return -EROFS;

spin_lock(&rbd_dev->lock);
if (test_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags))
removing = true;
else
rbd_dev->open_count++;
spin_unlock(&rbd_dev->lock);
if (removing)
return -ENOENT;

mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
(void) get_device(&rbd_dev->dev);
set_device_ro(bdev, rbd_dev->mapping.read_only);
rbd_dev->open_count++;
mutex_unlock(&ctl_mutex);

return 0;
Expand All @@ -399,10 +414,14 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
static int rbd_release(struct gendisk *disk, fmode_t mode)
{
struct rbd_device *rbd_dev = disk->private_data;
unsigned long open_count_before;

spin_lock(&rbd_dev->lock);
open_count_before = rbd_dev->open_count--;
spin_unlock(&rbd_dev->lock);
rbd_assert(open_count_before > 0);

mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
rbd_assert(rbd_dev->open_count > 0);
rbd_dev->open_count--;
put_device(&rbd_dev->dev);
mutex_unlock(&ctl_mutex);

Expand Down Expand Up @@ -4083,10 +4102,14 @@ static ssize_t rbd_remove(struct bus_type *bus,
goto done;
}

if (rbd_dev->open_count) {
spin_lock(&rbd_dev->lock);
if (rbd_dev->open_count)
ret = -EBUSY;
else
set_bit(RBD_DEV_FLAG_REMOVING, &rbd_dev->flags);
spin_unlock(&rbd_dev->lock);
if (ret < 0)
goto done;
}

rbd_remove_all_snaps(rbd_dev);
rbd_bus_del_dev(rbd_dev);
Expand Down

0 comments on commit c0a0bac

Please sign in to comment.