Merge tag 'rproc-v4.20' of git://github.com/andersson/remoteproc
[linux-2.6-block.git] / drivers / md / md.c
index 63ceabb4e020f656313fabff5e25e3ba593a8786..fc488cb30a94780d8a4fee0674d718aa901b047f 100644 (file)
@@ -452,10 +452,11 @@ static void md_end_flush(struct bio *fbio)
        rdev_dec_pending(rdev, mddev);
 
        if (atomic_dec_and_test(&fi->flush_pending)) {
-               if (bio->bi_iter.bi_size == 0)
+               if (bio->bi_iter.bi_size == 0) {
                        /* an empty barrier - all done */
                        bio_endio(bio);
-               else {
+                       mempool_free(fi, mddev->flush_pool);
+               } else {
                        INIT_WORK(&fi->flush_work, submit_flushes);
                        queue_work(md_wq, &fi->flush_work);
                }
@@ -509,10 +510,11 @@ void md_flush_request(struct mddev *mddev, struct bio *bio)
        rcu_read_unlock();
 
        if (atomic_dec_and_test(&fi->flush_pending)) {
-               if (bio->bi_iter.bi_size == 0)
+               if (bio->bi_iter.bi_size == 0) {
                        /* an empty barrier - all done */
                        bio_endio(bio);
-               else {
+                       mempool_free(fi, mddev->flush_pool);
+               } else {
                        INIT_WORK(&fi->flush_work, submit_flushes);
                        queue_work(md_wq, &fi->flush_work);
                }
@@ -5904,14 +5906,6 @@ static void __md_stop(struct mddev *mddev)
                mddev->to_remove = &md_redundancy_group;
        module_put(pers->owner);
        clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
-}
-
-void md_stop(struct mddev *mddev)
-{
-       /* stop the array and free an attached data structures.
-        * This is called from dm-raid
-        */
-       __md_stop(mddev);
        if (mddev->flush_bio_pool) {
                mempool_destroy(mddev->flush_bio_pool);
                mddev->flush_bio_pool = NULL;
@@ -5920,6 +5914,14 @@ void md_stop(struct mddev *mddev)
                mempool_destroy(mddev->flush_pool);
                mddev->flush_pool = NULL;
        }
+}
+
+void md_stop(struct mddev *mddev)
+{
+       /* stop the array and free an attached data structures.
+        * This is called from dm-raid
+        */
+       __md_stop(mddev);
        bioset_exit(&mddev->bio_set);
        bioset_exit(&mddev->sync_set);
 }
@@ -8370,9 +8372,17 @@ void md_do_sync(struct md_thread *thread)
                else if (!mddev->bitmap)
                        j = mddev->recovery_cp;
 
-       } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery))
+       } else if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
                max_sectors = mddev->resync_max_sectors;
-       else {
+               /*
+                * If the original node aborts reshaping then we continue the
+                * reshaping, so set j again to avoid restart reshape from the
+                * first beginning
+                */
+               if (mddev_is_clustered(mddev) &&
+                   mddev->reshape_position != MaxSector)
+                       j = mddev->reshape_position;
+       } else {
                /* recovery follows the physical size of devices */
                max_sectors = mddev->dev_sectors;
                j = MaxSector;
@@ -8623,8 +8633,10 @@ void md_do_sync(struct md_thread *thread)
                mddev_lock_nointr(mddev);
                md_set_array_sectors(mddev, mddev->pers->size(mddev, 0, 0));
                mddev_unlock(mddev);
-               set_capacity(mddev->gendisk, mddev->array_sectors);
-               revalidate_disk(mddev->gendisk);
+               if (!mddev_is_clustered(mddev)) {
+                       set_capacity(mddev->gendisk, mddev->array_sectors);
+                       revalidate_disk(mddev->gendisk);
+               }
        }
 
        spin_lock(&mddev->lock);
