Commit f38cb9d9 authored by Ilya Dryomov's avatar Ilya Dryomov

rbd: make get_lock_owner_info() return a single locker or NULL

Make the "num_lockers can be only 0 or 1" assumption explicit and
simplify the API by getting rid of output parameters in preparation
for calling get_lock_owner_info() twice before blocklisting.
Signed-off-by: default avatarIlya Dryomov <idryomov@gmail.com>
Reviewed-by: default avatarDongsheng Yang <dongsheng.yang@easystack.cn>
parent 50164507
...@@ -3849,10 +3849,17 @@ static void wake_lock_waiters(struct rbd_device *rbd_dev, int result) ...@@ -3849,10 +3849,17 @@ static void wake_lock_waiters(struct rbd_device *rbd_dev, int result)
list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list); list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list);
} }
static int get_lock_owner_info(struct rbd_device *rbd_dev, static void free_locker(struct ceph_locker *locker)
struct ceph_locker **lockers, u32 *num_lockers) {
if (locker)
ceph_free_lockers(locker, 1);
}
static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
{ {
struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc; struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
struct ceph_locker *lockers;
u32 num_lockers;
u8 lock_type; u8 lock_type;
char *lock_tag; char *lock_tag;
int ret; int ret;
...@@ -3861,39 +3868,45 @@ static int get_lock_owner_info(struct rbd_device *rbd_dev, ...@@ -3861,39 +3868,45 @@ static int get_lock_owner_info(struct rbd_device *rbd_dev,
ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid, ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid,
&rbd_dev->header_oloc, RBD_LOCK_NAME, &rbd_dev->header_oloc, RBD_LOCK_NAME,
&lock_type, &lock_tag, lockers, num_lockers); &lock_type, &lock_tag, &lockers, &num_lockers);
if (ret) if (ret) {
return ret; rbd_warn(rbd_dev, "failed to retrieve lockers: %d", ret);
return ERR_PTR(ret);
}
if (*num_lockers == 0) { if (num_lockers == 0) {
dout("%s rbd_dev %p no lockers detected\n", __func__, rbd_dev); dout("%s rbd_dev %p no lockers detected\n", __func__, rbd_dev);
lockers = NULL;
goto out; goto out;
} }
if (strcmp(lock_tag, RBD_LOCK_TAG)) { if (strcmp(lock_tag, RBD_LOCK_TAG)) {
rbd_warn(rbd_dev, "locked by external mechanism, tag %s", rbd_warn(rbd_dev, "locked by external mechanism, tag %s",
lock_tag); lock_tag);
ret = -EBUSY; goto err_busy;
goto out;
} }
if (lock_type == CEPH_CLS_LOCK_SHARED) { if (lock_type == CEPH_CLS_LOCK_SHARED) {
rbd_warn(rbd_dev, "shared lock type detected"); rbd_warn(rbd_dev, "shared lock type detected");
ret = -EBUSY; goto err_busy;
goto out;
} }
if (strncmp((*lockers)[0].id.cookie, RBD_LOCK_COOKIE_PREFIX, WARN_ON(num_lockers != 1);
if (strncmp(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX,
strlen(RBD_LOCK_COOKIE_PREFIX))) { strlen(RBD_LOCK_COOKIE_PREFIX))) {
rbd_warn(rbd_dev, "locked by external mechanism, cookie %s", rbd_warn(rbd_dev, "locked by external mechanism, cookie %s",
(*lockers)[0].id.cookie); lockers[0].id.cookie);
ret = -EBUSY; goto err_busy;
goto out;
} }
out: out:
kfree(lock_tag); kfree(lock_tag);
return ret; return lockers;
err_busy:
kfree(lock_tag);
ceph_free_lockers(lockers, num_lockers);
return ERR_PTR(-EBUSY);
} }
static int find_watcher(struct rbd_device *rbd_dev, static int find_watcher(struct rbd_device *rbd_dev,
...@@ -3947,51 +3960,56 @@ static int find_watcher(struct rbd_device *rbd_dev, ...@@ -3947,51 +3960,56 @@ static int find_watcher(struct rbd_device *rbd_dev,
static int rbd_try_lock(struct rbd_device *rbd_dev) static int rbd_try_lock(struct rbd_device *rbd_dev)
{ {
struct ceph_client *client = rbd_dev->rbd_client->client; struct ceph_client *client = rbd_dev->rbd_client->client;
struct ceph_locker *lockers; struct ceph_locker *locker;
u32 num_lockers;
int ret; int ret;
for (;;) { for (;;) {
locker = NULL;
ret = rbd_lock(rbd_dev); ret = rbd_lock(rbd_dev);
if (ret != -EBUSY) if (ret != -EBUSY)
return ret; goto out;
/* determine if the current lock holder is still alive */ /* determine if the current lock holder is still alive */
ret = get_lock_owner_info(rbd_dev, &lockers, &num_lockers); locker = get_lock_owner_info(rbd_dev);
if (ret) if (IS_ERR(locker)) {
return ret; ret = PTR_ERR(locker);
locker = NULL;
if (num_lockers == 0) goto out;
}
if (!locker)
goto again; goto again;
ret = find_watcher(rbd_dev, lockers); ret = find_watcher(rbd_dev, locker);
if (ret) if (ret)
goto out; /* request lock or error */ goto out; /* request lock or error */
rbd_warn(rbd_dev, "breaking header lock owned by %s%llu", rbd_warn(rbd_dev, "breaking header lock owned by %s%llu",
ENTITY_NAME(lockers[0].id.name)); ENTITY_NAME(locker->id.name));
ret = ceph_monc_blocklist_add(&client->monc, ret = ceph_monc_blocklist_add(&client->monc,
&lockers[0].info.addr); &locker->info.addr);
if (ret) { if (ret) {
rbd_warn(rbd_dev, "blocklist of %s%llu failed: %d", rbd_warn(rbd_dev, "failed to blocklist %s%llu: %d",
ENTITY_NAME(lockers[0].id.name), ret); ENTITY_NAME(locker->id.name), ret);
goto out; goto out;
} }
ret = ceph_cls_break_lock(&client->osdc, &rbd_dev->header_oid, ret = ceph_cls_break_lock(&client->osdc, &rbd_dev->header_oid,
&rbd_dev->header_oloc, RBD_LOCK_NAME, &rbd_dev->header_oloc, RBD_LOCK_NAME,
lockers[0].id.cookie, locker->id.cookie, &locker->id.name);
&lockers[0].id.name); if (ret && ret != -ENOENT) {
if (ret && ret != -ENOENT) rbd_warn(rbd_dev, "failed to break header lock: %d",
ret);
goto out; goto out;
}
again: again:
ceph_free_lockers(lockers, num_lockers); free_locker(locker);
} }
out: out:
ceph_free_lockers(lockers, num_lockers); free_locker(locker);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment