aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPhilipp Reisner <philipp.reisner@linbit.com>2011-04-24 04:53:19 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2012-11-08 10:49:06 -0500
commit0ace9dfabec3c1e96a1cd9fe0791ecbe6737c2f9 (patch)
treede80467afbc59c4d98cdf6a3defa55fee051ac98 /drivers
parent9dc9fbb35733c8ea97fe9b1cfc5499c7a625805c (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.h2
-rw-r--r--drivers/block/drbd/drbd_main.c6
-rw-r--r--drivers/block/drbd/drbd_nl.c15
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
1382struct drbd_tconn *conn_create(const char *name); 1382struct drbd_tconn *conn_create(const char *name);
1383extern void conn_destroy(struct kref *kref); 1383extern void conn_destroy(struct kref *kref);
1384struct drbd_tconn *conn_by_name(const char *name); 1384struct drbd_tconn *conn_get_by_name(const char *name);
1385extern void conn_free_crypto(struct drbd_tconn *tconn); 1385extern void conn_free_crypto(struct drbd_tconn *tconn);
1386 1386
1387extern int proc_details; 1387extern 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
2365struct drbd_tconn *conn_by_name(const char *name) 2365struct 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;
2378found: 2380found:
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
230fail: 229fail:
@@ -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;