Remove multiple KERN_ prefixes from printk formats
[safe/jmp/linux-2.6] / drivers / md / md.c
index 2be574c..d4351ff 100644 (file)
@@ -269,12 +269,7 @@ static inline mddev_t *mddev_get(mddev_t *mddev)
        return mddev;
 }
 
-static void mddev_delayed_delete(struct work_struct *ws)
-{
-       mddev_t *mddev = container_of(ws, mddev_t, del_work);
-       kobject_del(&mddev->kobj);
-       kobject_put(&mddev->kobj);
-}
+static void mddev_delayed_delete(struct work_struct *ws);
 
 static void mddev_put(mddev_t *mddev)
 {
@@ -445,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)
@@ -750,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)
@@ -802,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
@@ -841,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" ... */
@@ -871,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;
@@ -888,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))
@@ -1009,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)
@@ -1023,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);
@@ -1190,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;
 
@@ -1253,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;
@@ -1276,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);
@@ -1302,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) {
@@ -1380,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);
@@ -1404,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;
@@ -1774,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],
@@ -1788,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),
@@ -1899,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:
@@ -1928,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 */
@@ -2022,6 +2006,8 @@ repeat:
        clear_bit(MD_CHANGE_PENDING, &mddev->flags);
        spin_unlock_irq(&mddev->write_lock);
        wake_up(&mddev->sb_wait);
+       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+               sysfs_notify(&mddev->kobj, NULL, "sync_completed");
 
 }
 
@@ -2091,6 +2077,7 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
         *  -writemostly - clears write_mostly
         *  blocked - sets the Blocked flag
         *  -blocked - clears the Blocked flag
+        *  insync - sets Insync providing device isn't active
         */
        int err = -EINVAL;
        if (cmd_match(buf, "faulty") && rdev->mddev->pers) {
@@ -2123,6 +2110,9 @@ state_store(mdk_rdev_t *rdev, const char *buf, size_t len)
                md_wakeup_thread(rdev->mddev->thread);
 
                err = 0;
+       } else if (cmd_match(buf, "insync") && rdev->raid_disk == -1) {
+               set_bit(In_sync, &rdev->flags);
+               err = 0;
        }
        if (!err && rdev->sysfs_state)
                sysfs_notify_dirent(rdev->sysfs_state);
@@ -2195,7 +2185,7 @@ slot_store(mdk_rdev_t *rdev, const char *buf, size_t len)
        } else if (rdev->mddev->pers) {
                mdk_rdev_t *rdev2;
                /* Activating a spare .. or possibly reactivating
-                * if we every get bitmaps working here.
+                * if we ever get bitmaps working here.
                 */
 
                if (rdev->raid_disk != -1)
@@ -2593,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);
@@ -2742,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);
@@ -2760,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);
@@ -2796,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)
@@ -2853,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
@@ -2870,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;
 }
@@ -3065,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) {
@@ -3305,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";
@@ -3328,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);
@@ -3487,12 +3479,15 @@ sync_completed_show(mddev_t *mddev, char *page)
 {
        unsigned long max_sectors, resync;
 
+       if (!test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+               return sprintf(page, "none\n");
+
        if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
                max_sectors = mddev->resync_max_sectors;
        else
                max_sectors = mddev->dev_sectors;
 
-       resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active));
+       resync = mddev->curr_resync_completed;
        return sprintf(page, "%lu / %lu\n", resync, max_sectors);
 }
 
@@ -3516,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;
@@ -3553,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;
@@ -3578,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;
@@ -3606,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;
@@ -3645,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;
 }
 
@@ -3679,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;
        }
@@ -3811,6 +3810,21 @@ static struct kobj_type md_ktype = {
 
 int mdp_major = 0;
 
+static void mddev_delayed_delete(struct work_struct *ws)
+{
+       mddev_t *mddev = container_of(ws, mddev_t, del_work);
+
+       if (mddev->private == &md_redundancy_group) {
+               sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
+               if (mddev->sysfs_action)
+                       sysfs_put(mddev->sysfs_action);
+               mddev->sysfs_action = NULL;
+               mddev->private = NULL;
+       }
+       kobject_del(&mddev->kobj);
+       kobject_put(&mddev->kobj);
+}
+
 static int md_alloc(dev_t dev, char *name)
 {
        static DEFINE_MUTEX(disks_mutex);
@@ -3834,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.
@@ -3850,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 */
@@ -3870,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;
@@ -3896,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)
@@ -3950,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.. */
@@ -3972,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])
@@ -4278,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));
@@ -4313,17 +4294,20 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                        mddev->queue->merge_bvec_fn = NULL;
                        mddev->queue->unplug_fn = NULL;
                        mddev->queue->backing_dev_info.congested_fn = NULL;
-                       if (mddev->pers->sync_request) {
-                               sysfs_remove_group(&mddev->kobj, &md_redundancy_group);
-                               if (mddev->sysfs_action)
-                                       sysfs_put(mddev->sysfs_action);
-                               mddev->sysfs_action = NULL;
-                       }
                        module_put(mddev->pers->owner);
