diff options
author | Philipp Reisner <philipp.reisner@linbit.com> | 2011-04-13 14:21:29 -0700 |
---|---|---|
committer | Philipp Reisner <philipp.reisner@linbit.com> | 2012-11-08 16:45:17 +0100 |
commit | ef356262846eb49821db7b20a131b6573e4c7d2e (patch) | |
tree | 1c3947782009795f493ec1c27417c2f3d2ed7960 /drivers/block | |
parent | 695d08fa94ce5bb8d9880e260445fbcf50fa41b4 (diff) | |
download | linux-stable-ef356262846eb49821db7b20a131b6573e4c7d2e.tar.gz linux-stable-ef356262846eb49821db7b20a131b6573e4c7d2e.tar.bz2 linux-stable-ef356262846eb49821db7b20a131b6573e4c7d2e.zip |
drbd: Converted drbd_cfg_mutex into drbd_cfg_rwsem
Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: Lars Ellenberg <lars.ellenberg@linbit.com>
Diffstat (limited to 'drivers/block')
-rw-r--r-- | drivers/block/drbd/drbd_int.h | 4 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 10 | ||||
-rw-r--r-- | drivers/block/drbd/drbd_nl.c | 27 |
3 files changed, 24 insertions, 17 deletions
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); |