|
@@ -2052,7 +2052,7 @@ check_net_options(struct drbd_connection *connection, struct net_conf *new_net_c
|
|
|
rv = _check_net_options(connection, rcu_dereference(connection->net_conf), new_net_conf);
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
- /* connection->volumes protected by genl_lock() here */
|
|
|
+ /* connection->peer_devices protected by genl_lock() here */
|
|
|
idr_for_each_entry(&connection->peer_devices, peer_device, i) {
|
|
|
struct drbd_device *device = peer_device->device;
|
|
|
if (!device->bitmap) {
|
|
@@ -3483,7 +3483,7 @@ int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
|
|
|
* that first_peer_device(device)->connection and device->vnr match the request. */
|
|
|
if (adm_ctx.device) {
|
|
|
if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
|
|
|
- retcode = ERR_MINOR_EXISTS;
|
|
|
+ retcode = ERR_MINOR_OR_VOLUME_EXISTS;
|
|
|
/* else: still NO_ERROR */
|
|
|
goto out;
|
|
|
}
|
|
@@ -3530,6 +3530,27 @@ out:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int adm_del_resource(struct drbd_resource *resource)
|
|
|
+{
|
|
|
+ struct drbd_connection *connection;
|
|
|
+
|
|
|
+ for_each_connection(connection, resource) {
|
|
|
+ if (connection->cstate > C_STANDALONE)
|
|
|
+ return ERR_NET_CONFIGURED;
|
|
|
+ }
|
|
|
+ if (!idr_is_empty(&resource->devices))
|
|
|
+ return ERR_RES_IN_USE;
|
|
|
+
|
|
|
+ list_del_rcu(&resource->resources);
|
|
|
+ /* Make sure all threads have actually stopped: state handling only
|
|
|
+ * does drbd_thread_stop_nowait(). */
|
|
|
+ list_for_each_entry(connection, &resource->connections, connections)
|
|
|
+ drbd_thread_stop(&connection->worker);
|
|
|
+ synchronize_rcu();
|
|
|
+ drbd_free_resource(resource);
|
|
|
+ return NO_ERROR;
|
|
|
+}
|
|
|
+
|
|
|
int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
|
|
|
{
|
|
|
struct drbd_config_context adm_ctx;
|
|
@@ -3575,14 +3596,6 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* If we reach this, all volumes (of this connection) are Secondary,
|
|
|
- * Disconnected, Diskless, aka Unconfigured. Make sure all threads have
|
|
|
- * actually stopped, state handling only does drbd_thread_stop_nowait(). */
|
|
|
- for_each_connection(connection, resource)
|
|
|
- drbd_thread_stop(&connection->worker);
|
|
|
-
|
|
|
- /* Now, nothing can fail anymore */
|
|
|
-
|
|
|
/* delete volumes */
|
|
|
idr_for_each_entry(&resource->devices, device, i) {
|
|
|
retcode = adm_del_minor(device);
|
|
@@ -3593,10 +3606,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- list_del_rcu(&resource->resources);
|
|
|
- synchronize_rcu();
|
|
|
- drbd_free_resource(resource);
|
|
|
- retcode = NO_ERROR;
|
|
|
+ retcode = adm_del_resource(resource);
|
|
|
out:
|
|
|
mutex_unlock(&resource->adm_mutex);
|
|
|
finish:
|
|
@@ -3608,7 +3618,6 @@ int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
|
|
|
{
|
|
|
struct drbd_config_context adm_ctx;
|
|
|
struct drbd_resource *resource;
|
|
|
- struct drbd_connection *connection;
|
|
|
enum drbd_ret_code retcode;
|
|
|
|
|
|
retcode = drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE);
|
|
@@ -3616,27 +3625,10 @@ int drbd_adm_del_resource(struct sk_buff *skb, struct genl_info *info)
|
|
|
return retcode;
|
|
|
if (retcode != NO_ERROR)
|
|
|
goto finish;
|
|
|
-
|
|
|
resource = adm_ctx.resource;
|
|
|
- mutex_lock(&resource->adm_mutex);
|
|
|
- for_each_connection(connection, resource) {
|
|
|
- if (connection->cstate > C_STANDALONE) {
|
|
|
- retcode = ERR_NET_CONFIGURED;
|
|
|
- goto out;
|
|
|
- }
|
|
|
- }
|
|
|
- if (!idr_is_empty(&resource->devices)) {
|
|
|
- retcode = ERR_RES_IN_USE;
|
|
|
- goto out;
|
|
|
- }
|
|
|
|
|
|
- list_del_rcu(&resource->resources);
|
|
|
- for_each_connection(connection, resource)
|
|
|
- drbd_thread_stop(&connection->worker);
|
|
|
- synchronize_rcu();
|
|
|
- drbd_free_resource(resource);
|
|
|
- retcode = NO_ERROR;
|
|
|
-out:
|
|
|
+ mutex_lock(&resource->adm_mutex);
|
|
|
+ retcode = adm_del_resource(resource);
|
|
|
mutex_unlock(&resource->adm_mutex);
|
|
|
finish:
|
|
|
drbd_adm_finish(&adm_ctx, info, retcode);
|