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>
This commit is contained in:
parent
92e868122e
commit
f6fccb1213
|
@ -829,6 +829,49 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
|
||||||
* CRUD END
|
* CRUD END
|
||||||
*---------------------------------------------------------------*/
|
*---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static int dm_merge_bvec(struct request_queue *q,
|
||||||
|
struct bvec_merge_data *bvm,
|
||||||
|
struct bio_vec *biovec)
|
||||||
|
{
|
||||||
|
struct mapped_device *md = q->queuedata;
|
||||||
|
struct dm_table *map = dm_get_table(md);
|
||||||
|
struct dm_target *ti;
|
||||||
|
sector_t max_sectors;
|
||||||
|
int max_size;
|
||||||
|
|
||||||
|
if (unlikely(!map))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
ti = dm_table_find_target(map, bvm->bi_sector);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find maximum amount of I/O that won't need splitting
|
||||||
|
*/
|
||||||
|
max_sectors = min(max_io_len(md, bvm->bi_sector, ti),
|
||||||
|
(sector_t) BIO_MAX_SECTORS);
|
||||||
|
max_size = (max_sectors << SECTOR_SHIFT) - bvm->bi_size;
|
||||||
|
if (max_size < 0)
|
||||||
|
max_size = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* merge_bvec_fn() returns number of bytes
|
||||||
|
* it can accept at this offset
|
||||||
|
* max is precomputed maximal io size
|
||||||
|
*/
|
||||||
|
if (max_size && ti->type->merge)
|
||||||
|
max_size = ti->type->merge(ti, bvm, biovec, max_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Always allow an entire first page
|
||||||
|
*/
|
||||||
|
if (max_size <= biovec->bv_len && !(bvm->bi_size >> SECTOR_SHIFT))
|
||||||
|
max_size = biovec->bv_len;
|
||||||
|
|
||||||
|
dm_table_put(map);
|
||||||
|
|
||||||
|
return max_size;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The request function that just remaps the bio built up by
|
* The request function that just remaps the bio built up by
|
||||||
* dm_merge_bvec.
|
* dm_merge_bvec.
|
||||||
|
@ -1032,6 +1075,7 @@ static struct mapped_device *alloc_dev(int minor)
|
||||||
blk_queue_make_request(md->queue, dm_request);
|
blk_queue_make_request(md->queue, dm_request);
|
||||||
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
|
blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
|
||||||
md->queue->unplug_fn = dm_unplug_all;
|
md->queue->unplug_fn = dm_unplug_all;
|
||||||
|
blk_queue_merge_bvec(md->queue, dm_merge_bvec);
|
||||||
|
|
||||||
md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
|
md->io_pool = mempool_create_slab_pool(MIN_IOS, _io_cache);
|
||||||
if (!md->io_pool)
|
if (!md->io_pool)
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
#define _LINUX_DEVICE_MAPPER_H
|
#define _LINUX_DEVICE_MAPPER_H
|
||||||
|
|
||||||
#include <linux/bio.h>
|
#include <linux/bio.h>
|
||||||
|
#include <linux/blkdev.h>
|
||||||
|
|
||||||
struct dm_target;
|
struct dm_target;
|
||||||
struct dm_table;
|
struct dm_table;
|
||||||
struct dm_dev;
|
struct dm_dev;
|
||||||
struct mapped_device;
|
struct mapped_device;
|
||||||
|
struct bio_vec;
|
||||||
|
|
||||||
typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
|
typedef enum { STATUSTYPE_INFO, STATUSTYPE_TABLE } status_type_t;
|
||||||
|
|
||||||
|
@ -72,6 +74,9 @@ typedef int (*dm_ioctl_fn) (struct dm_target *ti, struct inode *inode,
|
||||||
struct file *filp, unsigned int cmd,
|
struct file *filp, unsigned int cmd,
|
||||||
unsigned long arg);
|
unsigned long arg);
|
||||||
|
|
||||||
|
typedef int (*dm_merge_fn) (struct dm_target *ti, struct bvec_merge_data *bvm,
|
||||||
|
struct bio_vec *biovec, int max_size);
|
||||||
|
|
||||||
void dm_error(const char *message);
|
void dm_error(const char *message);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -107,6 +112,7 @@ struct target_type {
|
||||||
dm_status_fn status;
|
dm_status_fn status;
|
||||||
dm_message_fn message;
|
dm_message_fn message;
|
||||||
dm_ioctl_fn ioctl;
|
dm_ioctl_fn ioctl;
|
||||||
|
dm_merge_fn merge;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct io_restrictions {
|
struct io_restrictions {
|
||||||
|
|
|
@ -256,9 +256,9 @@ enum {
|
||||||
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
|
#define DM_DEV_SET_GEOMETRY _IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)
|
||||||
|
|
||||||
#define DM_VERSION_MAJOR 4
|
#define DM_VERSION_MAJOR 4
|
||||||
#define DM_VERSION_MINOR 13
|
#define DM_VERSION_MINOR 14
|
||||||
#define DM_VERSION_PATCHLEVEL 0
|
#define DM_VERSION_PATCHLEVEL 0
|
||||||
#define DM_VERSION_EXTRA "-ioctl (2007-10-18)"
|
#define DM_VERSION_EXTRA "-ioctl (2008-04-23)"
|
||||||
|
|
||||||
/* Status bits */
|
/* Status bits */
|
||||||
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
|
#define DM_READONLY_FLAG (1 << 0) /* In/Out */
|
||||||
|
|
Loading…
Reference in New Issue