aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:51 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:09 -0500
commitd9d166c2a9d5d01af34396793950aa695883eed4 (patch)
tree6cb593cc0636476ebec9a9690aa48997510f9701 /drivers/md/md.c
parent8bb93aaca2062cd54cc2c58c76ee8409cae209a7 (diff)
[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>
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c61
1 files changed, 48 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ecc0166ba779..594d8c312e6a 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -303,12 +303,15 @@ static mdk_rdev_t * find_rdev(mddev_t * mddev, dev_t dev)
303 return NULL; 303 return NULL;
304} 304}
305 305
306static struct mdk_personality *find_pers(int level) 306static struct mdk_personality *find_pers(int level, char *clevel)
307{ 307{
308 struct mdk_personality *pers; 308 struct mdk_personality *pers;
309 list_for_each_entry(pers, &pers_list, list) 309 list_for_each_entry(pers, &pers_list, list) {
310 if (pers->level == level) 310 if (level != LEVEL_NONE && pers->level == level)
311 return pers; 311 return pers;
312 if (strcmp(pers->name, clevel)==0)
313 return pers;
314 }
312 return NULL; 315 return NULL;
313} 316}
314 317
@@ -715,6 +718,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
715 mddev->ctime = sb->ctime; 718 mddev->ctime = sb->ctime;
716 mddev->utime = sb->utime; 719 mddev->utime = sb->utime;
717 mddev->level = sb->level; 720 mddev->level = sb->level;
721 mddev->clevel[0] = 0;
718 mddev->layout = sb->layout; 722 mddev->layout = sb->layout;
719 mddev->raid_disks = sb->raid_disks; 723 mddev->raid_disks = sb->raid_disks;
720 mddev->size = sb->size; 724 mddev->size = sb->size;
@@ -1051,6 +1055,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
1051 mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1); 1055 mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
1052 mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1); 1056 mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
1053 mddev->level = le32_to_cpu(sb->level); 1057 mddev->level = le32_to_cpu(sb->level);
1058 mddev->clevel[0] = 0;
1054 mddev->layout = le32_to_cpu(sb->layout); 1059 mddev->layout = le32_to_cpu(sb->layout);
1055 mddev->raid_disks = le32_to_cpu(sb->raid_disks); 1060 mddev->raid_disks = le32_to_cpu(sb->raid_disks);
1056 mddev->size = le64_to_cpu(sb->size)/2; 1061 mddev->size = le64_to_cpu(sb->size)/2;
@@ -1774,15 +1779,36 @@ static ssize_t
1774level_show(mddev_t *mddev, char *page) 1779level_show(mddev_t *mddev, char *page)
1775{ 1780{
1776 struct mdk_personality *p = mddev->pers; 1781 struct mdk_personality *p = mddev->pers;
1777 if (p == NULL && mddev->raid_disks == 0) 1782 if (p)
1778 return 0;
1779 if (mddev->level >= 0)
1780 return sprintf(page, "raid%d\n", mddev->level);
1781 else
1782 return sprintf(page, "%s\n", p->name); 1783 return sprintf(page, "%s\n", p->name);
1784 else if (mddev->clevel[0])
1785 return sprintf(page, "%s\n", mddev->clevel);
1786 else if (mddev->level != LEVEL_NONE)
1787 return sprintf(page, "%d\n", mddev->level);
1788 else
1789 return 0;
1790}
1791
1792static ssize_t
1793level_store(mddev_t *mddev, const char *buf, size_t len)
1794{
1795 int rv = len;
1796 if (mddev->pers)
1797 return -EBUSY;
1798 if (len == 0)
1799 return 0;
1800 if (len >= sizeof(mddev->clevel))
1801 return -ENOSPC;
1802 strncpy(mddev->clevel, buf, len);
1803 if (mddev->clevel[len-1] == '\n')
1804 len--;
1805 mddev->clevel[len] = 0;
1806 mddev->level = LEVEL_NONE;
1807 return rv;
1783} 1808}
1784 1809
1785static struct md_sysfs_entry md_level = __ATTR_RO(level); 1810static struct md_sysfs_entry md_level =
1811__ATTR(level, 0644, level_show, level_store);
1786 1812
1787static ssize_t 1813static ssize_t
1788raid_disks_show(mddev_t *mddev, char *page) 1814raid_disks_show(mddev_t *mddev, char *page)
@@ -2158,7 +2184,10 @@ static int do_md_run(mddev_t * mddev)
2158 } 2184 }
2159 2185
2160#ifdef CONFIG_KMOD 2186#ifdef CONFIG_KMOD
2161 request_module("md-level-%d", mddev->level); 2187 if (mddev->level != LEVEL_NONE)
2188 request_module("md-level-%d", mddev->level);
2189 else if (mddev->clevel[0])
2190 request_module("md-%s", mddev->clevel);
2162#endif 2191#endif
2163 2192
2164 /* 2193 /*
@@ -2180,15 +2209,21 @@ static int do_md_run(mddev_t * mddev)
2180 return -ENOMEM; 2209 return -ENOMEM;
2181 2210
2182 spin_lock(&pers_lock); 2211 spin_lock(&pers_lock);
2183 pers = find_pers(mddev->level); 2212 pers = find_pers(mddev->level, mddev->clevel);
2184 if (!pers || !try_module_get(pers->owner)) { 2213 if (!pers || !try_module_get(pers->owner)) {
2185 spin_unlock(&pers_lock); 2214 spin_unlock(&pers_lock);
2186 printk(KERN_WARNING "md: personality for level %d is not loaded!\n", 2215 if (mddev->level != LEVEL_NONE)
2187 mddev->level); 2216 printk(KERN_WARNING "md: personality for level %d is not loaded!\n",
2217 mddev->level);
2218 else
2219 printk(KERN_WARNING "md: personality for level %s is not loaded!\n",
2220 mddev->clevel);
2188 return -EINVAL; 2221 return -EINVAL;
2189 } 2222 }
2190 mddev->pers = pers; 2223 mddev->pers = pers;
2191 spin_unlock(&pers_lock); 2224 spin_unlock(&pers_lock);
2225 mddev->level = pers->level;
2226 strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
2192 2227
2193 mddev->recovery = 0; 2228 mddev->recovery = 0;
2194 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ 2229 mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */