md: move headers out of include/linux/raid/
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / md / md.c
index 03b4cd0a6344cf2e458a035325eb2ec7ffc8805a..9a3214c8585f286ba8c743f3763065733a8289cc 100644 (file)
@@ -34,7 +34,6 @@
 
 #include <linux/kthread.h>
 #include <linux/raid/md.h>
-#include <linux/raid/bitmap.h>
 #include <linux/sysctl.h>
 #include <linux/buffer_head.h> /* for invalidate_bdev */
 #include <linux/poll.h>
@@ -45,8 +44,7 @@
 #include <linux/reboot.h>
 #include <linux/file.h>
 #include <linux/delay.h>
-
-#define MAJOR_NR MD_MAJOR
+#include "bitmap.h"
 
 /* 63 partitions with the alternate major number (mdp) */
 #define MdpMinorShift 6
@@ -1438,6 +1436,38 @@ static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2)
 
 static LIST_HEAD(pending_raid_disks);
 
+static void md_integrity_check(mdk_rdev_t *rdev, mddev_t *mddev)
+{
+       struct mdk_personality *pers = mddev->pers;
+       struct gendisk *disk = mddev->gendisk;
+       struct blk_integrity *bi_rdev = bdev_get_integrity(rdev->bdev);
+       struct blk_integrity *bi_mddev = blk_get_integrity(disk);
+
+       /* Data integrity passthrough not supported on RAID 4, 5 and 6 */
+       if (pers && pers->level >= 4 && pers->level <= 6)
+               return;
+
+       /* If rdev is integrity capable, register profile for mddev */
+       if (!bi_mddev && bi_rdev) {
+               if (blk_integrity_register(disk, bi_rdev))
+                       printk(KERN_ERR "%s: %s Could not register integrity!\n",
+                              __func__, disk->disk_name);
+               else
+                       printk(KERN_NOTICE "Enabling data integrity on %s\n",
+                              disk->disk_name);
+               return;
+       }
+
+       /* Check that mddev and rdev have matching profiles */
+       if (blk_integrity_compare(disk, rdev->bdev->bd_disk) < 0) {
+               printk(KERN_ERR "%s: %s/%s integrity mismatch!\n", __func__,
+                      disk->disk_name, rdev->bdev->bd_disk->disk_name);
+               printk(KERN_NOTICE "Disabling data integrity on %s\n",
+                      disk->disk_name);
+               blk_integrity_unregister(disk);
+       }
+}
+
 static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 {
        char b[BDEVNAME_SIZE];
@@ -1508,6 +1538,8 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev)
 
        /* May as well allow recovery to be retried once */
        mddev->recovery_disabled = 0;
+
+       md_integrity_check(rdev, mddev);
        return 0;
 
  fail:
@@ -3794,6 +3826,10 @@ static int do_md_run(mddev_t * mddev)
        mddev->level = pers->level;
        strlcpy(mddev->clevel, pers->name, sizeof(mddev->clevel));
 
+       if (pers->level >= 4 && pers->level <= 6)
+               /* Cannot support integrity (yet) */
+               blk_integrity_unregister(mddev->gendisk);
+
        if (mddev->reshape_position != MaxSector &&
            pers->start_reshape == NULL) {
                /* This personality cannot handle reshaping... */
@@ -4129,6 +4165,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
                printk(KERN_INFO "md: %s switched to read-only mode.\n",
                        mdname(mddev));
        err = 0;
+       blk_integrity_unregister(disk);
        md_new_event(mddev);
        sysfs_notify_dirent(mddev->sysfs_state);
 out:
@@ -5716,19 +5753,19 @@ int unregister_md_personality(struct mdk_personality *p)
        return 0;
 }
 
-static int is_mddev_idle(mddev_t *mddev)
+static int is_mddev_idle(mddev_t *mddev, int init)
 {
        mdk_rdev_t * rdev;
        int idle;
-       long curr_events;
+       int curr_events;
 
        idle = 1;
        rcu_read_lock();
        rdev_for_each_rcu(rdev, mddev) {
                struct gendisk *disk = rdev->bdev->bd_contains->bd_disk;
-               curr_events = part_stat_read(&disk->part0, sectors[0]) +
-                               part_stat_read(&disk->part0, sectors[1]) -
-                               atomic_read(&disk->sync_io);
+               curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
+                             (int)part_stat_read(&disk->part0, sectors[1]) -
+                             atomic_read(&disk->sync_io);
                /* sync IO will cause sync_io to increase before the disk_stats
                 * as sync_io is counted when a request starts, and
                 * disk_stats is counted when it completes.
@@ -5751,7 +5788,7 @@ static int is_mddev_idle(mddev_t *mddev)
                 * always make curr_events less than last_events.
                 *
                 */
-               if (curr_events - rdev->last_events > 4096) {
+               if (init || curr_events - rdev->last_events > 64) {
                        rdev->last_events = curr_events;
                        idle = 0;
                }
@@ -5994,7 +6031,7 @@ void md_do_sync(mddev_t *mddev)
               "(but not more than %d KB/sec) for %s.\n",
               speed_max(mddev), desc);
 
-       is_mddev_idle(mddev); /* this also initializes IO event counters */
+       is_mddev_idle(mddev, 1); /* this initializes IO event counters */
 
        io_sectors = 0;
        for (m = 0; m < SYNC_MARKS; m++) {
@@ -6096,7 +6133,7 @@ void md_do_sync(mddev_t *mddev)
 
                if (currspeed > speed_min(mddev)) {
                        if ((currspeed > speed_max(mddev)) ||
-                                       !is_mddev_idle(mddev)) {
+                                       !is_mddev_idle(mddev, 0)) {
                                msleep(500);
                                goto repeat;
                        }
@@ -6464,13 +6501,13 @@ static void md_geninit(void)
 
 static int __init md_init(void)
 {
-       if (register_blkdev(MAJOR_NR, "md"))
+       if (register_blkdev(MD_MAJOR, "md"))
                return -1;
        if ((mdp_major=register_blkdev(0, "mdp"))<=0) {
-               unregister_blkdev(MAJOR_NR, "md");
+               unregister_blkdev(MD_MAJOR, "md");
                return -1;
        }
-       blk_register_region(MKDEV(MAJOR_NR, 0), 1UL<<MINORBITS, THIS_MODULE,
+       blk_register_region(MKDEV(MD_MAJOR, 0), 1UL<<MINORBITS, THIS_MODULE,
                            md_probe, NULL, NULL);
        blk_register_region(MKDEV(mdp_major, 0), 1UL<<MINORBITS, THIS_MODULE,
                            md_probe, NULL, NULL);
@@ -6556,10 +6593,10 @@ static __exit void md_exit(void)
        mddev_t *mddev;
        struct list_head *tmp;
 
-       blk_unregister_region(MKDEV(MAJOR_NR,0), 1U << MINORBITS);
+       blk_unregister_region(MKDEV(MD_MAJOR,0), 1U << MINORBITS);
        blk_unregister_region(MKDEV(mdp_major,0), 1U << MINORBITS);
 
-       unregister_blkdev(MAJOR_NR,"md");
+       unregister_blkdev(MD_MAJOR,"md");
        unregister_blkdev(mdp_major, "mdp");
        unregister_reboot_notifier(&md_notifier);
        unregister_sysctl_table(raid_table_header);