From patchwork Wed Jan 7 19:31:23 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: 1229 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 n07JRrgk031668 for ; Wed, 7 Jan 2009 11:27:53 -0800 Received: from listman.util.phx.redhat.com (listman.util.phx.redhat.com [10.8.4.110]) by hormel.redhat.com (Postfix) with ESMTP id 39743619A92; Wed, 7 Jan 2009 14:31:28 -0500 (EST) Received: from int-mx2.corp.redhat.com (nat-pool.util.phx.redhat.com [10.8.5.200]) by listman.util.phx.redhat.com (8.13.1/8.13.1) with ESMTP id n07JVQ0c025717 for ; Wed, 7 Jan 2009 14:31:26 -0500 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 n07JVQi1024921; Wed, 7 Jan 2009 14:31:27 -0500 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 n07JVPv3002308; Wed, 7 Jan 2009 14:31:26 -0500 Received: from agk by agk.fab.redhat.com with local (Exim 4.34) id 1LKe7f-0007zI-NA; Wed, 07 Jan 2009 19:31:23 +0000 Date: Wed, 7 Jan 2009 19:31:23 +0000 From: Alasdair G Kergon To: "Martin K. Petersen" Subject: Re: [dm-devel] [PATCH] DM Block integrity support Message-ID: <20090107193123.GQ3512@agk.fab.redhat.com> Mail-Followup-To: "Martin K. Petersen" , jens.axboe@oracle.com, device-mapper development References: Mime-Version: 1.0 Content-Disposition: inline In-Reply-To: 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 , jens.axboe@oracle.com 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 New additions merged back into the original cleaned-up patch and unresolved header comments updated. Alasdair. From: Martin K. Petersen This patch provides support for data integrity passthrough in the device mapper. - If one or more component devices support integrity an integrity profile is preallocated for the DM device. [FIXME: Looks as if that will hit BUG_ON(template == NULL) - maybe there's an undocumented dependency on some other patch? Does this handle table swaps correctly? i.e. NULL must leave any existing (live) setting unchanged.] - If all component devices have compatible profiles the DM device is flagged as capable. - Handle integrity metadata when splitting and cloning bios. [FIXME: Does this cope with integrity profile needing removing after a table swap?] [FIXME: blk_integrity_register() allocating & manipulating kobjects needs moving outside __bind(). - Does the preallocation address this now, with the exception of some unimportant races we'll ignore but should document? E.g. If integrity profile appears on an underlying device between the reload and the table swap. Would it be better for the table swap to fail in that particular case?] Signed-off-by: Martin K. Petersen --- drivers/md/dm-ioctl.c | 21 +++++++++++++++++++++ drivers/md/dm-table.c | 39 +++++++++++++++++++++++++++++++++++++++ drivers/md/dm.c | 15 +++++++++++++++ 3 files changed, 75 insertions(+) -- dm-devel mailing list dm-devel@redhat.com https://www.redhat.com/mailman/listinfo/dm-devel Index: linux-2.6.28/drivers/md/dm-ioctl.c =================================================================== --- linux-2.6.28.orig/drivers/md/dm-ioctl.c 2009-01-06 21:36:12.000000000 +0000 +++ linux-2.6.28/drivers/md/dm-ioctl.c 2009-01-07 18:34:15.000000000 +0000 @@ -1047,6 +1047,19 @@ static int populate_table(struct dm_tabl return dm_table_complete(table); } +static int table_prealloc_integrity(struct dm_table *t, + struct mapped_device *md) +{ + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *dd; + + list_for_each_entry(dd, devices, list) + if (bdev_get_integrity(dd->dm_dev.bdev)) + return blk_integrity_register(dm_disk(md), NULL); + + return 0; +} + static int table_load(struct dm_ioctl *param, size_t param_size) { int r; @@ -1068,6 +1081,14 @@ static int table_load(struct dm_ioctl *p goto out; } + r = table_prealloc_integrity(t, md); + if (r) { + DMERR("%s: could not register integrity profile.", + dm_device_name(md)); + dm_table_destroy(t); + goto out; + } + down_write(&_hash_lock); hc = dm_get_mdptr(md); if (!hc || hc->md != md) { Index: linux-2.6.28/drivers/md/dm-table.c =================================================================== --- linux-2.6.28.orig/drivers/md/dm-table.c 2009-01-07 15:38:20.000000000 +0000 +++ linux-2.6.28/drivers/md/dm-table.c 2009-01-07 18:56:59.000000000 +0000 @@ -877,6 +877,44 @@ struct dm_target *dm_table_find_target(s return &t->targets[(KEYS_PER_NODE * n) + k]; } +/* + * Set the integrity profile for this device if all devices used have + * matching profiles. + */ +static void dm_table_set_integrity(struct dm_table *t) +{ + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *prev = NULL, *dd = NULL; + struct blk_integrity *bi; + + list_for_each_entry(dd, devices, list) { + if (prev && + blk_integrity_compare(prev->dm_dev.bdev->bd_disk, + dd->dm_dev.bdev->bd_disk) < 0) { + DMWARN("%s: integrity not set: %s and %s mismatch", + dm_device_name(t->md), + prev->dm_dev.bdev->bd_disk->disk_name, + dd->dm_dev.bdev->bd_disk->disk_name); + return; + } + prev = dd; + } + + if (!prev) + return; + + bi = bdev_get_integrity(prev->dm_dev.bdev); + if (!bi) + return; + + /* Register dm device as being integrity capable */ + if (blk_integrity_register(dm_disk(t->md), bi)) + DMERR("%s: %s: blk_integrity_register failed.", + __func__, dm_device_name(t->md)); + else + DMDEBUG("%s: Enabling data integrity.", dm_device_name(t->md)); +} + void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) { /* @@ -897,6 +935,7 @@ void dm_table_set_restrictions(struct dm else queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q); + dm_table_set_integrity(t); } unsigned int dm_table_get_num_targets(struct dm_table *t) Index: linux-2.6.28/drivers/md/dm.c =================================================================== --- linux-2.6.28.orig/drivers/md/dm.c 2009-01-07 15:38:20.000000000 +0000 +++ linux-2.6.28/drivers/md/dm.c 2009-01-07 18:43:17.000000000 +0000 @@ -703,6 +703,12 @@ static struct bio *split_bvec(struct bio clone->bi_io_vec->bv_len = clone->bi_size; clone->bi_flags |= 1 << BIO_CLONED; + if (bio_integrity(bio)) { + bio_integrity_clone(clone, bio, bs); + bio_integrity_trim(clone, + bio_sector_offset(bio, idx, offset), len); + } + return clone; } @@ -724,6 +730,14 @@ static struct bio *clone_bio(struct bio clone->bi_size = to_bytes(len); clone->bi_flags &= ~(1 << BIO_SEG_VALID); + if (bio_integrity(bio)) { + bio_integrity_clone(clone, bio, bs); + + if (idx != bio->bi_idx || clone->bi_size < bio->bi_size) + bio_integrity_trim(clone, + bio_sector_offset(bio, idx, 0), len); + } + return clone; } @@ -1191,6 +1205,7 @@ static void free_dev(struct mapped_devic mempool_destroy(md->tio_pool); mempool_destroy(md->io_pool); bioset_free(md->bs); + blk_integrity_unregister(md->disk); del_gendisk(md->disk); free_minor(minor);