Remove multiple KERN_ prefixes from printk formats
[linux-2.6.git] / drivers / md / md.c
index 8350bde..d4351ff 100644 (file)
@@ -440,15 +440,6 @@ static inline sector_t calc_dev_sboffset(struct block_device *bdev)
        return MD_NEW_SIZE_SECTORS(num_sectors);
 }
 
-static sector_t calc_num_sectors(mdk_rdev_t *rdev, unsigned chunk_size)
-{
-       sector_t num_sectors = rdev->sb_start;
-
-       if (chunk_size)
-               num_sectors &= ~((sector_t)chunk_size/512 - 1);
-       return num_sectors;
-}
-
 static int alloc_disk_sb(mdk_rdev_t * rdev)
 {
        if (rdev->sb_page)
@@ -745,6 +736,24 @@ struct super_type  {
 };
 
 /*
+ * Check that the given mddev has no bitmap.
+ *
+ * This function is called from the run method of all personalities that do not
+ * support bitmaps. It prints an error message and returns non-zero if mddev
+ * has a bitmap. Otherwise, it returns 0.
+ *
+ */
+int md_check_no_bitmap(mddev_t *mddev)
+{
+       if (!mddev->bitmap_file && !mddev->bitmap_offset)
+               return 0;
+       printk(KERN_ERR "%s: bitmaps are not supported for %s\n",
+               mdname(mddev), mddev->pers->name);
+       return 1;
+}
+EXPORT_SYMBOL(md_check_no_bitmap);
+
+/*
  * load_super for 0.90.0 
  */
 static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
@@ -797,17 +806,6 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
        rdev->data_offset = 0;
        rdev->sb_size = MD_SB_BYTES;
 
-       if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
-               if (sb->level != 1 && sb->level != 4
-                   && sb->level != 5 && sb->level != 6
-                   && sb->level != 10) {
-                       /* FIXME use a better test */
-                       printk(KERN_WARNING
-                              "md: bitmaps not supported for this level.\n");
-                       goto abort;
-               }
-       }
-
        if (sb->level == LEVEL_MULTIPATH)
                rdev->desc_nr = -1;
        else
@@ -836,7 +834,7 @@ static int super_90_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version
                else 
                        ret = 0;
        }
-       rdev->sectors = calc_num_sectors(rdev, sb->chunk_size);
+       rdev->sectors = rdev->sb_start;
 
        if (rdev->sectors < sb->size * 2 && sb->level > 1)
                /* "this cannot possibly happen" ... */
@@ -866,7 +864,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->minor_version = sb->minor_version;
                mddev->patch_version = sb->patch_version;
                mddev->external = 0;
-               mddev->chunk_size = sb->chunk_size;
+               mddev->chunk_sectors = sb->chunk_size >> 9;
                mddev->ctime = sb->ctime;
                mddev->utime = sb->utime;
                mddev->level = sb->level;
@@ -883,13 +881,13 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        mddev->delta_disks = sb->delta_disks;
                        mddev->new_level = sb->new_level;
                        mddev->new_layout = sb->new_layout;
-                       mddev->new_chunk = sb->new_chunk;
+                       mddev->new_chunk_sectors = sb->new_chunk >> 9;
                } else {
                        mddev->reshape_position = MaxSector;
                        mddev->delta_disks = 0;
                        mddev->new_level = mddev->level;
                        mddev->new_layout = mddev->layout;
-                       mddev->new_chunk = mddev->chunk_size;
+                       mddev->new_chunk_sectors = mddev->chunk_sectors;
                }
 
                if (sb->state & (1<<MD_SB_CLEAN))
@@ -1004,7 +1002,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                sb->new_level = mddev->new_level;
                sb->delta_disks = mddev->delta_disks;
                sb->new_layout = mddev->new_layout;
-               sb->new_chunk = mddev->new_chunk;
+               sb->new_chunk = mddev->new_chunk_sectors << 9;
        }
        mddev->minor_version = sb->minor_version;
        if (mddev->in_sync)
