md/raid1: ensure device failure recorded before write request returns.
[pandora-kernel.git] / drivers / md / md.c
index 5b62a3d..8644ce7 100644 (file)
@@ -502,6 +502,8 @@ static void mddev_put(struct mddev *mddev)
                bioset_free(bs);
 }
 
+static void md_safemode_timeout(unsigned long data);
+
 void mddev_init(struct mddev *mddev)
 {
        mutex_init(&mddev->open_mutex);
@@ -509,7 +511,8 @@ void mddev_init(struct mddev *mddev)
        mutex_init(&mddev->bitmap_info.mutex);
        INIT_LIST_HEAD(&mddev->disks);
        INIT_LIST_HEAD(&mddev->all_mddevs);
-       init_timer(&mddev->safemode_timer);
+       setup_timer(&mddev->safemode_timer, md_safemode_timeout,
+                   (unsigned long) mddev);
        atomic_set(&mddev->active, 1);
        atomic_set(&mddev->openers, 0);
        atomic_set(&mddev->active_io, 0);
@@ -3276,8 +3279,6 @@ int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale)
        return 0;
 }
 
-static void md_safemode_timeout(unsigned long data);
-
 static ssize_t
 safe_delay_show(struct mddev *mddev, char *page)
 {
@@ -5204,8 +5205,6 @@ int md_run(struct mddev *mddev)
        atomic_set(&mddev->max_corr_read_errors,
                   MD_DEFAULT_MAX_CORRECTED_READ_ERRORS);
        mddev->safemode = 0;
-       mddev->safemode_timer.function = md_safemode_timeout;
-       mddev->safemode_timer.data = (unsigned long) mddev;
        mddev->safemode_delay = (200 * HZ)/1000 +1; /* 200 msec delay */
        mddev->in_sync = 1;
        smp_wmb();
@@ -7428,15 +7427,19 @@ int unregister_md_personality(struct md_personality *p)
 }
 EXPORT_SYMBOL(unregister_md_personality);
 
-int register_md_cluster_operations(struct md_cluster_operations *ops, struct module *module)
+int register_md_cluster_operations(struct md_cluster_operations *ops,
+                                  struct module *module)
 {
-       if (md_cluster_ops != NULL)
-               return -EALREADY;
+       int ret = 0;
        spin_lock(&pers_lock);
-       md_cluster_ops = ops;
-       md_cluster_mod = module;
+       if (md_cluster_ops != NULL)
+               ret = -EALREADY;
+       else {
+               md_cluster_ops = ops;
+               md_cluster_mod = module;
+       }
        spin_unlock(&pers_lock);
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(register_md_cluster_operations);
 
@@ -7834,7 +7837,8 @@ void md_do_sync(struct md_thread *thread)
                      > (max_sectors >> 4)) ||
                     time_after_eq(jiffies, update_time + UPDATE_FREQUENCY) ||
                     (j - mddev->curr_resync_completed)*2
-                    >= mddev->resync_max - mddev->curr_resync_completed
+                    >= mddev->resync_max - mddev->curr_resync_completed ||
+                    mddev->curr_resync_completed > mddev->resync_max
                            )) {
                        /* time to update curr_resync_completed */
                        wait_event(mddev->recovery_wait,
@@ -7879,6 +7883,9 @@ void md_do_sync(struct md_thread *thread)
                        break;
 
                j += sectors;
+               if (j > max_sectors)
+                       /* when skipping, extra large numbers can be returned. */
+                       j = max_sectors;
                if (j > 2)
                        mddev->curr_resync = j;
                if (mddev_is_clustered(mddev))
@@ -7947,12 +7954,15 @@ void md_do_sync(struct md_thread *thread)
        blk_finish_plug(&plug);
        wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
+       if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
+           !test_bit(MD_RECOVERY_INTR, &mddev->recovery) &&
+           mddev->curr_resync > 2) {
+               mddev->curr_resync_completed = mddev->curr_resync;
+               sysfs_notify(&mddev->kobj, NULL, "sync_completed");
+       }
        /* tell personality that we are finished */
        mddev->pers->sync_request(mddev, max_sectors, &skipped);
 
-       if (mddev_is_clustered(mddev))
-               md_cluster_ops->resync_finish(mddev);
-
        if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) &&
            mddev->curr_resync > 2) {
                if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {
@@ -7986,6 +7996,9 @@ void md_do_sync(struct md_thread *thread)
                }
        }
  skip:
+       if (mddev_is_clustered(mddev))
+               md_cluster_ops->resync_finish(mddev);
+
        set_bit(MD_CHANGE_DEVS, &mddev->flags);
 
        spin_lock(&mddev->lock);
@@ -8616,6 +8629,7 @@ int rdev_set_badblocks(struct md_rdev *rdev, sector_t s, int sectors,
                /* Make sure they get written out promptly */
                sysfs_notify_dirent_safe(rdev->sysfs_state);
                set_bit(MD_CHANGE_CLEAN, &rdev->mddev->flags);
+               set_bit(MD_CHANGE_PENDING, &rdev->mddev->flags);
                md_wakeup_thread(rdev->mddev->thread);
        }
        return rv;