aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2006-01-06 03:20:36 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:34:06 -0500
commit2604b703b6b3db80e3c75ce472a54dfd0b7bf9f4 (patch)
tree8c0e985c455ff35af24fbe60d8a3f5a276034370 /drivers/md/md.c
parenta24a8dd858e0ba50f06a9fd8f61fe8c4fe7a8d8e (diff)
[PATCH] md: remove personality numbering from md
md supports multiple different RAID level, each being implemented by a 'personality' (which is often in a separate module). These personalities have fairly artificial 'numbers'. The numbers are use to: 1- provide an index into an array where the various personalities are recorded 2- identify the module (via an alias) which implements are particular personality. Neither of these uses really justify the existence of personality numbers. The array can be replaced by a linked list which is searched (array lookup only happens very rarely). Module identification can be done using an alias based on level rather than 'personality' number. The current 'raid5' modules support two level (4 and 5) but only one personality. This slight awkwardness (which was handled in the mapping from level to personality) can be better handled by allowing raid5 to register 2 personalities. With this change in place, the core md module does not need to have an exhaustive list of all possible personalities, so other personalities can be added independently. This patch also moves the check for chunksize being non-zero into the ->run routines for the personalities that need it, rather than having it in core-md. This has a side effect of allowing 'faulty' and 'linear' not to have a chunk-size set. Signed-off-by: Neil Brown <neilb@suse.de> 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.c79
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 @@
68static void autostart_arrays (int part); 68static void autostart_arrays (int part);
69#endif 69#endif
70 70
71static mdk_personality_t *pers[MAX_PERSONALITY]; 71static LIST_HEAD(pers_list);
72static DEFINE_SPINLOCK(pers_lock); 72static 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
306static 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
306static inline sector_t calc_dev_sboffset(struct block_device *bdev) 315static 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)
1744static ssize_t 1753static ssize_t
1745level_show(mddev_t *mddev, char *page) 1754level_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
1961static int do_md_run(mddev_t * mddev) 1970static 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
3873int register_md_personality(int pnum, mdk_personality_t *p) 3867int 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
3894int unregister_md_personality(int pnum) 3876int 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}