@@ -8790,6 +8802,18 @@ static void md_start_sync(struct work_struct *ws)
  */
 void md_check_recovery(struct mddev *mddev)
 {
+       if (test_bit(MD_ALLOW_SB_UPDATE, &mddev->flags) && mddev->sb_flags) {
+               /* Write superblock - thread that called mddev_suspend()
+                * holds reconfig_mutex for us.
+                */
+               set_bit(MD_UPDATING_SB, &mddev->flags);
+               smp_mb__after_atomic();
+               if (test_bit(MD_ALLOW_SB_UPDATE, &mddev->flags))
+                       md_update_sb(mddev, 0);
+               clear_bit_unlock(MD_UPDATING_SB, &mddev->flags);
+               wake_up(&mddev->sb_wait);
+       }
+
        if (mddev->suspended)
                return;
 
@@ -8949,16 +8973,6 @@ void md_check_recovery(struct mddev *mddev)
        unlock:
                wake_up(&mddev->sb_wait);
                mddev_unlock(mddev);
-       } else if (test_bit(MD_ALLOW_SB_UPDATE, &mddev->flags) && mddev->sb_flags) {
-               /* Write superblock - thread that called mddev_suspend()
-                * holds reconfig_mutex for us.
-                */
-               set_bit(MD_UPDATING_SB, &mddev->flags);
-               smp_mb__after_atomic();
-               if (test_bit(MD_ALLOW_SB_UPDATE, &mddev->flags))
-                       md_update_sb(mddev, 0);
-               clear_bit_unlock(MD_UPDATING_SB, &mddev->flags);
-               wake_up(&mddev->sb_wait);
        }
 }
 EXPORT_SYMBOL(md_check_recovery);
@@ -8966,6 +8980,8 @@ EXPORT_SYMBOL(md_check_recovery);
 void md_reap_sync_thread(struct mddev *mddev)
 {
        struct md_rdev *rdev;
+       sector_t old_dev_sectors = mddev->dev_sectors;
+       bool is_reshaped = false;
 
        /* resync has finished, collect result */
        md_unregister_thread(&mddev->sync_thread);
@@ -8980,8 +8996,11 @@ void md_reap_sync_thread(struct mddev *mddev)
                }
        }
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
-           mddev->pers->finish_reshape)
+           mddev->pers->finish_reshape) {
                mddev->pers->finish_reshape(mddev);
+               if (mddev_is_clustered(mddev))
+                       is_reshaped = true;
+       }
 
        /* If array is no-longer degraded, then any saved_raid_disk
         * information must be scrapped.
@@ -9002,6 +9021,14 @@ void md_reap_sync_thread(struct mddev *mddev)
        clear_bit(MD_RECOVERY_RESHAPE, &mddev->recovery);
        clear_bit(MD_RECOVERY_REQUESTED, &mddev->recovery);
        clear_bit(MD_RECOVERY_CHECK, &mddev->recovery);
+       /*
+        * We call md_cluster_ops->update_size here because sync_size could
+        * be changed by md_update_sb, and MD_RECOVERY_RESHAPE is cleared,
+        * so it is time to update size across cluster.
+        */
+       if (mddev_is_clustered(mddev) && is_reshaped
+                                     && !test_bit(MD_CLOSING, &mddev->flags))
+               md_cluster_ops->update_size(mddev, old_dev_sectors);
        wake_up(&resync_wait);
        /* flag recovery needed just to double check */
        set_bit(MD_RECOVERY_NEEDED, &mddev->recovery);
@@ -9201,8 +9228,12 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
                }
 
                if (role != rdev2->raid_disk) {
-                       /* got activated */
-                       if (rdev2->raid_disk == -1 && role != 0xffff) {
+                       /*
+                        * got activated except reshape is happening.
+                        */
+                       if (rdev2->raid_disk == -1 && role != 0xffff &&
+                           !(le32_to_cpu(sb->feature_map) &
+                             MD_FEATURE_RESHAPE_ACTIVE)) {
                                rdev2->saved_raid_disk = role;
                                ret = remove_and_add_spares(mddev, rdev2);
                                pr_info("Activated spare: %s\n",
@@ -9228,6 +9259,30 @@ static void check_sb_changes(struct mddev *mddev, struct md_rdev *rdev)
        if (mddev->raid_disks != le32_to_cpu(sb->raid_disks))
                update_raid_disks(mddev, le32_to_cpu(sb->raid_disks));
 
+       /*
+        * Since mddev->delta_disks has already updated in update_raid_disks,
+        * so it is time to check reshape.
+        */
+       if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) &&
+           (le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
+               /*
+                * reshape is happening in the remote node, we need to
+                * update reshape_position and call start_reshape.
+                */
+               mddev->reshape_position = sb->reshape_position;
+               if (mddev->pers->update_reshape_pos)
+                       mddev->pers->update_reshape_pos(mddev);
+               if (mddev->pers->start_reshape)
+                       mddev->pers->start_reshape(mddev);
+       } else if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) &&
+                  mddev->reshape_position != MaxSector &&
+                  !(le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) {
+               /* reshape is just done in another node. */
+               mddev->reshape_position = MaxSector;
+               if (mddev->pers->update_reshape_pos)
+                       mddev->pers->update_reshape_pos(mddev);
+       }
+
        /* Finally set the event to be up to date */
        mddev->events = le64_to_cpu(sb->events);
 }