Commit 0ace9dfa authored by Philipp Reisner's avatar Philipp Reisner

drbd: Take a reference on tconn when finding a tconn by name

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