vserver 2.0 rc7
[linux-2.6.git] / drivers / md / raid6main.c
index ac9420f..908edd7 100644 (file)
@@ -1652,6 +1652,15 @@ static int sync_request (mddev_t *mddev, sector_t sector_nr, int go_faster)
                unplug_slaves(mddev);
                return 0;
        }
+       /* if there are 2 or more failed drives and we are trying
+        * to resync, then assert that we are finished, because there is
+        * nothing we can do.
+        */
+       if (mddev->degraded >= 2 && test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
+               int rv = (mddev->size << 1) - sector_nr;
+               md_done_sync(mddev, rv, 1);
+               return rv;
+       }
 
        x = sector_nr;
        chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1770,9 +1779,6 @@ static int run (mddev_t *mddev)
        atomic_set(&conf->active_stripes, 0);
        atomic_set(&conf->preread_active_stripes, 0);
 
-       mddev->queue->unplug_fn = raid6_unplug_device;
-       mddev->queue->issue_flush_fn = raid6_issue_flush;
-
        PRINTK("raid6: run(%s) called.\n", mdname(mddev));
 
        ITERATE_RDEV(mddev,rdev,tmp) {
@@ -1886,6 +1892,9 @@ static int run (mddev_t *mddev)
 
        /* Ok, everything is just fine now */
        mddev->array_size =  mddev->size * (mddev->raid_disks - 2);
+
+       mddev->queue->unplug_fn = raid6_unplug_device;
+       mddev->queue->issue_flush_fn = raid6_issue_flush;
        return 0;
 abort:
        if (conf) {
@@ -2029,7 +2038,7 @@ static int raid6_remove_disk(mddev_t *mddev, int number)
                        goto abort;
                }
                p->rdev = NULL;
-               synchronize_kernel();
+               synchronize_rcu();
                if (atomic_read(&rdev->nr_pending)) {
                        /* lost the race, try later */
                        err = -EBUSY;
@@ -2050,6 +2059,9 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
        int disk;
        struct disk_info *p;
 
+       if (mddev->degraded > 2)
+               /* no point adding a device */
+               return 0;
        /*
         * find the disk ...
         */