Merge tag 'for-f2fs-v4.2-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeu...
[firefly-linux-kernel-4.4.55.git] / drivers / md / md-cluster.c
index 10c44a3a9d6acd4c727c379ede622793f17ee41e..0072190515e0f6edca1e09718dae5102b3e7d274 100644 (file)
@@ -44,6 +44,7 @@ struct resync_info {
 
 /* md_cluster_info flags */
 #define                MD_CLUSTER_WAITING_FOR_NEWDISK          1
+#define                MD_CLUSTER_SUSPEND_READ_BALANCING       2
 
 
 struct md_cluster_info {
@@ -72,6 +73,8 @@ enum msg_type {
        METADATA_UPDATED = 0,
        RESYNCING,
        NEWDISK,
+       REMOVE,
+       RE_ADD,
 };
 
 struct cluster_msg {
@@ -252,7 +255,7 @@ static void recover_bitmaps(struct md_thread *thread)
                                        str, ret);
                        goto clear_bit;
                }
-               ret = bitmap_copy_from_slot(mddev, slot, &lo, &hi);
+               ret = bitmap_copy_from_slot(mddev, slot, &lo, &hi, true);
                if (ret) {
                        pr_err("md-cluster: Could not copy data from bitmap %d\n", slot);
                        goto dlm_unlock;
@@ -273,6 +276,9 @@ clear_bit:
 
 static void recover_prep(void *arg)
 {
+       struct mddev *mddev = arg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       set_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state);
 }
 
 static void recover_slot(void *arg, struct dlm_slot *slot)
@@ -305,6 +311,7 @@ static void recover_done(void *arg, struct dlm_slot *slots,
 
        cinfo->slot_number = our_slot;
        complete(&cinfo->completion);
+       clear_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state);
 }
 
 static const struct dlm_lockspace_ops md_ls_ops = {
@@ -401,6 +408,26 @@ static void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg
        dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR);
 }
 
+static void process_remove_disk(struct mddev *mddev, struct cluster_msg *msg)
+{
+       struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+
+       if (rdev)
+               md_kick_rdev_from_array(rdev);
+       else
+               pr_warn("%s: %d Could not find disk(%d) to REMOVE\n", __func__, __LINE__, msg->raid_slot);
+}
+
+static void process_readd_disk(struct mddev *mddev, struct cluster_msg *msg)
+{
+       struct md_rdev *rdev = md_find_rdev_nr_rcu(mddev, msg->raid_slot);
+
+       if (rdev && test_bit(Faulty, &rdev->flags))
+               clear_bit(Faulty, &rdev->flags);
+       else
+               pr_warn("%s: %d Could not find disk(%d) which is faulty", __func__, __LINE__, msg->raid_slot);
+}
+
 static void process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg)
 {
        switch (msg->type) {
@@ -419,6 +446,20 @@ static void process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg)
                pr_info("%s: %d Received message: NEWDISK from %d\n",
                        __func__, __LINE__, msg->slot);
                process_add_new_disk(mddev, msg);
+               break;
+       case REMOVE:
+               pr_info("%s: %d Received REMOVE from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_remove_disk(mddev, msg);
+               break;
+       case RE_ADD:
+               pr_info("%s: %d Received RE_ADD from %d\n",
+                       __func__, __LINE__, msg->slot);
+               process_readd_disk(mddev, msg);
+               break;
+       default:
+               pr_warn("%s:%d Received unknown message from %d\n",
+                       __func__, __LINE__, msg->slot);
        }
 }
 
@@ -780,12 +821,17 @@ static void resync_finish(struct mddev *mddev)
        resync_send(mddev, RESYNCING, 0, 0);
 }
 
-static int area_resyncing(struct mddev *mddev, sector_t lo, sector_t hi)
+static int area_resyncing(struct mddev *mddev, int direction,
+               sector_t lo, sector_t hi)
 {
        struct md_cluster_info *cinfo = mddev->cluster_info;
        int ret = 0;
        struct suspend_info *s;
 
+       if ((direction == READ) &&
+               test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state))
+               return 1;
+
        spin_lock_irq(&cinfo->suspend_lock);
        if (list_empty(&cinfo->suspend_list))
                goto out;
@@ -854,6 +900,44 @@ static int new_disk_ack(struct mddev *mddev, bool ack)
        return 0;
 }
 
+static int remove_disk(struct mddev *mddev, struct md_rdev *rdev)
+{
+       struct cluster_msg cmsg;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+       cmsg.type = REMOVE;
+       cmsg.raid_slot = rdev->desc_nr;
+       return __sendmsg(cinfo, &cmsg);
+}
+
+static int gather_bitmaps(struct md_rdev *rdev)
+{
+       int sn, err;
+       sector_t lo, hi;
+       struct cluster_msg cmsg;
+       struct mddev *mddev = rdev->mddev;
+       struct md_cluster_info *cinfo = mddev->cluster_info;
+
+       cmsg.type = RE_ADD;
+       cmsg.raid_slot = rdev->desc_nr;
+       err = sendmsg(cinfo, &cmsg);
+       if (err)
+               goto out;
+
+       for (sn = 0; sn < mddev->bitmap_info.nodes; sn++) {
+               if (sn == (cinfo->slot_number - 1))
+                       continue;
+               err = bitmap_copy_from_slot(mddev, sn, &lo, &hi, false);
+               if (err) {
+                       pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn);
+                       goto out;
+               }
+               if ((hi > 0) && (lo < mddev->recovery_cp))
+                       mddev->recovery_cp = lo;
+       }
+out:
+       return err;
+}
+
 static struct md_cluster_operations cluster_ops = {
        .join   = join,
        .leave  = leave,
@@ -868,6 +952,8 @@ static struct md_cluster_operations cluster_ops = {
        .add_new_disk_start = add_new_disk_start,
        .add_new_disk_finish = add_new_disk_finish,
        .new_disk_ack = new_disk_ack,
+       .remove_disk = remove_disk,
+       .gather_bitmaps = gather_bitmaps,
 };
 
 static int __init cluster_init(void)