Explorar o código

[PATCH] md: allow array level to be set textually via sysfs

Signed-off-by: Neil Brown <neilb@suse.de>
Acked-by: Greg KH <greg@kroah.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
NeilBrown %!s(int64=19) %!d(string=hai) anos
pai
achega
d9d166c2a9

+ 8 - 0
Documentation/md.txt

@@ -189,6 +189,14 @@ All md devices contain:
      1.2 (newer format in varying locations) or "none" indicating that
      1.2 (newer format in varying locations) or "none" indicating that
      the kernel isn't managing metadata at all.
      the kernel isn't managing metadata at all.
 
 
+  level
+     The raid 'level' for this array.  The name will often (but not
+     always) be the same as the name of the module that implements the
+     level.  To be auto-loaded the module must have an alias
+        md-$LEVEL  e.g. md-raid5
+     This can be written only while the array is being assembled, not
+     after it is started.
+
 As component devices are added to an md array, they appear in the 'md'
 As component devices are added to an md array, they appear in the 'md'
 directory as new directories named
 directory as new directories named
       dev-XXX
       dev-XXX

+ 1 - 0
drivers/md/faulty.c

@@ -342,4 +342,5 @@ module_init(raid_init);
 module_exit(raid_exit);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-10"); /* faulty */
 MODULE_ALIAS("md-personality-10"); /* faulty */
+MODULE_ALIAS("md-faulty");
 MODULE_ALIAS("md-level--5");
 MODULE_ALIAS("md-level--5");

+ 2 - 1
drivers/md/linear.c

@@ -376,5 +376,6 @@ static void linear_exit (void)
 module_init(linear_init);
 module_init(linear_init);
 module_exit(linear_exit);
 module_exit(linear_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("md-personality-1"); /* LINEAR - degrecated*/
+MODULE_ALIAS("md-personality-1"); /* LINEAR - deprecated*/
+MODULE_ALIAS("md-linear");
 MODULE_ALIAS("md-level--1");
 MODULE_ALIAS("md-level--1");

+ 48 - 13
drivers/md/md.c

@@ -303,12 +303,15 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
 	return NULL;
 	return NULL;
 }
 }
 
 
-static struct mdk_personality *find_pers(int level)
+static struct mdk_personality *find_pers(int level, char *clevel)
 {
 {
 	struct mdk_personality *pers;
 	struct mdk_personality *pers;
-	list_for_each_entry(pers, &pers_list, list)
-		if (pers->level == level)
+	list_for_each_entry(pers, &pers_list, list) {
+		if (level != LEVEL_NONE && pers->level == level)
 			return pers;
 			return pers;
+		if (strcmp(pers->name, clevel)==0)
+			return pers;
+	}
 	return NULL;
 	return NULL;
 }
 }
 
 
@@ -715,6 +718,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 		mddev->ctime = sb->ctime;
 		mddev->ctime = sb->ctime;
 		mddev->utime = sb->utime;
 		mddev->utime = sb->utime;
 		mddev->level = sb->level;
 		mddev->level = sb->level;
+		mddev->clevel[0] = 0;
 		mddev->layout = sb->layout;
 		mddev->layout = sb->layout;
 		mddev->raid_disks = sb->raid_disks;
 		mddev->raid_disks = sb->raid_disks;
 		mddev->size = sb->size;
 		mddev->size = sb->size;
@@ -1051,6 +1055,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
 		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
 		mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
 		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
 		mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
 		mddev->level = le32_to_cpu(sb->level);
 		mddev->level = le32_to_cpu(sb->level);
+		mddev->clevel[0] = 0;
 		mddev->layout = le32_to_cpu(sb->layout);
 		mddev->layout = le32_to_cpu(sb->layout);
 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
 		mddev->raid_disks = le32_to_cpu(sb->raid_disks);
 		mddev->size = le64_to_cpu(sb->size)/2;
 		mddev->size = le64_to_cpu(sb->size)/2;
@@ -1774,15 +1779,36 @@ static ssize_t
 level_show(mddev_t *mddev, char *page)
 level_show(mddev_t *mddev, char *page)
 {
 {
 	struct mdk_personality *p = mddev->pers;
 	struct mdk_personality *p = mddev->pers;
-	if (p == NULL && mddev->raid_disks == 0)
-		return 0;
-	if (mddev->level >= 0)
-		return sprintf(page, "raid%d\n", mddev->level);
-	else
+	if (p)
 		return sprintf(page, "%s\n", p->name);
 		return sprintf(page, "%s\n", p->name);
+	else if (mddev->clevel[0])
+		return sprintf(page, "%s\n", mddev->clevel);
+	else if (mddev->level != LEVEL_NONE)
+		return sprintf(page, "%d\n", mddev->level);
+	else
+		return 0;
+}
+
+static ssize_t
+level_store(mddev_t *mddev, const char *buf, size_t len)
+{
+	int rv = len;
+	if (mddev->pers)
+		return -EBUSY;
+	if (len == 0)
+		return 0;
+	if (len >= sizeof(mddev->clevel))
+		return -ENOSPC;
+	strncpy(mddev->clevel, buf, len);
+	if (mddev->clevel[len-1] == '\n')
+		len--;
+	mddev->clevel[len] = 0;
+	mddev->level = LEVEL_NONE;
+	return rv;
 }
 }
 
 
