Commit ef356262 authored by Philipp Reisner's avatar Philipp Reisner

drbd: Converted drbd_cfg_mutex into drbd_cfg_rwsem

Signed-off-by: default avatarPhilipp Reisner <philipp.reisner@linbit.com>
Signed-off-by: default avatarLars Ellenberg <lars.ellenberg@linbit.com>
parent 695d08fa
...@@ -171,7 +171,9 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) { ...@@ -171,7 +171,9 @@ drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
extern struct ratelimit_state drbd_ratelimit_state; extern struct ratelimit_state drbd_ratelimit_state;
extern struct idr minors; extern struct idr minors;
extern struct list_head drbd_tconns; 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 */ /* on the wire */
enum drbd_packet { enum drbd_packet {
......
...@@ -120,7 +120,7 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0 ...@@ -120,7 +120,7 @@ module_param_string(usermode_helper, usermode_helper, sizeof(usermode_helper), 0
*/ */
struct idr minors; struct idr minors;
struct list_head drbd_tconns; /* list of struct drbd_tconn */ 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_request_cache;
struct kmem_cache *drbd_ee_cache; /* peer requests */ struct kmem_cache *drbd_ee_cache; /* peer requests */
...@@ -2330,14 +2330,14 @@ struct drbd_tconn *conn_by_name(const char *name) ...@@ -2330,14 +2330,14 @@ struct drbd_tconn *conn_by_name(const char *name)
if (!name || !name[0]) if (!name || !name[0])
return NULL; return NULL;
mutex_lock(&drbd_cfg_mutex); down_read(&drbd_cfg_rwsem);
list_for_each_entry(tconn, &drbd_tconns, all_tconn) { list_for_each_entry(tconn, &drbd_tconns, all_tconn) {
if (!strcmp(tconn->name, name)) if (!strcmp(tconn->name, name))
goto found; goto found;
} }
tconn = NULL; tconn = NULL;
found: found:
mutex_unlock(&drbd_cfg_mutex); up_read(&drbd_cfg_rwsem);
return tconn; return tconn;
} }
...@@ -2404,9 +2404,9 @@ struct drbd_tconn *drbd_new_tconn(const char *name) ...@@ -2404,9 +2404,9 @@ struct drbd_tconn *drbd_new_tconn(const char *name)
DRBD_ON_NO_DATA_DEF, /* on_no_data */ 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); list_add_tail(&tconn->all_tconn, &drbd_tconns);
mutex_unlock(&drbd_cfg_mutex); up_write(&drbd_cfg_rwsem);
return tconn; return tconn;
......
...@@ -1905,7 +1905,7 @@ int drbd_adm_connect(struct sk_buff *skb, struct genl_info *info) ...@@ -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_my_addr = (struct sockaddr *)&new_conf->my_addr;
new_peer_addr = (struct sockaddr *)&new_conf->peer_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 * strictly serialized on genl_lock(). We are protected against
* concurrent reconfiguration/addition/deletion */ * concurrent reconfiguration/addition/deletion */
list_for_each_entry(oconn, &drbd_tconns, all_tconn) { 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) ...@@ -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 */ /* synchronize with drbd_new_tconn/drbd_free_tconn */
mutex_lock(&drbd_cfg_mutex); down_read(&drbd_cfg_rwsem);
next_tconn: next_tconn:
/* revalidate iterator position */ /* revalidate iterator position */
list_for_each_entry(tmp, &drbd_tconns, all_tconn) { list_for_each_entry(tmp, &drbd_tconns, all_tconn) {
...@@ -2642,7 +2642,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -2642,7 +2642,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
} }
out: out:
mutex_unlock(&drbd_cfg_mutex); up_read(&drbd_cfg_rwsem);
/* where to start the next iteration */ /* where to start the next iteration */
cb->args[0] = (long)pos; cb->args[0] = (long)pos;
cb->args[1] = (pos == tconn) ? volume + 1 : 0; 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) ...@@ -2894,9 +2894,9 @@ int drbd_adm_delete_minor(struct sk_buff *skb, struct genl_info *info)
if (retcode != NO_ERROR) if (retcode != NO_ERROR)
goto out; goto out;
mutex_lock(&drbd_cfg_mutex); down_write(&drbd_cfg_rwsem);
retcode = adm_delete_minor(adm_ctx.mdev); 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, /* if this was the last volume of this connection,
* this will terminate all threads */ * this will terminate all threads */
if (retcode == NO_ERROR) if (retcode == NO_ERROR)
...@@ -2924,7 +2924,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) ...@@ -2924,7 +2924,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
goto out; goto out;
} }
mutex_lock(&drbd_cfg_mutex); down_read(&drbd_cfg_rwsem);
/* demote */ /* demote */
idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) { idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
retcode = drbd_set_role(mdev, R_SECONDARY, 0); retcode = drbd_set_role(mdev, R_SECONDARY, 0);
...@@ -2951,14 +2951,17 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info) ...@@ -2951,14 +2951,17 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
goto out_unlock; goto out_unlock;
} }
} }
up_read(&drbd_cfg_rwsem);
/* delete volumes */ /* delete volumes */
down_write(&drbd_cfg_rwsem);
idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) { idr_for_each_entry(&adm_ctx.tconn->volumes, mdev, i) {
retcode = adm_delete_minor(mdev); retcode = adm_delete_minor(mdev);
if (retcode != NO_ERROR) { if (retcode != NO_ERROR) {
/* "can not happen" */ /* "can not happen" */
drbd_msg_put_info("failed to delete volume"); 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) ...@@ -2973,10 +2976,12 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
/* "can not happen" */ /* "can not happen" */
retcode = ERR_CONN_IN_USE; retcode = ERR_CONN_IN_USE;
drbd_msg_put_info("failed to delete connection"); drbd_msg_put_info("failed to delete connection");
goto out_unlock;
} }
up_write(&drbd_cfg_rwsem);
goto out;
out_unlock: out_unlock:
mutex_unlock(&drbd_cfg_mutex); up_read(&drbd_cfg_rwsem);
out: out:
drbd_adm_finish(info, retcode); drbd_adm_finish(info, retcode);
return 0; return 0;
...@@ -2992,14 +2997,14 @@ int drbd_adm_delete_connection(struct sk_buff *skb, struct genl_info *info) ...@@ -2992,14 +2997,14 @@ int drbd_adm_delete_connection(struct sk_buff *skb, struct genl_info *info)
if (retcode != NO_ERROR) if (retcode != NO_ERROR)
goto out; goto out;
mutex_lock(&drbd_cfg_mutex); down_write(&drbd_cfg_rwsem);
if (conn_lowest_minor(adm_ctx.tconn) < 0) { if (conn_lowest_minor(adm_ctx.tconn) < 0) {
drbd_free_tconn(adm_ctx.tconn); drbd_free_tconn(adm_ctx.tconn);
retcode = NO_ERROR; retcode = NO_ERROR;
} else { } else {
retcode = ERR_CONN_IN_USE; retcode = ERR_CONN_IN_USE;
} }
mutex_unlock(&drbd_cfg_mutex); up_write(&drbd_cfg_rwsem);
out: out:
drbd_adm_finish(info, retcode); drbd_adm_finish(info, retcode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment