From patchwork Wed Apr 22 13:25:43 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alasdair G Kergon X-Patchwork-Id: 19346 Received: from hormel.redhat.com (hormel1.redhat.com [209.132.177.33]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n3MDPoNI010634 for ; Wed, 22 Apr 2009 13:25:51 GMT Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id AEC1A619103; Wed, 22 Apr 2009 09:25:47 -0400 (EDT) Received: from int-mx2.corp.redhat.com ([172.16.27.26]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id n3MDPjQc007401 for ; Wed, 22 Apr 2009 09:25:45 -0400 Received: from ns3.rdu.redhat.com (ns3.rdu.redhat.com [10.11.255.199]) by int-mx2.corp.redhat.com (8.13.1/8.13.1) with ESMTP id n3MDPilg026874; Wed, 22 Apr 2009 09:25:44 -0400 Received: from agk.fab.redhat.com (agk.fab.redhat.com [10.33.0.19]) by ns3.rdu.redhat.com (8.13.8/8.13.8) with ESMTP id n3MDPhCT017012; Wed, 22 Apr 2009 09:25:43 -0400 Received: from agk by agk.fab.redhat.com with local (Exim 4.34) id 1LwcSN-00025Q-64; Wed, 22 Apr 2009 14:25:43 +0100 Date: Wed, 22 Apr 2009 14:25:43 +0100 From: Alasdair G Kergon To: Mike Snitzer Subject: Re: [dm-devel] [PATCH v2] dm table: verify a DM device is H/W sector aligned Message-ID: <20090422132543.GA7778@agk.fab.redhat.com> Mail-Followup-To: Mike Snitzer , device-mapper development References: <1240327259-14412-1-git-send-email-snitzer@redhat.com> Mime-Version: 1.0 Content-Disposition: inline In-Reply-To: <1240327259-14412-1-git-send-email-snitzer@redhat.com> User-Agent: Mutt/1.4.1i Organization: Red Hat UK Ltd. Registered in England and Wales, number 03798903. Registered Office: Amberley Place, 107-111 Peascod Street, Windsor, Berkshire, SL4 1TE. X-Scanned-By: MIMEDefang 2.58 on 172.16.27.26 X-loop: dm-devel@redhat.com Cc: device-mapper development X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.5 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com I've tried to make this easier to understand. Please check I've not broken something in the process... From: Mike Snitzer Impose necessary and sufficient conditions on a devices's table such that any incoming bio which respects its hardsect_size can be processed successfully. Signed-off-by: Mike Snitzer --- drivers/md/dm-table.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel Index: linux-2.6.30-rc2/drivers/md/dm-table.c =================================================================== --- linux-2.6.30-rc2.orig/drivers/md/dm-table.c +++ linux-2.6.30-rc2/drivers/md/dm-table.c @@ -719,6 +719,70 @@ static void check_for_valid_limits(struc rs->bounce_pfn = -1; } +/* + * Impose necessary and sufficient conditions on a devices's table such + * that any incoming bio which respects its hardsect_size can be + * processed successfully. If it falls across the boundary between + * two or more targets, the size of each piece it gets split into must + * be compatible with the hardsect_size of the target processing it. + */ +static int validate_hardsect_alignment(struct dm_table *table) +{ + /* + * This function uses arithmetic modulo the hardsect_size + * (in units of 512-byte sectors). + */ + unsigned short device_hardsect_size_sects = + table->limits.hardsect_size >> SECTOR_SHIFT; + + /* + * Offset of the start of the next table entry, mod hardsect_size. + */ + unsigned short next_target_start = 0; + + /* + * Given an aligned bio that extends beyond the end of a + * target, how many sectors must the next target handle? + */ + unsigned short remaining = 0; + + struct dm_target *ti; + unsigned i = 0; + + /* + * Check each entry in the table in turn. + */ + while (i < dm_table_get_num_targets(table)) { + ti = dm_table_get_target(table, i++); + + /* + * If the remaining sectors fall entirely within this + * table entry are they compatible with its hardsect_size? + */ + if (remaining < ti->len && + remaining & (ti->limits.hardsect_size >> SECTOR_SHIFT) - 1) + break; /* Error */ + + next_target_start = + (unsigned short) ((next_target_start + ti->len) & + (device_hardsect_size_sects - 1)); + remaining = next_target_start ? + device_hardsect_size_sects - next_target_start : 0; + } + + if (remaining) { + DMWARN("%s: table line %u (start sect %llu len %llu) " + "not aligned to hardware sector size %hu", + dm_device_name(table->md), i, + (unsigned long long) ti->begin, + (unsigned long long) ti->len, + table->limits.hardsect_size); + return -EINVAL; + } + + return 0; +} + int dm_table_add_target(struct dm_table *t, const char *type, sector_t start, sector_t len, char *params) { @@ -818,6 +882,10 @@ int dm_table_complete(struct dm_table *t check_for_valid_limits(&t->limits); + r = validate_hardsect_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);