Commit c46501b2deaa06efcaaf82917281941f02c6b307

Authored by NeilBrown
1 parent b721420e87

md/raid5: use seqcount to protect access to shape in make_request.

make_request() access various shape parameters (raid_disks, chunk_size
etc) which might be changed by raid5_start_reshape().

If the later is called at and awkward time during the form, the wrong
stripe_head might be used.

So introduce a 'seqcount' and after finding a stripe_head make sure
there is no reason to expect that we got the wrong one.

Signed-off-by: NeilBrown <neilb@suse.de>

Showing 2 changed files with 14 additions and 1 deletions Side-by-side Diff

... ... @@ -4408,8 +4408,10 @@
4408 4408 for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
4409 4409 DEFINE_WAIT(w);
4410 4410 int previous;
  4411 + int seq;
4411 4412  
4412 4413 retry:
  4414 + seq = read_seqcount_begin(&conf->gen_lock);
4413 4415 previous = 0;
4414 4416 prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
4415 4417 if (unlikely(conf->reshape_progress != MaxSector)) {
... ... @@ -4442,7 +4444,7 @@
4442 4444 previous,
4443 4445 &dd_idx, NULL);
4444 4446 pr_debug("raid456: make_request, sector %llu logical %llu\n",
4445   - (unsigned long long)new_sector,
  4447 + (unsigned long long)new_sector,
4446 4448 (unsigned long long)logical_sector);
4447 4449  
4448 4450 sh = get_active_stripe(conf, new_sector, previous,
... ... @@ -4471,6 +4473,13 @@
4471 4473 goto retry;
4472 4474 }
4473 4475 }
  4476 + if (read_seqcount_retry(&conf->gen_lock, seq)) {
  4477 + /* Might have got the wrong stripe_head
  4478 + * by accident
  4479 + */
  4480 + release_stripe(sh);
  4481 + goto retry;
  4482 + }
4474 4483  
4475 4484 if (rw == WRITE &&
4476 4485 logical_sector >= mddev->suspend_lo &&
... ... @@ -5437,6 +5446,7 @@
5437 5446 if (alloc_thread_groups(conf, 0))
5438 5447 goto abort;
5439 5448 spin_lock_init(&conf->device_lock);
  5449 + seqcount_init(&conf->gen_lock);
5440 5450 init_waitqueue_head(&conf->wait_for_stripe);
5441 5451 init_waitqueue_head(&conf->wait_for_overlap);
5442 5452 INIT_LIST_HEAD(&conf->handle_list);
... ... @@ -6249,6 +6259,7 @@
6249 6259  
6250 6260 atomic_set(&conf->reshape_stripes, 0);
6251 6261 spin_lock_irq(&conf->device_lock);
  6262 + write_seqcount_begin(&conf->gen_lock);
6252 6263 conf->previous_raid_disks = conf->raid_disks;
6253 6264 conf->raid_disks += mddev->delta_disks;
6254 6265 conf->prev_chunk_sectors = conf->chunk_sectors;
... ... @@ -6265,6 +6276,7 @@
6265 6276 else
6266 6277 conf->reshape_progress = 0;
6267 6278 conf->reshape_safe = conf->reshape_progress;
  6279 + write_seqcount_end(&conf->gen_lock);
6268 6280 spin_unlock_irq(&conf->device_lock);
6269 6281  
6270 6282 /* Add some new drives, as many as will fit.
... ... @@ -400,6 +400,7 @@
400 400 int prev_chunk_sectors;
401 401 int prev_algo;
402 402 short generation; /* increments with every reshape */
  403 + seqcount_t gen_lock; /* lock against generation changes */
403 404 unsigned long reshape_checkpoint; /* Time we last updated
404 405 * metadata */
405 406 long long min_offset_diff; /* minimum difference between