drbd: get_one_status(): Iterate over resource->devices instead of connection->peer_de...
[deliverable/linux.git] / drivers / block / drbd / drbd_nl.c
index af26a0b099ca42dfd38d8e89ca8bb494126c23a4..6f11d85792631223264d03e5252afe7b6e00af2d 100644 (file)
@@ -590,7 +590,7 @@ drbd_set_role(struct drbd_device *device, enum drbd_role new_role, int force)
 
                if (rv == SS_NO_UP_TO_DATE_DISK &&
                    device->state.disk == D_CONSISTENT && mask.pdsk == 0) {
-                       D_ASSERT(device->state.pdsk == D_UNKNOWN);
+                       D_ASSERT(device, device->state.pdsk == D_UNKNOWN);
 
                        if (conn_try_outdate_peer(first_peer_device(device)->connection)) {
                                val.disk = D_UP_TO_DATE;
@@ -1644,7 +1644,7 @@ int drbd_adm_attach(struct sk_buff *skb, struct genl_info *info)
         * Devices and memory are no longer released by error cleanup below.
         * now device takes over responsibility, and the state engine should
         * clean it up somewhere.  */
-       D_ASSERT(device->ldev == NULL);
+       D_ASSERT(device, device->ldev == NULL);
        device->ldev = nbc;
        device->resync = resync_lru;
        device->rs_plan_s = new_plan;
@@ -2752,23 +2752,28 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info)
        return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED));
 }
 
-static int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_connection *connection, unsigned vnr)
+static int nla_put_drbd_cfg_context(struct sk_buff *skb,
+                                   struct drbd_resource *resource,
+                                   struct drbd_connection *connection,
+                                   struct drbd_device *device)
 {
        struct nlattr *nla;
        nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT);
        if (!nla)
                goto nla_put_failure;
-       if (vnr != VOLUME_UNSPECIFIED &&
-           nla_put_u32(skb, T_ctx_volume, vnr))
+       if (device &&
+           nla_put_u32(skb, T_ctx_volume, device->vnr))
                goto nla_put_failure;
        if (nla_put_string(skb, T_ctx_resource_name, connection->resource->name))
                goto nla_put_failure;
-       if (connection->my_addr_len &&
-           nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
-               goto nla_put_failure;
-       if (connection->peer_addr_len &&
-           nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
-               goto nla_put_failure;
+       if (connection) {
+               if (connection->my_addr_len &&
+                   nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
+                       goto nla_put_failure;
+               if (connection->peer_addr_len &&
+                   nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
+                       goto nla_put_failure;
+       }
        nla_nest_end(skb, nla);
        return 0;
 
@@ -2778,9 +2783,22 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
+/*
+ * Return the connection of @resource if @resource has exactly one connection.
+ */
+static struct drbd_connection *the_only_connection(struct drbd_resource *resource)
+{
+       struct list_head *connections = &resource->connections;
+
+       if (list_empty(connections) || connections->next->next != connections)
+               return NULL;
+       return list_first_entry(&resource->connections, struct drbd_connection, connections);
+}
+
+int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
                const struct sib_info *sib)
 {
+       struct drbd_resource *resource = device->resource;
        struct state_info *si = NULL; /* for sizeof(si->member); */
        struct nlattr *nla;
        int got_ldev;
@@ -2804,7 +2822,7 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
 
        /* We need to add connection name and volume number information still.
         * Minor number is in drbd_genlmsghdr. */
-       if (nla_put_drbd_cfg_context(skb, first_peer_device(device)->connection, device->vnr))
+       if (nla_put_drbd_cfg_context(skb, resource, the_only_connection(resource), device))
                goto nla_put_failure;
 
        if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive))
@@ -2922,19 +2940,17 @@ out:
 
 static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       struct drbd_peer_device *peer_device;
        struct drbd_device *device;
        struct drbd_genlmsghdr *dh;
        struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
        struct drbd_resource *resource = NULL;
-       struct drbd_connection *connection;
        struct drbd_resource *tmp;
        unsigned volume = cb->args[1];
 
        /* Open coded, deferred, iteration:
         * for_each_resource_safe(resource, tmp, &drbd_resources) {
-        *      connection = "first connection of resource";
-        *      idr_for_each_entry(&connection->peer_devices, peer_device, i) {
+        *      connection = "first connection of resource or undefined";
+        *      idr_for_each_entry(&resource->devices, device, i) {
         *        ...
         *      }
         * }
@@ -2969,9 +2985,8 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
        }
        if (resource) {
 next_resource:
-               connection = first_connection(resource);
-               peer_device = idr_get_next(&connection->peer_devices, &volume);
-               if (!peer_device) {
+               device = idr_get_next(&resource->devices, &volume);
+               if (!device) {
                        /* No more volumes to dump on this resource.
                         * Advance resource iterator. */
                        pos = list_entry_rcu(resource->resources.next,
@@ -2995,24 +3010,29 @@ next_resource:
                if (!dh)
                        goto out;
 
-               if (!peer_device) {
+               if (!device) {
                        /* This is a connection without a single volume.
                         * Suprisingly enough, it may have a network
                         * configuration. */
-                       struct net_conf *nc;
+                       struct drbd_connection *connection;
+
                        dh->minor = -1U;
                        dh->ret_code = NO_ERROR;
-                       if (nla_put_drbd_cfg_context(skb, connection, VOLUME_UNSPECIFIED))
-                               goto cancel;
-                       nc = rcu_dereference(connection->net_conf);
-                       if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+                       connection = the_only_connection(resource);
+                       if (nla_put_drbd_cfg_context(skb, resource, connection, NULL))
                                goto cancel;
+                       if (connection) {
+                               struct net_conf *nc;
+
+                               nc = rcu_dereference(connection->net_conf);
+                               if (nc && net_conf_to_skb(skb, nc, 1) != 0)
+                                       goto cancel;
+                       }
                        goto done;
                }
 
-               device = peer_device->device;
-               D_ASSERT(device->vnr == volume);
-               D_ASSERT(first_peer_device(device)->connection == connection);
+               D_ASSERT(device, device->vnr == volume);
+               D_ASSERT(device, device->resource == resource);
 
                dh->minor = device_to_minor(device);
                dh->ret_code = NO_ERROR;
@@ -3328,7 +3348,7 @@ int drbd_adm_new_minor(struct sk_buff *skb, struct genl_info *info)
                goto out;
        }
 
-       retcode = drbd_create_minor(adm_ctx.connection, dh->minor, adm_ctx.volume);
+       retcode = drbd_create_device(adm_ctx.connection, dh->minor, adm_ctx.volume);
 out:
        drbd_adm_finish(info, retcode);
        return 0;
@@ -3343,7 +3363,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);
-               drbd_delete_minor(device);
+               drbd_delete_device(device);
                return NO_ERROR;
        } else
                return ERR_MINOR_CONFIGURED;
This page took 0.027135 seconds and 5 git commands to generate.