@@ -1018,7 +1016,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                sb->recovery_cp = 0;
 
        sb->layout = mddev->layout;
-       sb->chunk_size = mddev->chunk_size;
+       sb->chunk_size = mddev->chunk_sectors << 9;
 
        if (mddev->bitmap && mddev->bitmap_file == NULL)
                sb->state |= (1<<MD_SB_BITMAP_PRESENT);
@@ -1185,24 +1183,13 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
                       bdevname(rdev->bdev,b));
                return -EINVAL;
        }
-       if ((le32_to_cpu(sb->feature_map) & MD_FEATURE_BITMAP_OFFSET)) {
-               if (sb->level != cpu_to_le32(1) &&
-                   sb->level != cpu_to_le32(4) &&
-                   sb->level != cpu_to_le32(5) &&
-                   sb->level != cpu_to_le32(6) &&
-                   sb->level != cpu_to_le32(10)) {
-                       printk(KERN_WARNING
-                              "md: bitmaps not supported for this level.\n");
-                       return -EINVAL;
-               }
-       }
 
        rdev->preferred_minor = 0xffff;
        rdev->data_offset = le64_to_cpu(sb->data_offset);
        atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read));
 
        rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
-       bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1;
+       bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1;
        if (rdev->sb_size & bmask)
                rdev->sb_size = (rdev->sb_size | bmask) + 1;
 
@@ -1248,9 +1235,6 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version)
        if (rdev->sectors < le64_to_cpu(sb->data_size))
                return -EINVAL;
        rdev->sectors = le64_to_cpu(sb->data_size);
-       if (le32_to_cpu(sb->chunksize))
-               rdev->sectors &= ~((sector_t)le32_to_cpu(sb->chunksize) - 1);
-
        if (le64_to_cpu(sb->size) > rdev->sectors)
                return -EINVAL;
        return ret;
@@ -1271,7 +1255,7 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                mddev->major_version = 1;
                mddev->patch_version = 0;
                mddev->external = 0;
-               mddev->chunk_size = le32_to_cpu(sb->chunksize) << 9;
+               mddev->chunk_sectors = le32_to_cpu(sb->chunksize);
                mddev->ctime = le64_to_cpu(sb->ctime) & ((1ULL << 32)-1);
                mddev->utime = le64_to_cpu(sb->utime) & ((1ULL << 32)-1);
                mddev->level = le32_to_cpu(sb->level);
@@ -1297,13 +1281,13 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev)
                        mddev->delta_disks = le32_to_cpu(sb->delta_disks);
                        mddev->new_level = le32_to_cpu(sb->new_level);
                        mddev->new_layout = le32_to_cpu(sb->new_layout);
-                       mddev->new_chunk = le32_to_cpu(sb->new_chunk)<<9;
+                       mddev->new_chunk_sectors = le32_to_cpu(sb->new_chunk);
                } else {
                        mddev->reshape_position = MaxSector;
                        mddev->delta_disks = 0;
                        mddev->new_level = mddev->level;
                        mddev->new_layout = mddev->layout;
-                       mddev->new_chunk = mddev->chunk_size;
+                       mddev->new_chunk_sectors = mddev->chunk_sectors;
                }
 
        } else if (mddev->pers == NULL) {
@@ -1375,6 +1359,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
 
        sb->raid_disks = cpu_to_le32(mddev->raid_disks);
        sb->size = cpu_to_le64(mddev->dev_sectors);
+       sb->chunksize = cpu_to_le32(mddev->chunk_sectors);
+       sb->level = cpu_to_le32(mddev->level);
+       sb->layout = cpu_to_le32(mddev->layout);
 
        if (mddev->bitmap && mddev->bitmap_file == NULL) {
                sb->bitmap_offset = cpu_to_le32((__u32)mddev->bitmap_offset);
@@ -1399,7 +1386,7 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev)
                sb->new_layout = cpu_to_le32(mddev->new_layout);
                sb->delta_disks = cpu_to_le32(mddev->delta_disks);
                sb->new_level = cpu_to_le32(mddev->new_level);
-               sb->new_chunk = cpu_to_le32(mddev->new_chunk>>9);
+               sb->new_chunk = cpu_to_le32(mddev->new_chunk_sectors);
        }
 
        max_dev = 0;
