mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/
synced 2025-04-19 20:58:31 +09:00
md: switch personalities to use md_submodule_head
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>
This commit is contained in:
parent
d3beb7c9c6
commit
3d44e1d157
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user