md: switch personalities to use md_submodule_head
authorYu Kuai <yukuai3@huawei.com>
Sat, 15 Feb 2025 09:22:22 +0000 (17:22 +0800)
committerYu Kuai <yukuai@kernel.org>
Tue, 4 Mar 2025 16:27:20 +0000 (00:27 +0800)
Remove the global list 'pers_list', and switch to use md_submodule_head,
which is managed by xarry. Prepare to unify registration and unregistration
for all sub modules.

Link: https://lore.kernel.org/linux-raid/20250215092225.2427977-5-yukuai1@huaweicloud.com
Signed-off-by: Yu Kuai <yukuai3@huawei.com>
drivers/md/md-linear.c
drivers/md/md.c
drivers/md/md.h
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c

index 369aed044b409f14bb5a84b9158f1514c888f66f..5d9b081153757eda44a93f3cd9d56ee9258e0c00 100644 (file)
@@ -5,7 +5,6 @@
  */
 
 #include <linux/blkdev.h>
-#include <linux/raid/md_u.h>
 #include <linux/seq_file.h>
 #include <linux/module.h>
 #include <linux/slab.h>
@@ -320,9 +319,13 @@ static void linear_quiesce(struct mddev *mddev, int state)
 }
 
 static struct md_personality linear_personality = {
-       .name           = "linear",
-       .level          = LEVEL_LINEAR,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_LINEAR,
+               .name   = "linear",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = linear_make_request,
        .run            = linear_run,
        .free           = linear_free,
@@ -335,12 +338,12 @@ static struct md_personality linear_personality = {
 
 static int __init linear_init(void)
 {
-       return register_md_personality(&linear_personality);
+       return register_md_submodule(&linear_personality.head);
 }
 
 static void linear_exit(void)
 {
-       unregister_md_personality(&linear_personality);
+       unregister_md_submodule(&linear_personality.head);
 }
 
 module_init(linear_init);
index 638929889289f99f1dd11e2dcb1896d3353ddb2e..af6f2e8da4e6833a2a9e8dc25d4d97046a616798 100644 (file)
@@ -81,8 +81,6 @@ static const char *action_name[NR_SYNC_ACTIONS] = {
 
 static DEFINE_XARRAY(md_submodule);
 
-/* pers_list is a list of registered personalities protected by pers_lock. */
-static LIST_HEAD(pers_list);
 static DEFINE_SPINLOCK(pers_lock);
 
 static const struct kobj_type md_ktype;
@@ -893,18 +891,21 @@ EXPORT_SYMBOL_GPL(md_find_rdev_rcu);
 static struct md_personality *get_pers(int level, char *clevel)
 {
        struct md_personality *ret = NULL;
-       struct md_personality *pers;
+       struct md_submodule_head *head;
+       unsigned long i;
 
-       spin_lock(&pers_lock);
-       list_for_each_entry(pers, &pers_list, list) {
-               if ((level != LEVEL_NONE && pers->level == level) ||
-                   !strcmp(pers->name, clevel)) {
-                       if (try_module_get(pers->owner))
-                               ret = pers;
+       xa_lock(&md_submodule);
+       xa_for_each(&md_submodule, i, head) {
+               if (head->type != MD_PERSONALITY)
+                       continue;
+               if ((level != LEVEL_NONE && head->id == level) ||
+                   !strcmp(head->name, clevel)) {
+                       if (try_module_get(head->owner))
+                               ret = (void *)head;
                        break;
                }
        }
-       spin_unlock(&pers_lock);
+       xa_unlock(&md_submodule);
 
        if (!ret) {
                if (level != LEVEL_NONE)
@@ -920,7 +921,7 @@ static struct md_personality *get_pers(int level, char *clevel)
 
 static void put_pers(struct md_personality *pers)
 {
-       module_put(pers->owner);
+       module_put(pers->head.owner);
 }
 
 /* return the offset of the super block in 512byte sectors */
@@ -1203,7 +1204,7 @@ int md_check_no_bitmap(struct mddev *mddev)
        if (!mddev->bitmap_info.file && !mddev->bitmap_info.offset)
                return 0;
        pr_warn("%s: bitmaps are not supported for %s\n",
-               mdname(mddev), mddev->pers->name);
+               mdname(mddev), mddev->pers->head.name);
        return 1;
 }
 EXPORT_SYMBOL(md_check_no_bitmap);
@@ -3883,7 +3884,7 @@ level_show(struct mddev *mddev, char *page)
        spin_lock(&mddev->lock);
        p = mddev->pers;
        if (p)
-               ret = sprintf(page, "%s\n", p->name);
+               ret = sprintf(page, "%s\n", p->head.name);
        else if (mddev->clevel[0])
                ret = sprintf(page, "%s\n", mddev->clevel);
        else if (mddev->level != LEVEL_NONE)
@@ -3940,7 +3941,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
        rv = -EINVAL;
        if (!mddev->pers->quiesce) {
                pr_warn("md: %s: %s does not support online personality change\n",
-                       mdname(mddev), mddev->pers->name);
+                       mdname(mddev), mddev->pers->head.name);
                goto out_unlock;
        }
 
@@ -4003,7 +4004,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
        oldpriv = mddev->private;
        mddev->pers = pers;
        mddev->private = priv;
-       strscpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+       strscpy(mddev->clevel, pers->head.name, sizeof(mddev->clevel));
        mddev->level = mddev->new_level;
        mddev->layout = mddev->new_layout;
        mddev->chunk_sectors = mddev->new_chunk_sectors;
@@ -5603,7 +5604,7 @@ __ATTR(fail_last_dev, S_IRUGO | S_IWUSR, fail_last_dev_show,
 
 static ssize_t serialize_policy_show(struct mddev *mddev, char *page)
 {
-       if (mddev->pers == NULL || (mddev->pers->level != 1))
+       if (mddev->pers == NULL || (mddev->pers->head.id != ID_RAID1))
                return sprintf(page, "n/a\n");
        else
                return sprintf(page, "%d\n", mddev->serialize_policy);
@@ -5629,7 +5630,7 @@ serialize_policy_store(struct mddev *mddev, const char *buf, size_t len)
        err = mddev_suspend_and_lock(mddev);
        if (err)
                return err;
-       if (mddev->pers == NULL || (mddev->pers->level != 1)) {
+       if (mddev->pers == NULL || (mddev->pers->head.id != ID_RAID1)) {
                pr_err("md: serialize_policy is only effective for raid1\n");
                err = -EINVAL;
                goto unlock;
@@ -6120,11 +6121,11 @@ int md_run(struct mddev *mddev)
                err = -EINVAL;
                goto abort;
        }
-       if (mddev->level != pers->level) {
-               mddev->level = pers->level;
-               mddev->new_level = pers->level;
+       if (mddev->level != pers->head.id) {
+               mddev->level = pers->head.id;
+               mddev->new_level = pers->head.id;
        }
-       strscpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
+       strscpy(mddev->clevel, pers->head.name, sizeof(mddev->clevel));
 
        if (mddev->reshape_position != MaxSector &&
            pers->start_reshape == NULL) {
@@ -8134,7 +8135,8 @@ void md_error(struct mddev *mddev, struct md_rdev *rdev)
                return;
        mddev->pers->error_handler(mddev, rdev);
 
-       if (mddev->pers->level == 0 || mddev->pers->level == LEVEL_LINEAR)
+       if (mddev->pers->head.id == ID_RAID0 ||
+           mddev->pers->head.id == ID_LINEAR)
                return;
 
        if (mddev->degraded && !test_bit(MD_BROKEN, &mddev->flags))
@@ -8172,14 +8174,17 @@ static void status_unused(struct seq_file *seq)
 
 static void status_personalities(struct seq_file *seq)
 {
-       struct md_personality *pers;
+       struct md_submodule_head *head;
+       unsigned long i;
 
        seq_puts(seq, "Personalities : ");
-       spin_lock(&pers_lock);
-       list_for_each_entry(pers, &pers_list, list)
-               seq_printf(seq, "[%s] ", pers->name);
 
-       spin_unlock(&pers_lock);
+       xa_lock(&md_submodule);
+       xa_for_each(&md_submodule, i, head)
+               if (head->type == MD_PERSONALITY)
+                       seq_printf(seq, "[%s] ", head->name);
+       xa_unlock(&md_submodule);
+
        seq_puts(seq, "\n");
 }
 
@@ -8402,7 +8407,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
                                seq_printf(seq, " (read-only)");
                        if (mddev->ro == MD_AUTO_READ)
                                seq_printf(seq, " (auto-read-only)");
-                       seq_printf(seq, " %s", mddev->pers->name);
+                       seq_printf(seq, " %s", mddev->pers->head.name);
                } else {
                        seq_printf(seq, "inactive");
                }
@@ -8536,27 +8541,6 @@ void unregister_md_submodule(struct md_submodule_head *msh)
 }
 EXPORT_SYMBOL_GPL(unregister_md_submodule);
 
-int register_md_personality(struct md_personality *p)
-{
-       pr_debug("md: %s personality registered for level %d\n",
-                p->name, p->level);
-       spin_lock(&pers_lock);
-       list_add_tail(&p->list, &pers_list);
-       spin_unlock(&pers_lock);
-       return 0;
-}
-EXPORT_SYMBOL(register_md_personality);
-
-int unregister_md_personality(struct md_personality *p)
-{
-       pr_debug("md: %s personality unregistered\n", p->name);
-       spin_lock(&pers_lock);
-       list_del_init(&p->list);
-       spin_unlock(&pers_lock);
-       return 0;
-}
-EXPORT_SYMBOL(unregister_md_personality);
-
 int register_md_cluster_operations(const struct md_cluster_operations *ops,
                                   struct module *module)
 {
index 4807fa0d0362f2fe996870aef8022c8a2d15ac0d..f9e0f0d390f13f66d438ac1670d2ef2a24fc7299 100644 (file)
@@ -726,10 +726,7 @@ static inline void md_sync_acct_bio(struct bio *bio, unsigned long nr_sectors)
 struct md_personality
 {
        struct md_submodule_head head;
-       char *name;
-       int level;
-       struct list_head list;
-       struct module *owner;
+
        bool __must_check (*make_request)(struct mddev *mddev, struct bio *bio);
        /*
         * start up works that do NOT require md_thread. tasks that
@@ -873,8 +870,6 @@ static inline void safe_put_page(struct page *p)
 int register_md_submodule(struct md_submodule_head *msh);
 void unregister_md_submodule(struct md_submodule_head *msh);
 
-extern int register_md_personality(struct md_personality *p);
-extern int unregister_md_personality(struct md_personality *p);
 extern struct md_thread *md_register_thread(
        void (*run)(struct md_thread *thread),
        struct mddev *mddev,
index 8fc9339b00c728f3e46e9b143b35a8af5aeb472b..2aec92e6e0a9d42610dd06d5967cb89c2a6584ab 100644 (file)
@@ -811,9 +811,13 @@ static void raid0_quiesce(struct mddev *mddev, int quiesce)
 
 static struct md_personality raid0_personality=
 {
-       .name           = "raid0",
-       .level          = 0,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID0,
+               .name   = "raid0",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid0_make_request,
        .run            = raid0_run,
        .free           = raid0_free,
@@ -824,14 +828,14 @@ static struct md_personality raid0_personality=
        .error_handler  = raid0_error,
 };
 
-static int __init raid0_init (void)
+static int __init raid0_init(void)
 {
-       return register_md_personality (&raid0_personality);
+       return register_md_submodule(&raid0_personality.head);
 }
 
-static void raid0_exit (void)
+static void __exit raid0_exit(void)
 {
-       unregister_md_personality (&raid0_personality);
+       unregister_md_submodule(&raid0_personality.head);
 }
 
 module_init(raid0_init);
index 789e8b73df9b2e4868714fdb66c237d0fba03271..87ec691920cd69a80c81b773a9a2ea2f94c329c6 100644 (file)
@@ -3500,9 +3500,13 @@ static void *raid1_takeover(struct mddev *mddev)
 
 static struct md_personality raid1_personality =
 {
-       .name           = "raid1",
-       .level          = 1,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID1,
+               .name   = "raid1",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid1_make_request,
        .run            = raid1_run,
        .free           = raid1_free,
@@ -3519,18 +3523,18 @@ static struct md_personality raid1_personality =
        .takeover       = raid1_takeover,
 };
 
-static int __init raid_init(void)
+static int __init raid1_init(void)
 {
-       return register_md_personality(&raid1_personality);
+       return register_md_submodule(&raid1_personality.head);
 }
 
-static void raid_exit(void)
+static void __exit raid1_exit(void)
 {
-       unregister_md_personality(&raid1_personality);
+       unregister_md_submodule(&raid1_personality.head);
 }
 
-module_init(raid_init);
-module_exit(raid_exit);
+module_init(raid1_init);
+module_exit(raid1_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RAID1 (mirroring) personality for MD");
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
index 3df39b2399b2924c2af7b299eee3fb55bf0f9622..5823329841bab325355b8e56c53db5fd9a6d0ee4 100644 (file)
@@ -5126,9 +5126,13 @@ static void raid10_finish_reshape(struct mddev *mddev)
 
 static struct md_personality raid10_personality =
 {
-       .name           = "raid10",
-       .level          = 10,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID10,
+               .name   = "raid10",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid10_make_request,
        .run            = raid10_run,
        .free           = raid10_free,
@@ -5148,18 +5152,18 @@ static struct md_personality raid10_personality =
        .update_reshape_pos = raid10_update_reshape_pos,
 };
 
-static int __init raid_init(void)
+static int __init raid10_init(void)
 {
-       return register_md_personality(&raid10_personality);
+       return register_md_submodule(&raid10_personality.head);
 }
 
-static void raid_exit(void)
+static void __exit raid10_exit(void)
 {
-       unregister_md_personality(&raid10_personality);
+       unregister_md_submodule(&raid10_personality.head);
 }
 
-module_init(raid_init);
-module_exit(raid_exit);
+module_init(raid10_init);
+module_exit(raid10_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RAID10 (striped mirror) personality for MD");
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
index 5c79429acc64da55bfd22b0ba5e3415113573a95..d73a775b16c52fcf14b6e9fb1c71f5e964aa3cfc 100644 (file)
@@ -8954,9 +8954,13 @@ static void raid5_prepare_suspend(struct mddev *mddev)
 
 static struct md_personality raid6_personality =
 {
-       .name           = "raid6",
-       .level          = 6,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID6,
+               .name   = "raid6",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid5_make_request,
        .run            = raid5_run,
        .start          = raid5_start,
@@ -8980,9 +8984,13 @@ static struct md_personality raid6_personality =
 };
 static struct md_personality raid5_personality =
 {
-       .name           = "raid5",
-       .level          = 5,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID5,
+               .name   = "raid5",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid5_make_request,
        .run            = raid5_run,
        .start          = raid5_start,
@@ -9007,9 +9015,13 @@ static struct md_personality raid5_personality =
 
 static struct md_personality raid4_personality =
 {
-       .name           = "raid4",
-       .level          = 4,
-       .owner          = THIS_MODULE,
+       .head = {
+               .type   = MD_PERSONALITY,
+               .id     = ID_RAID4,
+               .name   = "raid4",
+               .owner  = THIS_MODULE,
+       },
+
        .make_request   = raid5_make_request,
        .run            = raid5_run,
        .start          = raid5_start,
@@ -9045,21 +9057,39 @@ static int __init raid5_init(void)
                                      "md/raid5:prepare",
                                      raid456_cpu_up_prepare,
                                      raid456_cpu_dead);
-       if (ret) {
-               destroy_workqueue(raid5_wq);
-               return ret;
-       }
-       register_md_personality(&raid6_personality);
-       register_md_personality(&raid5_personality);
-       register_md_personality(&raid4_personality);
+       if (ret)
+               goto err_destroy_wq;
+
+       ret = register_md_submodule(&raid6_personality.head);
+       if (ret)
+               goto err_cpuhp_remove;
+
+       ret = register_md_submodule(&raid5_personality.head);
+       if (ret)
+               goto err_unregister_raid6;
+
+       ret = register_md_submodule(&raid4_personality.head);
+       if (ret)
+               goto err_unregister_raid5;
+
        return 0;
+
+err_unregister_raid5:
+       unregister_md_submodule(&raid5_personality.head);
+err_unregister_raid6:
+       unregister_md_submodule(&raid6_personality.head);
+err_cpuhp_remove:
+       cpuhp_remove_multi_state(CPUHP_MD_RAID5_PREPARE);
+err_destroy_wq:
+       destroy_workqueue(raid5_wq);
+       return ret;
 }
 
-static void raid5_exit(void)
+static void __exit raid5_exit(void)
 {
-       unregister_md_personality(&raid6_personality);
-       unregister_md_personality(&raid5_personality);
-       unregister_md_personality(&raid4_personality);
+       unregister_md_submodule(&raid6_personality.head);
+       unregister_md_submodule(&raid5_personality.head);
+       unregister_md_submodule(&raid4_personality.head);
        cpuhp_remove_multi_state(CPUHP_MD_RAID5_PREPARE);
        destroy_workqueue(raid5_wq);
 }