Re: [RFC][PATCH] identify raid rcu-protected pointer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



>From "Paul E. McKenney" October 11, 2005 4:02 PM

> On Tue, Oct 11, 2005 at 02:48:37PM -0700, Suzanne Wood wrote:
> 
> Acked-by: <[email protected]>
> 
> Thanx, Paul

Thank you.  Recognizing that the comment in raid1.c will be
addressed and/or removed, please consider this.

Signed-off-by: <[email protected]>

> 
>> Elements of this patch were submitted Oct 5-6, 2005, but
>> are being resent with some explanation of reasoning employed
>> and additions. Insertions of rcu_dereference() 
>> are done in response to previously marked rcu readside 
>> critical sections with corresponding rcu_assign_pointer().
>>
>> Because synchronize_rcu() occurs after p->rdev = NULL; 
>> in the five files (multipath.c, raid10.c, raid1.c, 
>> raid5.c, and raid6main.c) within drivers/md, it is 
>> thought that the rcu_dereference() protects the later 
>> dereference of that pointer which is type mdk_rdev_t
>> defined in md_k.h for the struct mdk_rdev_s for the 
>> extended device.
>> 
>> In a case like the following from raid10.c:
>>         while (!conf->mirrors[disk].rdev ||
>>                !conf->mirrors[disk].rdev->in_sync) {
>> 
>> with no assignment of the rdev, the thought is that
>> an rcu-dereference() of the rdev protects the access
>> of, e.g, in_sync.  While in_sync is an integer (flag),
>> it's validity for the current object would be protected.
>> More likely, a temporary variable will be used in
>> read_balance() as seen in raid1.c, e.g.:
>>   rdev = conf->mirrors[new_disk].rdev)
>> 
>> In read_balance() of raid1.c, it was assumed that the 
>> extent of the rcu readside critical section was due to 
>> the "retry" label and the possibility of desiring to be 
>> external to the loop, but the "goto retry" is nested 
>> in 2 levels of conditionals.  This may indicate 
>> a reconsideration of the placement of rcu_read_lock()/
>> unlock().  raid10.c read_balance() may also merit
>> reevaluation.
>> 
>> The rcu_assign_pointer(rdev->mddev, mddev) is inserted
>> to make the mddev object globally visible because it
>> is the structure referenced by the rcu protected rdev
>> pointer.  Other assignments to rdev fields in md.c 
>> appear to be in regard to initialization, but the
>> developer will want to consider this.  
>> 
>> Thank you.
>>
>> ----------------------------------------------------
>> 
>>  md.c        |    2 +-
>>  multipath.c |    6 +++---
>>  raid1.c     |   18 +++++++++---------
>>  raid10.c    |   14 +++++++-------
>>  raid5.c     |    8 ++++----
>>  raid6main.c |    6 +++---
>>  6 files changed, 27 insertions(+), 27 deletions(-)
>> 
>> ----------------------------------------------------
>> 
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/md.c linux-2.6.14-rc4_patch/drivers/md/md.c
>> --- linux-2.6.14-rc4/drivers/md/md.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/md.c 2005-10-11 13:30:22.000000000 -0700
>> @@ -1145,7 +1145,7 @@ static int bind_rdev_to_array(mdk_rdev_t
>>  }
>>  
>>  list_add(&rdev->same_set, &mddev->disks);
>> - rdev->mddev = mddev;
>> + rcu_assign_pointer(rdev->mddev, mddev);
>>  printk(KERN_INFO "md: bind<%s>\n", bdevname(rdev->bdev,b));
>>  return 0;
>>  }
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/multipath.c linux-2.6.14-rc4_patch/drivers/md/multipath.c
>> --- linux-2.6.14-rc4/drivers/md/multipath.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/multipath.c 2005-10-11 10:28:33.000000000 -0700
>> @@ -63,7 +63,7 @@ static int multipath_map (multipath_conf
>>  
>>  rcu_read_lock();
>>  for (i = 0; i < disks; i++) {
>> - mdk_rdev_t *rdev = conf->multipaths[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
>>  if (rdev && rdev->in_sync) {
>>  atomic_inc(&rdev->nr_pending);
>>  rcu_read_unlock();
>> @@ -139,7 +139,7 @@ static void unplug_slaves(mddev_t *mddev
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks; i++) {
>> - mdk_rdev_t *rdev = conf->multipaths[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
>>  if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
>>  request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
>>  
>> @@ -228,7 +228,7 @@ static int multipath_issue_flush(request
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks && ret == 0; i++) {
>> - mdk_rdev_t *rdev = conf->multipaths[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
>>  if (rdev && !rdev->faulty) {
>>  struct block_device *bdev = rdev->bdev;
>>  request_queue_t *r_queue = bdev_get_queue(bdev);
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/raid10.c linux-2.6.14-rc4_patch/drivers/md/raid10.c
>> --- linux-2.6.14-rc4/drivers/md/raid10.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/raid10.c 2005-10-11 14:09:20.000000000 -0700
>> @@ -510,7 +510,7 @@ static int read_balance(conf_t *conf, r1
>>  slot = 0;
>>  disk = r10_bio->devs[slot].devnum;
>>  
>> - while (!conf->mirrors[disk].rdev ||
>> + while (!rcu_dereference(conf->mirrors[disk].rdev) ||
>>         !conf->mirrors[disk].rdev->in_sync) {
>>  slot++;
>>  if (slot == conf->copies) {
>> @@ -527,7 +527,7 @@ static int read_balance(conf_t *conf, r1
>>  /* make sure the disk is operational */
>>  slot = 0;
>>  disk = r10_bio->devs[slot].devnum;
>> - while (!conf->mirrors[disk].rdev ||
>> + while (!rcu_dereference(conf->mirrors[disk].rdev) ||
>>         !conf->mirrors[disk].rdev->in_sync) {
>>  slot ++;
>>  if (slot == conf->copies) {
>> @@ -547,7 +547,7 @@ static int read_balance(conf_t *conf, r1
>>  int ndisk = r10_bio->devs[nslot].devnum;
>>  
>>  
>> - if (!conf->mirrors[ndisk].rdev ||
>> + if (!rcu_dereference(conf->mirrors[ndisk].rdev) ||
>>      !conf->mirrors[ndisk].rdev->in_sync)
>>  continue;
>>  
>> @@ -569,7 +569,7 @@ rb_out:
>>  r10_bio->read_slot = slot;
>>  /* conf->next_seq_sect = this_sector + sectors;*/
>>  
>> - if (disk >= 0 && conf->mirrors[disk].rdev)
>> + if (disk >= 0 && rcu_dereference(conf->mirrors[disk].rdev))
>>  atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
>>  rcu_read_unlock();
>>  
>> @@ -583,7 +583,7 @@ static void unplug_slaves(mddev_t *mddev
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks; i++) {
>> - mdk_rdev_t *rdev = conf->mirrors[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
>>  if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
>>  request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
>>  
>> @@ -614,7 +614,7 @@ static int raid10_issue_flush(request_qu
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks && ret == 0; i++) {
>> - mdk_rdev_t *rdev = conf->mirrors[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
>>  if (rdev && !rdev->faulty) {
>>  struct block_device *bdev = rdev->bdev;
>>  request_queue_t *r_queue = bdev_get_queue(bdev);
>> @@ -772,7 +772,7 @@ static int make_request(request_queue_t 
>>  rcu_read_lock();
>>  for (i = 0;  i < conf->copies; i++) {
>>  int d = r10_bio->devs[i].devnum;
>> - if (conf->mirrors[d].rdev &&
>> + if (rcu_dereference(conf->mirrors[d].rdev) &&
>>      !conf->mirrors[d].rdev->faulty) {
>>  atomic_inc(&conf->mirrors[d].rdev->nr_pending);
>>  r10_bio->devs[i].bio = bio;
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/raid1.c linux-2.6.14-rc4_patch/drivers/md/raid1.c
>> --- linux-2.6.14-rc4/drivers/md/raid1.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/raid1.c 2005-10-11 13:23:23.000000000 -0700
>> @@ -416,10 +416,10 @@ static int read_balance(conf_t *conf, r1
>>  /* Choose the first operation device, for consistancy */
>>  new_disk = 0;
>>  
>> - for (rdev = conf->mirrors[new_disk].rdev;
>> + for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
>>       !rdev || !rdev->in_sync
>>       || test_bit(WriteMostly, &rdev->flags);
>> -      rdev = conf->mirrors[++new_disk].rdev) {
>> +      rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) {
>>  
>>  if (rdev && rdev->in_sync)
>>  wonly_disk = new_disk;
>> @@ -434,10 +434,10 @@ static int read_balance(conf_t *conf, r1
>>  
>>  
>>  /* make sure the disk is operational */
>> - for (rdev = conf->mirrors[new_disk].rdev;
>> + for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
>>       !rdev || !rdev->in_sync ||
>>       test_bit(WriteMostly, &rdev->flags);
>> -      rdev = conf->mirrors[new_disk].rdev) {
>> +      rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) {  // increment new_disk? 
>>  
>>  if (rdev && rdev->in_sync)
>>  wonly_disk = new_disk;
>> @@ -474,7 +474,7 @@ static int read_balance(conf_t *conf, r1
>>  disk = conf->raid_disks;
>>  disk--;
>>  
>> - rdev = conf->mirrors[disk].rdev;
>> + rdev = rcu_dereference(conf->mirrors[disk].rdev);
>>  
>>  if (!rdev ||
>>      !rdev->in_sync ||
>> @@ -496,7 +496,7 @@ static int read_balance(conf_t *conf, r1
>>  
>>  
>>  if (new_disk >= 0) {
>> - rdev = conf->mirrors[new_disk].rdev;
>> + rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
>>  if (!rdev)
>>  goto retry;
>>  atomic_inc(&rdev->nr_pending);
>> @@ -522,7 +522,7 @@ static void unplug_slaves(mddev_t *mddev
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks; i++) {
>> - mdk_rdev_t *rdev = conf->mirrors[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
>>  if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
>>  request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
>>  
>> @@ -547,6 +547,7 @@ static void raid1_unplug(request_queue_t
>>  md_wakeup_thread(mddev->thread);
>>  }
>>  
>>  static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk,
>>       sector_t *error_sector)
>>  {
>> @@ -556,7 +557,7 @@ static int raid1_issue_flush(request_que
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks && ret == 0; i++) {
>> - mdk_rdev_t *rdev = conf->mirrors[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
>>  if (rdev && !rdev->faulty) {
>>  struct block_device *bdev = rdev->bdev;
>>  request_queue_t *r_queue = bdev_get_queue(bdev);
>> @@ -732,7 +733,7 @@ static int make_request(request_queue_t 
>>  #endif
>>  rcu_read_lock();
>>  for (i = 0;  i < disks; i++) {
>> - if ((rdev=conf->mirrors[i].rdev) != NULL &&
>> + if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL &&
>>      !rdev->faulty) {
>>  atomic_inc(&rdev->nr_pending);
>>  if (rdev->faulty) {
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/raid5.c linux-2.6.14-rc4_patch/drivers/md/raid5.c
>> --- linux-2.6.14-rc4/drivers/md/raid5.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/raid5.c 2005-10-11 13:27:27.000000000 -0700
>> @@ -1305,12 +1305,11 @@ static void handle_stripe(struct stripe_
>>  bi->bi_end_io = raid5_end_read_request;
>>   
>>  rcu_read_lock();
>> - rdev = conf->disks[i].rdev;
>> + rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && rdev->faulty)
>>  rdev = NULL;
>>  if (rdev)
>>  atomic_inc(&rdev->nr_pending);
>> - rcu_read_unlock();
>>   
>>  if (rdev) {
>>  if (test_bit(R5_Syncio, &sh->dev[i].flags))
>> @@ -1339,6 +1338,7 @@ static void handle_stripe(struct stripe_
>>  clear_bit(R5_LOCKED, &sh->dev[i].flags);
>>  set_bit(STRIPE_HANDLE, &sh->state);
>>  }
>> + rcu_read_unlock();
>>  }
>>  }
>>  
>> @@ -1379,7 +1379,7 @@ static void unplug_slaves(mddev_t *mddev
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks; i++) {
>> - mdk_rdev_t *rdev = conf->disks[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
>>  request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
>>  
>> @@ -1424,7 +1424,7 @@ static int raid5_issue_flush(request_que
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks && ret == 0; i++) {
>> - mdk_rdev_t *rdev = conf->disks[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && !rdev->faulty) {
>>  struct block_device *bdev = rdev->bdev;
>>  request_queue_t *r_queue = bdev_get_queue(bdev);
>> diff -urpNa -X dontdiff linux-2.6.14-rc4/drivers/md/raid6main.c linux-2.6.14-rc4_patch/drivers/md/raid6main.c
>> --- linux-2.6.14-rc4/drivers/md/raid6main.c 2005-10-10 18:19:19.000000000 -0700
>> +++ linux-2.6.14-rc4_patch/drivers/md/raid6main.c 2005-10-11 13:29:08.000000000 -0700
>> @@ -1464,7 +1464,7 @@ static void handle_stripe(struct stripe_
>>  bi->bi_end_io = raid6_end_read_request;
>>  
>>  rcu_read_lock();
>> - rdev = conf->disks[i].rdev;
>> + rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && rdev->faulty)
>>  rdev = NULL;
>>  if (rdev)
>> @@ -1538,7 +1538,7 @@ static void unplug_slaves(mddev_t *mddev
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks; i++) {
>> - mdk_rdev_t *rdev = conf->disks[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
>>  request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
>>  
>> @@ -1583,7 +1583,7 @@ static int raid6_issue_flush(request_que
>>  
>>  rcu_read_lock();
>>  for (i=0; i<mddev->raid_disks && ret == 0; i++) {
>> - mdk_rdev_t *rdev = conf->disks[i].rdev;
>> + mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
>>  if (rdev && !rdev->faulty) {
>>  struct block_device *bdev = rdev->bdev;
>>  request_queue_t *r_queue = bdev_get_queue(bdev);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

[Index of Archives]     [Kernel Newbies]     [Netfilter]     [Bugtraq]     [Photo]     [Stuff]     [Gimp]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Video 4 Linux]     [Linux for the blind]     [Linux Resources]
  Powered by Linux