static void raid5_build_block (struct stripe_head *sh, int i);
 
-static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx)
+static void init_stripe(struct stripe_head *sh, sector_t sector, int pd_idx, int disks)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = conf->raid_disks, i;
+       int i;
 
        if (atomic_read(&sh->count) != 0)
                BUG();
        sh->pd_idx = pd_idx;
        sh->state = 0;
 
-       for (i=disks; i--; ) {
+       sh->disks = disks;
+
+       for (i = sh->disks; i--; ) {
                struct r5dev *dev = &sh->dev[i];
 
                if (dev->toread || dev->towrite || dev->written ||
        insert_hash(conf, sh);
 }
 
-static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector)
+static struct stripe_head *__find_stripe(raid5_conf_t *conf, sector_t sector, int disks)
 {
        struct stripe_head *sh;
        struct hlist_node *hn;
        CHECK_DEVLOCK();
        PRINTK("__find_stripe, sector %llu\n", (unsigned long long)sector);
        hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash)
-               if (sh->sector == sector)
+               if (sh->sector == sector && sh->disks == disks)
                        return sh;
        PRINTK("__stripe %llu not in cache\n", (unsigned long long)sector);
        return NULL;
 static void unplug_slaves(mddev_t *mddev);
 static void raid5_unplug_device(request_queue_t *q);
 
-static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector,
-                                            int pd_idx, int noblock) 
+static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector, int disks,
+                                            int pd_idx, int noblock)
 {
        struct stripe_head *sh;
 
                wait_event_lock_irq(conf->wait_for_stripe,
                                    conf->quiesce == 0,
                                    conf->device_lock, /* nothing */);
-               sh = __find_stripe(conf, sector);
+               sh = __find_stripe(conf, sector, disks);
                if (!sh) {
                        if (!conf->inactive_blocked)
                                sh = get_free_stripe(conf);
                                        );
                                conf->inactive_blocked = 0;
                        } else
