X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmd%2Fraid0.c;h=dfe32149ad3ae1b0caf77fc39003d82cb640f3f7;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=5f4b8bfefc91001abb6b3f3c093ea441f6fe5731;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 5f4b8bfef..dfe32149a 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -40,6 +40,42 @@ static void raid0_unplug(request_queue_t *q) } } +static int raid0_issue_flush(request_queue_t *q, struct gendisk *disk, + sector_t *error_sector) +{ + mddev_t *mddev = q->queuedata; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t **devlist = conf->strip_zone[0].dev; + int i, ret = 0; + + for (i=0; iraid_disks && ret == 0; i++) { + struct block_device *bdev = devlist[i]->bdev; + request_queue_t *r_queue = bdev_get_queue(bdev); + + if (!r_queue->issue_flush_fn) + ret = -EOPNOTSUPP; + else + ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector); + } + return ret; +} + +static int raid0_congested(void *data, int bits) +{ + mddev_t *mddev = data; + raid0_conf_t *conf = mddev_to_conf(mddev); + mdk_rdev_t **devlist = conf->strip_zone[0].dev; + int i, ret = 0; + + for (i = 0; i < mddev->raid_disks && !ret ; i++) { + request_queue_t *q = bdev_get_queue(devlist[i]->bdev); + + ret |= bdi_congested(&q->backing_dev_info, bits); + } + return ret; +} + + static int create_strip_zones (mddev_t *mddev) { int i, c, j; @@ -92,21 +128,16 @@ static int create_strip_zones (mddev_t *mddev) } printk("raid0: FINAL %d zones\n", conf->nr_strip_zones); - conf->strip_zone = kmalloc(sizeof(struct strip_zone)* + conf->strip_zone = kzalloc(sizeof(struct strip_zone)* conf->nr_strip_zones, GFP_KERNEL); if (!conf->strip_zone) return 1; - conf->devlist = kmalloc(sizeof(mdk_rdev_t*)* + conf->devlist = kzalloc(sizeof(mdk_rdev_t*)* conf->nr_strip_zones*mddev->raid_disks, GFP_KERNEL); if (!conf->devlist) return 1; - memset(conf->strip_zone, 0,sizeof(struct strip_zone)* - conf->nr_strip_zones); - memset(conf->devlist, 0, - sizeof(mdk_rdev_t*) * conf->nr_strip_zones * mddev->raid_disks); - /* The first zone must contain all devices, so here we check that * there is a proper alignment of slots to devices and find them all */ @@ -137,7 +168,7 @@ static int create_strip_zones (mddev_t *mddev) if (rdev1->bdev->bd_disk->queue->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) - mddev->queue->max_sectors = (PAGE_SIZE>>9); + blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); if (!smallest || (rdev1->size size)) smallest = rdev1; @@ -219,6 +250,10 @@ static int create_strip_zones (mddev_t *mddev) mddev->queue->unplug_fn = raid0_unplug; + mddev->queue->issue_flush_fn = raid0_issue_flush; + mddev->queue->backing_dev_info.congested_fn = raid0_congested; + mddev->queue->backing_dev_info.congested_data = mddev; + printk("raid0: done.\n"); return 0; abort: @@ -257,7 +292,11 @@ static int raid0_run (mddev_t *mddev) mdk_rdev_t *rdev; struct list_head *tmp; - printk("%s: setting max_sectors to %d, segment boundary to %d\n", + if (mddev->chunk_size == 0) { + printk(KERN_ERR "md/raid0: non-zero chunk size required.\n"); + return -EINVAL; + } + printk(KERN_INFO "%s: setting max_sectors to %d, segment boundary to %d\n", mdname(mddev), mddev->chunk_size >> 9, (mddev->chunk_size>>1)-1); @@ -284,23 +323,20 @@ static int raid0_run (mddev_t *mddev) printk("raid0 : conf->hash_spacing is %llu blocks.\n", (unsigned long long)conf->hash_spacing); { -#if __GNUC__ < 3 - volatile -#endif sector_t s = mddev->array_size; sector_t space = conf->hash_spacing; int round; conf->preshift = 0; - if (sizeof(sector_t) > sizeof(unsigned long)) { + if (sizeof(sector_t) > sizeof(u32)) { /*shift down space and s so that sector_div will work */ - while (space > (sector_t) (~(unsigned long)0)) { + while (space > (sector_t) (~(u32)0)) { s >>= 1; space >>= 1; s += 1; /* force round-up */ conf->preshift++; } } - round = sector_div(s, (unsigned long)space) ? 1 : 0; + round = sector_div(s, (u32)space) ? 1 : 0; nb_zone = s + round; } printk("raid0 : nb_zone is %d.\n", nb_zone); @@ -312,13 +348,14 @@ static int raid0_run (mddev_t *mddev) goto out_free_conf; size = conf->strip_zone[cur].size; - for (i=0; i< nb_zone; i++) { - conf->hash_table[i] = conf->strip_zone + cur; + conf->hash_table[0] = conf->strip_zone + cur; + for (i=1; i< nb_zone; i++) { while (size <= conf->hash_spacing) { cur++; size += conf->strip_zone[cur].size; } size -= conf->hash_spacing; + conf->hash_table[i] = conf->strip_zone + cur; } if (conf->preshift) { conf->hash_spacing >>= conf->preshift; @@ -338,7 +375,7 @@ static int raid0_run (mddev_t *mddev) * chunksize should be used in that case. */ { - int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_CACHE_SIZE; + int stripe = mddev->raid_disks * mddev->chunk_size / PAGE_SIZE; if (mddev->queue->backing_dev_info.ra_pages < 2* stripe) mddev->queue->backing_dev_info.ra_pages = 2* stripe; } @@ -348,25 +385,24 @@ static int raid0_run (mddev_t *mddev) return 0; out_free_conf: - if (conf->strip_zone) - kfree(conf->strip_zone); - if (conf->devlist) - kfree (conf->devlist); + kfree(conf->strip_zone); + kfree(conf->devlist); kfree(conf); mddev->private = NULL; out: - return 1; + return -ENOMEM; } static int raid0_stop (mddev_t *mddev) { raid0_conf_t *conf = mddev_to_conf(mddev); - kfree (conf->hash_table); + blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ + kfree(conf->hash_table); conf->hash_table = NULL; - kfree (conf->strip_zone); + kfree(conf->strip_zone); conf->strip_zone = NULL; - kfree (conf); + kfree(conf); mddev->private = NULL; return 0; @@ -381,15 +417,16 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio) mdk_rdev_t *tmp_dev; unsigned long chunk; sector_t block, rsect; + const int rw = bio_data_dir(bio); - if (bio_data_dir(bio)==WRITE) { - disk_stat_inc(mddev->gendisk, writes); - disk_stat_add(mddev->gendisk, write_sectors, bio_sectors(bio)); - } else { - disk_stat_inc(mddev->gendisk, reads); - disk_stat_add(mddev->gendisk, read_sectors, bio_sectors(bio)); + if (unlikely(bio_barrier(bio))) { + bio_endio(bio, bio->bi_size, -EOPNOTSUPP); + return 0; } + disk_stat_inc(mddev->gendisk, ios[rw]); + disk_stat_add(mddev->gendisk, sectors[rw], bio_sectors(bio)); + chunk_size = mddev->chunk_size >> 10; chunk_sects = mddev->chunk_size >> 9; chunksize_bits = ffz(~chunk_size); @@ -417,11 +454,8 @@ static int raid0_make_request (request_queue_t *q, struct bio *bio) { -#if __GNUC__ < 3 - volatile -#endif sector_t x = block >> conf->preshift; - sector_div(x, (unsigned long)conf->hash_spacing); + sector_div(x, (u32)conf->hash_spacing); zone = conf->hash_table[x]; } @@ -489,9 +523,10 @@ static void raid0_status (struct seq_file *seq, mddev_t *mddev) return; } -static mdk_personality_t raid0_personality= +static struct mdk_personality raid0_personality= { .name = "raid0", + .level = 0, .owner = THIS_MODULE, .make_request = raid0_make_request, .run = raid0_run, @@ -501,15 +536,17 @@ static mdk_personality_t raid0_personality= static int __init raid0_init (void) { - return register_md_personality (RAID0, &raid0_personality); + return register_md_personality (&raid0_personality); } static void raid0_exit (void) { - unregister_md_personality (RAID0); + unregister_md_personality (&raid0_personality); } module_init(raid0_init); module_exit(raid0_exit); MODULE_LICENSE("GPL"); MODULE_ALIAS("md-personality-2"); /* RAID0 */ +MODULE_ALIAS("md-raid0"); +MODULE_ALIAS("md-level-0");