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 | } |
