Commit 3d44e1d1 authored by Yu Kuai's avatar Yu Kuai Committed by Yu Kuai
Browse files

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: default avatarYu Kuai <yukuai3@huawei.com>
parent d3beb7c9
Loading
Loading
Loading
Loading
+9 −6
Original line number Diff line number Diff line
@@ -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 = {
	.head = {
		.type	= MD_PERSONALITY,
		.id	= ID_LINEAR,
		.name	= "linear",
	.level		= LEVEL_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);
+33 −49
Original line number Diff line number Diff line
@@ -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)
{
+1 −6
Original line number Diff line number Diff line
@@ -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,
+11 −7
Original line number Diff line number Diff line
@@ -811,9 +811,13 @@ static void raid0_quiesce(struct mddev *mddev, int quiesce)

static struct md_personality raid0_personality=
{
	.head = {
		.type	= MD_PERSONALITY,
		.id	= ID_RAID0,
		.name	= "raid0",
	.level		= 0,
		.owner	= THIS_MODULE,
	},

	.make_request	= raid0_make_request,
	.run		= raid0_run,
	.free		= raid0_free,
@@ -826,12 +830,12 @@ static struct md_personality raid0_personality=

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);
+13 −9
Original line number Diff line number Diff line
@@ -3500,9 +3500,13 @@ static void *raid1_takeover(struct mddev *mddev)

static struct md_personality raid1_personality =
{
	.head = {
		.type	= MD_PERSONALITY,
		.id	= ID_RAID1,
		.name	= "raid1",
	.level		= 1,
		.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 */
Loading