]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 01:57:29 +0000 (17:57 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 14 Feb 2016 01:57:29 +0000 (17:57 -0800)
added patches:
md-raid-only-permit-hot-add-of-compatible-integrity-profiles.patch

queue-4.4/md-raid-only-permit-hot-add-of-compatible-integrity-profiles.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/md-raid-only-permit-hot-add-of-compatible-integrity-profiles.patch b/queue-4.4/md-raid-only-permit-hot-add-of-compatible-integrity-profiles.patch
new file mode 100644 (file)
index 0000000..548793e
--- /dev/null
@@ -0,0 +1,178 @@
+From 1501efadc524a0c99494b576923091589a52d2a4 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 13 Jan 2016 16:00:07 -0800
+Subject: md/raid: only permit hot-add of compatible integrity profiles
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 1501efadc524a0c99494b576923091589a52d2a4 upstream.
+
+It is not safe for an integrity profile to be changed while i/o is
+in-flight in the queue.  Prevent adding new disks or otherwise online
+spares to an array if the device has an incompatible integrity profile.
+
+The original change to the blk_integrity_unregister implementation in
+md, commmit c7bfced9a671 "md: suspend i/o during runtime
+blk_integrity_unregister" introduced an immediate hang regression.
+
+This policy of disallowing changes the integrity profile once one has
+been established is shared with DM.
+
+Here is an abbreviated log from a test run that:
+1/ Creates a degraded raid1 with an integrity-enabled device (pmem0s) [   59.076127]
+2/ Tries to add an integrity-disabled device (pmem1m) [   90.489209]
+3/ Retries with an integrity-enabled device (pmem1s) [  205.671277]
+
+[   59.076127] md/raid1:md0: active with 1 out of 2 mirrors
+[   59.078302] md: data integrity enabled on md0
+[..]
+[   90.489209] md0: incompatible integrity profile for pmem1m
+[..]
+[  205.671277] md: super_written gets error=-5
+[  205.677386] md/raid1:md0: Disk failure on pmem1m, disabling device.
+[  205.677386] md/raid1:md0: Operation continuing on 1 devices.
+[  205.683037] RAID1 conf printout:
+[  205.684699]  --- wd:1 rd:2
+[  205.685972]  disk 0, wo:0, o:1, dev:pmem0s
+[  205.687562]  disk 1, wo:1, o:1, dev:pmem1s
+[  205.691717] md: recovery of RAID array md0
+
+Fixes: c7bfced9a671 ("md: suspend i/o during runtime blk_integrity_unregister")
+Cc: Mike Snitzer <snitzer@redhat.com>
+Reported-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: NeilBrown <neilb@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/md/md.c        |   28 ++++++++++++++++------------
+ drivers/md/md.h        |    2 +-
+ drivers/md/multipath.c |    6 +++---
+ drivers/md/raid1.c     |    6 +++---
+ drivers/md/raid10.c    |    6 +++---
+ 5 files changed, 26 insertions(+), 22 deletions(-)
+
+--- a/drivers/md/md.c
++++ b/drivers/md/md.c
+@@ -2017,28 +2017,32 @@ int md_integrity_register(struct 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);
+--- a/drivers/md/md.h
++++ b/drivers/md/md.h
+@@ -657,7 +657,7 @@ extern void md_wait_for_blocked_rdev(str
+ extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
+ extern int md_check_no_bitmap(struct mddev *mddev);
+ extern int md_integrity_register(struct mddev *mddev);
+-extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
++extern int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
+ extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
+ extern void mddev_init(struct mddev *mddev);
+--- a/drivers/md/multipath.c
++++ b/drivers/md/multipath.c
+@@ -257,6 +257,9 @@ static int multipath_add_disk(struct mdd
+                       disk_stack_limits(mddev->gendisk, rdev->bdev,
+                                         rdev->data_offset << 9);
++                      err = md_integrity_add_rdev(rdev, mddev);
++                      if (err)
++                              break;
+                       spin_lock_irq(&conf->device_lock);
+                       mddev->degraded--;
+                       rdev->raid_disk = path;
+@@ -264,9 +267,6 @@ static int multipath_add_disk(struct mdd
+                       spin_unlock_irq(&conf->device_lock);
+                       rcu_assign_pointer(p->rdev, rdev);
+                       err = 0;
+-                      mddev_suspend(mddev);
+-                      md_integrity_add_rdev(rdev, mddev);
+-                      mddev_resume(mddev);
+                       break;
+               }
+--- a/drivers/md/raid1.c
++++ b/drivers/md/raid1.c
+@@ -1589,6 +1589,9 @@ static int raid1_add_disk(struct mddev *
+       if (mddev->recovery_disabled == conf->recovery_disabled)
+               return -EBUSY;
++      if (md_integrity_add_rdev(rdev, mddev))
++              return -ENXIO;
++
+       if (rdev->raid_disk >= 0)
+               first = last = rdev->raid_disk;
+@@ -1632,9 +1635,6 @@ static int raid1_add_disk(struct mddev *
+                       break;
+               }
+       }
+-      mddev_suspend(mddev);
+-      md_integrity_add_rdev(rdev, mddev);
+-      mddev_resume(mddev);
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
+       print_conf(conf);
+--- a/drivers/md/raid10.c
++++ b/drivers/md/raid10.c
+@@ -1698,6 +1698,9 @@ static int raid10_add_disk(struct mddev
+       if (rdev->saved_raid_disk < 0 && !_enough(conf, 1, -1))
+               return -EINVAL;
++      if (md_integrity_add_rdev(rdev, mddev))
++              return -ENXIO;
++
+       if (rdev->raid_disk >= 0)
+               first = last = rdev->raid_disk;
+@@ -1739,9 +1742,6 @@ static int raid10_add_disk(struct mddev
+               rcu_assign_pointer(p->rdev, rdev);
+               break;
+       }
+-      mddev_suspend(mddev);
+-      md_integrity_add_rdev(rdev, mddev);
+-      mddev_resume(mddev);
+       if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
+               queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
index e5fed62a338e542f3053cff61aead9c27724f656..945d4bc2b1c6e99e057bffe52cd786b439bee8cf 100644 (file)
@@ -19,3 +19,4 @@ printk-do-cond_resched-between-lines-while-outputting-to-consoles.patch
 parisc-protect-huge-page-pte-changes-with-spinlocks.patch
 parisc-fix-__arch_si_preamble_size.patch
 media-i2c-don-t-export-ir-kbd-i2c-module-alias.patch
+md-raid-only-permit-hot-add-of-compatible-integrity-profiles.patch