Skip to content

Commit 0ace9df

Browse files
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>
1 parent 9dc9fbb commit 0ace9df

File tree

3 files changed

+16
-7
lines changed

3 files changed

+16
-7
lines changed

drivers/block/drbd/drbd_int.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1381,7 +1381,7 @@ extern void drbd_delete_device(struct drbd_conf *mdev);
13811381

13821382
struct drbd_tconn *conn_create(const char *name);
13831383
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);
13851385
extern void conn_free_crypto(struct drbd_tconn *tconn);
13861386

13871387
extern int proc_details;

drivers/block/drbd/drbd_main.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -2362,7 +2362,7 @@ static void drbd_init_workqueue(struct drbd_work_queue* wq)
23622362
INIT_LIST_HEAD(&wq->q);
23632363
}
23642364

2365-
struct drbd_tconn *conn_by_name(const char *name)
2365+
struct drbd_tconn *conn_get_by_name(const char *name)
23662366
{
23672367
struct drbd_tconn *tconn;
23682368

@@ -2371,8 +2371,10 @@ struct drbd_tconn *conn_by_name(const char *name)
23712371

23722372
down_read(&drbd_cfg_rwsem);
23732373
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);
23752376
goto found;
2377+
}
23762378
}
23772379
tconn = NULL;
23782380
found:

drivers/block/drbd/drbd_nl.c

+11-4
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
195195

196196
adm_ctx.minor = d_in->minor;
197197
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);
199199

200200
if (!adm_ctx.mdev && (flags & DRBD_ADM_NEED_MINOR)) {
201201
drbd_msg_put_info("unknown minor");
@@ -223,8 +223,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
223223
drbd_msg_put_info("minor exists as different volume");
224224
return ERR_INVALID_REQUEST;
225225
}
226-
if (adm_ctx.mdev && !adm_ctx.tconn)
227-
adm_ctx.tconn = adm_ctx.mdev->tconn;
226+
228227
return NO_ERROR;
229228

230229
fail:
@@ -238,6 +237,11 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
238237
struct nlattr *nla;
239238
const char *conn_name = NULL;
240239

240+
if (adm_ctx.tconn) {
241+
kref_put(&adm_ctx.tconn->kref, &conn_destroy);
242+
adm_ctx.tconn = NULL;
243+
}
244+
241245
if (!adm_ctx.reply_skb)
242246
return -ENOMEM;
243247

@@ -2748,10 +2752,13 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
27482752
if (!nla)
27492753
return -EINVAL;
27502754
conn_name = nla_data(nla);
2751-
tconn = conn_by_name(conn_name);
2755+
tconn = conn_get_by_name(conn_name);
2756+
27522757
if (!tconn)
27532758
return -ENODEV;
27542759

2760+
kref_put(&tconn->kref, &conn_destroy); /* get_one_status() (re)validates tconn by itself */
2761+
27552762
/* prime iterators, and set "filter" mode mark:
27562763
* only dump this tconn. */
27572764
cb->args[0] = (long)tconn;

0 commit comments

Comments
 (0)