X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fmd%2Fmultipath.c;h=14da37fee37b428b72f2f5339f465ad4bfa3e3e8;hb=7a44e910f43cbb5186e7242f4c32b3a5d2fb6666;hp=e6aa309a66d7b7a4d71525702706f1bae99a8461;hpb=b9abaa3fb7328851bdeaad19e694048f0ff71d9a;p=linux-2.6 diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index e6aa309a66..14da37fee3 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -35,18 +35,6 @@ #define NR_RESERVED_BUFS 32 -static void *mp_pool_alloc(gfp_t gfp_flags, void *data) -{ - struct multipath_bh *mpb; - mpb = kzalloc(sizeof(*mpb), gfp_flags); - return mpb; -} - -static void mp_pool_free(void *mpb, void *data) -{ - kfree(mpb); -} - static int multipath_map (multipath_conf_t *conf) { int i, disks = conf->raid_disks; @@ -240,6 +228,28 @@ static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_unlock(); return ret; } +static int multipath_congested(void *data, int bits) +{ + mddev_t *mddev = data; + multipath_conf_t *conf = mddev_to_conf(mddev); + int i, ret = 0; + + rcu_read_lock(); + for (i = 0; i < mddev->raid_disks ; i++) { + mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); + if (rdev && !test_bit(Faulty, &rdev->flags)) { + request_queue_t *q = bdev_get_queue(rdev->bdev); + + ret |= bdi_congested(&q->backing_dev_info, bits); + /* Just like multipath_map, we just check the + * first available device + */ + break; + } + } + rcu_read_unlock(); + return ret; +} /* * Careful, this can execute in IRQ contexts as well! @@ -265,8 +275,9 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) char b[BDEVNAME_SIZE]; clear_bit(In_sync, &rdev->flags); set_bit(Faulty, &rdev->flags); - mddev->sb_dirty = 1; + set_bit(MD_CHANGE_DEVS, &mddev->flags); conf->working_disks--; + mddev->degraded++; printk(KERN_ALERT "multipath: IO failure on %s," " disabling IO path. \n Operation continuing" " on %d IO paths.\n", @@ -303,6 +314,7 @@ static void print_multipath_conf (multipath_conf_t *conf) static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) { multipath_conf_t *conf = mddev->private; + struct request_queue *q; int found = 0; int path; struct multipath_info *p; @@ -311,8 +323,8 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) for (path=0; pathraid_disks; path++) if ((p=conf->multipaths+path)->rdev == NULL) { - blk_queue_stack_limits(mddev->queue, - rdev->bdev->bd_disk->queue); + q = rdev->bdev->bd_disk->queue; + blk_queue_stack_limits(mddev->queue, q); /* as we don't honour merge_bvec_fn, we must never risk * violating it, so limit ->max_sector to one PAGE, as @@ -320,11 +332,12 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) * (Note: it is very unlikely that a device with * merge_bvec_fn will be involved in multipath.) */ - if (rdev->bdev->bd_disk->queue->merge_bvec_fn && + if (q->merge_bvec_fn && mddev->queue->max_sectors > (PAGE_SIZE>>9)) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); conf->working_disks++; + mddev->degraded--; rdev->raid_disk = path; set_bit(In_sync, &rdev->flags); rcu_assign_pointer(p->rdev, rdev); @@ -481,7 +494,6 @@ static int multipath_run (mddev_t *mddev) } conf->raid_disks = mddev->raid_disks; - mddev->sb_dirty = 1; conf->mddev = mddev; spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); @@ -491,11 +503,10 @@ static int multipath_run (mddev_t *mddev) mdname(mddev)); goto out_free_conf; } - mddev->degraded = conf->raid_disks = conf->working_disks; + mddev->degraded = conf->raid_disks - conf->working_disks; - conf->pool = mempool_create(NR_RESERVED_BUFS, - mp_pool_alloc, mp_pool_free, - NULL); + conf->pool = mempool_create_kzalloc_pool(NR_RESERVED_BUFS, + sizeof(struct multipath_bh)); if (conf->pool == NULL) { printk(KERN_ERR "multipath: couldn't allocate memory for %s\n", @@ -522,6 +533,8 @@ static int multipath_run (mddev_t *mddev) mddev->queue->unplug_fn = multipath_unplug; mddev->queue->issue_flush_fn = multipath_issue_flush; + mddev->queue->backing_dev_info.congested_fn = multipath_congested; + mddev->queue->backing_dev_info.congested_data = mddev; return 0;