Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Milan Broz and committed by
Alasdair G Kergon
f6fccb12 92e86812

+52 -2
+44
drivers/md/dm.c
··· 829 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 876 * The request function that just remaps the bio built up by 834 877 * dm_merge_bvec. ··· 1075 1032 blk_queue_make_request(md->queue, dm_request); 1076 1033 blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY); 1077 1034 md->queue->unplug_fn = dm_unplug_all; 1035 + blk_queue_merge_bvec(md->queue, dm_merge_bvec); 1078 1036 1079 1037 md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache); 1080 1038 if (!md->io_pool)
+6
include/linux/device-mapper.h
··· 9 9 #define _LINUX_DEVICE_MAPPER_H 10 10 11 11 #include <linux/bio.h> 12 + #include <linux/blkdev.h> 12 13 13 14 struct dm_target; 14 15 struct dm_table; 15 16 struct dm_dev; 16 17 struct mapped_device; 18 + struct bio_vec; 17 19 18 20 typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t; 19 21 ··· 74 72 struct file *filp, unsigned int cmd, 75 73 unsigned long arg); 76 74 75 + typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm, 76 + struct bio_vec *biovec, int max_size); 77 + 77 78 void dm_error(const char *message); 78 79 79 80 /* ··· 112 107 dm_status_fn status; 113 108 dm_message_fn message; 114 109 dm_ioctl_fn ioctl; 110 + dm_merge_fn merge; 115 111 }; 116 112 117 113 struct io_restrictions {
+2 -2
include/linux/dm-ioctl.h
··· 256 256 #define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl) 257 257 258 258 #define DM_VERSION_MAJOR 4 259 - #define DM_VERSION_MINOR 13 259 + #define DM_VERSION_MINOR 14 260 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 263 /* Status bits */ 264 264 #define DM_READONLY_FLAG (1 << 0) /* In/Out */