@@ -1769,9 +1756,10 @@ static void print_sb_1(struct mdp_superblock_1 *sb)
        __u8 *uuid;
 
        uuid = sb->set_uuid;
-       printk(KERN_INFO "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
-                       ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
-              KERN_INFO "md:    Name: \"%s\" CT:%llu\n",
+       printk(KERN_INFO
+              "md:  SB: (V:%u) (F:0x%08x) Array-ID:<%02x%02x%02x%02x"
+              ":%02x%02x:%02x%02x:%02x%02x:%02x%02x%02x%02x%02x%02x>\n"
+              "md:    Name: \"%s\" CT:%llu\n",
                le32_to_cpu(sb->major_version),
                le32_to_cpu(sb->feature_map),
                uuid[0], uuid[1], uuid[2], uuid[3],
@@ -1783,12 +1771,13 @@ static void print_sb_1(struct mdp_superblock_1 *sb)
                       & MD_SUPERBLOCK_1_TIME_SEC_MASK);
 
        uuid = sb->device_uuid;
-       printk(KERN_INFO "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
+       printk(KERN_INFO
+              "md:       L%u SZ%llu RD:%u LO:%u CS:%u DO:%llu DS:%llu SO:%llu"
                        " RO:%llu\n"
-              KERN_INFO "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
-                       ":%02x%02x%02x%02x%02x%02x\n"
-              KERN_INFO "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
-              KERN_INFO "md:         (MaxDev:%u) \n",
+              "md:     Dev:%08x UUID: %02x%02x%02x%02x:%02x%02x:%02x%02x:%02x%02x"
+                       ":%02x%02x%02x%02x%02x%02x\n"
+              "md:       (F:0x%08x) UT:%llu Events:%llu ResyncOffset:%llu CSUM:0x%08x\n"
+              "md:         (MaxDev:%u) \n",
                le32_to_cpu(sb->level),
                (unsigned long long)le64_to_cpu(sb->size),
                le32_to_cpu(sb->raid_disks),
@@ -1894,6 +1883,7 @@ static void md_update_sb(mddev_t * mddev, int force_change)
        int sync_req;
        int nospares = 0;
 
+       mddev->utime = get_seconds();
        if (mddev->external)
                return;
 repeat:
@@ -1923,7 +1913,6 @@ repeat:
                nospares = 0;
 
        sync_req = mddev->in_sync;
-       mddev->utime = get_seconds();
 
        /* If this is just a dirty<->clean transition, and the array is clean
         * and 'events' is odd, we can roll back to the previous clean state */
@@ -2594,15 +2583,6 @@ static void analyze_sbs(mddev_t * mddev)
                        clear_bit(In_sync, &rdev->flags);
                }
        }
-
-
-
-       if (mddev->recovery_cp != MaxSector &&
-           mddev->level >= 1)
-               printk(KERN_ERR "md: %s: raid array is not clean"
-                      " -- starting background reconstruction\n",
-                      mdname(mddev));
-
 }
 
 static void md_safemode_timeout(unsigned long data);