+                       if (mddev->pers->sync_request)
+                               mddev->private = &md_redundancy_group;
                        mddev->pers = NULL;
                        /* 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;
 
@@ -4344,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));
 
@@ -4356,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();
 
@@ -4383,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;
@@ -4391,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;
@@ -4596,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;
@@ -4821,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) {
@@ -4891,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 
@@ -5040,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;
 
@@ -5059,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;
 
@@ -5169,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)
                )
@@ -5193,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);
@@ -5545,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,
@@ -5690,37 +5671,38 @@ static void status_unused(struct seq_file *seq)
 
 static void status_resync(struct seq_file *seq, mddev_t * mddev)
 {
-       sector_t max_blocks, resync, res;
-       unsigned long dt, db, rt;
+       sector_t max_sectors, resync, res;
+       unsigned long dt, db;
+       sector_t rt;
        int scale;
        unsigned int per_milli;
 
-       resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
+       resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
 
        if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
-               max_blocks = mddev->resync_max_sectors >> 1;
+               max_sectors = mddev->resync_max_sectors;
        else
-               max_blocks = mddev->dev_sectors / 2;
+               max_sectors = mddev->dev_sectors;
 
        /*
         * Should not happen.
         */
-       if (!max_blocks) {
+       if (!max_sectors) {
                MD_BUG();
                return;
        }
        /* Pick 'scale' such that (resync>>scale)*1000 will fit
-        * in a sector_t, and (max_blocks>>scale) will fit in a
+        * in a sector_t, and (max_sectors>>scale) will fit in a
         * u32, as those are the requirements for sector_div.
         * Thus 'scale' must be at least 10
         */
        scale = 10;
        if (sizeof(sector_t) > sizeof(unsigned long)) {
-               while ( max_blocks/2 > (1ULL<<(scale+32)))
+               while ( max_sectors/2 > (1ULL<<(scale+32)))
                        scale++;
        }
        res = (resync>>scale)*1000;
-       sector_div(res, (u32)((max_blocks>>scale)+1));
+       sector_div(res, (u32)((max_sectors>>scale)+1));
 
        per_milli = res;
        {
@@ -5741,25 +5723,35 @@ static void status_resync(struct seq_file *seq, mddev_t * mddev)
                     (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
                      "resync" : "recovery"))),
                   per_milli/10, per_milli % 10,
-                  (unsigned long long) resync,
-                  (unsigned long long) max_blocks);
+                  (unsigned long long) resync/2,
+                  (unsigned long long) max_sectors/2);
 
        /*
-        * We do not want to overflow, so the order of operands and
-        * the * 100 / 100 trick are important. We do a +1 to be
-        * safe against division by zero. We only estimate anyway.
-        *
         * dt: time from mark until now
         * db: blocks written from mark until now
         * rt: remaining time
+        *
+        * rt is a sector_t, so could be 32bit or 64bit.
+        * So we divide before multiply in case it is 32bit and close
+        * to the limit.
+        * We scale the divisor (db) by 32 to avoid loosing precision
+        * near the end of resync when the number of remaining sectors
+        * is close to 'db'.
+        * We then divide rt by 32 after multiplying by db to compensate.
+        * The '+1' avoids division by zero if db is very small.
         */
        dt = ((jiffies - mddev->resync_mark) / HZ);
        if (!dt) dt++;
        db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
                - mddev->resync_mark_cnt;
-       rt = (dt * ((unsigned long)(max_blocks-resync) / (db/2/100+1)))/100;
 
-       seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
+       rt = max_sectors - resync;    /* number of remaining sectors */
+       sector_div(rt, db/32+1);
+       rt *= dt;
+       rt >>= 5;
+
+       seq_printf(seq, " finish=%lu.%lumin", (unsigned long)rt / 60,
+                  ((unsigned long)rt % 60)/6);
 
        seq_printf(seq, " speed=%ldK/sec", db/2/dt);
 }
@@ -5950,7 +5942,7 @@ static int md_seq_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations md_seq_ops = {
+static const struct seq_operations md_seq_ops = {
        .start  = md_seq_start,
        .next   = md_seq_next,
        .stop   = md_seq_stop,
@@ -6328,18 +6320,14 @@ void md_do_sync(mddev_t *mddev)
                sector_t sectors;
 
                skipped = 0;
-               if (j >= mddev->resync_max) {
-                       sysfs_notify(&mddev->kobj, NULL, "sync_completed");
-                       wait_event(mddev->recovery_wait,
-                                  mddev->resync_max > j
-                                  || kthread_should_stop());
-               }
-               if (kthread_should_stop())
-                       goto interrupted;
 
-               if (mddev->curr_resync > mddev->curr_resync_completed &&
-                   (mddev->curr_resync - mddev->curr_resync_completed)
-                   > (max_sectors >> 4)) {
+               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,
@@ -6347,7 +6335,23 @@ void md_do_sync(mddev_t *mddev)
                        mddev->curr_resync_completed =
                                mddev->curr_resync;
                        set_bit(MD_CHANGE_CLEAN, &mddev->flags);
+                       sysfs_notify(&mddev->kobj, NULL, "sync_completed");
                }
+
+               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;
+
                sectors = mddev->pers->sync_request(mddev, j, &skipped,
                                                  currspeed < speed_min(mddev));
                if (sectors == 0) {
@@ -6455,6 +6459,7 @@ void md_do_sync(mddev_t *mddev)
 
  skip:
        mddev->curr_resync = 0;
+       mddev->curr_resync_completed = 0;
        mddev->resync_min = 0;
        mddev->resync_max = MaxSector;
        sysfs_notify(&mddev->kobj, NULL, "sync_completed");
@@ -6677,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);