Commit ec0bddbc authored by Philipp Reisner's avatar Philipp Reisner
Browse files

drbd: Use RCU for the drbd_tconns list



Preparing removal of drbd_cfg_rwsem

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 81fa2e67
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -2341,7 +2341,7 @@ static void drbd_cleanup(void)
	}

	list_for_each_entry_safe(tconn, tmp, &drbd_tconns, all_tconn) {
		list_del(&tconn->all_tconn);
		list_del_rcu(&tconn->all_tconn);
		synchronize_rcu();
		kref_put(&tconn->kref, &conn_destroy);
	}
@@ -2409,7 +2409,7 @@ struct drbd_tconn *conn_get_by_name(const char *name)
		return NULL;

	down_read(&drbd_cfg_rwsem);
	list_for_each_entry(tconn, &drbd_tconns, all_tconn) {
	list_for_each_entry_rcu(tconn, &drbd_tconns, all_tconn) {
		if (!strcmp(tconn->name, name)) {
			kref_get(&tconn->kref);
			goto found;
@@ -2459,6 +2459,7 @@ void conn_free_crypto(struct drbd_tconn *tconn)
	tconn->int_dig_vv = NULL;
}

/* caller must be under genl_lock() */
struct drbd_tconn *conn_create(const char *name)
{
	struct drbd_tconn *tconn;
@@ -2503,7 +2504,7 @@ struct drbd_tconn *conn_create(const char *name)

	down_write(&drbd_cfg_rwsem);
	kref_init(&tconn->kref);
	list_add_tail(&tconn->all_tconn, &drbd_tconns);
	list_add_tail_rcu(&tconn->all_tconn, &drbd_tconns);
	up_write(&drbd_cfg_rwsem);

	return tconn;
+7 −5
Original line number Diff line number Diff line
@@ -2674,7 +2674,7 @@ int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
	/* synchronize with conn_create()/conn_destroy() */
	down_read(&drbd_cfg_rwsem);
	/* revalidate iterator position */
	list_for_each_entry(tmp, &drbd_tconns, all_tconn) {
	list_for_each_entry_rcu(tmp, &drbd_tconns, all_tconn) {
		if (pos == NULL) {
			/* first iteration */
			pos = tmp;
@@ -2692,7 +2692,7 @@ int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
		if (!mdev) {
			/* No more volumes to dump on this tconn.
			 * Advance tconn iterator. */
			pos = list_entry(tconn->all_tconn.next,
			pos = list_entry_rcu(tconn->all_tconn.next,
					     struct drbd_tconn, all_tconn);
			/* Did we dump any volume on this tconn yet? */
			if (volume != 0) {
@@ -3130,7 +3130,8 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)

	/* delete connection */
	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
		list_del(&adm_ctx.tconn->all_tconn);
		list_del_rcu(&adm_ctx.tconn->all_tconn);
		synchronize_rcu();
		kref_put(&adm_ctx.tconn->kref, &conn_destroy);

		retcode = NO_ERROR;
@@ -3160,7 +3161,8 @@ int drbd_adm_delete_connection(struct sk_buff *skb, struct genl_info *info)

	down_write(&drbd_cfg_rwsem);
	if (conn_lowest_minor(adm_ctx.tconn) < 0) {
		list_del(&adm_ctx.tconn->all_tconn);
		list_del_rcu(&adm_ctx.tconn->all_tconn);
		synchronize_rcu();
		kref_put(&adm_ctx.tconn->kref, &conn_destroy);

		retcode = NO_ERROR;