If all subdevices support the same protection format the DM device is
flagged as capable.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
---
drivers/md/dm-table.c | 35 ++++++++++++++++++++++++++++++++++-
drivers/md/dm.c | 26 ++++++++++++++++++++++++--
drivers/md/dm.h | 2 +-
include/linux/device-mapper.h | 1 +
4 files changed, 60 insertions(+), 4 deletions(-)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 61f4414..006a10e 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -841,8 +841,12 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}
-void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
+void dm_table_set_restrictions(struct dm_table *t, struct mapped_device *md)
{
+ struct request_queue *q = dm_queue(md);
+ struct list_head *devices = dm_table_get_devices(t);
+ struct dm_dev *prev, *cur;
+
/*
* Make sure we obey the optimistic sub devices
* restrictions.
@@ -861,6 +865,35 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
else
queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
+ /*
+ * Run through all devices to ensure they have matching
+ * integrity profile
+ */
+ cur = prev = NULL;
+
+ list_for_each_entry(cur, devices, list) {
+
+ if (prev && blk_integrity_compare(prev->bdev, cur->bdev) < 0) {
+ printk(KERN_ERR "%s: %s %s Integrity mismatch!\n",
+ __func__, prev->bdev->bd_disk->disk_name,
+ cur->bdev->bd_disk->disk_name);
+ return;
+ }
+ prev = cur;
+ }
+
+ /* Register dm device as being integrity capable */
+ if (prev && bdev_get_integrity(prev->bdev)) {
+ struct gendisk *disk = dm_disk(md);
+
+ if (blk_integrity_register(dm_disk(md),
+ bdev_get_integrity(prev->bdev)))
+ printk(KERN_ERR "%s: %s Could not register integrity!\n",
+ __func__, ...Please use checkpatch. Always. There's just no reason not to. Sure, you can make a decision to ignore some of its reports, but at least For better or for worse, the developers of dm.c have chosen to keep the whole file presentable in an 80-col display. This patch breaks that, This will provide no more information than the oops which will happen This (unused, undocumented) function should be inlined. --
Sorry about the delayed response. I'm still on the road after LPC. Andrew> For better or for worse, the developers of dm.c have chosen to Andrew> keep the whole file presentable in an 80-col display. This Andrew> patch breaks that, and they might not like this. I've broken the lines. [Excessive BUG_ONs] Andrew> This will provide no more information than the oops which will Andrew> happen two lines later. Andrew> This (unused, undocumented) function should be inlined. - It's not unused. - return md->queue is more descriptive than anything I could possibly put in a comment. - None of the other accessor functions in DM are inlined. I'll let Alasdair decide. Updated patches follow. -- Martin K. Petersen Oracle Linux Engineering --
If all subdevices support the same protection format the DM device is
flagged as capable.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
---
drivers/md/dm-table.c | 35 ++++++++++++++++++++++++++++++++++-
drivers/md/dm.c | 24 ++++++++++++++++++++++--
drivers/md/dm.h | 2 +-
include/linux/device-mapper.h | 1 +
4 files changed, 58 insertions(+), 4 deletions(-)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index 61f4414..7290a90 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -841,8 +841,12 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
return &t->targets[(KEYS_PER_NODE * n) + k];
}
-void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
+void dm_table_set_restrictions(struct dm_table *t, struct mapped_device *md)
{
+ struct request_queue *q = dm_queue(md);
+ struct list_head *devices = dm_table_get_devices(t);
+ struct dm_dev *prev, *cur;
+
/*
* Make sure we obey the optimistic sub devices
* restrictions.
@@ -861,6 +865,35 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q)
else
queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, q);
+ /*
+ * Run through all devices to ensure they have matching
+ * integrity profile
+ */
+ cur = prev = NULL;
+
+ list_for_each_entry(cur, devices, list) {
+
+ if (prev && blk_integrity_compare(prev->bdev, cur->bdev) < 0) {
+ printk(KERN_ERR "%s: %s %s Integrity mismatch!\n",
+ __func__, prev->bdev->bd_disk->disk_name,
+ cur->bdev->bd_disk->disk_name);
+ return;
+ }
+ prev = cur;
+ }
+
+ /* Register dm device as being integrity capable */
+ if (prev && bdev_get_integrity(prev->bdev)) {
+ struct gendisk *disk = dm_disk(md);
+
+ if (blk_integrity_register(dm_disk(md),
+ bdev_get_integrity(prev->bdev)))
+ printk(KERN_ERR "%s: %s Could not register integrity!\n",
+ __func__, ...Hi Martin, Creating another function (e.g. dm_table_set_integrity(t, md)) may be better, since then you wouldn't need dm_queue() nor need to change If you need dm_queue() anyway, this part should be in drivers/md/dm.h because other kernel modules like dm target drivers (e.g. dm-mirror) don't use it. Thanks, Kiyoshi Ueda --
Hi Martin, Or you can also get md from t->md or q->queuedata, if you don't mind to pass q as an argument of the function which sets integrity feature. (I thought you mind that, since the integrity feature is set to md (md->disk), not q.) Thanks, Kiyoshi Ueda --
>>>>> "Kiyoshi" == Kiyoshi Ueda <k-ueda@ct.jp.nec.com> writes: Kiyoshi> Creating another function (e.g. dm_table_set_integrity(t, Kiyoshi> md)) may be better, since then you wouldn't need dm_queue() Kiyoshi> nor need to change the function interface of Kiyoshi> dm_table_set_restrictions() I think. You are right. Originally I had more reasons for having that calling interface change but that's no longer the case. I'll fan the integrity bits out to a separate function. -- Martin K. Petersen Oracle Linux Engineering --
Helper function to find the sector offset in a bio given bvec index
and page offset.
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
---
fs/bio.c | 34 ++++++++++++++++++++++++++++++++++
include/linux/bio.h | 1 +
2 files changed, 35 insertions(+), 0 deletions(-)
diff --git a/fs/bio.c b/fs/bio.c
index e56e768..55ee2fd 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -1300,6 +1300,40 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors)
return bp;
}
+/**
+ * bio_sector_offset - Find hardware sector offset in bio
+ * @bio: bio to inspect
+ * @index: bio_vec index
+ * @offset: offset in bv_page
+ *
+ * Return the number of hardware sectors between beginning of bio
+ * and an end point indicated by a bio_vec index and an offset
+ * within that vector's page.
+ */
+sector_t bio_sector_offset(struct bio *bio, unsigned short index,
+ unsigned int offset)
+{
+ struct bio_vec *bv;
+ unsigned int sector_sz = bio->bi_bdev->bd_disk->queue->hardsect_size;
+ sector_t sectors;
+ int i;
+
+ sectors = 0;
+
+ BUG_ON(index >= bio->bi_vcnt);
+
+ bio_for_each_segment(bv, bio, i) {
+ if (i == index) {
+ if (offset > bv->bv_offset)
+ sectors += (offset - bv->bv_offset) / sector_sz;
+ return sectors;
+ }
+
+ sectors += bv->bv_len / sector_sz;
+ }
+
+ BUG();
+}
/*
* create memory pools for biovec's in a bio_set.
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 6aba97d..386a1df 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -327,6 +327,7 @@ extern int bio_add_page(struct bio *, struct page *, unsigned int,unsigned int);
extern int bio_add_pc_page(struct request_queue *, struct bio *, struct page *,
unsigned int, unsigned int);
extern int bio_get_nr_vecs(struct block_device *);
+extern sector_t bio_sector_offset(struct bio *, unsigned short, unsigned int);
extern struct bio *bio_map_user(struct request_queue *, struct block_device *,
unsigned long, ...