Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44ed167d authored by Philipp Reisner's avatar Philipp Reisner
Browse files

drbd: rcu_read_lock() and rcu_dereference() for tconn->net_conf



Removing the get_net_conf()/put_net_conf() calls

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent b032b6fa
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -832,7 +832,7 @@ struct drbd_tconn { /* is a resource from the config file */
	struct mutex cstate_mutex;	/* Protects graceful disconnects */

	unsigned long flags;
	struct net_conf *net_conf;	/* protected by get_net_conf() and put_net_conf() */
	struct net_conf *net_conf;	/* content protected by rcu */
	atomic_t net_cnt;		/* Users of net_conf */
	wait_queue_head_t net_cnt_wait;
	wait_queue_head_t ping_wait;		/* Woken upon reception of a ping, and a state change */
@@ -2059,11 +2059,14 @@ static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
 * maybe re-implement using semaphores? */
static inline int drbd_get_max_buffers(struct drbd_conf *mdev)
{
	int mxb = 1000000; /* arbitrary limit on open requests */
	if (get_net_conf(mdev->tconn)) {
		mxb = mdev->tconn->net_conf->max_buffers;
		put_net_conf(mdev->tconn);
	}
	struct net_conf *nc;
	int mxb;

	rcu_read_lock();
	nc = rcu_dereference(mdev->tconn->net_conf);
	mxb = nc ? nc->max_buffers : 1000000;  /* arbitrary limit on open requests */
	rcu_read_unlock();

	return mxb;
}

+50 −28
Original line number Diff line number Diff line
@@ -843,15 +843,19 @@ int drbd_send_sync_param(struct drbd_conf *mdev)
	int size;
	const int apv = mdev->tconn->agreed_pro_version;
	enum drbd_packet cmd;
	struct net_conf *nc;

	sock = &mdev->tconn->data;
	p = drbd_prepare_command(mdev, sock);
	if (!p)
		return -EIO;

	rcu_read_lock();
	nc = rcu_dereference(mdev->tconn->net_conf);

	size = apv <= 87 ? sizeof(struct p_rs_param)
		: apv == 88 ? sizeof(struct p_rs_param)
			+ strlen(mdev->tconn->net_conf->verify_alg) + 1
			+ strlen(nc->verify_alg) + 1
		: apv <= 94 ? sizeof(struct p_rs_param_89)
		: /* apv >= 95 */ sizeof(struct p_rs_param_95);

@@ -876,9 +880,10 @@ int drbd_send_sync_param(struct drbd_conf *mdev)
	}

	if (apv >= 88)
		strcpy(p->verify_alg, mdev->tconn->net_conf->verify_alg);
		strcpy(p->verify_alg, nc->verify_alg);
	if (apv >= 89)
		strcpy(p->csums_alg, mdev->tconn->net_conf->csums_alg);
		strcpy(p->csums_alg, nc->csums_alg);
	rcu_read_unlock();

	return drbd_send_command(mdev, sock, cmd, size, NULL, 0);
}
@@ -887,36 +892,44 @@ int drbd_send_protocol(struct drbd_tconn *tconn)
{
	struct drbd_socket *sock;
	struct p_protocol *p;
	struct net_conf *nc;
	int size, cf;

	if (tconn->net_conf->dry_run && tconn->agreed_pro_version < 92) {
		conn_err(tconn, "--dry-run is not supported by peer");
		return -EOPNOTSUPP;
	}

	sock = &tconn->data;
	p = conn_prepare_command(tconn, sock);
	if (!p)
		return -EIO;

	rcu_read_lock();
	nc = rcu_dereference(tconn->net_conf);

	if (nc->dry_run && tconn->agreed_pro_version < 92) {
		rcu_read_unlock();
		mutex_unlock(&sock->mutex);
		conn_err(tconn, "--dry-run is not supported by peer");
		return -EOPNOTSUPP;
	}

	size = sizeof(*p);
	if (tconn->agreed_pro_version >= 87)
		size += strlen(tconn->net_conf->integrity_alg) + 1;
		size += strlen(nc->integrity_alg) + 1;

	p->protocol      = cpu_to_be32(tconn->net_conf->wire_protocol);
	p->after_sb_0p   = cpu_to_be32(tconn->net_conf->after_sb_0p);
	p->after_sb_1p   = cpu_to_be32(tconn->net_conf->after_sb_1p);
	p->after_sb_2p   = cpu_to_be32(tconn->net_conf->after_sb_2p);
	p->two_primaries = cpu_to_be32(tconn->net_conf->two_primaries);
	p->protocol      = cpu_to_be32(nc->wire_protocol);
	p->after_sb_0p   = cpu_to_be32(nc->after_sb_0p);
	p->after_sb_1p   = cpu_to_be32(nc->after_sb_1p);
	p->after_sb_2p   = cpu_to_be32(nc->after_sb_2p);
	p->two_primaries = cpu_to_be32(nc->two_primaries);
	cf = 0;
	if (tconn->net_conf->want_lose)
	if (nc->want_lose)
		cf |= CF_WANT_LOSE;
	if (tconn->net_conf->dry_run)
	if (nc->dry_run)
		cf |= CF_DRY_RUN;
	p->conn_flags    = cpu_to_be32(cf);

	if (tconn->agreed_pro_version >= 87)
		strcpy(p->integrity_alg, tconn->net_conf->integrity_alg);
		strcpy(p->integrity_alg, nc->integrity_alg);
	rcu_read_unlock();

	return conn_send_command(tconn, sock, P_PROTOCOL, size, NULL, 0);
}

