static struct block_device_operations md_fops;
 
+static int start_readonly;
+
 /*
  * Enables to iterate over all existing md arrays
  * all_mddevs_lock protects this list.
        mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */
        mddev->barriers_work = 1;
 
+       if (start_readonly)
+               mddev->ro = 2; /* read-only, but switch on first write */
+
        /* before we start the array running, initialise the bitmap */
        err = bitmap_create(mddev);
        if (err)
 
                if (ro) {
                        err  = -ENXIO;
-                       if (mddev->ro)
+                       if (mddev->ro==1)
                                goto out;
                        mddev->ro = 1;
                } else {
 
        /*
         * The remaining ioctls are changing the state of the
-        * superblock, so we do not allow read-only arrays
-        * here:
+        * superblock, so we do not allow them on read-only arrays.
+        * However non-MD ioctls (e.g. get-size) will still come through
+        * here and hit the 'default' below, so only disallow
+        * 'md' ioctls, and switch to rw mode if started auto-readonly.
         */
-       if (mddev->ro) {
-               err = -EROFS;
-               goto abort_unlock;
+       if (_IOC_TYPE(cmd) == MD_MAJOR &&
+           mddev->ro && mddev->pers) {
+               if (mddev->ro == 2) {
+                       mddev->ro = 0;
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+               md_wakeup_thread(mddev->thread);
+
+               } else {
+                       err = -EROFS;
+                       goto abort_unlock;
+               }
        }
 
        switch (cmd)
                seq_printf(seq, "%s : %sactive", mdname(mddev),
                                                mddev->pers ? "" : "in");
                if (mddev->pers) {
-                       if (mddev->ro)
+                       if (mddev->ro==1)
                                seq_printf(seq, " (read-only)");
+                       if (mddev->ro==2)
+                               seq_printf(seq, "(auto-read-only)");
                        seq_printf(seq, " %s", mddev->pers->name);
                }
 
                                status_resync (seq, mddev);
                                seq_printf(seq, "\n      ");
                        } else if (mddev->curr_resync == 1 || mddev->curr_resync == 2)
-                               seq_printf(seq, "       resync=DELAYED\n      ");
+                               seq_printf(seq, "\tresync=DELAYED\n      ");
+                       else if (mddev->recovery_cp < MaxSector)
+                               seq_printf(seq, "\tresync=PENDING\n      ");
                } else
                        seq_printf(seq, "\n       ");
 
        if (bio_data_dir(bi) != WRITE)
                return;
 
+       BUG_ON(mddev->ro == 1);
+       if (mddev->ro == 2) {
+               /* need to switch to read/write */
+               mddev->ro = 0;
+               set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
+               md_wakeup_thread(mddev->thread);
+       }
        atomic_inc(&mddev->writes_pending);
        if (mddev->in_sync) {
                spin_lock_irq(&mddev->write_lock);
 module_init(md_init)
 module_exit(md_exit)
 
+static int get_ro(char *buffer, struct kernel_param *kp)
+{
+       return sprintf(buffer, "%d", start_readonly);
+}
+static int set_ro(const char *val, struct kernel_param *kp)
+{
+       char *e;
+       int num = simple_strtoul(val, &e, 10);
+       if (*val && (*e == '\0' || *e == '\n')) {
+               start_readonly = num;
+               return 0;;
+       }
+       return -EINVAL;
+}
+
+module_param_call(start_ro, set_ro, get_ro, NULL, 0600);
+
 EXPORT_SYMBOL(register_md_personality);
 EXPORT_SYMBOL(unregister_md_personality);
 EXPORT_SYMBOL(md_error);