From: Philipp Reisner Date: Wed, 13 Apr 2011 21:21:29 +0000 (-0700) Subject: drbd: Converted drbd_cfg_mutex into drbd_cfg_rwsem X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=ef356262846eb49821db7b20a131b6573e4c7d2e;p=linux-beck.git drbd: Converted drbd_cfg_mutex into drbd_cfg_rwsem Signed-off-by: Philipp Reisner Signed-off-by: Lars Ellenberg --- diff --git a/drivers/block/drbd/drbd_int.h b/drivers/block/drbd/drbd_int.h index c49dc085d93a..7896a648d4ad 100644 --- a/drivers/block/drbd/drbd_int.h +++ b/drivers/block/drbd/drbd_int.h @@ -171,7 +171,9 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) { extern struct ratelimit_state drbd_ratelimit_state; extern struct idr minors; extern struct list_head drbd_tconns; -extern struct mutex drbd_cfg_mutex; +extern struct rw_semaphore drbd_cfg_rwsem; +/* drbd_cfg_rwsem protects: drbd_tconns list, + note: non sleeping iterations over the idrs are protoected by RCU */ /* on the wire */ enum drbd_packet { diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5abbdaf04663..86fd4c829005 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c @@ -120,7 +120,7 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0 */ struct idr minors; struct list_head drbd_tconns; /* list of struct drbd_tconn */ -DEFINE_MUTEX(drbd_cfg_mutex); +DECLARE_RWSEM(drbd_cfg_rwsem); struct kmem_cache *drbd_request_cache; struct kmem_cache *drbd_ee_cache; /* peer requests */ @@ -2330,14 +2330,14 @@ struct drbd_tconn *conn_by_name(const char *name) if (!name || !name[0]) return NULL; - mutex_lock(&drbd_cfg_mutex); + down_read(&drbd_cfg_rwsem); list_for_each_entry(tconn, &drbd_tconns, all_tconn) { if (!strcmp(tconn->name, name)) goto found; } tconn = NULL; found: - mutex_unlock(&drbd_cfg_mutex); + up_read(&drbd_cfg_rwsem); return tconn; } @@ -2404,9 +2404,9 @@ struct drbd_tconn *drbd_new_tconn(const char *name) DRBD_ON_NO_DATA_DEF, /* on_no_data */ }; - mutex_lock(&drbd_cfg_mutex); + down_write(&drbd_cfg_rwsem); list_add_tail(&tconn->all_tconn, &drbd_tconns); - mutex_unlock(&drbd_cfg_mutex); + up_write(&drbd_cfg_rwsem); return tconn; diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c index 60c171b17156..424dcb30ee1c 100644 --- a/drivers/block/drbd/drbd_nl.c +++ b/drivers/block/drbd/drbd_nl.c @@ -1905,7 +1905,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) new_my_addr = (struct sockaddr *)&new_conf->my_addr; new_peer_addr = (struct sockaddr *)&new_conf->peer_addr; - /* No need to take drbd_cfg_mutex here. All reconfiguration is + /* No need to take drbd_cfg_rwsem here. All reconfiguration is * strictly serialized on genl_lock(). We are protected against * concurrent reconfiguration/addition/deletion */ list_for_each_entry(oconn, &drbd_tconns, all_tconn) { @@ -2581,7 +2581,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) */ /* synchronize with drbd_new_tconn/drbd_free_tconn */ - mutex_lock(&drbd_cfg_mutex); + down_read(&drbd_cfg_rwsem); next_tconn: /* revalidate iterator position */ list_for_each_entry(tmp, &drbd_tconns, all_tconn) { @@ -2642,7 +2642,7 @@ next_tconn: } out: - mutex_unlock(&drbd_cfg_mutex); + up_read(&drbd_cfg_rwsem); /* where to start the next iteration */ cb->args[0] = (long)pos; cb->args[1] = (pos == tconn) ? volume + 1 : 0; @@ -2894,9 +2894,9 @@ int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info) if (retcode != NO_ERROR) goto out; - mutex_lock(&drbd_cfg_mutex); + down_write(&drbd_cfg_rwsem); retcode = adm_delete_minor(adm_ctx.mdev); - mutex_unlock(&drbd_cfg_mutex); + up_write(&drbd_cfg_rwsem); /* if this was the last volume of this connection, * this will terminate all threads */ if (retcode == NO_ERROR) @@ -2924,7 +2924,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) goto out; } - mutex_lock(&drbd_cfg_mutex); + down_read(&drbd_cfg_rwsem); /* demote */ idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) { retcode = drbd_set_role(mdev, R_SECONDARY, 0); @@ -2951,14 +2951,17 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) goto out_unlock; } } + up_read(&drbd_cfg_rwsem); /* delete volumes */ + down_write(&drbd_cfg_rwsem); idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) { retcode = adm_delete_minor(mdev); if (retcode != NO_ERROR) { /* "can not happen" */ drbd_msg_put_info("failed to delete volume"); - goto out_unlock; + up_write(&drbd_cfg_rwsem); + goto out; } } @@ -2973,10 +2976,12 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) /* "can not happen" */ retcode = ERR_CONN_IN_USE; drbd_msg_put_info("failed to delete connection"); - goto out_unlock; } + + up_write(&drbd_cfg_rwsem); + goto out; out_unlock: - mutex_unlock(&drbd_cfg_mutex); + up_read(&drbd_cfg_rwsem); out: drbd_adm_finish(info, retcode); return 0; @@ -2992,14 +2997,14 @@ int drbd_adm_delete_connection(struct sk_buff *skb, struct genl_info *info) if (retcode != NO_ERROR) goto out; - mutex_lock(&drbd_cfg_mutex); + down_write(&drbd_cfg_rwsem); if (conn_lowest_minor(adm_ctx.tconn) < 0) { drbd_free_tconn(adm_ctx.tconn); retcode = NO_ERROR; } else { retcode = ERR_CONN_IN_USE; } - mutex_unlock(&drbd_cfg_mutex); + up_write(&drbd_cfg_rwsem); out: drbd_adm_finish(info, retcode);