diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2003-05-26 07:05:55 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-05-26 07:05:55 -0700 |
| commit | 31458043214802d7bb86552a420f2a7e3c81e1b7 (patch) | |
| tree | 2d3c4b9427390efd065c85fc65ff3ff5567a0004 | |
| parent | 757400c3f3d5d732d04fb9b20cf45797387a3917 (diff) | |
[PATCH] md: Remove MD_SB_DISKS limits from raid1
raid1 uses MD_SB_DISKS to size two data structures,
but the new version-1 superblock allows for more than
this number of disks (and most actual arrays use many
fewer).
This patch sizes to two arrays dynamically.
One becomes a separate kmalloced array.
The other is moved to the end of the containing structure
and appropriate extra space is allocated.
Also, change r1buf_pool_alloc (which allocates buffers for
a mempool for doing re-sync) to not get r1bio structures
from the r1bio pool (which could exhaust the pool) but instead
to allocate them separately.
| -rw-r--r-- | drivers/md/raid1.c | 29 | ||||
| -rw-r--r-- | include/linux/raid/raid1.h | 11 |
2 files changed, 28 insertions, 12 deletions
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 3c92652762c3..9cf99f812690 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -40,9 +40,12 @@ static LIST_HEAD(retry_list_head); static void * r1bio_pool_alloc(int gfp_flags, void *data) { + mddev_t *mddev = data; r1bio_t *r1_bio; - r1_bio = kmalloc(sizeof(r1bio_t), gfp_flags); + /* allocate a r1bio with room for raid_disks entries in the write_bios array */ + r1_bio = kmalloc(sizeof(r1bio_t) + sizeof(struct bio*)*mddev->raid_disks, + gfp_flags); if (r1_bio) memset(r1_bio, 0, sizeof(*r1_bio)); @@ -67,8 +70,9 @@ static void * r1buf_pool_alloc(int gfp_flags, void *data) struct bio *bio; int i, j; - r1_bio = mempool_alloc(conf->r1bio_pool, gfp_flags); - + r1_bio = r1bio_pool_alloc(gfp_flags, conf->mddev); + if (!r1_bio) + return NULL; bio = bio_alloc(gfp_flags, RESYNC_PAGES); if (!bio) goto out_free_r1_bio; @@ -101,7 +105,7 @@ out_free_pages: __free_page(bio->bi_io_vec[j].bv_page); bio_put(bio); out_free_r1_bio: - mempool_free(r1_bio, conf->r1bio_pool); + r1bio_pool_free(r1_bio, conf->mddev); return NULL; } @@ -121,7 +125,7 @@ static void r1buf_pool_free(void *__r1_bio, void *data) if (atomic_read(&bio->bi_cnt) != 1) BUG(); bio_put(bio); - mempool_free(r1bio, conf->r1bio_pool); + r1bio_pool_free(r1bio, conf->mddev); } static void put_all_bios(conf_t *conf, r1bio_t *r1_bio) @@ -1085,13 +1089,20 @@ static int run(mddev_t *mddev) goto out; } memset(conf, 0, sizeof(*conf)); + conf->mirrors = kmalloc(sizeof(struct mirror_info)*mddev->raid_disks, + GFP_KERNEL); + if (!conf->mirrors) { + printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", + mdidx(mddev)); + goto out_free_conf; + } conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc, - r1bio_pool_free, NULL); + r1bio_pool_free, mddev); if (!conf->r1bio_pool) { printk(KERN_ERR "raid1: couldn't allocate memory for md%d\n", mdidx(mddev)); - goto out; + goto out_free_conf; } @@ -1169,6 +1180,8 @@ static int run(mddev_t *mddev) out_free_conf: if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); + if (conf->mirrors) + kfree(conf->mirrors); kfree(conf); mddev->private = NULL; out: @@ -1183,6 +1196,8 @@ static int stop(mddev_t *mddev) mddev->thread = NULL; if (conf->r1bio_pool) mempool_destroy(conf->r1bio_pool); + if (conf->mirrors) + kfree(conf->mirrors); kfree(conf); mddev->private = NULL; return 0; diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index cc7aa899a613..a9d1161ccab3 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h @@ -14,7 +14,7 @@ typedef struct r1bio_s r1bio_t; struct r1_private_data_s { mddev_t *mddev; - mirror_info_t mirrors[MD_SB_DISKS]; + mirror_info_t *mirrors; int raid_disks; int working_disks; int last_used; @@ -67,13 +67,14 @@ struct r1bio_s { */ struct bio *read_bio; int read_disk; - /* - * if the IO is in WRITE direction, then multiple bios are used: - */ - struct bio *write_bios[MD_SB_DISKS]; r1bio_t *next_r1; /* next for retry or in free list */ struct list_head retry_list; + /* + * if the IO is in WRITE direction, then multiple bios are used. + * We choose the number when they are allocated. + */ + struct bio *write_bios[0]; }; /* bits for r1bio.state */ |