@@ -940,7 +953,9 @@ int _drbd_send_uuids(struct drbd_conf *mdev, u64 uuid_flags)

	mdev->comm_bm_set = drbd_bm_total_weight(mdev);
	p->uuid[UI_SIZE] = cpu_to_be64(mdev->comm_bm_set);
	uuid_flags |= mdev->tconn->net_conf->want_lose ? 1 : 0;
	rcu_read_lock();
	uuid_flags |= rcu_dereference(mdev->tconn->net_conf)->want_lose ? 1 : 0;
	rcu_read_unlock();
	uuid_flags |= test_bit(CRASHED_PRIMARY, &mdev->flags) ? 2 : 0;
	uuid_flags |= mdev->new_state_tmp.disk == D_INCONSISTENT ? 4 : 0;
	p->uuid[UI_FLAGS] = cpu_to_be64(uuid_flags);
@@ -1136,11 +1151,13 @@ int fill_bitmap_rle_bits(struct drbd_conf *mdev,
	unsigned long rl;
	unsigned len;
	unsigned toggle;
	int bits;
	int bits, use_rle;

	/* may we use this feature? */
	if ((mdev->tconn->net_conf->use_rle == 0) ||
		(mdev->tconn->agreed_pro_version < 90))
	rcu_read_lock();
	use_rle = rcu_dereference(mdev->tconn->net_conf)->use_rle;
	rcu_read_unlock();
	if (!use_rle || mdev->tconn->agreed_pro_version < 90)
		return 0;

	if (c->bit_offset >= c->bm_bits)
@@ -1812,7 +1829,9 @@ int drbd_send(struct drbd_tconn *tconn, struct socket *sock,
	msg.msg_flags      = msg_flags | MSG_NOSIGNAL;

	if (sock == tconn->data.socket) {
		tconn->ko_count = tconn->net_conf->ko_count;
		rcu_read_lock();
		tconn->ko_count = rcu_dereference(tconn->net_conf)->ko_count;
		rcu_read_unlock();
		drbd_update_congested(tconn);
	}
	do {
@@ -3235,15 +3254,18 @@ const char *cmdname(enum drbd_packet cmd)
 */
int drbd_wait_misc(struct drbd_conf *mdev, struct drbd_interval *i)
{
	struct net_conf *net_conf = mdev->tconn->net_conf;
	struct net_conf *nc;
	DEFINE_WAIT(wait);
	long timeout;

	if (!net_conf)
	rcu_read_lock();
	nc = rcu_dereference(mdev->tconn->net_conf);
	if (!nc) {
		rcu_read_unlock();
		return -ETIMEDOUT;
	timeout = MAX_SCHEDULE_TIMEOUT;
	if (net_conf->ko_count)
		timeout = net_conf->timeout * HZ / 10 * net_conf->ko_count;
	}
	timeout = nc->ko_count ? nc->timeout * HZ / 10 * nc->ko_count : MAX_SCHEDULE_TIMEOUT;
	rcu_read_unlock();

	/* Indicate to wake up mdev->misc_wait on progress.  */
	i->waiting = true;
+108 −74
Original line number Diff line number Diff line
@@ -257,27 +257,30 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
static void setup_khelper_env(struct drbd_tconn *tconn, char **envp)
{
	char *afs;
	struct net_conf *nc;

	if (get_net_conf(tconn)) {
		switch (((struct sockaddr *)tconn->net_conf->peer_addr)->sa_family) {
	rcu_read_lock();
	nc = rcu_dereference(tconn->net_conf);
	if (nc) {
		switch (((struct sockaddr *)nc->peer_addr)->sa_family) {
		case AF_INET6:
			afs = "ipv6";
			snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI6",
				 &((struct sockaddr_in6 *)tconn->net_conf->peer_addr)->sin6_addr);
				 &((struct sockaddr_in6 *)nc->peer_addr)->sin6_addr);
			break;
		case AF_INET:
			afs = "ipv4";
			snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
				 &((struct sockaddr_in *)tconn->net_conf->peer_addr)->sin_addr);
				 &((struct sockaddr_in *)nc->peer_addr)->sin_addr);
			break;
		default:
			afs = "ssocks";
			snprintf(envp[4], 60, "DRBD_PEER_ADDRESS=%pI4",
				 &((struct sockaddr_in *)tconn->net_conf->peer_addr)->sin_addr);
				 &((struct sockaddr_in *)nc->peer_addr)->sin_addr);
		}
		snprintf(envp[3], 20, "DRBD_PEER_AF=%s", afs);
		put_net_conf(tconn);
	}
	rcu_read_unlock();
}

int drbd_khelper(struct drbd_conf *mdev, char *cmd)
@@ -493,6 +496,7 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
{
	const int max_tries = 4;
	enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
	struct net_conf *nc;
	int try = 0;
	int forced = 0;
	union drbd_state mask, val;
@@ -550,7 +554,12 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
		if (rv == SS_TWO_PRIMARIES) {
			/* Maybe the peer is detected as dead very soon...
			   retry at most once more in this case. */
			schedule_timeout_interruptible((mdev->tconn->net_conf->ping_timeo+1)*HZ/10);
			int timeo;
			rcu_read_lock();
			nc = rcu_dereference(mdev->tconn->net_conf);
			timeo = nc ? (nc->ping_timeo + 1) * HZ / 10 : 1;
			rcu_read_unlock();
			schedule_timeout_interruptible(timeo);
			if (try < max_tries)
				try = max_tries - 1;
			continue;
@@ -580,10 +589,11 @@ drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
			put_ldev(mdev);
		}
	} else {
		if (get_net_conf(mdev->tconn)) {
			mdev->tconn->net_conf->want_lose = 0;
			put_net_conf(mdev->tconn);
		}
		rcu_read_lock();
		nc = rcu_dereference(mdev->tconn->net_conf);
		if (nc)
			nc->want_lose = 0;
		rcu_read_unlock();
		set_disk_ro(mdev->vdisk, false);
		if (get_ldev(mdev)) {
			if (((mdev->state.conn < C_CONNECTED ||
@@ -1193,6 +1203,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
	struct lru_cache *resync_lru = NULL;
	union drbd_state ns, os;
	enum drbd_state_rv rv;
	struct net_conf *nc;
	int cp_discovered = 0;

	retcode = drbd_adm_prepare(skb, info, DRBD_ADM_NEED_MINOR);
@@ -1256,14 +1267,16 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
		goto fail;
	}

	if (get_net_conf(mdev->tconn)) {
		int prot = mdev->tconn->net_conf->wire_protocol;
		put_net_conf(mdev->tconn);
		if (nbc->dc.fencing == FP_STONITH && prot == DRBD_PROT_A) {
	rcu_read_lock();
	nc = rcu_dereference(mdev->tconn->net_conf);
	if (nc) {
		if (nbc->dc.fencing == FP_STONITH && nc->wire_protocol == DRBD_PROT_A) {
			rcu_read_unlock();
			retcode = ERR_STONITH_AND_PROT_A;
			goto fail;
		}
	}
	rcu_read_unlock();

	bdev = blkdev_get_by_path(nbc->dc.backing_dev,
				  FMODE_READ | FMODE_WRITE | FMODE_EXCL, mdev);
@@ -1666,42 +1679,30 @@ static bool conn_ov_running(struct drbd_tconn *tconn)
}

static enum drbd_ret_code
check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf)
_check_net_options(struct drbd_tconn *tconn, struct net_conf *old_conf, struct net_conf *new_conf)
{
	struct drbd_conf *mdev;
	int i;

	if (tconn->net_conf && tconn->agreed_pro_version < 100 &&
	if (old_conf && tconn->agreed_pro_version < 100 &&
	    tconn->cstate == C_WF_REPORT_PARAMS &&
	    new_conf->wire_protocol != tconn->net_conf->wire_protocol)
	    new_conf->wire_protocol != old_conf->wire_protocol)
		return ERR_NEED_APV_100;

	if (new_conf->two_primaries &&
	    (new_conf->wire_protocol != DRBD_PROT_C))
		return ERR_NOT_PROTO_C;

	rcu_read_lock();
	idr_for_each_entry(&tconn->volumes, mdev, i) {
		if (get_ldev(mdev)) {
			enum drbd_fencing_p fp = mdev->ldev->dc.fencing;
			put_ldev(mdev);
			if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH) {
				rcu_read_unlock();
			if (new_conf->wire_protocol == DRBD_PROT_A && fp == FP_STONITH)
				return ERR_STONITH_AND_PROT_A;
		}
		}
		if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
			rcu_read_unlock();
		if (mdev->state.role == R_PRIMARY && new_conf->want_lose)
			return ERR_DISCARD;
	}
		if (!mdev->bitmap) {
			if(drbd_bm_init(mdev)) {
				rcu_read_unlock();
				return ERR_NOMEM;
			}
		}
	}
	rcu_read_unlock();

	if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A)
		return ERR_CONG_NOT_PROTO_A;
@@ -1709,11 +1710,33 @@ check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf)
	return NO_ERROR;
}

static enum drbd_ret_code
check_net_options(struct drbd_tconn *tconn, struct net_conf *new_conf)
{
	static enum drbd_ret_code rv;
	struct drbd_conf *mdev;
	int i;

	rcu_read_lock();
	rv = _check_net_options(tconn, rcu_dereference(tconn->net_conf), new_conf);
	rcu_read_unlock();

	/* tconn->volumes protected by genl_lock() here */
	idr_for_each_entry(&tconn->volumes, mdev, i) {
		if (!mdev->bitmap) {
			if(drbd_bm_init(mdev))
				return ERR_NOMEM;
		}
	}

	return rv;
}

int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
{
	enum drbd_ret_code retcode;
	struct drbd_tconn *tconn;
	struct net_conf *new_conf = NULL;
	struct net_conf *old_conf, *new_conf = NULL;
	int err;
	int ovr; /* online verify running */
	int rsr; /* re-sync running */
@@ -1735,17 +1758,20 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
		goto out;
	}

	/* we also need a net config
	 * to change the options on */
	if (!get_net_conf(tconn)) {
	conn_reconfig_start(tconn);

	rcu_read_lock();
	old_conf = rcu_dereference(tconn->net_conf);

	if (!old_conf) {
		drbd_msg_put_info("net conf missing, try connect");
		retcode = ERR_INVALID_REQUEST;
		goto out;
		goto fail_rcu_unlock;
	}

	conn_reconfig_start(tconn);
	*new_conf = *old_conf;
	rcu_read_unlock();

	memcpy(new_conf, tconn->net_conf, sizeof(*new_conf));
	err = net_conf_from_attrs_for_change(new_conf, info);
	if (err) {
		retcode = ERR_MANDATORY_TAG;
@@ -1759,10 +1785,13 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)

	/* re-sync running */
	rsr = conn_resync_running(tconn);
	if (rsr && strcmp(new_conf->csums_alg, tconn->net_conf->csums_alg)) {
	rcu_read_lock();
	old_conf = rcu_dereference(tconn->net_conf);
	if (rsr && old_conf && strcmp(new_conf->csums_alg, old_conf->csums_alg)) {
		retcode = ERR_CSUMS_RESYNC_RUNNING;
		goto fail;
		goto fail_rcu_unlock;
	}
	rcu_read_unlock();

	if (!rsr && new_conf->csums_alg[0]) {
		csums_tfm = crypto_alloc_hash(new_conf->csums_alg, 0, CRYPTO_ALG_ASYNC);
@@ -1780,12 +1809,15 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)

	/* online verify running */
	ovr = conn_ov_running(tconn);
	if (ovr) {
		if (strcmp(new_conf->verify_alg, tconn->net_conf->verify_alg)) {
	rcu_read_lock();
	old_conf = rcu_dereference(tconn->net_conf);
	if (ovr && old_conf) {
		if (strcmp(new_conf->verify_alg, old_conf->verify_alg)) {
			retcode = ERR_VERIFY_RUNNING;
			goto fail;
			goto fail_rcu_unlock;
		}
	}
	rcu_read_unlock();

	if (!ovr && new_conf->verify_alg[0]) {
		verify_tfm = crypto_alloc_hash(new_conf->verify_alg, 0, CRYPTO_ALG_ASYNC);
@@ -1801,16 +1833,9 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
		}
	}


	/* For now, use struct assignment, not pointer assignment.
	 * We don't have any means to determine who might still
	 * keep a local alias into the struct,
	 * so we cannot just free it and hope for the best :(
	 * FIXME
	 * To avoid someone looking at a half-updated struct, we probably
	 * should have a rw-semaphor on net_conf and disk_conf.
	 */
	*tconn->net_conf = *new_conf;
	rcu_assign_pointer(tconn->net_conf, new_conf);
	synchronize_rcu();
	kfree(old_conf);

	if (!rsr) {
		crypto_free_hash(tconn->csums_tfm);
@@ -1826,11 +1851,12 @@ int drbd_adm_net_opts(struct sk_buff *skb, struct genl_info *info)
	if (tconn->cstate >= C_WF_REPORT_PARAMS)
		drbd_send_sync_param(minor_to_mdev(conn_lowest_minor(tconn)));

 fail_rcu_unlock:
	rcu_read_unlock();
 fail:
	crypto_free_hash(csums_tfm);
	crypto_free_hash(verify_tfm);
	kfree(new_conf);
	put_net_conf(tconn);
	conn_reconfig_done(tconn);
 out:
	drbd_adm_finish(info, retcode);
@@ -1841,7 +1867,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
{
	char hmac_name[CRYPTO_MAX_ALG_NAME];
	struct drbd_conf *mdev;
	struct net_conf *new_conf = NULL;
	struct net_conf *old_conf, *new_conf = NULL;
	struct crypto_hash *tfm = NULL;
	struct crypto_hash *integrity_w_tfm = NULL;
	struct crypto_hash *integrity_r_tfm = NULL;
@@ -1929,24 +1955,27 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)
	 * strictly serialized on genl_lock(). We are protected against
	 * concurrent reconfiguration/addition/deletion */
	list_for_each_entry(oconn, &drbd_tconns, all_tconn) {
		struct net_conf *nc;
		if (oconn == tconn)
			continue;
		if (get_net_conf(oconn)) {
			taken_addr = (struct sockaddr *)&oconn->net_conf->my_addr;
			if (new_conf->my_addr_len == oconn->net_conf->my_addr_len &&

		rcu_read_lock();
		nc = rcu_dereference(oconn->net_conf);
		if (nc) {
			taken_addr = (struct sockaddr *)&nc->my_addr;
			if (new_conf->my_addr_len == nc->my_addr_len &&
			    !memcmp(new_my_addr, taken_addr, new_conf->my_addr_len))
				retcode = ERR_LOCAL_ADDR;

			taken_addr = (struct sockaddr *)&oconn->net_conf->peer_addr;
			if (new_conf->peer_addr_len == oconn->net_conf->peer_addr_len &&
			taken_addr = (struct sockaddr *)&nc->peer_addr;
			if (new_conf->peer_addr_len == nc->peer_addr_len &&
			    !memcmp(new_peer_addr, taken_addr, new_conf->peer_addr_len))
				retcode = ERR_PEER_ADDR;

			put_net_conf(oconn);
		}
		rcu_read_unlock();
		if (retcode != NO_ERROR)
			goto fail;
	}
	}

	if (new_conf->cram_hmac_alg[0] != 0) {
		snprintf(hmac_name, CRYPTO_MAX_ALG_NAME, "hmac(%s)",
@@ -2004,12 +2033,15 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info)

	conn_flush_workqueue(tconn);
	spin_lock_irq(&tconn->req_lock);
	if (tconn->net_conf != NULL) {
	rcu_read_lock();
	old_conf = rcu_dereference(tconn->net_conf);
	if (old_conf != NULL) {
		retcode = ERR_NET_CONFIGURED;
		rcu_read_unlock();
		spin_unlock_irq(&tconn->req_lock);
		goto fail;
	}
	tconn->net_conf = new_conf;
	rcu_assign_pointer(tconn->net_conf, new_conf);

	crypto_free_hash(tconn->cram_hmac_tfm);
	tconn->cram_hmac_tfm = tfm;
@@ -2464,9 +2496,9 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
		const struct sib_info *sib)
{
	struct state_info *si = NULL; /* for sizeof(si->member); */
	struct net_conf *nc;
	struct nlattr *nla;
	int got_ldev;
	int got_net;
	int err = 0;
	int exclude_sensitive;

@@ -2484,7 +2516,6 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
	exclude_sensitive = sib || !capable(CAP_SYS_ADMIN);

	got_ldev = get_ldev(mdev);
	got_net = get_net_conf(mdev->tconn);

	/* We need to add connection name and volume number information still.
	 * Minor number is in drbd_genlmsghdr. */
@@ -2497,8 +2528,13 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
	if (got_ldev)
		if (disk_conf_to_skb(skb, &mdev->ldev->dc, exclude_sensitive))
			goto nla_put_failure;
	if (got_net)
		if (net_conf_to_skb(skb, mdev->tconn->net_conf, exclude_sensitive))

	rcu_read_lock();
	nc = rcu_dereference(mdev->tconn->net_conf);
	if (nc)
		err = net_conf_to_skb(skb, nc, exclude_sensitive);
	rcu_read_unlock();
	if (err)
		goto nla_put_failure;

	nla = nla_nest_start(skb, DRBD_NLA_STATE_INFO);
@@ -2546,8 +2582,6 @@ int nla_put_status_info(struct sk_buff *skb, struct drbd_conf *mdev,
		err = -EMSGSIZE;
	if (got_ldev)
		put_ldev(mdev);
	if (got_net)
		put_net_conf(mdev->tconn);
	return err;
}

+7 −2
Original line number Diff line number Diff line
@@ -197,6 +197,8 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
	int i, prev_i = -1;
	const char *sn;
	struct drbd_conf *mdev;
	struct net_conf *nc;
	char wp;

	static char write_ordering_chars[] = {
		[WO_none] = 'n',
@@ -240,6 +242,10 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
		    mdev->state.role == R_SECONDARY) {
			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
		} else {
			rcu_read_lock();
			nc = rcu_dereference(mdev->tconn->net_conf);
			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
			rcu_read_unlock();
			seq_printf(seq,
			   "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
			   "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
@@ -249,8 +255,7 @@ static int drbd_seq_show(struct seq_file *seq, void *v)
			   drbd_role_str(mdev->state.peer),
			   drbd_disk_str(mdev->state.disk),
			   drbd_disk_str(mdev->state.pdsk),
			   (mdev->tconn->net_conf == NULL ? ' ' :
			    (mdev->tconn->net_conf->wire_protocol - DRBD_PROT_A+'A')),
			   wp,
			   drbd_suspended(mdev) ? 's' : 'r',
			   mdev->state.aftr_isp ? 'a' : '-',
			   mdev->state.peer_isp ? 'p' : '-',
+167 −78

File changed.

Preview size limit exceeded, changes collapsed.

Loading