drbd: Take a reference on tconn when finding a tconn by name
Rule #3 of kref.txt Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com> Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
This commit is contained in:
parent
9dc9fbb357
commit
0ace9dfabe
|
@ -1381,7 +1381,7 @@ extern void drbd_delete_device(struct drbd_conf *mdev);
|
|||
|
||||
struct drbd_tconn *conn_create(const char *name);
|
||||
extern void conn_destroy(struct kref *kref);
|
||||
struct drbd_tconn *conn_by_name(const char *name);
|
||||
struct drbd_tconn *conn_get_by_name(const char *name);
|
||||
extern void conn_free_crypto(struct drbd_tconn *tconn);
|
||||
|
||||
extern int proc_details;
|
||||
|
|
|
@ -2362,7 +2362,7 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq)
|
|||
INIT_LIST_HEAD(&wq->q);
|
||||
}
|
||||
|
||||
struct drbd_tconn *conn_by_name(const char *name)
|
||||
struct drbd_tconn *conn_get_by_name(const char *name)
|
||||
{
|
||||
struct drbd_tconn *tconn;
|
||||
|
||||
|
@ -2371,8 +2371,10 @@ struct drbd_tconn *conn_by_name(const char *name)
|
|||
|
||||
down_read(&drbd_cfg_rwsem);
|
||||
list_for_each_entry(tconn, &drbd_tconns, all_tconn) {
|
||||
if (!strcmp(tconn->name, name))
|
||||
if (!strcmp(tconn->name, name)) {
|
||||
kref_get(&tconn->kref);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
tconn = NULL;
|
||||
found:
|
||||
|
|
|
@ -195,7 +195,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
|
|||
|
||||
adm_ctx.minor = d_in->minor;
|
||||
adm_ctx.mdev = minor_to_mdev(d_in->minor);
|
||||
adm_ctx.tconn = conn_by_name(adm_ctx.conn_name);
|
||||
adm_ctx.tconn = conn_get_by_name(adm_ctx.conn_name);
|
||||
|
||||
if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) {
|
||||
drbd_msg_put_info("unknown minor");
|
||||
|
@ -223,8 +223,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
|
|||
drbd_msg_put_info("minor exists as different volume");
|
||||
return ERR_INVALID_REQUEST;
|
||||
}
|
||||
if (adm_ctx.mdev && !adm_ctx.tconn)
|
||||
adm_ctx.tconn = adm_ctx.mdev->tconn;
|
||||
|
||||
return NO_ERROR;
|
||||
|
||||
fail:
|
||||
|
@ -238,6 +237,11 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
|
|||
struct nlattr *nla;
|
||||
const char *conn_name = NULL;
|
||||
|
||||
if (adm_ctx.tconn) {
|
||||
kref_put(&adm_ctx.tconn->kref, &conn_destroy);
|
||||
adm_ctx.tconn = NULL;
|
||||
}
|
||||
|
||||
if (!adm_ctx.reply_skb)
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -2748,10 +2752,13 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
if (!nla)
|
||||
return -EINVAL;
|
||||
conn_name = nla_data(nla);
|
||||
tconn = conn_by_name(conn_name);
|
||||
tconn = conn_get_by_name(conn_name);
|
||||
|
||||
if (!tconn)
|
||||
return -ENODEV;
|
||||
|
||||
kref_put(&tconn->kref, &conn_destroy); /* get_one_status() (re)validates tconn by itself */
|
||||
|
||||
/* prime iterators, and set "filter" mode mark:
|
||||
* only dump this tconn. */
|
||||
cb->args[0] = (long)tconn;
|
||||
|
|
Loading…
Reference in New Issue