Signed-off-by: Sandeep K Sinha <sandeepksinha@xxxxxxxxx> Protecting mddev with barriers to avoid races. diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 9ad6ec4..a56095c 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -28,9 +28,11 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) { int lo, mid, hi; - linear_conf_t *conf = mddev_to_conf(mddev); + linear_conf_t *conf; + rcu_read_lock(); lo = 0; + conf = rcu_dereference(mddev->private); hi = mddev->raid_disks - 1; /* @@ -45,7 +47,7 @@ static inline dev_info_t *which_dev(mddev_t *mddev, sector_t sector) else lo = mid + 1; } - + rcu_read_unlock(); return conf->disks + lo; } @@ -86,36 +88,49 @@ static int linear_mergeable_bvec(struct request_queue *q, static void linear_unplug(struct request_queue *q) { mddev_t *mddev = q->queuedata; - linear_conf_t *conf = mddev_to_conf(mddev); + linear_conf_t *conf; int i; + rcu_read_lock(); + conf = rcu_dereference(mddev->private); + for (i=0; i < mddev->raid_disks; i++) { struct request_queue *r_queue = bdev_get_queue(conf->disks[i].rdev->bdev); blk_unplug(r_queue); } + rcu_read_unlock(); } static int linear_congested(void *data, int bits) { mddev_t *mddev = data; - linear_conf_t *conf = mddev_to_conf(mddev); + linear_conf_t *conf; int i, ret = 0; + rcu_read_lock(); + conf = rcu_dereference(mddev->private); + for (i = 0; i < mddev->raid_disks && !ret ; i++) { struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev); ret |= bdi_congested(&q->backing_dev_info, bits); } + + rcu_read_unlock(); return ret; } static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks) { - linear_conf_t *conf = mddev_to_conf(mddev); - + linear_conf_t *conf; + sector_t array_sectors; + rcu_read_lock(); + conf = rcu_dereference(mddev->private); WARN_ONCE(sectors || raid_disks, "%s does not support generic reshape\n", __func__); - - return conf->array_sectors; + array_sectors = conf->array_sectors; + rcu_read_unlock(); + + return array_sectors; } static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) @@ -215,15 +230,14 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev) return -EINVAL; rdev->raid_disk = rdev->saved_raid_disk; - - newconf = linear_conf(mddev,mddev->raid_disks+1); + newconf = linear_conf(mddev,mddev->raid_disks + 1); if (!newconf) return -ENOMEM; newconf->prev = mddev_to_conf(mddev); - mddev->private = newconf; mddev->raid_disks++; + rcu_assign_pointer(mddev->private,newconf); md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); set_capacity(mddev->gendisk, mddev->array_sectors); return 0; @@ -231,14 +245,17 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev) static int linear_stop (mddev_t *mddev) { - linear_conf_t *conf = mddev_to_conf(mddev); - + linear_conf_t *conf; + + rcu_read_lock(); + conf = rcu_dereference(mddev->private); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ do { linear_conf_t *t = conf->prev; kfree(conf); conf = t; } while (conf); + rcu_read_unlock(); return 0; } -- Regards, Sandeep. “To learn is to change. Education is a process that changes the learner.” -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html