diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-04-24 04:53:19 -0400 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 10:49:06 -0500 |
commit | 0ace9dfabec3c1e96a1cd9fe0791ecbe6737c2f9 (patch) | |
tree | de80467afbc59c4d98cdf6a3defa55fee051ac98 /drivers | |
parent | 9dc9fbb35733c8ea97fe9b1cfc5499c7a625805c (diff) |
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 2 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 6 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 15 |
3 files changed, 16 insertions, 7 deletions
diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index 3abf982ec559..7797879d3264 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h | |||
@@ -1381,7 +1381,7 @@ extern void drbd_delete_device(struct drbd_conf *mdev); | |||
1381 | 1381 | ||
1382 | struct drbd_tconn *conn_create(const char *name); | 1382 | struct drbd_tconn *conn_create(const char *name); |
1383 | extern void conn_destroy(struct kref *kref); | 1383 | extern void conn_destroy(struct kref *kref); |
1384 | struct drbd_tconn *conn_by_name(const char *name); | 1384 | struct drbd_tconn *conn_get_by_name(const char *name); |
1385 | extern void conn_free_crypto(struct drbd_tconn *tconn); | 1385 | extern void conn_free_crypto(struct drbd_tconn *tconn); |
1386 | 1386 | ||
1387 | extern int proc_details; | 1387 | extern int proc_details; |
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 11427f59c5af..f0a0e1759bab 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -2362,7 +2362,7 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq) | |||
2362 | INIT_LIST_HEAD(&wq->q); | 2362 | INIT_LIST_HEAD(&wq->q); |
2363 | } | 2363 | } |
2364 | 2364 | ||
2365 | struct drbd_tconn *conn_by_name(const char *name) | 2365 | struct drbd_tconn *conn_get_by_name(const char *name) |
2366 | { | 2366 | { |
2367 | struct drbd_tconn *tconn; | 2367 | struct drbd_tconn *tconn; |
2368 | 2368 | ||
@@ -2371,8 +2371,10 @@ struct drbd_tconn *conn_by_name(const char *name) | |||
2371 | 2371 | ||
2372 | down_read(&drbd_cfg_rwsem); | 2372 | down_read(&drbd_cfg_rwsem); |
2373 | list_for_each_entry(tconn, &drbd_tconns, all_tconn) { | 2373 | list_for_each_entry(tconn, &drbd_tconns, all_tconn) { |
2374 | if (!strcmp(tconn->name, name)) | 2374 | if (!strcmp(tconn->name, name)) { |
2375 | kref_get(&tconn->kref); | ||
2375 | goto found; | 2376 | goto found; |
2377 | } | ||
2376 | } | 2378 | } |
2377 | tconn = NULL; | 2379 | tconn = NULL; |
2378 | found: | 2380 | found: |
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 23c34baa75a4..272c4a08ee42 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c | |||
@@ -195,7 +195,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, | |||
195 | 195 | ||
196 | adm_ctx.minor = d_in->minor; | 196 | adm_ctx.minor = d_in->minor; |
197 | adm_ctx.mdev = minor_to_mdev(d_in->minor); | 197 | adm_ctx.mdev = minor_to_mdev(d_in->minor); |
198 | adm_ctx.tconn = conn_by_name(adm_ctx.conn_name); | 198 | adm_ctx.tconn = conn_get_by_name(adm_ctx.conn_name); |
199 | 199 | ||
200 | if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) { | 200 | if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) { |
201 | drbd_msg_put_info("unknown minor"); | 201 | drbd_msg_put_info("unknown minor"); |
@@ -223,8 +223,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info, | |||
223 | drbd_msg_put_info("minor exists as different volume"); | 223 | drbd_msg_put_info("minor exists as different volume"); |
224 | return ERR_INVALID_REQUEST; | 224 | return ERR_INVALID_REQUEST; |
225 | } | 225 | } |
226 | if (adm_ctx.mdev && !adm_ctx.tconn) | 226 | |
227 | adm_ctx.tconn = adm_ctx.mdev->tconn; | ||
228 | return NO_ERROR; | 227 | return NO_ERROR; |
229 | 228 | ||
230 | fail: | 229 | fail: |
@@ -238,6 +237,11 @@ static int drbd_adm_finish(struct genl_info *info, int retcode) | |||
238 | struct nlattr *nla; | 237 | struct nlattr *nla; |
239 | const char *conn_name = NULL; | 238 | const char *conn_name = NULL; |
240 | 239 | ||
240 | if (adm_ctx.tconn) { | ||
241 | kref_put(&adm_ctx.tconn->kref, &conn_destroy); | ||
242 | adm_ctx.tconn = NULL; | ||
243 | } | ||
244 | |||
241 | if (!adm_ctx.reply_skb) | 245 | if (!adm_ctx.reply_skb) |
242 | return -ENOMEM; | 246 | return -ENOMEM; |
243 | 247 | ||
@@ -2748,10 +2752,13 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
2748 | if (!nla) | 2752 | if (!nla) |
2749 | return -EINVAL; | 2753 | return -EINVAL; |
2750 | conn_name = nla_data(nla); | 2754 | conn_name = nla_data(nla); |
2751 | tconn = conn_by_name(conn_name); | 2755 | tconn = conn_get_by_name(conn_name); |
2756 | |||
2752 | if (!tconn) | 2757 | if (!tconn) |
2753 | return -ENODEV; | 2758 | return -ENODEV; |
2754 | 2759 | ||
2760 | kref_put(&tconn->kref, &conn_destroy); /* get_one_status() (re)validates tconn by itself */ | ||
2761 | |||
2755 | /* prime iterators, and set "filter" mode mark: | 2762 | /* prime iterators, and set "filter" mode mark: |
2756 | * only dump this tconn. */ | 2763 | * only dump this tconn. */ |
2757 | cb->args[0] = (long)tconn; | 2764 | cb->args[0] = (long)tconn; |