-                               init_stripe(sh, sector, pd_idx);
+                               init_stripe(sh, sector, pd_idx, disks);
                } else {
                        if (atomic_read(&sh->count)) {
                                if (!list_empty(&sh->lru))
                kmem_cache_free(conf->slab_cache, sh);
                return 0;
        }
+       sh->disks = conf->raid_disks;
        /* we just created an active stripe so... */
        atomic_set(&sh->count, 1);
        atomic_inc(&conf->active_stripes);
 {
        struct stripe_head *sh = bi->bi_private;
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = conf->raid_disks, i;
+       int disks = sh->disks, i;
        int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 
        if (bi->bi_size)
 {
        struct stripe_head *sh = bi->bi_private;
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = conf->raid_disks, i;
+       int disks = sh->disks, i;
        unsigned long flags;
        int uptodate = test_bit(BIO_UPTODATE, &bi->bi_flags);
 
 static sector_t compute_blocknr(struct stripe_head *sh, int i)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int raid_disks = conf->raid_disks, data_disks = raid_disks - 1;
+       int raid_disks = sh->disks, data_disks = raid_disks - 1;
        sector_t new_sector = sh->sector, check;
        int sectors_per_chunk = conf->chunk_size >> 9;
        sector_t stripe;
 
 static void compute_block(struct stripe_head *sh, int dd_idx)
 {
-       raid5_conf_t *conf = sh->raid_conf;
-       int i, count, disks = conf->raid_disks;
+       int i, count, disks = sh->disks;
        void *ptr[MAX_XOR_BLOCKS], *p;
 
        PRINTK("compute_block, stripe %llu, idx %d\n", 
 static void compute_parity(struct stripe_head *sh, int method)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count;
+       int i, pd_idx = sh->pd_idx, disks = sh->disks, count;
        void *ptr[MAX_XOR_BLOCKS];
        struct bio *chosen;
 
 static void handle_stripe(struct stripe_head *sh)
 {
        raid5_conf_t *conf = sh->raid_conf;
-       int disks = conf->raid_disks;
+       int disks = sh->disks;
        struct bio *return_bi= NULL;
        struct bio *bi;
        int i;
        spin_unlock_irq(&conf->device_lock);
 }
 
-static int make_request (request_queue_t *q, struct bio * bi)
+static int make_request(request_queue_t *q, struct bio * bi)
 {
        mddev_t *mddev = q->queuedata;
        raid5_conf_t *conf = mddev_to_conf(mddev);
-       const unsigned int raid_disks = conf->raid_disks;
-       const unsigned int data_disks = raid_disks - 1;
        unsigned int dd_idx, pd_idx;
        sector_t new_sector;
        sector_t logical_sector, last_sector;
 
        for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
                DEFINE_WAIT(w);
+               int disks;
                
-               new_sector = raid5_compute_sector(logical_sector,
-                                                 raid_disks, data_disks, &dd_idx, &pd_idx, conf);
-
+       retry:
+               if (likely(conf->expand_progress == MaxSector))
+                       disks = conf->raid_disks;
+               else {
+                       spin_lock_irq(&conf->device_lock);
+                       disks = conf->raid_disks;
+                       if (logical_sector >= conf->expand_progress)
+                               disks = conf->previous_raid_disks;
+                       spin_unlock_irq(&conf->device_lock);
+               }
+               new_sector = raid5_compute_sector(logical_sector, disks, disks - 1,
+                                                 &dd_idx, &pd_idx, conf);
                PRINTK("raid5: make_request, sector %llu logical %llu\n",
                        (unsigned long long)new_sector, 
                        (unsigned long long)logical_sector);
 
-       retry:
                prepare_to_wait(&conf->wait_for_overlap, &w, TASK_UNINTERRUPTIBLE);
-               sh = get_active_stripe(conf, new_sector, pd_idx, (bi->bi_rw&RWA_MASK));
+               sh = get_active_stripe(conf, new_sector, disks, pd_idx, (bi->bi_rw&RWA_MASK));
                if (sh) {
-                       if (!add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
-                               /* Add failed due to overlap.  Flush everything
+                       if (unlikely(conf->expand_progress != MaxSector)) {
+                               /* expansion might have moved on while waiting for a
+                                * stripe, so we much do the range check again.
+                                */
+                               int must_retry = 0;
+                               spin_lock_irq(&conf->device_lock);
+                               if (logical_sector <  conf->expand_progress &&
+                                   disks == conf->previous_raid_disks)
+                                       /* mismatch, need to try again */
+                                       must_retry = 1;
+                               spin_unlock_irq(&conf->device_lock);
+                               if (must_retry) {
+                                       release_stripe(sh);
+                                       goto retry;
+                               }
+                       }
+
+                       if (test_bit(STRIPE_EXPANDING, &sh->state) ||
+                           !add_stripe_bio(sh, bi, dd_idx, (bi->bi_rw&RW_MASK))) {
+                               /* Stripe is busy expanding or
+                                * add failed due to overlap.  Flush everything
                                 * and wait a while
                                 */
                                raid5_unplug_device(mddev->queue);
                        raid5_plug_device(conf);
                        handle_stripe(sh);
                        release_stripe(sh);
-
                } else {
                        /* cannot get stripe for read-ahead, just give-up */
                        clear_bit(BIO_UPTODATE, &bi->bi_flags);
 
        first_sector = raid5_compute_sector((sector_t)stripe*data_disks*sectors_per_chunk
                + chunk_offset, raid_disks, data_disks, &dd_idx, &pd_idx, conf);
-       sh = get_active_stripe(conf, sector_nr, pd_idx, 1);
+       sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 1);
        if (sh == NULL) {
-               sh = get_active_stripe(conf, sector_nr, pd_idx, 0);
+               sh = get_active_stripe(conf, sector_nr, raid_disks, pd_idx, 0);
                /* make sure we don't swamp the stripe cache if someone else
                 * is trying to get access 
                 */
        conf->level = mddev->level;
        conf->algorithm = mddev->layout;
        conf->max_nr_stripes = NR_STRIPES;
+       conf->expand_progress = MaxSector;
 
        /* device size must be a multiple of chunk size */
        mddev->size &= ~(mddev->chunk_size/1024 -1);
        printk("sh %llu,  count %d.\n",
                (unsigned long long)sh->sector, atomic_read(&sh->count));
        printk("sh %llu, ", (unsigned long long)sh->sector);
-       for (i = 0; i < sh->raid_conf->raid_disks; i++) {
+       for (i = 0; i < sh->disks; i++) {
                printk("(cache%d: %p %ld) ", 
                        i, sh->dev[i].page, sh->dev[i].flags);
        }