aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/linear.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/linear.c')
-rw-r--r--drivers/md/linear.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index fa211d80fc0a..21014836bdbf 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -138,6 +138,7 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
138 struct linear_conf *conf; 138 struct linear_conf *conf;
139 struct md_rdev *rdev; 139 struct md_rdev *rdev;
140 int i, cnt; 140 int i, cnt;
141 bool discard_supported = false;
141 142
142 conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info), 143 conf = kzalloc (sizeof (*conf) + raid_disks*sizeof(struct dev_info),
143 GFP_KERNEL); 144 GFP_KERNEL);
@@ -171,6 +172,8 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
171 conf->array_sectors += rdev->sectors; 172 conf->array_sectors += rdev->sectors;
172 cnt++; 173 cnt++;
173 174
175 if (blk_queue_discard(bdev_get_queue(rdev->bdev)))
176 discard_supported = true;
174 } 177 }
175 if (cnt != raid_disks) { 178 if (cnt != raid_disks) {
176 printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n", 179 printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n",
@@ -178,6 +181,11 @@ static struct linear_conf *linear_conf(struct mddev *mddev, int raid_disks)
178 goto out; 181 goto out;
179 } 182 }
180 183
184 if (!discard_supported)
185 queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
186 else
187 queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
188
181 /* 189 /*
182 * Here we calculate the device offsets. 190 * Here we calculate the device offsets.
183 */ 191 */
@@ -244,7 +252,9 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
244 if (!newconf) 252 if (!newconf)
245 return -ENOMEM; 253 return -ENOMEM;
246 254
247 oldconf = rcu_dereference(mddev->private); 255 oldconf = rcu_dereference_protected(mddev->private,
256 lockdep_is_held(
257 &mddev->reconfig_mutex));
248 mddev->raid_disks++; 258 mddev->raid_disks++;
249 rcu_assign_pointer(mddev->private, newconf); 259 rcu_assign_pointer(mddev->private, newconf);
250 md_set_array_sectors(mddev, linear_size(mddev, 0, 0)); 260 md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
@@ -256,7 +266,10 @@ static int linear_add(struct mddev *mddev, struct md_rdev *rdev)
256 266
257static int linear_stop (struct mddev *mddev) 267static int linear_stop (struct mddev *mddev)
258{ 268{
259 struct linear_conf *conf = mddev->private; 269 struct linear_conf *conf =
270 rcu_dereference_protected(mddev->private,
271 lockdep_is_held(
272 &mddev->reconfig_mutex));
260 273
261 /* 274 /*
262 * We do not require rcu protection here since 275 * We do not require rcu protection here since
@@ -326,6 +339,14 @@ static void linear_make_request(struct mddev *mddev, struct bio *bio)
326 bio->bi_sector = bio->bi_sector - start_sector 339 bio->bi_sector = bio->bi_sector - start_sector
327 + tmp_dev->rdev->data_offset; 340 + tmp_dev->rdev->data_offset;
328 rcu_read_unlock(); 341 rcu_read_unlock();
342
343 if (unlikely((bio->bi_rw & REQ_DISCARD) &&
344 !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
345 /* Just ignore it */
346 bio_endio(bio, 0);
347 return;
348 }
349
329 generic_make_request(bio); 350 generic_make_request(bio);
330} 351}
331 352