@@ -2743,7 +2723,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        if (IS_ERR(priv)) {
                mddev->new_level = mddev->level;
                mddev->new_layout = mddev->layout;
-               mddev->new_chunk = mddev->chunk_size;
+               mddev->new_chunk_sectors = mddev->chunk_sectors;
                mddev->raid_disks -= mddev->delta_disks;
                mddev->delta_disks = 0;
                module_put(pers->owner);
@@ -2761,7 +2741,7 @@ level_store(mddev_t *mddev, const char *buf, size_t len)
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
        mddev->level = mddev->new_level;
        mddev->layout = mddev->new_layout;
-       mddev->chunk_size = mddev->new_chunk;
+       mddev->chunk_sectors = mddev->new_chunk_sectors;
        mddev->delta_disks = 0;
        pers->run(mddev);
        mddev_resume(mddev);
@@ -2797,11 +2777,14 @@ layout_store(mddev_t *mddev, const char *buf, size_t len)
 
        if (mddev->pers) {
                int err;
-               if (mddev->pers->reconfig == NULL)
+               if (mddev->pers->check_reshape == NULL)
                        return -EBUSY;
-               err = mddev->pers->reconfig(mddev, n, -1);
-               if (err)
+               mddev->new_layout = n;
+               err = mddev->pers->check_reshape(mddev);
+               if (err) {
+                       mddev->new_layout = mddev->layout;
                        return err;
+               }
        } else {
                mddev->new_layout = n;
                if (mddev->reshape_position == MaxSector)
@@ -2854,10 +2837,11 @@ static ssize_t
 chunk_size_show(mddev_t *mddev, char *page)
 {
        if (mddev->reshape_position != MaxSector &&
-           mddev->chunk_size != mddev->new_chunk)
-               return sprintf(page, "%d (%d)\n", mddev->new_chunk,
-                              mddev->chunk_size);
-       return sprintf(page, "%d\n", mddev->chunk_size);
+           mddev->chunk_sectors != mddev->new_chunk_sectors)
+               return sprintf(page, "%d (%d)\n",
+                              mddev->new_chunk_sectors << 9,
+                              mddev->chunk_sectors << 9);
+       return sprintf(page, "%d\n", mddev->chunk_sectors << 9);
 }
 
 static ssize_t
@@ -2871,15 +2855,18 @@ chunk_size_store(mddev_t *mddev, const char *buf, size_t len)
 
        if (mddev->pers) {
                int err;
-               if (mddev->pers->reconfig == NULL)
+               if (mddev->pers->check_reshape == NULL)
                        return -EBUSY;
-               err = mddev->pers->reconfig(mddev, -1, n);
-               if (err)
+               mddev->new_chunk_sectors = n >> 9;
+               err = mddev->pers->check_reshape(mddev);
+               if (err) {
+                       mddev->new_chunk_sectors = mddev->chunk_sectors;
                        return err;
+               }
        } else {
-               mddev->new_chunk = n;
+               mddev->new_chunk_sectors = n >> 9;
                if (mddev->reshape_position == MaxSector)
-                       mddev->chunk_size = n;
+                       mddev->chunk_sectors = n >> 9;
        }
        return len;
 }
@@ -3066,11 +3053,8 @@ array_state_store(mddev_t *mddev, const char *buf, size_t len)
                        } else
                                err = -EBUSY;
                        spin_unlock_irq(&mddev->write_lock);
