Linux Headquarters
[ Register ]
[ About us ] [ Home Page ]

Advertisement
[ Kernel ] [ Documentation ] [ Links ] [ Books ]

Kernel v2.6.26-rc3 /drivers/md/raid10.c

Filename:/drivers/md/raid10.c
Lines Added:31
Lines Deleted:6
Also changed in: (Previous) 2.6.26-rc2-git5  2.6.26-rc2-git4  2.6.26-rc2  2.6.26-rc1-git9  2.6.26-rc1-git8  2.6.26-rc1-git7 
(Following) 2.6.26-rc3-git7  2.6.26-rc3-git8  2.6.26-rc4  2.6.26-rc5  2.6.26-rc6  2.6.26-rc7 

Location
[  2.6.26-rc3
  [  drivers
    [  md
       o  raid10.c

Patch

diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 32389d2..8536ede 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -790,6 +790,7 @@ static int make_request(struct request_queue *q, struct bio * bio)
    const int do_sync = bio_sync(bio);
    struct bio_list bl;
    unsigned long flags;
+   mdk_rdev_t *blocked_rdev;
 
    if (unlikely(bio_barrier(bio))) {
       bio_endio(bio, -EOPNOTSUPP);
@@ -879,17 +880,23 @@ static int make_request(struct request_queue *q, struct bio * bio)
    /*
     * WRITE:
     */
-   /* first select target devices under spinlock and
+   /* first select target devices under rcu_lock and
     * inc refcount on their rdev.  Record them by setting
     * bios[x] to bio
     */
    raid10_find_phys(conf, r10_bio);
+ retry_write:
+   blocked_rdev = NULL;
    rcu_read_lock();
    for (i = 0;  i < conf->copies; i++) {
       int d = r10_bio->devs[i].devnum;
       mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev);
-      if (rdev &&
-          !test_bit(Faulty, &rdev->flags)) {
+      if (rdev && unlikely(test_bit(Blocked, &rdev->flags))) {
+         atomic_inc(&rdev->nr_pending);
+         blocked_rdev = rdev;
+         break;
+      }
+      if (rdev && !test_bit(Faulty, &rdev->flags)) {
          atomic_inc(&rdev->nr_pending);
          r10_bio->devs[i].bio = bio;
       } else {
@@ -899,6 +906,22 @@ static int make_request(struct request_queue *q, struct bio * bio)
    }
    rcu_read_unlock();
 
+   if (unlikely(blocked_rdev)) {
+      /* Have to wait for this device to get unblocked, then retry */
+      int j;
+      int d;
+
+      for (j = 0; j < i; j++)
+         if (r10_bio->devs[j].bio) {
+            d = r10_bio->devs[j].devnum;
+            rdev_dec_pending(conf->mirrors[d].rdev, mddev);
+         }
+      allow_barrier(conf);
+      md_wait_for_blocked_rdev(blocked_rdev, mddev);
+      wait_barrier(conf);
+      goto retry_write;
+   }
+
    atomic_set(&r10_bio->remaining, 0);
 
    bio_list_init(&bl);
@@ -1001,8 +1024,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
    }
    set_bit(Faulty, &rdev->flags);
    set_bit(MD_CHANGE_DEVS, &mddev->flags);
-   printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n"
-      "   Operation continuing on %d devices\n",
+   printk(KERN_ALERT "raid10: Disk failure on %s, disabling device.\n"
+      "raid10: Operation continuing on %d devices.\n",
       bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded);
 }
 
@@ -2059,6 +2082,9 @@ static int run(mddev_t *mddev)
       goto out_free_conf;
    }
 
+   spin_lock_init(&conf->device_lock);
+   mddev->queue->queue_lock = &conf->device_lock;
+
    rdev_for_each(rdev, tmp, mddev) {
       disk_idx = rdev->raid_disk;
       if (disk_idx >= mddev->raid_disks
@@ -2080,7 +2106,6 @@ static int run(mddev_t *mddev)
 
       disk->head_position = 0;
    }
-   spin_lock_init(&conf->device_lock);
    INIT_LIST_HEAD(&conf->retry_list);
 
    spin_lock_init(&conf->resync_lock);


Comments: webmaster (at) linuxhq.com.
Advertising: banners (at) linuxhq.com.
Compilation ©1998-2008 Linux Headquarters, Inc.