diff options
author | Milan Broz <mbroz@redhat.com> | 2008-07-21 07:00:37 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2008-07-21 07:00:37 -0400 |
commit | f6fccb1213ba3d661baeb2a5eee0a9701dc03e1b (patch) | |
tree | 456671e791f8a61b40e0d622591b902ca1351ae7 | |
parent | 92e868122edf08b9fc06b112e7e0c80ab94c1f93 (diff) |
dm: introduce merge_bvec_fn
Introduce a bvec merge function for device mapper devices
for dynamic size restrictions.
This code ensures the requested biovec lies within a single
target and then calls a target-specific function to check
against any constraints imposed by underlying devices.
Signed-off-by: Milan Broz <mbroz@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r-- | drivers/md/dm.c | 44 | ||||
-rw-r--r-- | include/linux/device-mapper.h | 6 | ||||
-rw-r--r-- | include/linux/dm-ioctl.h | 4 |
3 files changed, 52 insertions, 2 deletions
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index efe969074928..bca448e11878 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -829,6 +829,49 @@ static int __split_bio(struct mapped_device *md, struct bio *bio) | |||
829 | * CRUD END | 829 | * CRUD END |
830 | *---------------------------------------------------------------*/ | 830 | *---------------------------------------------------------------*/ |
831 | 831 | ||
832 | static int dm_merge_bvec(struct request_queue *q, | ||
833 | struct bvec_merge_data *bvm, | ||
834 | struct bio_vec *biovec) | ||
835 | { | ||
836 | struct mapped_device *md = q->queuedata; | ||
837 | struct dm_table *map = dm_get_table(md); | ||
838 | struct dm_target *ti; | ||
839 | sector_t max_sectors; | ||
840 | int max_size; | ||
841 | |||
842 | if (unlikely(!map)) | ||
843 | return 0; | ||
844 | |||
845 | ti = dm_table_find_target(map, bvm->bi_sector); | ||
846 | |||
847 | /* | ||
848 | * Find maximum amount of I/O that won't need splitting | ||
849 | */ | ||
850 | max_sectors = min(max_io_len(md, bvm->bi_sector, ti), | ||
851 | (sector_t) BIO_MAX_SECTORS); | ||
852 | max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size; | ||
853 | if (max_size < 0) | ||
854 | max_size = 0; | ||
855 | |||
856 | /* | ||
857 | * merge_bvec_fn() returns number of bytes | ||
858 | * it can accept at this offset | ||
859 | * max is precomputed maximal io size | ||
860 | */ | ||
861 | if (max_size && ti->type->merge) | ||
862 | max_size = ti->type->merge(ti, bvm, biovec, max_size); | ||
863 | |||
864 | /* | ||
865 | * Always allow an entire first page | ||
866 | */ | ||
867 | if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT)) | ||
868 | max_size = biovec->bv_len; | ||
869 | |||
870 | dm_table_put(map); | ||
871 | |||
872 | return max_size; | ||
873 | } | ||
874 | |||
832 | /* | 875 | /* |
833 | * The request function that just remaps the bio built up by | 876 | * The request function that just remaps the bio built up by |
834 | * dm_merge_bvec. | 877 | * dm_merge_bvec. |
@@ -1032,6 +1075,7 @@ static struct mapped_device *alloc_dev(int minor) | |||
1032 | blk_queue_make_request(md->queue, dm_request); | 1075 | blk_queue_make_request(md->queue, dm_request); |
1033 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); | 1076 | blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); |
1034 | md->queue->unplug_fn = dm_unplug_all; | 1077 | md->queue->unplug_fn = dm_unplug_all; |
1078 | blk_queue_merge_bvec(md->queue, dm_merge_bvec); | ||
1035 | 1079 | ||
1036 | md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); | 1080 | md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); |
1037 | if (!md->io_pool) | 1081 | if (!md->io_pool) |
diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 0d8d419d191a..a90222e3297d 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h | |||
@@ -9,11 +9,13 @@ | |||
9 | #define _LINUX_DEVICE_MAPPER_H | 9 | #define _LINUX_DEVICE_MAPPER_H |
10 | 10 | ||
11 | #include <linux/bio.h> | 11 | #include <linux/bio.h> |
12 | #include <linux/blkdev.h> | ||
12 | 13 | ||
13 | struct dm_target; | 14 | struct dm_target; |
14 | struct dm_table; | 15 | struct dm_table; |
15 | struct dm_dev; | 16 | struct dm_dev; |
16 | struct mapped_device; | 17 | struct mapped_device; |
18 | struct bio_vec; | ||
17 | 19 | ||
18 | typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; | 20 | typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; |
19 | 21 | ||
@@ -72,6 +74,9 @@ typedef int (*dm_ioctl_fn) (struct dm_target *ti, struct inode *inode, | |||
72 | struct file *filp, unsigned int cmd, | 74 | struct file *filp, unsigned int cmd, |
73 | unsigned long arg); | 75 | unsigned long arg); |
74 | 76 | ||
77 | typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm, | ||
78 | struct bio_vec *biovec, int max_size); | ||
79 | |||
75 | void dm_error(const char *message); | 80 | void dm_error(const char *message); |
76 | 81 | ||
77 | /* | 82 | /* |
@@ -107,6 +112,7 @@ struct target_type { | |||
107 | dm_status_fn status; | 112 | dm_status_fn status; |
108 | dm_message_fn message; | 113 | dm_message_fn message; |
109 | dm_ioctl_fn ioctl; | 114 | dm_ioctl_fn ioctl; |
115 | dm_merge_fn merge; | ||
110 | }; | 116 | }; |
111 | 117 | ||
112 | struct io_restrictions { | 118 | struct io_restrictions { |
diff --git a/include/linux/dm-ioctl.h b/include/linux/dm-ioctl.h index b03c41bbfa14..28c2940eb30d 100644 --- a/include/linux/dm-ioctl.h +++ b/include/linux/dm-ioctl.h | |||
@@ -256,9 +256,9 @@ enum { | |||
256 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) | 256 | #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) |
257 | 257 | ||
258 | #define DM_VERSION_MAJOR 4 | 258 | #define DM_VERSION_MAJOR 4 |
259 | #define DM_VERSION_MINOR 13 | 259 | #define DM_VERSION_MINOR 14 |
260 | #define DM_VERSION_PATCHLEVEL 0 | 260 | #define DM_VERSION_PATCHLEVEL 0 |
261 | #define DM_VERSION_EXTRA "-ioctl (2007-10-18)" | 261 | #define DM_VERSION_EXTRA "-ioctl (2008-04-23)" |
262 | 262 | ||
263 | /* Status bits */ | 263 | /* Status bits */ |
264 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ | 264 | #define DM_READONLY_FLAG (1 << 0) /* In/Out */ |