aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/block/drbd/drbd_nl.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@linbit.com>2011-07-05 12:23:07 -0400
committerPhilipp Reisner <philipp.reisner@linbit.com>2014-02-17 10:46:38 -0500
commit251b8f8eafcb8f3d6c11b061d23eddf7c0723da7 (patch)
tree85e0d9e9efdac67bd3a6c051203720bbcfc3a823 /drivers/block/drbd/drbd_nl.c
parentf82795d683333a4701ab48b0d422ebbc437f25a5 (diff)
drbd: get_one_status(): Iterate over resource->devices instead of connection->peer_devices
Signed-off-by: Andreas Gruenbacher <agruen@linbit.com> Signed-off-by: Philipp Reisner <philipp.reisner@linbit.com>
Diffstat (limited to 'drivers/block/drbd/drbd_nl.c')
-rw-r--r--drivers/block/drbd/drbd_nl.c72
1 files changed, 46 insertions, 26 deletions
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index 81e07e2664b3..6f11d8579263 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -2752,23 +2752,28 @@ int drbd_adm_outdate(struct sk_buff *skb, struct genl_info *info)
2752 return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED)); 2752 return drbd_adm_simple_request_state(skb, info, NS(disk, D_OUTDATED));
2753} 2753}
2754 2754
2755static int nla_put_drbd_cfg_context(struct sk_buff *skb, struct drbd_connection *connection, unsigned vnr) 2755static int nla_put_drbd_cfg_context(struct sk_buff *skb,
2756 struct drbd_resource *resource,
2757 struct drbd_connection *connection,
2758 struct drbd_device *device)
2756{ 2759{
2757 struct nlattr *nla; 2760 struct nlattr *nla;
2758 nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT); 2761 nla = nla_nest_start(skb, DRBD_NLA_CFG_CONTEXT);
2759 if (!nla) 2762 if (!nla)
2760 goto nla_put_failure; 2763 goto nla_put_failure;
2761 if (vnr != VOLUME_UNSPECIFIED && 2764 if (device &&
2762 nla_put_u32(skb, T_ctx_volume, vnr)) 2765 nla_put_u32(skb, T_ctx_volume, device->vnr))
2763 goto nla_put_failure; 2766 goto nla_put_failure;
2764 if (nla_put_string(skb, T_ctx_resource_name, connection->resource->name)) 2767 if (nla_put_string(skb, T_ctx_resource_name, connection->resource->name))
2765 goto nla_put_failure; 2768 goto nla_put_failure;
2766 if (connection->my_addr_len && 2769 if (connection) {
2767 nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr)) 2770 if (connection->my_addr_len &&
2768 goto nla_put_failure; 2771 nla_put(skb, T_ctx_my_addr, connection->my_addr_len, &connection->my_addr))
2769 if (connection->peer_addr_len && 2772 goto nla_put_failure;
2770 nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr)) 2773 if (connection->peer_addr_len &&
2771 goto nla_put_failure; 2774 nla_put(skb, T_ctx_peer_addr, connection->peer_addr_len, &connection->peer_addr))
2775 goto nla_put_failure;
2776 }
2772 nla_nest_end(skb, nla); 2777 nla_nest_end(skb, nla);
2773 return 0; 2778 return 0;
2774 2779
@@ -2778,9 +2783,22 @@ nla_put_failure:
2778 return -EMSGSIZE; 2783 return -EMSGSIZE;
2779} 2784}
2780 2785
2781static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device, 2786/*
2787 * Return the connection of @resource if @resource has exactly one connection.
2788 */
2789static struct drbd_connection *the_only_connection(struct drbd_resource *resource)
2790{
2791 struct list_head *connections = &resource->connections;
2792
2793 if (list_empty(connections) || connections->next->next != connections)
2794 return NULL;
2795 return list_first_entry(&resource->connections, struct drbd_connection, connections);
2796}
2797
2798int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
2782 const struct sib_info *sib) 2799 const struct sib_info *sib)
2783{ 2800{
2801 struct drbd_resource *resource = device->resource;
2784 struct state_info *si = NULL; /* for sizeof(si->member); */ 2802 struct state_info *si = NULL; /* for sizeof(si->member); */
2785 struct nlattr *nla; 2803 struct nlattr *nla;
2786 int got_ldev; 2804 int got_ldev;
@@ -2804,7 +2822,7 @@ static int nla_put_status_info(struct sk_buff *skb, struct drbd_device *device,
2804 2822
2805 /* We need to add connection name and volume number information still. 2823 /* We need to add connection name and volume number information still.
2806 * Minor number is in drbd_genlmsghdr. */ 2824 * Minor number is in drbd_genlmsghdr. */
2807 if (nla_put_drbd_cfg_context(skb, first_peer_device(device)->connection, device->vnr)) 2825 if (nla_put_drbd_cfg_context(skb, resource, the_only_connection(resource), device))
2808 goto nla_put_failure; 2826 goto nla_put_failure;
2809 2827
2810 if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive)) 2828 if (res_opts_to_skb(skb, &device->resource->res_opts, exclude_sensitive))
@@ -2922,19 +2940,17 @@ out:
2922 2940
2923static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb) 2941static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
2924{ 2942{
2925 struct drbd_peer_device *peer_device;
2926 struct drbd_device *device; 2943 struct drbd_device *device;
2927 struct drbd_genlmsghdr *dh; 2944 struct drbd_genlmsghdr *dh;
2928 struct drbd_resource *pos = (struct drbd_resource *)cb->args[0]; 2945 struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
2929 struct drbd_resource *resource = NULL; 2946 struct drbd_resource *resource = NULL;
2930 struct drbd_connection *connection;
2931 struct drbd_resource *tmp; 2947 struct drbd_resource *tmp;
2932 unsigned volume = cb->args[1]; 2948 unsigned volume = cb->args[1];
2933 2949
2934 /* Open coded, deferred, iteration: 2950 /* Open coded, deferred, iteration:
2935 * for_each_resource_safe(resource, tmp, &drbd_resources) { 2951 * for_each_resource_safe(resource, tmp, &drbd_resources) {
2936 * connection = "first connection of resource"; 2952 * connection = "first connection of resource or undefined";
2937 * idr_for_each_entry(&connection->peer_devices, peer_device, i) { 2953 * idr_for_each_entry(&resource->devices, device, i) {
2938 * ... 2954 * ...
2939 * } 2955 * }
2940 * } 2956 * }
@@ -2969,9 +2985,8 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
2969 } 2985 }
2970 if (resource) { 2986 if (resource) {
2971next_resource: 2987next_resource:
2972 connection = first_connection(resource); 2988 device = idr_get_next(&resource->devices, &volume);
2973 peer_device = idr_get_next(&connection->peer_devices, &volume); 2989 if (!device) {
2974 if (!peer_device) {
2975 /* No more volumes to dump on this resource. 2990 /* No more volumes to dump on this resource.
2976 * Advance resource iterator. */ 2991 * Advance resource iterator. */
2977 pos = list_entry_rcu(resource->resources.next, 2992 pos = list_entry_rcu(resource->resources.next,
@@ -2995,24 +3010,29 @@ next_resource:
2995 if (!dh) 3010 if (!dh)
2996 goto out; 3011 goto out;
2997 3012
2998 if (!peer_device) { 3013 if (!device) {
2999 /* This is a connection without a single volume. 3014 /* This is a connection without a single volume.
3000 * Suprisingly enough, it may have a network 3015 * Suprisingly enough, it may have a network
3001 * configuration. */ 3016 * configuration. */
3002 struct net_conf *nc; 3017 struct drbd_connection *connection;
3018
3003 dh->minor = -1U; 3019 dh->minor = -1U;
3004 dh->ret_code = NO_ERROR; 3020 dh->ret_code = NO_ERROR;
3005 if (nla_put_drbd_cfg_context(skb, connection, VOLUME_UNSPECIFIED)) 3021 connection = the_only_connection(resource);
3006 goto cancel; 3022 if (nla_put_drbd_cfg_context(skb, resource, connection, NULL))
3007 nc = rcu_dereference(connection->net_conf);
3008 if (nc && net_conf_to_skb(skb, nc, 1) != 0)
3009 goto cancel; 3023 goto cancel;
3024 if (connection) {
3025 struct net_conf *nc;
3026
3027 nc = rcu_dereference(connection->net_conf);
3028 if (nc && net_conf_to_skb(skb, nc, 1) != 0)
3029 goto cancel;
3030 }
3010 goto done; 3031 goto done;
3011 } 3032 }
3012 3033
3013 device = peer_device->device;
3014 D_ASSERT(device, device->vnr == volume); 3034 D_ASSERT(device, device->vnr == volume);
3015 D_ASSERT(device, first_peer_device(device)->connection == connection); 3035 D_ASSERT(device, device->resource == resource);
3016 3036
3017 dh->minor = device_to_minor(device); 3037 dh->minor = device_to_minor(device);
3018 dh->ret_code = NO_ERROR; 3038 dh->ret_code = NO_ERROR;