[dm-devel] [PATCH] dm table: verify a DM device is H/W sector aligned
Mike Snitzer
snitzer at redhat.com
Wed Apr 15 18:46:35 UTC 2009
Verify a table's targets can collectively accommodate the device's
hardsect_size aligned I/O in addition to their own hardsect_size
alignment; paying attention to target boundaries in the table.
- incoming I/O is aligned to the device's hardsect_size
- each target is aligned to the target's hardsect_size
- device's hardsect_size >= each targets' hardsect_size
- device and targets' hardsect_size are always powers of 2
Signed-off-by: Mike Snitzer <snitzer at redhat.com>
---
drivers/md/dm-table.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 65 insertions(+), 0 deletions(-)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index e8f8d11..6e74e9a 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -717,6 +717,67 @@ static void check_for_valid_limits(struct io_restrictions *rs)
rs->bounce_pfn = -1;
}
+/*
+ * Verify a table's targets can collectively accommodate the device's
+ * hardsect_size aligned I/O in addition to their own hardsect_size
+ * alignment; paying attention to target boundaries in the table
+ * - incoming I/O is aligned to the device's hardsect_size
+ * - each target is aligned to the target's hardsect_size
+ * - device's hardsect_size >= each targets' hardsect_size
+ * - device and targets' hardsect_size are always powers of 2
+ */
+static int check_for_valid_alignment(struct dm_table *table)
+{
+ int r = 0;
+ unsigned int i, num_targets;
+ struct dm_target *ti = NULL;
+ unsigned short partial_sectors, remaining_sectors = 0;
+ unsigned short ti_hardsect_size_sectors = 0;
+ unsigned short device_hardsect_size_sectors =
+ table->limits.hardsect_size >> SECTOR_SHIFT;
+
+ num_targets = dm_table_get_num_targets(table);
+ for (i = 0; i < num_targets; i++) {
+ ti = dm_table_get_target(table, i);
+ ti_hardsect_size_sectors =
+ ti->limits.hardsect_size >> SECTOR_SHIFT;
+
+ /*
+ * Check that remaining_sectors from the previous target
+ * do not disturb this target's hardsect_size alignment
+ * - if remaining_sectors is greater than this
+ * target's len: it is the next target's concern
+ */
+ if ((remaining_sectors && remaining_sectors < ti->len) &&
+ (remaining_sectors & (ti_hardsect_size_sectors - 1))) {
+ r = -EINVAL;
+ break;
+ }
+
+ /*
+ * Determine if device's hardsect_size aligned I/O crosses
+ * target boundaries; any remaining_sectors must be handled
+ * by the next target(s) -- otherwise the table is misaligned
+ */
+ partial_sectors = (ti->begin + ti->len) &
+ (device_hardsect_size_sectors - 1);
+ if (partial_sectors) {
+ remaining_sectors = device_hardsect_size_sectors -
+ partial_sectors;
+ } else
+ remaining_sectors = 0;
+ }
+
+ if (remaining_sectors) {
+ DMWARN("%s: mapping with begin=%lu len=%lu "
+ "not device H/W sector aligned",
+ dm_device_name(table->md), ti->begin, ti->len);
+ r = -EINVAL;
+ }
+
+ return r;
+}
+
int dm_table_add_target(struct dm_table *t, const char *type,
sector_t start, sector_t len, char *params)
{
@@ -816,6 +877,10 @@ int dm_table_complete(struct dm_table *t)
check_for_valid_limits(&t->limits);
+ r = check_for_valid_alignment(t);
+ if (r)
+ return r;
+
/* how many indexes will the btree have ? */
leaf_nodes = dm_div_up(t->num_targets, KEYS_PER_NODE);
t->depth = 1 + int_log(leaf_nodes, CHILDREN_PER_NODE);
--
1.6.0.6
More information about the dm-devel
mailing list