-               } else {
-                       mddev->ro = 0;
-                       mddev->recovery_cp = MaxSector;
-                       err = do_md_run(mddev);
-               }
+               } else
+                       err = -EINVAL;
                break;
        case active:
                if (mddev->pers) {
@@ -3306,7 +3290,9 @@ static ssize_t
 action_show(mddev_t *mddev, char *page)
 {
        char *type = "idle";
-       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
+       if (test_bit(MD_RECOVERY_FROZEN, &mddev->recovery))
+               type = "frozen";
+       else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
            (!mddev->ro && test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))) {
                if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
                        type = "reshape";
@@ -3329,7 +3315,12 @@ action_store(mddev_t *mddev, const char *page, size_t len)
        if (!mddev->pers || !mddev->pers->sync_request)
                return -EINVAL;
 
-       if (cmd_match(page, "idle")) {
+       if (cmd_match(page, "frozen"))
+               set_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+       else
+               clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+
+       if (cmd_match(page, "idle") || cmd_match(page, "frozen")) {
                if (mddev->sync_thread) {
                        set_bit(MD_RECOVERY_INTR, &mddev->recovery);
                        md_unregister_thread(mddev->sync_thread);
@@ -3520,8 +3511,9 @@ min_sync_store(mddev_t *mddev, const char *buf, size_t len)
                return -EBUSY;
 
        /* Must be a multiple of chunk_size */
-       if (mddev->chunk_size) {
-               if (min & (sector_t)((mddev->chunk_size>>9)-1))
+       if (mddev->chunk_sectors) {
+               sector_t temp = min;
+               if (sector_div(temp, mddev->chunk_sectors))
                        return -EINVAL;
        }
        mddev->resync_min = min;
@@ -3557,8 +3549,9 @@ max_sync_store(mddev_t *mddev, const char *buf, size_t len)
                        return -EBUSY;
 
                /* Must be a multiple of chunk_size */
-               if (mddev->chunk_size) {
-                       if (max & (sector_t)((mddev->chunk_size>>9)-1))
+               if (mddev->chunk_sectors) {
+                       sector_t temp = max;
+                       if (sector_div(temp, mddev->chunk_sectors))
                                return -EINVAL;
                }
                mddev->resync_max = max;
@@ -3582,7 +3575,8 @@ suspend_lo_store(mddev_t *mddev, const char *buf, size_t len)
        char *e;
        unsigned long long new = simple_strtoull(buf, &e, 10);
 
-       if (mddev->pers->quiesce == NULL)
+       if (mddev->pers == NULL || 
+           mddev->pers->quiesce == NULL)
                return -EINVAL;
        if (buf == e || (*e && *e != '\n'))
                return -EINVAL;
@@ -3610,7 +3604,8 @@ suspend_hi_store(mddev_t *mddev, const char *buf, size_t len)
        char *e;
        unsigned long long new = simple_strtoull(buf, &e, 10);
 
-       if (mddev->pers->quiesce == NULL)
+       if (mddev->pers == NULL ||
+           mddev->pers->quiesce == NULL)
                return -EINVAL;
        if (buf == e || (*e && *e != '\n'))
                return -EINVAL;
@@ -3649,7 +3644,7 @@ reshape_position_store(mddev_t *mddev, const char *buf, size_t len)
        mddev->delta_disks = 0;
        mddev->new_level = mddev->level;
        mddev->new_layout = mddev->layout;
-       mddev->new_chunk = mddev->chunk_size;
+       mddev->new_chunk_sectors = mddev->chunk_sectors;
        return len;
 }
 
@@ -3683,7 +3678,7 @@ array_size_store(mddev_t *mddev, const char *buf, size_t len)
                if (strict_blocks_to_sectors(buf, &sectors) < 0)
                        return -EINVAL;
                if (mddev->pers && mddev->pers->size(mddev, 0, 0) < sectors)
-                       return -EINVAL;
+                       return -E2BIG;
 
                mddev->external_size = 1;
        }
@@ -3853,11 +3848,9 @@ static int md_alloc(dev_t dev, char *name)
        flush_scheduled_work();
 
        mutex_lock(&disks_mutex);
-       if (mddev->gendisk) {
-               mutex_unlock(&disks_mutex);
-               mddev_put(mddev);
-               return -EEXIST;
-       }
+       error = -EEXIST;
+       if (mddev->gendisk)
+               goto abort;
 
        if (name) {
                /* Need to ensure that 'name' is not a duplicate.
@@ -3869,17 +3862,15 @@ static int md_alloc(dev_t dev, char *name)
                        if (mddev2->gendisk &&
                            strcmp(mddev2->gendisk->disk_name, name) == 0) {
                                spin_unlock(&all_mddevs_lock);
-                               return -EEXIST;
+                               goto abort;
                        }
                spin_unlock(&all_mddevs_lock);
        }
 
+       error = -ENOMEM;
        mddev->queue = blk_alloc_queue(GFP_KERNEL);
-       if (!mddev->queue) {
-               mutex_unlock(&disks_mutex);
-               mddev_put(mddev);
-               return -ENOMEM;
-       }
+       if (!mddev->queue)
+               goto abort;
        mddev->queue->queuedata = mddev;
 
        /* Can be unlocked because the queue is new: no concurrency */
@@ -3889,11 +3880,9 @@ static int md_alloc(dev_t dev, char *name)
 
        disk = alloc_disk(1 << shift);
        if (!disk) {
-               mutex_unlock(&disks_mutex);
                blk_cleanup_queue(mddev->queue);
                mddev->queue = NULL;
-               mddev_put(mddev);
-               return -ENOMEM;
+               goto abort;
        }
        disk->major = MAJOR(mddev->unit);
        disk->first_minor = unit << shift;
@@ -3915,16 +3904,22 @@ static int md_alloc(dev_t dev, char *name)
        mddev->gendisk = disk;
        error = kobject_init_and_add(&mddev->kobj, &md_ktype,
                                     &disk_to_dev(disk)->kobj, "%s", "md");
-       mutex_unlock(&disks_mutex);
-       if (error)
+       if (error) {
+               /* This isn't possible, but as kobject_init_and_add is marked
+                * __must_check, we must do something with the result
+                */
                printk(KERN_WARNING "md: cannot register %s/md - name in use\n",
                       disk->disk_name);
-       else {
+               error = 0;
+       }
+ abort:
+       mutex_unlock(&disks_mutex);
+       if (!error) {
                kobject_uevent(&mddev->kobj, KOBJ_ADD);
                mddev->sysfs_state = sysfs_get_dirent(mddev->kobj.sd, "array_state");
        }
        mddev_put(mddev);
-       return 0;
+       return error;
 }
 
 static struct kobject *md_probe(dev_t dev, int *part, void *data)
@@ -3969,11 +3964,9 @@ static int start_dirty_degraded;
 static int do_md_run(mddev_t * mddev)
 {
        int err;
-       int chunk_size;
        mdk_rdev_t *rdev;
        struct gendisk *disk;
        struct mdk_personality *pers;
-       char b[BDEVNAME_SIZE];
 
        if (list_empty(&mddev->disks))
                /* cannot run an array with no devices.. */
@@ -3991,38 +3984,6 @@ static int do_md_run(mddev_t * mddev)
                analyze_sbs(mddev);
        }
 
-       chunk_size = mddev->chunk_size;
-
-       if (chunk_size) {
-               if (chunk_size > MAX_CHUNK_SIZE) {
-                       printk(KERN_ERR "too big chunk_size: %d > %d\n",
-                               chunk_size, MAX_CHUNK_SIZE);
-                       return -EINVAL;
-               }
-               /*
-                * chunk-size has to be a power of 2
-                */
-               if ( (1 << ffz(~chunk_size)) != chunk_size) {
-                       printk(KERN_ERR "chunk_size of %d not valid\n", chunk_size);
-                       return -EINVAL;
-               }
-
-               /* devices must have minimum size of one chunk */
-               list_for_each_entry(rdev, &mddev->disks, same_set) {
-                       if (test_bit(Faulty, &rdev->flags))
-                               continue;
-                       if (rdev->sectors < chunk_size / 512) {
-                               printk(KERN_WARNING
-                                       "md: Dev %s smaller than chunk_size:"
-                                       " %llu < %d\n",
-                                       bdevname(rdev->bdev,b),
-                                       (unsigned long long)rdev->sectors,
-                                       chunk_size / 512);
-                               return -EINVAL;
-                       }
-               }
-       }
-
        if (mddev->level != LEVEL_NONE)
                request_module("md-level-%d", mddev->level);
        else if (mddev->clevel[0])
@@ -4297,6 +4258,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
 {
        int err = 0;
        struct gendisk *disk = mddev->gendisk;
+       mdk_rdev_t *rdev;
 
        if (atomic_read(&mddev->openers) > is_open) {
                printk("md: %s still in use.\n",mdname(mddev));
@@ -4339,6 +4301,13 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                        /* tell userspace to handle 'inactive' */
                        sysfs_notify_dirent(mddev->sysfs_state);
 
+                       list_for_each_entry(rdev, &mddev->disks, same_set)
+                               if (rdev->raid_disk >= 0) {
+                                       char nm[20];
+                                       sprintf(nm, "rd%d", rdev->raid_disk);
+                                       sysfs_remove_link(&mddev->kobj, nm);
+                               }
+
                        set_capacity(disk, 0);
                        mddev->changed = 1;
 
@@ -4359,7 +4328,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
         * Free resources if final stop
         */
        if (mode == 0) {
-               mdk_rdev_t *rdev;
 
                printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
 
@@ -4371,13 +4339,6 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                }
                mddev->bitmap_offset = 0;
 
-               list_for_each_entry(rdev, &mddev->disks, same_set)
-                       if (rdev->raid_disk >= 0) {
-                               char nm[20];
-                               sprintf(nm, "rd%d", rdev->raid_disk);
-                               sysfs_remove_link(&mddev->kobj, nm);
-                       }
-
                /* make sure all md_delayed_delete calls have finished */
                flush_scheduled_work();
 
@@ -4398,7 +4359,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                mddev->flags = 0;
                mddev->ro = 0;
                mddev->metadata_type[0] = 0;
-               mddev->chunk_size = 0;
+               mddev->chunk_sectors = 0;
                mddev->ctime = mddev->utime = 0;
                mddev->layout = 0;
                mddev->max_disks = 0;
@@ -4406,7 +4367,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                mddev->delta_disks = 0;
                mddev->new_level = LEVEL_NONE;
                mddev->new_layout = 0;
-               mddev->new_chunk = 0;
+               mddev->new_chunk_sectors = 0;
                mddev->curr_resync = 0;
                mddev->resync_mismatches = 0;
                mddev->suspend_lo = mddev->suspend_hi = 0;
@@ -4611,7 +4572,7 @@ static int get_array_info(mddev_t * mddev, void __user * arg)
        info.spare_disks   = spare;
 
        info.layout        = mddev->layout;
-       info.chunk_size    = mddev->chunk_size;
+       info.chunk_size    = mddev->chunk_sectors << 9;
 
        if (copy_to_user(arg, &info, sizeof(info)))
                return -EFAULT;
@@ -4836,7 +4797,7 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info)
                        rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
                } else 
                        rdev->sb_start = calc_dev_sboffset(rdev->bdev);
-               rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
+               rdev->sectors = rdev->sb_start;
 
                err = bind_rdev_to_array(rdev, mddev);
                if (err) {
@@ -4906,7 +4867,7 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev)
        else
                rdev->sb_start = rdev->bdev->bd_inode->i_size / 512;
 
-       rdev->sectors = calc_num_sectors(rdev, mddev->chunk_size);
+       rdev->sectors = rdev->sb_start;
 
        if (test_bit(Faulty, &rdev->flags)) {
                printk(KERN_WARNING 
@@ -5055,7 +5016,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
        mddev->external      = 0;
 
        mddev->layout        = info->layout;
-       mddev->chunk_size    = info->chunk_size;
+       mddev->chunk_sectors = info->chunk_size >> 9;
 
        mddev->max_disks     = MD_SB_DISKS;
 
@@ -5074,7 +5035,7 @@ static int set_array_info(mddev_t * mddev, mdu_array_info_t *info)
        get_random_bytes(mddev->uuid, 16);
 
        mddev->new_level = mddev->level;
-       mddev->new_chunk = mddev->chunk_size;
+       mddev->new_chunk_sectors = mddev->chunk_sectors;
        mddev->new_layout = mddev->layout;
        mddev->delta_disks = 0;
 
@@ -5184,7 +5145,7 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
            mddev->level         != info->level         ||
 /*         mddev->layout        != info->layout        || */
            !mddev->persistent   != info->not_persistent||
-           mddev->chunk_size    != info->chunk_size    ||
+           mddev->chunk_sectors != info->chunk_size >> 9 ||
            /* ignore bottom 8 bits of state, and allow SB_BITMAP_PRESENT to change */
            ((state^info->state) & 0xfffffe00)
                )
@@ -5208,10 +5169,15 @@ static int update_array_info(mddev_t *mddev, mdu_array_info_t *info)
                 * we don't need to do anything at the md level, the
                 * personality will take care of it all.
                 */
-               if (mddev->pers->reconfig == NULL)
+               if (mddev->pers->check_reshape == NULL)
                        return -EINVAL;
-               else
-                       return mddev->pers->reconfig(mddev, info->layout, -1);
+               else {
+                       mddev->new_layout = info->layout;
+                       rv = mddev->pers->check_reshape(mddev);
+                       if (rv)
+                               mddev->new_layout = mddev->layout;
+                       return rv;
+               }
        }
        if (info->size >= 0 && mddev->dev_sectors / 2 != info->size)
                rv = update_size(mddev, (sector_t)info->size * 2);
@@ -5560,7 +5526,7 @@ static struct block_device_operations md_fops =
        .owner          = THIS_MODULE,
        .open           = md_open,
        .release        = md_release,
-       .locked_ioctl   = md_ioctl,
+       .ioctl          = md_ioctl,
        .getgeo         = md_getgeo,
        .media_changed  = md_media_changed,
        .revalidate_disk= md_revalidate,
@@ -6355,12 +6321,13 @@ void md_do_sync(mddev_t *mddev)
 
                skipped = 0;
 
-               if ((mddev->curr_resync > mddev->curr_resync_completed &&
-                    (mddev->curr_resync - mddev->curr_resync_completed)
-                   > (max_sectors >> 4)) ||
-                   (j - mddev->curr_resync_completed)*2
-                   >= mddev->resync_max - mddev->curr_resync_completed
-                       ) {
+               if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+                   ((mddev->curr_resync > mddev->curr_resync_completed &&
+                     (mddev->curr_resync - mddev->curr_resync_completed)
+                     > (max_sectors >> 4)) ||
+                    (j - mddev->curr_resync_completed)*2
+                    >= mddev->resync_max - mddev->curr_resync_completed
+                           )) {
                        /* time to update curr_resync_completed */
                        blk_unplug(mddev->queue);
                        wait_event(mddev->recovery_wait,
@@ -6371,10 +6338,16 @@ void md_do_sync(mddev_t *mddev)
                        sysfs_notify(&mddev->kobj, NULL, "sync_completed");
                }
 
-               if (j >= mddev->resync_max)
-                       wait_event(mddev->recovery_wait,
-                                  mddev->resync_max > j
-                                  || kthread_should_stop());
+               while (j >= mddev->resync_max && !kthread_should_stop()) {
+                       /* As this condition is controlled by user-space,
+                        * we can block indefinitely, so use '_interruptible'
+                        * to avoid triggering warnings.
+                        */
+                       flush_signals(current); /* just in case */
+                       wait_event_interruptible(mddev->recovery_wait,
+                                                mddev->resync_max > j
+                                                || kthread_should_stop());
+               }
 
                if (kthread_should_stop())
                        goto interrupted;
@@ -6709,7 +6682,8 @@ void md_check_recovery(mddev_t *mddev)
                 */
 
                if (mddev->reshape_position != MaxSector) {
-                       if (mddev->pers->check_reshape(mddev) != 0)
+                       if (mddev->pers->check_reshape == NULL ||
+                           mddev->pers->check_reshape(mddev) != 0)
                                /* Cannot proceed */
                                goto unlock;
                        set_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);