diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 79 |
1 files changed, 29 insertions, 50 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index a6a066fc92e3..07f180f95b47 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -68,7 +68,7 @@ | |||
68 | static void autostart_arrays (int part); | 68 | static void autostart_arrays (int part); |
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | static mdk_personality_t *pers[MAX_PERSONALITY]; | 71 | static LIST_HEAD(pers_list); |
72 | static DEFINE_SPINLOCK(pers_lock); | 72 | static DEFINE_SPINLOCK(pers_lock); |
73 | 73 | ||
74 | /* | 74 | /* |
@@ -303,6 +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) | ||
307 | { | ||
308 | struct mdk_personality *pers; | ||
309 | list_for_each_entry(pers, &pers_list, list) | ||
310 | if (pers->level == level) | ||
311 | return pers; | ||
312 | return NULL; | ||
313 | } | ||
314 | |||
306 | static inline sector_t calc_dev_sboffset(struct block_device *bdev) | 315 | static inline sector_t calc_dev_sboffset(struct block_device *bdev) |
307 | { | 316 | { |
308 | sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; | 317 | sector_t size = bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; |
@@ -1744,7 +1753,7 @@ static void analyze_sbs(mddev_t * mddev) | |||
1744 | static ssize_t | 1753 | static ssize_t |
1745 | level_show(mddev_t *mddev, char *page) | 1754 | level_show(mddev_t *mddev, char *page) |
1746 | { | 1755 | { |
1747 | mdk_personality_t *p = mddev->pers; | 1756 | struct mdk_personality *p = mddev->pers; |
1748 | if (p == NULL && mddev->raid_disks == 0) | 1757 | if (p == NULL && mddev->raid_disks == 0) |
1749 | return 0; | 1758 | return 0; |
1750 | if (mddev->level >= 0) | 1759 | if (mddev->level >= 0) |
@@ -1960,11 +1969,12 @@ static int start_dirty_degraded; | |||
1960 | 1969 | ||
1961 | static int do_md_run(mddev_t * mddev) | 1970 | static int do_md_run(mddev_t * mddev) |
1962 | { | 1971 | { |
1963 | int pnum, err; | 1972 | int err; |
1964 | int chunk_size; | 1973 | int chunk_size; |
1965 | struct list_head *tmp; | 1974 | struct list_head *tmp; |
1966 | mdk_rdev_t *rdev; | 1975 | mdk_rdev_t *rdev; |
1967 | struct gendisk *disk; | 1976 | struct gendisk *disk; |
1977 | struct mdk_personality *pers; | ||
1968 | char b[BDEVNAME_SIZE]; | 1978 | char b[BDEVNAME_SIZE]; |
1969 | 1979 | ||
1970 | if (list_empty(&mddev->disks)) | 1980 | if (list_empty(&mddev->disks)) |
@@ -1981,20 +1991,8 @@ static int do_md_run(mddev_t * mddev) | |||
1981 | analyze_sbs(mddev); | 1991 | analyze_sbs(mddev); |
1982 | 1992 | ||
1983 | chunk_size = mddev->chunk_size; | 1993 | chunk_size = mddev->chunk_size; |
1984 | pnum = level_to_pers(mddev->level); | ||
1985 | 1994 | ||
1986 | if ((pnum != MULTIPATH) && (pnum != RAID1)) { | 1995 | if (chunk_size) { |
1987 | if (!chunk_size) { | ||
1988 | /* | ||
1989 | * 'default chunksize' in the old md code used to | ||
1990 | * be PAGE_SIZE, baaad. | ||
1991 | * we abort here to be on the safe side. We don't | ||
1992 | * want to continue the bad practice. | ||
1993 | */ | ||
1994 | printk(KERN_ERR | ||
1995 | "no chunksize specified, see 'man raidtab'\n"); | ||
1996 | return -EINVAL; | ||
1997 | } | ||
1998 | if (chunk_size > MAX_CHUNK_SIZE) { | 1996 | if (chunk_size > MAX_CHUNK_SIZE) { |
1999 | printk(KERN_ERR "too big chunk_size: %d > %d\n", | 1997 | printk(KERN_ERR "too big chunk_size: %d > %d\n", |
2000 | chunk_size, MAX_CHUNK_SIZE); | 1998 | chunk_size, MAX_CHUNK_SIZE); |
@@ -2030,10 +2028,7 @@ static int do_md_run(mddev_t * mddev) | |||
2030 | } | 2028 | } |
2031 | 2029 | ||
2032 | #ifdef CONFIG_KMOD | 2030 | #ifdef CONFIG_KMOD |
2033 | if (!pers[pnum]) | 2031 | request_module("md-level-%d", mddev->level); |
2034 | { | ||
2035 | request_module("md-personality-%d", pnum); | ||
2036 | } | ||
2037 | #endif | 2032 | #endif |
2038 | 2033 | ||
2039 | /* | 2034 | /* |
@@ -2055,14 +2050,14 @@ static int do_md_run(mddev_t * mddev) | |||
2055 | return -ENOMEM; | 2050 | return -ENOMEM; |
2056 | 2051 | ||
2057 | spin_lock(&pers_lock); | 2052 | spin_lock(&pers_lock); |
2058 | if (!pers[pnum] || !try_module_get(pers[pnum]->owner)) { | 2053 | pers = find_pers(mddev->level); |
2054 | if (!pers || !try_module_get(pers->owner)) { | ||
2059 | spin_unlock(&pers_lock); | 2055 | spin_unlock(&pers_lock); |
2060 | printk(KERN_WARNING "md: personality %d is not loaded!\n", | 2056 | printk(KERN_WARNING "md: personality for level %d is not loaded!\n", |
2061 | pnum); | 2057 | mddev->level); |
2062 | return -EINVAL; | 2058 | return -EINVAL; |
2063 | } | 2059 | } |
2064 | 2060 | mddev->pers = pers; | |
2065 | mddev->pers = pers[pnum]; | ||
2066 | spin_unlock(&pers_lock); | 2061 | spin_unlock(&pers_lock); |
2067 | 2062 | ||
2068 | mddev->recovery = 0; | 2063 | mddev->recovery = 0; |
@@ -3701,15 +3696,14 @@ static int md_seq_show(struct seq_file *seq, void *v) | |||
3701 | struct list_head *tmp2; | 3696 | struct list_head *tmp2; |
3702 | mdk_rdev_t *rdev; | 3697 | mdk_rdev_t *rdev; |
3703 | struct mdstat_info *mi = seq->private; | 3698 | struct mdstat_info *mi = seq->private; |
3704 | int i; | ||
3705 | struct bitmap *bitmap; | 3699 | struct bitmap *bitmap; |
3706 | 3700 | ||
3707 | if (v == (void*)1) { | 3701 | if (v == (void*)1) { |
3702 | struct mdk_personality *pers; | ||
3708 | seq_printf(seq, "Personalities : "); | 3703 | seq_printf(seq, "Personalities : "); |
3709 | spin_lock(&pers_lock); | 3704 | spin_lock(&pers_lock); |
3710 | for (i = 0; i < MAX_PERSONALITY; i++) | 3705 | list_for_each_entry(pers, &pers_list, list) |
3711 | if (pers[i]) | 3706 | seq_printf(seq, "[%s] ", pers->name); |
3712 | seq_printf(seq, "[%s] ", pers[i]->name); | ||
3713 | 3707 | ||
3714 | spin_unlock(&pers_lock); | 3708 | spin_unlock(&pers_lock); |
3715 | seq_printf(seq, "\n"); | 3709 | seq_printf(seq, "\n"); |
@@ -3870,35 +3864,20 @@ static struct file_operations md_seq_fops = { | |||
3870 | .poll = mdstat_poll, | 3864 | .poll = mdstat_poll, |
3871 | }; | 3865 | }; |
3872 | 3866 | ||
3873 | int register_md_personality(int pnum, mdk_personality_t *p) | 3867 | int register_md_personality(struct mdk_personality *p) |
3874 | { | 3868 | { |
3875 | if (pnum >= MAX_PERSONALITY) { | ||
3876 | printk(KERN_ERR | ||
3877 | "md: tried to install personality %s as nr %d, but max is %lu\n", | ||
3878 | p->name, pnum, MAX_PERSONALITY-1); | ||
3879 | return -EINVAL; | ||
3880 | } | ||
3881 | |||
3882 | spin_lock(&pers_lock); | 3869 | spin_lock(&pers_lock); |
3883 | if (pers[pnum]) { | 3870 | list_add_tail(&p->list, &pers_list); |
3884 | spin_unlock(&pers_lock); | 3871 | printk(KERN_INFO "md: %s personality registered for level %d\n", p->name, p->level); |
3885 | return -EBUSY; | ||
3886 | } | ||
3887 | |||
3888 | pers[pnum] = p; | ||
3889 | printk(KERN_INFO "md: %s personality registered as nr %d\n", p->name, pnum); | ||
3890 | spin_unlock(&pers_lock); | 3872 | spin_unlock(&pers_lock); |
3891 | return 0; | 3873 | return 0; |
3892 | } | 3874 | } |
3893 | 3875 | ||
3894 | int unregister_md_personality(int pnum) | 3876 | int unregister_md_personality(struct mdk_personality *p) |
3895 | { | 3877 | { |
3896 | if (pnum >= MAX_PERSONALITY) | 3878 | printk(KERN_INFO "md: %s personality unregistered\n", p->name); |
3897 | return -EINVAL; | ||
3898 | |||
3899 | printk(KERN_INFO "md: %s personality unregistered\n", pers[pnum]->name); | ||
3900 | spin_lock(&pers_lock); | 3879 | spin_lock(&pers_lock); |
3901 | pers[pnum] = NULL; | 3880 | list_del_init(&p->list); |
3902 | spin_unlock(&pers_lock); | 3881 | spin_unlock(&pers_lock); |
3903 | return 0; | 3882 | return 0; |
3904 | } | 3883 | } |