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

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
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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,9 +2371,11 @@ 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:
	up_read(&drbd_cfg_rwsem);
+11 −4
Original line number Diff line number Diff line
@@ -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;