arm64: dts add Rockchip RK3328 EVB board for wifi
[firefly-linux-kernel-4.4.55.git] / drivers / md / md.c
index dbedc58d8c00fdcdacb5a9e24d3a5c8571b988a8..eff554a12fb428560310da77b7b08457d9d57e7b 100644 (file)
@@ -293,6 +293,8 @@ static blk_qc_t md_make_request(struct request_queue *q, struct bio *bio)
         * go away inside make_request
         */
        sectors = bio_sectors(bio);
+       /* bio could be mergeable after passing to underlayer */
+       bio->bi_rw &= ~REQ_NOMERGE;
        mddev->pers->make_request(mddev, bio);
 
        cpu = part_stat_lock();
@@ -2017,28 +2019,32 @@ int md_integrity_register(struct mddev *mddev)
 }
 EXPORT_SYMBOL(md_integrity_register);
 
-/* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
+/*
+ * Attempt to add an rdev, but only if it is consistent with the current
+ * integrity profile
+ */
+int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
 {
        struct blk_integrity *bi_rdev;
        struct blk_integrity *bi_mddev;
+       char name[BDEVNAME_SIZE];
 
        if (!mddev->gendisk)
-               return;
+               return 0;
 
        bi_rdev = bdev_get_integrity(rdev->bdev);
        bi_mddev = blk_get_integrity(mddev->gendisk);
 
        if (!bi_mddev) /* nothing to do */
-               return;
-       if (rdev->raid_disk < 0) /* skip spares */
-               return;
-       if (bi_rdev && blk_integrity_compare(mddev->gendisk,
-                                            rdev->bdev->bd_disk) >= 0)
-               return;
-       WARN_ON_ONCE(!mddev->suspended);
-       printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
-       blk_integrity_unregister(mddev->gendisk);
+               return 0;
+
+       if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
+               printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
+                               mdname(mddev), bdevname(rdev->bdev, name));
+               return -ENXIO;
+       }
+
+       return 0;
 }
 EXPORT_SYMBOL(md_integrity_add_rdev);
 
@@ -4326,8 +4332,7 @@ action_store(struct mddev *mddev, const char *page, size_t len)
                        }
                        mddev_unlock(mddev);
                }
-       } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery) ||
-                  test_bit(MD_RECOVERY_NEEDED, &mddev->recovery))
+       } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
                return -EBUSY;
        else if (cmd_match(page, "resync"))
                clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
@@ -4340,8 +4345,12 @@ action_store(struct mddev *mddev, const char *page, size_t len)
                        return -EINVAL;
                err = mddev_lock(mddev);
                if (!err) {
-                       clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
-                       err = mddev->pers->start_reshape(mddev);
+                       if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery))
+                               err =  -EBUSY;
+                       else {
+                               clear_bit(MD_RECOVERY_FROZEN, &mddev->recovery);
+                               err = mddev->pers->start_reshape(mddev);
+                       }
                        mddev_unlock(mddev);
                }
                if (err)
@@ -6762,7 +6771,7 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                /* need to ensure recovery thread has run */
                wait_event_interruptible_timeout(mddev->sb_wait,
                                                 !test_bit(MD_RECOVERY_NEEDED,
-                                                          &mddev->flags),
+                                                          &mddev->recovery),
                                                 msecs_to_jiffies(5000));
        if (cmd == STOP_ARRAY || cmd == STOP_ARRAY_RO) {
                /* Need to flush page cache, and ensure no-one else opens
@@ -7563,16 +7572,12 @@ EXPORT_SYMBOL(unregister_md_cluster_operations);
 
 int md_setup_cluster(struct mddev *mddev, int nodes)
 {
-       int err;
-
-       err = request_module("md-cluster");
-       if (err) {
-               pr_err("md-cluster module not found.\n");
-               return -ENOENT;
-       }
-
+       if (!md_cluster_ops)
+               request_module("md-cluster");
        spin_lock(&pers_lock);
+       /* ensure module won't be unloaded */
        if (!md_cluster_ops || !try_module_get(md_cluster_mod)) {
+               pr_err("can't find md-cluster module or get it's reference.\n");
                spin_unlock(&pers_lock);
                return -ENOENT;
        }