-static struct md_sysfs_entry md_level = __ATTR_RO(level);
+static struct md_sysfs_entry md_level =
+__ATTR(level, 0644, level_show, level_store);
 
 
 static ssize_t
 static ssize_t
 raid_disks_show(mddev_t *mddev, char *page)
 raid_disks_show(mddev_t *mddev, char *page)
@@ -2158,7 +2184,10 @@ static int do_md_run(mddev_t * mddev)
 	}
 	}
 
 
 #ifdef CONFIG_KMOD
 #ifdef CONFIG_KMOD
-	request_module("md-level-%d", mddev->level);
+	if (mddev->level != LEVEL_NONE)
+		request_module("md-level-%d", mddev->level);
+	else if (mddev->clevel[0])
+		request_module("md-%s", mddev->clevel);
 #endif
 #endif
 
 
 	/*
 	/*
@@ -2180,15 +2209,21 @@ static int do_md_run(mddev_t * mddev)
 		return -ENOMEM;
 		return -ENOMEM;
 
 
 	spin_lock(&pers_lock);
 	spin_lock(&pers_lock);
-	pers = find_pers(mddev->level);
+	pers = find_pers(mddev->level, mddev->clevel);
 	if (!pers || !try_module_get(pers->owner)) {
 	if (!pers || !try_module_get(pers->owner)) {
 		spin_unlock(&pers_lock);
 		spin_unlock(&pers_lock);
-		printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
-		       mddev->level);
+		if (mddev->level != LEVEL_NONE)
+			printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
+			       mddev->level);
+		else
+			printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
+			       mddev->clevel);
 		return -EINVAL;
 		return -EINVAL;
 	}
 	}
 	mddev->pers = pers;
 	mddev->pers = pers;
 	spin_unlock(&pers_lock);
 	spin_unlock(&pers_lock);
+	mddev->level = pers->level;
+	strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
 
 	mddev->recovery = 0;
 	mddev->recovery = 0;
 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
 	mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */

+ 1 - 0
drivers/md/multipath.c

@@ -578,4 +578,5 @@ module_init(multipath_init);
 module_exit(multipath_exit);
 module_exit(multipath_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-7"); /* MULTIPATH */
 MODULE_ALIAS("md-personality-7"); /* MULTIPATH */
+MODULE_ALIAS("md-multipath");
 MODULE_ALIAS("md-level--4");
 MODULE_ALIAS("md-level--4");

+ 1 - 0
drivers/md/raid0.c

@@ -536,4 +536,5 @@ module_init(raid0_init);
 module_exit(raid0_exit);
 module_exit(raid0_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-2"); /* RAID0 */
 MODULE_ALIAS("md-personality-2"); /* RAID0 */
+MODULE_ALIAS("md-raid0");
 MODULE_ALIAS("md-level-0");
 MODULE_ALIAS("md-level-0");

+ 1 - 0
drivers/md/raid1.c

@@ -2092,4 +2092,5 @@ module_init(raid_init);
 module_exit(raid_exit);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
 MODULE_ALIAS("md-personality-3"); /* RAID1 */
+MODULE_ALIAS("md-raid1");
 MODULE_ALIAS("md-level-1");
 MODULE_ALIAS("md-level-1");

+ 1 - 0
drivers/md/raid10.c

@@ -2117,4 +2117,5 @@ module_init(raid_init);
 module_exit(raid_exit);
 module_exit(raid_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
 MODULE_ALIAS("md-personality-9"); /* RAID10 */
+MODULE_ALIAS("md-raid10");
 MODULE_ALIAS("md-level-10");
 MODULE_ALIAS("md-level-10");

+ 2 - 0
drivers/md/raid5.c

@@ -2240,5 +2240,7 @@ module_init(raid5_init);
 module_exit(raid5_exit);
 module_exit(raid5_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-4"); /* RAID5 */
 MODULE_ALIAS("md-personality-4"); /* RAID5 */
+MODULE_ALIAS("md-raid5");
+MODULE_ALIAS("md-raid4");
 MODULE_ALIAS("md-level-5");
 MODULE_ALIAS("md-level-5");
 MODULE_ALIAS("md-level-4");
 MODULE_ALIAS("md-level-4");

+ 1 - 0
drivers/md/raid6main.c

@@ -2341,4 +2341,5 @@ module_init(raid6_init);
 module_exit(raid6_exit);
 module_exit(raid6_exit);
 MODULE_LICENSE("GPL");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("md-personality-8"); /* RAID6 */
 MODULE_ALIAS("md-personality-8"); /* RAID6 */
+MODULE_ALIAS("md-raid6");
 MODULE_ALIAS("md-level-6");
 MODULE_ALIAS("md-level-6");

+ 1 - 0
include/linux/raid/md_k.h

@@ -119,6 +119,7 @@ struct mddev_s
 	int				chunk_size;
 	int				chunk_size;
 	time_t				ctime, utime;
 	time_t				ctime, utime;
 	int				level, layout;
 	int				level, layout;
+	char				clevel[16];
 	int				raid_disks;
 	int				raid_disks;
 	int				max_disks;
 	int				max_disks;
 	sector_t			size; /* used size of component devices */
 	sector_t			size; /* used size of component devices */