]> www.infradead.org Git - users/willy/xarray.git/commitdiff
drbd: Convert drbd devices to XArray
authorMatthew Wilcox <willy@infradead.org>
Fri, 15 Feb 2019 21:48:39 +0000 (16:48 -0500)
committerMatthew Wilcox (Oracle) <willy@infradead.org>
Thu, 8 Aug 2019 02:35:38 +0000 (22:35 -0400)
Signed-off-by: Matthew Wilcox <willy@infradead.org>
drivers/block/drbd/drbd_debugfs.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_proc.c
drivers/block/drbd/drbd_receiver.c
drivers/block/drbd/drbd_state.c
drivers/block/drbd/drbd_worker.c

index b3b9cd5628fdf73c0788d06a8970c34380be0e28..9dd1c2ae2367c35c495b94ac046d66f539401dbb 100644 (file)
@@ -128,11 +128,11 @@ static void seq_print_minor_vnr_req(struct seq_file *m, struct drbd_request *req
 static void seq_print_resource_pending_meta_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
 {
        struct drbd_device *device;
-       unsigned int i;
+       unsigned long i;
 
        seq_puts(m, "minor\tvnr\tstart\tsubmit\tintent\n");
        rcu_read_lock();
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, i, device) {
                struct drbd_md_io tmp;
                /* In theory this is racy,
                 * in the sense that there could have been a
@@ -156,11 +156,11 @@ static void seq_print_resource_pending_meta_io(struct seq_file *m, struct drbd_r
 static void seq_print_waiting_for_AL(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
 {
        struct drbd_device *device;
-       unsigned int i;
+       unsigned long i;
 
        seq_puts(m, "minor\tvnr\tage\t#waiting\n");
        rcu_read_lock();
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, i, device) {
                unsigned long jif;
                struct drbd_request *req;
                int n = atomic_read(&device->ap_actlog_cnt);
@@ -216,11 +216,11 @@ static void seq_print_device_bitmap_io(struct seq_file *m, struct drbd_device *d
 static void seq_print_resource_pending_bitmap_io(struct seq_file *m, struct drbd_resource *resource, unsigned long now)
 {
        struct drbd_device *device;
-       unsigned int i;
+       unsigned long i;
 
        seq_puts(m, "minor\tvnr\trw\tage\t#in-flight\n");
        rcu_read_lock();
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, i, device) {
                seq_print_device_bitmap_io(m, device, now);
        }
        rcu_read_unlock();
@@ -288,10 +288,10 @@ static void seq_print_resource_pending_peer_requests(struct seq_file *m,
        struct drbd_resource *resource, unsigned long now)
 {
        struct drbd_device *device;
-       unsigned int i;
+       unsigned long i;
 
        rcu_read_lock();
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, i, device) {
                seq_print_device_peer_requests(m, device, now);
        }
        rcu_read_unlock();
index ddbf56014c51a906349fbc85fbd75a7d627e757d..0546a55a872f6c62fc30d0d6de903e8bca8d40f3 100644 (file)
@@ -177,7 +177,7 @@ drbd_insert_fault(struct drbd_device *device, unsigned int type) {
 #define div_floor(A, B) ((A)/(B))
 
 extern struct ratelimit_state drbd_ratelimit_state;
-extern struct idr drbd_devices; /* RCU, updates: genl_lock() */
+extern struct xarray drbd_devices; /* RCU, updates: genl_lock() */
 extern struct list_head drbd_resources; /* RCU, updates: genl_lock() */
 
 extern const char *cmdname(enum drbd_packet cmd);
@@ -658,7 +658,7 @@ struct drbd_resource {
        struct dentry *debugfs_res_in_flight_summary;
 #endif
        struct kref kref;
-       struct idr devices;             /* volume number to device mapping */
+       struct xarray devices;          /* volume number to device mapping */
        struct list_head connections;
        struct list_head resources;
        struct res_opts res_opts;
@@ -1010,7 +1010,7 @@ struct drbd_config_context {
 
 static inline struct drbd_device *minor_to_device(unsigned int minor)
 {
-       return (struct drbd_device *)idr_find(&drbd_devices, minor);
+       return xa_load(&drbd_devices, minor);
 }
 
 static inline struct drbd_peer_device *first_peer_device(struct drbd_device *device)
index 9bd4ddd12b25c542ae9fad6fae963f66414b496c..45480a72aa3ebf296c64006559238fd6aa919292 100644 (file)
@@ -104,7 +104,7 @@ module_param_string(usermode_helper, drbd_usermode_helper, sizeof(drbd_usermode_
 /* in 2.6.x, our device mapping and config info contains our virtual gendisks
  * as member "struct gendisk *vdisk;"
  */
-struct idr drbd_devices;
+DEFINE_XARRAY(drbd_devices);
 struct list_head drbd_resources;
 struct mutex resources_mutex;
 
@@ -2352,7 +2352,7 @@ void drbd_destroy_resource(struct kref *kref)
        struct drbd_resource *resource =
                container_of(kref, struct drbd_resource, kref);
 
-       idr_destroy(&resource->devices);
+       xa_destroy(&resource->devices);
        free_cpumask_var(resource->cpu_mask);
        kfree(resource->name);
        memset(resource, 0xf2, sizeof(*resource));
@@ -2374,7 +2374,7 @@ void drbd_free_resource(struct drbd_resource *resource)
 
 static void drbd_cleanup(void)
 {
-       unsigned int i;
+       unsigned long i;
        struct drbd_device *device;
        struct drbd_resource *resource, *tmp;
 
@@ -2394,8 +2394,9 @@ static void drbd_cleanup(void)
 
        drbd_genl_unregister();
 
-       idr_for_each_entry(&drbd_devices, device, i)
+       xa_for_each(&drbd_devices, i, device)
                drbd_delete_device(device);
+       xa_destroy(&drbd_devices);
 
        /* not _rcu since, no other updater anymore. Genl already unregistered */
        for_each_resource_safe(resource, tmp, &drbd_resources) {
@@ -2408,8 +2409,6 @@ static void drbd_cleanup(void)
        drbd_destroy_mempools();
        unregister_blkdev(DRBD_MAJOR, "drbd");
 
-       idr_destroy(&drbd_devices);
-
        pr_info("module cleanup done.\n");
 }
 
@@ -2647,7 +2646,7 @@ struct drbd_resource *drbd_create_resource(const char *name)
        if (!zalloc_cpumask_var(&resource->cpu_mask, GFP_KERNEL))
                goto fail_free_name;
        kref_init(&resource->kref);
-       idr_init(&resource->devices);
+       xa_init(&resource->devices);
        INIT_LIST_HEAD(&resource->connections);
        resource->write_ordering = WO_BDEV_FLUSH;
        list_add_tail_rcu(&resource->resources, &drbd_resources);
@@ -2779,7 +2778,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
        struct drbd_peer_device *peer_device, *tmp_peer_device;
        struct gendisk *disk;
        struct request_queue *q;
-       int id;
+       int ret;
        int vnr = adm_ctx->volume;
        enum drbd_ret_code err = ERR_NOMEM;
 
@@ -2842,19 +2841,19 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
        device->read_requests = RB_ROOT;
        device->write_requests = RB_ROOT;
 
-       id = idr_alloc(&drbd_devices, device, minor, minor + 1, GFP_KERNEL);
-       if (id < 0) {
-               if (id == -ENOSPC)
+       ret = xa_insert(&drbd_devices, minor, device, GFP_KERNEL);
+       if (ret < 0) {
+               if (ret == -EBUSY)
                        err = ERR_MINOR_OR_VOLUME_EXISTS;
-               goto out_no_minor_idr;
+               goto out_no_minor;
        }
        kref_get(&device->kref);
 
-       id = idr_alloc(&resource->devices, device, vnr, vnr + 1, GFP_KERNEL);
-       if (id < 0) {
-               if (id == -ENOSPC)
+       ret = xa_insert(&resource->devices, vnr, device, GFP_KERNEL);
+       if (ret < 0) {
+               if (ret == -EBUSY)
                        err = ERR_MINOR_OR_VOLUME_EXISTS;
-               goto out_idr_remove_minor;
+               goto out_remove_minor;
        }
        kref_get(&device->kref);
 
@@ -2863,18 +2862,18 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
        for_each_connection(connection, resource) {
                peer_device = kzalloc(sizeof(struct drbd_peer_device), GFP_KERNEL);
                if (!peer_device)
-                       goto out_idr_remove_from_resource;
+                       goto out_remove_from_resource;
                peer_device->connection = connection;
                peer_device->device = device;
 
                list_add(&peer_device->peer_devices, &device->peer_devices);
                kref_get(&device->kref);
 
-               id = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
-               if (id < 0) {
-                       if (id == -ENOSPC)
+               ret = idr_alloc(&connection->peer_devices, peer_device, vnr, vnr + 1, GFP_KERNEL);
+               if (ret < 0) {
+                       if (ret == -ENOSPC)
                                err = ERR_INVALID_REQUEST;
-                       goto out_idr_remove_from_resource;
+                       goto out_remove_from_resource;
                }
                kref_get(&connection->kref);
                INIT_WORK(&peer_device->send_acks_work, drbd_send_acks_wf);
@@ -2901,7 +2900,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
 
 out_idr_remove_vol:
        idr_remove(&connection->peer_devices, vnr);
-out_idr_remove_from_resource:
+out_remove_from_resource:
        for_each_connection(connection, resource) {
                peer_device = idr_remove(&connection->peer_devices, vnr);
                if (peer_device)
@@ -2911,11 +2910,11 @@ out_idr_remove_from_resource:
                list_del(&peer_device->peer_devices);
                kfree(peer_device);
        }
-       idr_remove(&resource->devices, vnr);
-out_idr_remove_minor:
-       idr_remove(&drbd_devices, minor);
+       xa_erase(&resource->devices, vnr);
+out_remove_minor:
+       xa_erase(&drbd_devices, minor);
        synchronize_rcu();
-out_no_minor_idr:
+out_no_minor:
        drbd_bm_cleanup(device);
 out_no_bitmap:
        __free_page(device->md_io.page);
@@ -2943,9 +2942,9 @@ void drbd_delete_device(struct drbd_device *device)
                idr_remove(&connection->peer_devices, device->vnr);
                kref_put(&device->kref, drbd_destroy_device);
        }
-       idr_remove(&resource->devices, device->vnr);
+       xa_erase(&resource->devices, device->vnr);
        kref_put(&device->kref, drbd_destroy_device);
-       idr_remove(&drbd_devices, device_to_minor(device));
+       xa_erase(&drbd_devices, device_to_minor(device));
        kref_put(&device->kref, drbd_destroy_device);
        del_gendisk(device->vdisk);
        synchronize_rcu();
@@ -2978,7 +2977,6 @@ static int __init drbd_init(void)
        init_waitqueue_head(&drbd_pp_wait);
 
        drbd_proc = NULL; /* play safe for drbd_cleanup */
-       idr_init(&drbd_devices);
 
        mutex_init(&resources_mutex);
        INIT_LIST_HEAD(&drbd_resources);
index 5d52a2d321559ed60b04d4fd57f2523233bffa0c..1b8497729f380fc7c2e8bdb452447f549d1e40e1 100644 (file)
@@ -3424,11 +3424,12 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb)
        struct nlattr *resource_filter;
        struct drbd_resource *resource;
        struct drbd_device *uninitialized_var(device);
-       int minor, err, retcode;
+       int err, retcode;
+       unsigned long minor;
        struct drbd_genlmsghdr *dh;
        struct device_info device_info;
        struct device_statistics device_statistics;
-       struct idr *idr_to_search;
+       struct xarray *devices;
 
        resource = (struct drbd_resource *)cb->args[0];
        if (!cb->args[0] && !cb->args[1]) {
@@ -3444,18 +3445,13 @@ int drbd_adm_dump_devices(struct sk_buff *skb, struct netlink_callback *cb)
 
        rcu_read_lock();
        minor = cb->args[1];
-       idr_to_search = resource ? &resource->devices : &drbd_devices;
-       device = idr_get_next(idr_to_search, &minor);
+       devices = resource ? &resource->devices : &drbd_devices;
+       device = xa_find_after(devices, &minor, ULONG_MAX, XA_PRESENT);
        if (!device) {
                err = 0;
                goto out;
        }
-       idr_for_each_entry_continue(idr_to_search, device, minor) {
-               retcode = NO_ERROR;
-               goto put_result;  /* only one iteration */
-       }
-       err = 0;
-       goto out;  /* no more devices */
+       retcode = NO_ERROR;
 
 put_result:
        dh = genlmsg_put(skb, NETLINK_CB(cb->skb).portid,
@@ -3676,9 +3672,10 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb)
        struct drbd_resource *resource;
        struct drbd_device *uninitialized_var(device);
        struct drbd_peer_device *peer_device = NULL;
-       int minor, err, retcode;
+       int err, retcode;
+       unsigned long minor;
        struct drbd_genlmsghdr *dh;
-       struct idr *idr_to_search;
+       struct xarray *devices;
 
        resource = (struct drbd_resource *)cb->args[0];
        if (!cb->args[0] && !cb->args[1]) {
@@ -3694,13 +3691,12 @@ int drbd_adm_dump_peer_devices(struct sk_buff *skb, struct netlink_callback *cb)
 
        rcu_read_lock();
        minor = cb->args[1];
-       idr_to_search = resource ? &resource->devices : &drbd_devices;
-       device = idr_find(idr_to_search, minor);
+       devices = resource ? &resource->devices : &drbd_devices;
+       device = xa_load(devices, minor);
        if (!device) {
 next_device:
-               minor++;
                cb->args[2] = 0;
-               device = idr_get_next(idr_to_search, &minor);
+               device = xa_find_after(devices, &minor, ULONG_MAX, XA_PRESENT);
                if (!device) {
                        err = 0;
                        goto out;
@@ -3929,12 +3925,12 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
        struct drbd_resource *pos = (struct drbd_resource *)cb->args[0];
        struct drbd_resource *resource = NULL;
        struct drbd_resource *tmp;
-       unsigned volume = cb->args[1];
+       unsigned long volume = cb->args[1];
 
        /* Open coded, deferred, iteration:
         * for_each_resource_safe(resource, tmp, &drbd_resources) {
         *      connection = "first connection of resource or undefined";
-        *      idr_for_each_entry(&resource->devices, device, i) {
+        *      xa_for_each(&resource->devices, i, device) {
         *        ...
         *      }
         * }
@@ -3969,7 +3965,8 @@ static int get_one_status(struct sk_buff *skb, struct netlink_callback *cb)
        }
        if (resource) {
 next_resource:
-               device = idr_get_next(&resource->devices, &volume);
+               device = xa_find(&resource->devices, &volume,
+                               ULONG_MAX, XA_PRESENT);
                if (!device) {
                        /* No more volumes to dump on this resource.
                         * Advance resource iterator. */
@@ -4477,7 +4474,7 @@ static int adm_del_resource(struct drbd_resource *resource)
                if (connection->cstate > C_STANDALONE)
                        return ERR_NET_CONFIGURED;
        }
-       if (!idr_is_empty(&resource->devices))
+       if (!xa_empty(&resource->devices))
                return ERR_RES_IN_USE;
 
        /* The state engine has stopped the sender thread, so we don't
@@ -4507,6 +4504,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
        struct drbd_device *device;
        int retcode; /* enum drbd_ret_code rsp. enum drbd_state_rv */
        unsigned i;
+       unsigned long index;
 
        retcode = drbd_adm_prepare(&adm_ctx, skb, info, DRBD_ADM_NEED_RESOURCE);
        if (!adm_ctx.reply_skb)
@@ -4536,7 +4534,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
        }
 
        /* detach */
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, index, device) {
                retcode = adm_detach(device, 0);
                if (retcode < SS_SUCCESS || retcode > NO_ERROR) {
                        drbd_msg_put_info(adm_ctx.reply_skb, "failed to detach");
@@ -4545,7 +4543,7 @@ int drbd_adm_down(struct sk_buff *skb, struct genl_info *info)
        }
 
        /* delete volumes */
-       idr_for_each_entry(&resource->devices, device, i) {
+       xa_for_each(&resource->devices, index, device) {
                retcode = adm_del_minor(device);
                if (retcode != NO_ERROR) {
                        /* "can not happen" */
index 1c41cd9982a257acf7f41450c67a8a4fe303c5d2..4a1589b936d537f20c2855211f2d959382b69ea8 100644 (file)
@@ -214,7 +214,7 @@ static void drbd_syncer_progress(struct drbd_device *device, struct seq_file *se
 
 int drbd_seq_show(struct seq_file *seq, void *v)
 {
-       int i, prev_i = -1;
+       unsigned long i, prev_i = -1;
        const char *sn;
        struct drbd_device *device;
        struct net_conf *nc;
@@ -251,7 +251,7 @@ int drbd_seq_show(struct seq_file *seq, void *v)
        */
 
        rcu_read_lock();
-       idr_for_each_entry(&drbd_devices, device, i) {
+       xa_for_each(&drbd_devices, i, device) {
                if (prev_i != i - 1)
                        seq_putc(seq, '\n');
                prev_i = i;
@@ -262,7 +262,7 @@ int drbd_seq_show(struct seq_file *seq, void *v)
                if (state.conn == C_STANDALONE &&
                    state.disk == D_DISKLESS &&
                    state.role == R_SECONDARY) {
-                       seq_printf(seq, "%2d: cs:Unconfigured\n", i);
+                       seq_printf(seq, "%2ld: cs:Unconfigured\n", i);
                } else {
                        /* reset device->congestion_reason */
                        bdi_rw_congested(device->rq_queue->backing_dev_info);
@@ -270,7 +270,7 @@ int drbd_seq_show(struct seq_file *seq, void *v)
                        nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
                        wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
                        seq_printf(seq,
-                          "%2d: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
+                          "%2ld: cs:%s ro:%s/%s ds:%s/%s %c %c%c%c%c%c%c\n"
                           "    ns:%u nr:%u dw:%u dr:%u al:%u bm:%u "
                           "lo:%d pe:%d ua:%d ap:%d ep:%d wo:%c",
                           i, sn,
index 2b3103c308573a5398237bd90d78c6957108ce08..8b2e405e0bfea8e8a3f7b7fd39542d3abd529ea9 100644 (file)
@@ -1448,7 +1448,7 @@ void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backin
 {
        struct drbd_device *device;
        enum write_ordering_e pwo;
-       int vnr;
+       unsigned long vnr;
        static char *write_ordering_str[] = {
                [WO_NONE] = "none",
                [WO_DRAIN_IO] = "drain",
@@ -1459,7 +1459,7 @@ void drbd_bump_write_ordering(struct drbd_resource *resource, struct drbd_backin
        if (wo != WO_BDEV_FLUSH)
                wo = min(pwo, wo);
        rcu_read_lock();
-       idr_for_each_entry(&resource->devices, device, vnr) {
+       xa_for_each(&resource->devices, vnr, device) {
                if (get_ldev(device)) {
                        wo = max_allowed_wo(device->ldev, wo);
                        if (device->ldev == bdev)
index eeaa3b49b264967ff43b4c2f2d71331d2ae555e6..8bf56bcc77e44bcedbc51d72f55fb0472f682a2d 100644 (file)
@@ -44,12 +44,12 @@ static void count_objects(struct drbd_resource *resource,
 {
        struct drbd_device *device;
        struct drbd_connection *connection;
-       int vnr;
+       unsigned long vnr;
 
        *n_devices = 0;
        *n_connections = 0;
 
-       idr_for_each_entry(&resource->devices, device, vnr)
+       xa_for_each(&resource->devices, vnr, device)
                (*n_devices)++;
        for_each_connection(connection, resource)
                (*n_connections)++;
@@ -87,7 +87,7 @@ struct drbd_state_change *remember_old_state(struct drbd_resource *resource, gfp
        unsigned int n_devices;
        struct drbd_connection *connection;
        unsigned int n_connections;
-       int vnr;
+       unsigned long vnr;
 
        struct drbd_device_state_change *device_state_change;
        struct drbd_peer_device_state_change *peer_device_state_change;
@@ -121,7 +121,7 @@ struct drbd_state_change *remember_old_state(struct drbd_resource *resource, gfp
 
        device_state_change = state_change->devices;
        peer_device_state_change = state_change->peer_devices;
-       idr_for_each_entry(&resource->devices, device, vnr) {
+       xa_for_each(&resource->devices, vnr, device) {
                kref_get(&device->kref);
                device_state_change->device = device;
                device_state_change->disk_state[OLD] = device->state.disk;
index 5bdcc70ad5897b350800b966c3975631850ce7fe..d4f052861aa802ad0642e61160aa9e5cba03a73a 100644 (file)
@@ -1563,10 +1563,10 @@ static bool drbd_pause_after(struct drbd_device *device)
 {
        bool changed = false;
        struct drbd_device *odev;
-       int i;
+       unsigned long i;
 
        rcu_read_lock();
-       idr_for_each_entry(&drbd_devices, odev, i) {
+       xa_for_each(&drbd_devices, i, odev) {
                if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
                        continue;
                if (!_drbd_may_sync_now(odev) &&
@@ -1589,10 +1589,10 @@ static bool drbd_resume_next(struct drbd_device *device)
 {
        bool changed = false;
        struct drbd_device *odev;
-       int i;
+       unsigned long i;
 
        rcu_read_lock();
-       idr_for_each_entry(&drbd_devices, odev, i) {
+       xa_for_each(&drbd_devices, i, odev) {
                if (odev->state.conn == C_STANDALONE && odev->state.disk == D_DISKLESS)
                        continue;
                if (odev->state.aftr_isp) {