diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 61 |
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 | ||
306 | static struct mdk_personality *find_pers(int level) | 306 | static 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 | |||
1774 | level_show(mddev_t *mddev, char *page) | 1779 | level_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 | |||
1792 | static ssize_t | ||
1793 | level_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 | ||
1785 | static struct md_sysfs_entry md_level = __ATTR_RO(level); | 1810 | static struct md_sysfs_entry md_level = |
1811 | __ATTR(level, 0644, level_show, level_store); | ||
1786 | 1812 | ||
1787 | static ssize_t | 1813 | static ssize_t |
1788 | raid_disks_show(mddev_t *mddev, char *page) | 1814 | raid_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 */ |