dm table: propagate BDI_CAP_STABLE_WRITES to fix sporadic checksum errors [Linux 3.16.72]

This Linux kernel change "dm table: propagate BDI_CAP_STABLE_WRITES to fix sporadic checksum errors" is included in the Linux 3.16.72 release. This change is authored by Ilya Dryomov <idryomov [at] gmail.com> on Tue Mar 26 20:20:58 2019 +0100. The commit for this change in Linux stable tree is 2f62bb9 (patch) which is from upstream commit eb40c0a. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream eb40c0a.

dm table: propagate BDI_CAP_STABLE_WRITES to fix sporadic checksum errors

commit eb40c0acdc342b815d4d03ae6abb09e80c0f2988 upstream.

Some devices don't use blk_integrity but still want stable pages
because they do their own checksumming.  Examples include rbd and iSCSI
when data digests are negotiated.  Stacking DM (and thus LVM) on top of
these devices results in sporadic checksum errors.

Set BDI_CAP_STABLE_WRITES if any underlying device has it set.

Signed-off-by: Ilya Dryomov <[email protected]>
Signed-off-by: Mike Snitzer <[email protected]>
[bwh: Backported to 3.16: request_queue::backing_dev_info is a struct
 not a pointer]
Signed-off-by: Ben Hutchings <[email protected]>

There are 39 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/md/dm-table.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index f5f1837..b010f96 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1432,6 +1432,36 @@ static bool dm_table_supports_write_same(struct dm_table *t)
    return true;
 }

+static int device_requires_stable_pages(struct dm_target *ti,
+                   struct dm_dev *dev, sector_t start,
+                   sector_t len, void *data)
+{
+   struct request_queue *q = bdev_get_queue(dev->bdev);
+
+   return q && bdi_cap_stable_pages_required(&q->backing_dev_info);
+}
+
+/*
+ * If any underlying device requires stable pages, a table must require
+ * them as well.  Only targets that support iterate_devices are considered:
+ * don't want error, zero, etc to require stable pages.
+ */
+static bool dm_table_requires_stable_pages(struct dm_table *t)
+{
+   struct dm_target *ti;
+   unsigned i;
+
+   for (i = 0; i < dm_table_get_num_targets(t); i++) {
+       ti = dm_table_get_target(t, i);
+
+       if (ti->type->iterate_devices &&
+           ti->type->iterate_devices(ti, device_requires_stable_pages, NULL))
+           return true;
+   }
+
+   return false;
+}
+
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
                   struct queue_limits *limits)
 {
@@ -1474,6 +1504,15 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
    dm_table_set_integrity(t);

    /*
+    * Some devices don't use blk_integrity but still want stable pages
+    * because they do their own checksumming.
+    */
+   if (dm_table_requires_stable_pages(t))
+       q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+   else
+       q->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES;
+
+   /*
     * Determine whether or not this queue's I/O timings contribute
     * to the entropy pool, Only request-based targets use this.
     * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not

Leave a Reply

Your email address will not be published. Required fields are marked *