drbd: conn_try_disconnect(): Use parameter instead of the global variable
[deliverable/linux.git] / drivers / block / drbd / drbd_nl.c
index ddff39182a23784ded047107f3a13fc22a71aa8f..cb241d1d46681d4f4be8572bbf9e0710cc581d5a 100644 (file)
@@ -104,6 +104,7 @@ static struct drbd_config_context {
        struct drbd_genlmsghdr *reply_dh;
        /* resolved from attributes, if possible */
        struct drbd_device *device;
+       struct drbd_resource *resource;
        struct drbd_connection *connection;
 } adm_ctx;
 
@@ -213,13 +214,19 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
 
        adm_ctx.minor = d_in->minor;
        adm_ctx.device = minor_to_device(d_in->minor);
-       adm_ctx.connection = conn_get_by_name(adm_ctx.resource_name);
+       if (adm_ctx.resource_name) {
+               adm_ctx.resource = drbd_find_resource(adm_ctx.resource_name);
+               if (adm_ctx.resource) {
+                       adm_ctx.connection = first_connection(adm_ctx.resource);
+                       kref_get(&adm_ctx.connection->kref);
+               }
+       }
 
        if (!adm_ctx.device && (flags & DRBD_ADM_NEED_MINOR)) {
                drbd_msg_put_info("unknown minor");
                return ERR_MINOR_INVALID;
        }
-       if (!adm_ctx.connection && (flags & DRBD_ADM_NEED_RESOURCE)) {
+       if (!adm_ctx.resource && (flags & DRBD_ADM_NEED_RESOURCE)) {
                drbd_msg_put_info("unknown resource");
                if (adm_ctx.resource_name)
                        return ERR_RES_NOT_KNOWN;
@@ -247,11 +254,11 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
        }
 
        /* some more paranoia, if the request was over-determined */
-       if (adm_ctx.device && adm_ctx.connection &&
-           first_peer_device(adm_ctx.device)->connection != adm_ctx.connection) {
-               pr_warning("request: minor=%u, resource=%s; but that minor belongs to connection %s\n",
-                               adm_ctx.minor, adm_ctx.resource_name,
-                               first_peer_device(adm_ctx.device)->connection->resource->name);
+       if (adm_ctx.device && adm_ctx.resource &&
+           adm_ctx.device->resource != adm_ctx.resource) {
+               pr_warning("request: minor=%u, resource=%s; but that minor belongs to resource %s\n",
+                               adm_ctx.minor, adm_ctx.resource->name,
+                               adm_ctx.device->resource->name);
                drbd_msg_put_info("minor exists in different resource");
                return ERR_INVALID_REQUEST;
        }
@@ -261,7 +268,7 @@ static int drbd_adm_prepare(struct sk_buff *skb, struct genl_info *info,
                pr_warning("request: minor=%u, volume=%u; but that minor is volume %u in %s\n",
                                adm_ctx.minor, adm_ctx.volume,
                                adm_ctx.device->vnr,
-                               first_peer_device(adm_ctx.device)->connection->resource->name);
+                               adm_ctx.device->resource->name);
                drbd_msg_put_info("minor exists as different volume");
                return ERR_INVALID_REQUEST;
        }
@@ -280,6 +287,10 @@ static int drbd_adm_finish(struct genl_info *info, int retcode)
                kref_put(&adm_ctx.connection->kref, drbd_destroy_connection);
                adm_ctx.connection = NULL;
        }
+       if (adm_ctx.resource) {
+               kref_put(&adm_ctx.resource->kref, drbd_destroy_resource);
+               adm_ctx.resource = NULL;
+       }
 
        if (!adm_ctx.reply_skb)
                return -ENOMEM;
@@ -2306,7 +2317,7 @@ static enum drbd_state_rv conn_try_disconnect(struct drbd_connection *connection
                 * The state handling only uses drbd_thread_stop_nowait(),
                 * we want to really wait here until the receiver is no more.
                 */
-               drbd_thread_stop(&adm_ctx.connection->receiver);
+               drbd_thread_stop(&connection->receiver);
 
                /* Race breaker.  This additional state change request may be
                 * necessary, if this was a forced disconnect during a receiver
@@ -3034,7 +3045,7 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
        const unsigned hdrlen = GENL_HDRLEN + GENL_MAGIC_FAMILY_HDRSZ;
        struct nlattr *nla;
        const char *resource_name;
-       struct drbd_connection *connection;
+       struct drbd_resource *resource;
        int maxtype;
 
        /* Is this a followup call? */
@@ -3063,18 +3074,19 @@ int drbd_adm_get_status_all(struct sk_buff *skb, struct netlink_callback *cb)
        if (!nla)
                return -EINVAL;
        resource_name = nla_data(nla);
-       connection = conn_get_by_name(resource_name);
-
-       if (!connection)
+       if (!*resource_name)
+               return -ENODEV;
+       resource = drbd_find_resource(resource_name);
+       if (!resource)
                return -ENODEV;
 
-       kref_put(&connection->kref, drbd_destroy_connection); /* get_one_status() (re)validates connection by itself */
+       kref_put(&resource->kref, drbd_destroy_resource); /* get_one_status() revalidates the resource */
 
        /* prime iterators, and set "filter" mode mark:
         * only dump this connection. */
-       cb->args[0] = (long)connection;
+       cb->args[0] = (long)resource;
        /* cb->args[1] = 0; passed in this way. */
-       cb->args[2] = (long)connection;
+       cb->args[2] = (long)resource;
 
 dump:
        return get_one_status(skb, cb);
@@ -3324,12 +3336,7 @@ static enum drbd_ret_code adm_del_minor(struct drbd_device *device)
            device->state.role == R_SECONDARY) {
                _drbd_request_state(device, NS(conn, C_WF_REPORT_PARAMS),
                                    CS_VERBOSE + CS_WAIT_COMPLETE);
-               idr_remove(&first_peer_device(device)->connection->volumes, device->vnr);
-               idr_remove(&drbd_devices, device_to_minor(device));
-               destroy_workqueue(device->submit.wq);
-               del_gendisk(device->vdisk);
-               synchronize_rcu();
-               kref_put(&device->kref, drbd_destroy_device);
+               drbd_delete_minor(device);
                return NO_ERROR;
        } else
                return ERR_MINOR_CONFIGURED;
This page took 0.026975 seconds and 5 git commands to generate.