diff options
| -rw-r--r-- | drivers/md/raid5.c | 40 | ||||
| -rw-r--r-- | drivers/md/raid6main.c | 46 | ||||
| -rw-r--r-- | include/linux/raid/raid5.h | 4 |
3 files changed, 33 insertions, 57 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 9fc50487e2ed..6e4db95cebb1 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -35,12 +35,10 @@ | |||
| 35 | #define STRIPE_SHIFT (PAGE_SHIFT - 9) | 35 | #define STRIPE_SHIFT (PAGE_SHIFT - 9) |
| 36 | #define STRIPE_SECTORS (STRIPE_SIZE>>9) | 36 | #define STRIPE_SECTORS (STRIPE_SIZE>>9) |
| 37 | #define IO_THRESHOLD 1 | 37 | #define IO_THRESHOLD 1 |
| 38 | #define HASH_PAGES 1 | 38 | #define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) |
| 39 | #define HASH_PAGES_ORDER 0 | ||
| 40 | #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) | ||
| 41 | #define HASH_MASK (NR_HASH - 1) | 39 | #define HASH_MASK (NR_HASH - 1) |
| 42 | 40 | ||
| 43 | #define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]) | 41 | #define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) |
| 44 | 42 | ||
| 45 | /* bio's attached to a stripe+device for I/O are linked together in bi_sector | 43 | /* bio's attached to a stripe+device for I/O are linked together in bi_sector |
| 46 | * order without overlap. There may be several bio's per stripe+device, and | 44 | * order without overlap. There may be several bio's per stripe+device, and |
| @@ -113,29 +111,21 @@ static void release_stripe(struct stripe_head *sh) | |||
| 113 | spin_unlock_irqrestore(&conf->device_lock, flags); | 111 | spin_unlock_irqrestore(&conf->device_lock, flags); |
| 114 | } | 112 | } |
| 115 | 113 | ||
| 116 | static void remove_hash(struct stripe_head *sh) | 114 | static inline void remove_hash(struct stripe_head *sh) |
| 117 | { | 115 | { |
| 118 | PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); | 116 | PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); |
| 119 | 117 | ||
| 120 | if (sh->hash_pprev) { | 118 | hlist_del_init(&sh->hash); |
| 121 | if (sh->hash_next) | ||
| 122 | sh->hash_next->hash_pprev = sh->hash_pprev; | ||
| 123 | *sh->hash_pprev = sh->hash_next; | ||
| 124 | sh->hash_pprev = NULL; | ||
| 125 | } | ||
| 126 | } | 119 | } |
| 127 | 120 | ||
| 128 | static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) | 121 | static inline void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) |
| 129 | { | 122 | { |
| 130 | struct stripe_head **shp = &stripe_hash(conf, sh->sector); | 123 | struct hlist_head *hp = stripe_hash(conf, sh->sector); |
| 131 | 124 | ||
| 132 | PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); | 125 | PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); |
| 133 | 126 | ||
| 134 | CHECK_DEVLOCK(); | 127 | CHECK_DEVLOCK(); |
| 135 | if ((sh->hash_next = *shp) != NULL) | 128 | hlist_add_head(&sh->hash, hp); |
| 136 | (*shp)->hash_pprev = &sh->hash_next; | ||
| 137 | *shp = sh; | ||
| 138 | sh->hash_pprev = shp; | ||
| 139 | } | 129 | } |
| 140 | 130 | ||
| 141 | 131 | ||
| @@ -228,10 +218,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i | |||
| 228 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) | 218 | static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector) |
| 229 | { | 219 | { |
| 230 | struct stripe_head *sh; | 220 | struct stripe_head *sh; |
| 221 | struct hlist_node *hn; | ||
| 231 | 222 | ||
| 232 | CHECK_DEVLOCK(); | 223 | CHECK_DEVLOCK(); |
| 233 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); | 224 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); |
| 234 | for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next) | 225 | hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) |
| 235 | if (sh->sector == sector) | 226 | if (sh->sector == sector) |
| 236 | return sh; | 227 | return sh; |
| 237 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); | 228 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); |
| @@ -1835,9 +1826,8 @@ static int run(mddev_t *mddev) | |||
| 1835 | 1826 | ||
| 1836 | conf->mddev = mddev; | 1827 | conf->mddev = mddev; |
| 1837 | 1828 | ||
| 1838 | if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) | 1829 | if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) |
| 1839 | goto abort; | 1830 | goto abort; |
| 1840 | memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); | ||
| 1841 | 1831 | ||
| 1842 | spin_lock_init(&conf->device_lock); | 1832 | spin_lock_init(&conf->device_lock); |
| 1843 | init_waitqueue_head(&conf->wait_for_stripe); | 1833 | init_waitqueue_head(&conf->wait_for_stripe); |
| @@ -1972,9 +1962,7 @@ static int run(mddev_t *mddev) | |||
| 1972 | abort: | 1962 | abort: |
| 1973 | if (conf) { | 1963 | if (conf) { |
| 1974 | print_raid5_conf(conf); | 1964 | print_raid5_conf(conf); |
| 1975 | if (conf->stripe_hashtbl) | 1965 | kfree(conf->stripe_hashtbl); |
| 1976 | free_pages((unsigned long) conf->stripe_hashtbl, | ||
| 1977 | HASH_PAGES_ORDER); | ||
| 1978 | kfree(conf); | 1966 | kfree(conf); |
| 1979 | } | 1967 | } |
| 1980 | mddev->private = NULL; | 1968 | mddev->private = NULL; |
| @@ -1991,7 +1979,7 @@ static int stop(mddev_t *mddev) | |||
| 1991 | md_unregister_thread(mddev->thread); | 1979 | md_unregister_thread(mddev->thread); |
| 1992 | mddev->thread = NULL; | 1980 | mddev->thread = NULL; |
| 1993 | shrink_stripes(conf); | 1981 | shrink_stripes(conf); |
| 1994 | free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); | 1982 | kfree(conf->stripe_hashtbl); |
| 1995 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 1983 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 1996 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); | 1984 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); |
| 1997 | kfree(conf); | 1985 | kfree(conf); |
| @@ -2019,12 +2007,12 @@ static void print_sh (struct stripe_head *sh) | |||
| 2019 | static void printall (raid5_conf_t *conf) | 2007 | static void printall (raid5_conf_t *conf) |
| 2020 | { | 2008 | { |
| 2021 | struct stripe_head *sh; | 2009 | struct stripe_head *sh; |
| 2010 | struct hlist_node *hn; | ||
| 2022 | int i; | 2011 | int i; |
| 2023 | 2012 | ||
| 2024 | spin_lock_irq(&conf->device_lock); | 2013 | spin_lock_irq(&conf->device_lock); |
| 2025 | for (i = 0; i < NR_HASH; i++) { | 2014 | for (i = 0; i < NR_HASH; i++) { |
| 2026 | sh = conf->stripe_hashtbl[i]; | 2015 | hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { |
| 2027 | for (; sh; sh = sh->hash_next) { | ||
| 2028 | if (sh->raid_conf != conf) | 2016 | if (sh->raid_conf != conf) |
| 2029 | continue; | 2017 | continue; |
| 2030 | print_sh(sh); | 2018 | print_sh(sh); |
diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 4062fc16ac2b..79b5244f44f4 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c | |||
| @@ -40,12 +40,10 @@ | |||
| 40 | #define STRIPE_SHIFT (PAGE_SHIFT - 9) | 40 | #define STRIPE_SHIFT (PAGE_SHIFT - 9) |
| 41 | #define STRIPE_SECTORS (STRIPE_SIZE>>9) | 41 | #define STRIPE_SECTORS (STRIPE_SIZE>>9) |
| 42 | #define IO_THRESHOLD 1 | 42 | #define IO_THRESHOLD 1 |
| 43 | #define HASH_PAGES 1 | 43 | #define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) |
| 44 | #define HASH_PAGES_ORDER 0 | ||
| 45 | #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) | ||
| 46 | #define HASH_MASK (NR_HASH - 1) | 44 | #define HASH_MASK (NR_HASH - 1) |
| 47 | 45 | ||
| 48 | #define stripe_hash(conf, sect) ((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK]) | 46 | #define stripe_hash(conf, sect) (&((conf)->stripe_hashtbl[((sect) >> STRIPE_SHIFT) & HASH_MASK])) |
| 49 | 47 | ||
| 50 | /* bio's attached to a stripe+device for I/O are linked together in bi_sector | 48 | /* bio's attached to a stripe+device for I/O are linked together in bi_sector |
| 51 | * order without overlap. There may be several bio's per stripe+device, and | 49 | * order without overlap. There may be several bio's per stripe+device, and |
| @@ -132,29 +130,21 @@ static void release_stripe(struct stripe_head *sh) | |||
| 132 | spin_unlock_irqrestore(&conf->device_lock, flags); | 130 | spin_unlock_irqrestore(&conf->device_lock, flags); |
| 133 | } | 131 | } |
| 134 | 132 | ||
| 135 | static void remove_hash(struct stripe_head *sh) | 133 | static inline void remove_hash(struct stripe_head *sh) |
| 136 | { | 134 | { |
| 137 | PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); | 135 | PRINTK("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); |
| 138 | 136 | ||
| 139 | if (sh->hash_pprev) { | 137 | hlist_del_init(&sh->hash); |
| 140 | if (sh->hash_next) | ||
| 141 | sh->hash_next->hash_pprev = sh->hash_pprev; | ||
| 142 | *sh->hash_pprev = sh->hash_next; | ||
| 143 | sh->hash_pprev = NULL; | ||
| 144 | } | ||
| 145 | } | 138 | } |
| 146 | 139 | ||
| 147 | static __inline__ void insert_hash(raid6_conf_t *conf, struct stripe_head *sh) | 140 | static inline void insert_hash(raid6_conf_t *conf, struct stripe_head *sh) |
| 148 | { | 141 | { |
| 149 | struct stripe_head **shp = &stripe_hash(conf, sh->sector); | 142 | struct hlist_head *hp = stripe_hash(conf, sh->sector); |
| 150 | 143 | ||
| 151 | PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); | 144 | PRINTK("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); |
| 152 | 145 | ||
| 153 | CHECK_DEVLOCK(); | 146 | CHECK_DEVLOCK(); |
| 154 | if ((sh->hash_next = *shp) != NULL) | 147 | hlist_add_head(&sh->hash, hp); |
| 155 | (*shp)->hash_pprev = &sh->hash_next; | ||
| 156 | *shp = sh; | ||
| 157 | sh->hash_pprev = shp; | ||
| 158 | } | 148 | } |
| 159 | 149 | ||
| 160 | 150 | ||
| @@ -247,10 +237,11 @@ static inline void init_stripe(struct stripe_head *sh, sector_t sector, int pd_i | |||
| 247 | static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector) | 237 | static struct stripe_head *__find_stripe(raid6_conf_t *conf, sector_t sector) |
| 248 | { | 238 | { |
| 249 | struct stripe_head *sh; | 239 | struct stripe_head *sh; |
| 240 | struct hlist_node *hn; | ||
| 250 | 241 | ||
| 251 | CHECK_DEVLOCK(); | 242 | CHECK_DEVLOCK(); |
| 252 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); | 243 | PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector); |
| 253 | for (sh = stripe_hash(conf, sector); sh; sh = sh->hash_next) | 244 | hlist_for_each_entry (sh, hn, stripe_hash(conf, sector), hash) |
| 254 | if (sh->sector == sector) | 245 | if (sh->sector == sector) |
| 255 | return sh; | 246 | return sh; |
| 256 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); | 247 | PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector); |
| @@ -1931,17 +1922,15 @@ static int run(mddev_t *mddev) | |||
| 1931 | return -EIO; | 1922 | return -EIO; |
| 1932 | } | 1923 | } |
| 1933 | 1924 | ||
| 1934 | mddev->private = kmalloc (sizeof (raid6_conf_t) | 1925 | mddev->private = kzalloc(sizeof (raid6_conf_t) |
| 1935 | + mddev->raid_disks * sizeof(struct disk_info), | 1926 | + mddev->raid_disks * sizeof(struct disk_info), |
| 1936 | GFP_KERNEL); | 1927 | GFP_KERNEL); |
| 1937 | if ((conf = mddev->private) == NULL) | 1928 | if ((conf = mddev->private) == NULL) |
| 1938 | goto abort; | 1929 | goto abort; |
| 1939 | memset (conf, 0, sizeof (*conf) + mddev->raid_disks * sizeof(struct disk_info) ); | ||
| 1940 | conf->mddev = mddev; | 1930 | conf->mddev = mddev; |
| 1941 | 1931 | ||
| 1942 | if ((conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) | 1932 | if ((conf->stripe_hashtbl = kzalloc(PAGE_SIZE, GFP_KERNEL)) == NULL) |
| 1943 | goto abort; | 1933 | goto abort; |
| 1944 | memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); | ||
| 1945 | 1934 | ||
| 1946 | conf->spare_page = alloc_page(GFP_KERNEL); | 1935 | conf->spare_page = alloc_page(GFP_KERNEL); |
| 1947 | if (!conf->spare_page) | 1936 | if (!conf->spare_page) |
| @@ -2085,9 +2074,7 @@ abort: | |||
| 2085 | print_raid6_conf(conf); | 2074 | print_raid6_conf(conf); |
| 2086 | if (conf->spare_page) | 2075 | if (conf->spare_page) |
| 2087 | put_page(conf->spare_page); | 2076 | put_page(conf->spare_page); |
| 2088 | if (conf->stripe_hashtbl) | 2077 | kfree(conf->stripe_hashtbl); |
| 2089 | free_pages((unsigned long) conf->stripe_hashtbl, | ||
| 2090 | HASH_PAGES_ORDER); | ||
| 2091 | kfree(conf); | 2078 | kfree(conf); |
| 2092 | } | 2079 | } |
| 2093 | mddev->private = NULL; | 2080 | mddev->private = NULL; |
| @@ -2104,7 +2091,7 @@ static int stop (mddev_t *mddev) | |||
| 2104 | md_unregister_thread(mddev->thread); | 2091 | md_unregister_thread(mddev->thread); |
| 2105 | mddev->thread = NULL; | 2092 | mddev->thread = NULL; |
| 2106 | shrink_stripes(conf); | 2093 | shrink_stripes(conf); |
| 2107 | free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); | 2094 | kfree(conf->stripe_hashtbl); |
| 2108 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 2095 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
| 2109 | kfree(conf); | 2096 | kfree(conf); |
| 2110 | mddev->private = NULL; | 2097 | mddev->private = NULL; |
| @@ -2131,12 +2118,13 @@ static void print_sh (struct seq_file *seq, struct stripe_head *sh) | |||
| 2131 | static void printall (struct seq_file *seq, raid6_conf_t *conf) | 2118 | static void printall (struct seq_file *seq, raid6_conf_t *conf) |
| 2132 | { | 2119 | { |
| 2133 | struct stripe_head *sh; | 2120 | struct stripe_head *sh; |
| 2121 | struct hlist_node *hn; | ||
| 2134 | int i; | 2122 | int i; |
| 2135 | 2123 | ||
| 2136 | spin_lock_irq(&conf->device_lock); | 2124 | spin_lock_irq(&conf->device_lock); |
| 2137 | for (i = 0; i < NR_HASH; i++) { | 2125 | for (i = 0; i < NR_HASH; i++) { |
| 2138 | sh = conf->stripe_hashtbl[i]; | 2126 | sh = conf->stripe_hashtbl[i]; |
| 2139 | for (; sh; sh = sh->hash_next) { | 2127 | hlist_for_each_entry(sh, hn, &conf->stripe_hashtbl[i], hash) { |
| 2140 | if (sh->raid_conf != conf) | 2128 | if (sh->raid_conf != conf) |
| 2141 | continue; | 2129 | continue; |
| 2142 | print_sh(seq, sh); | 2130 | print_sh(seq, sh); |
diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 28fcd7533ac4..394da8207b34 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h | |||
| @@ -126,7 +126,7 @@ | |||
| 126 | */ | 126 | */ |
| 127 | 127 | ||
| 128 | struct stripe_head { | 128 | struct stripe_head { |
| 129 | struct stripe_head *hash_next, **hash_pprev; /* hash pointers */ | 129 | struct hlist_node hash; |
| 130 | struct list_head lru; /* inactive_list or handle_list */ | 130 | struct list_head lru; /* inactive_list or handle_list */ |
| 131 | struct raid5_private_data *raid_conf; | 131 | struct raid5_private_data *raid_conf; |
| 132 | sector_t sector; /* sector of this row */ | 132 | sector_t sector; /* sector of this row */ |
| @@ -204,7 +204,7 @@ struct disk_info { | |||
| 204 | }; | 204 | }; |
| 205 | 205 | ||
| 206 | struct raid5_private_data { | 206 | struct raid5_private_data { |
| 207 | struct stripe_head **stripe_hashtbl; | 207 | struct hlist_head *stripe_hashtbl; |
| 208 | mddev_t *mddev; | 208 | mddev_t *mddev; |
| 209 | struct disk_info *spare; | 209 | struct disk_info *spare; |
| 210 | int chunk_size, level, algorithm; | 210 | int chunk_size, level, algorithm; |
