Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f6fccb12 authored by Milan Broz's avatar Milan Broz Committed by Alasdair G Kergon
Browse files

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: default avatarMilan Broz <mbroz@redhat.com>
Signed-off-by: default avatarAlasdair G Kergon <agk@redhat.com>
parent 92e86812
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -829,6 +829,49 @@ static int __split_bio(struct mapped_device *md, struct bio *bio)
 * 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
 * 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_bounce_limit(md->queue, BLK_BOUNCE_ANY);
	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);
	if (!md->io_pool)
+6 −0
Original line number Diff line number Diff line
@@ -9,11 +9,13 @@
#define _LINUX_DEVICE_MAPPER_H

#include <linux/bio.h>
#include <linux/blkdev.h>

struct dm_target;
struct dm_table;
struct dm_dev;
struct mapped_device;
struct bio_vec;

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,
			    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);

/*
@@ -107,6 +112,7 @@ struct target_type {
	dm_status_fn status;
	dm_message_fn message;
	dm_ioctl_fn ioctl;
	dm_merge_fn merge;
};

struct io_restrictions {
+2 −2
Original line number Diff line number Diff line
@@ -256,9 +256,9 @@ enum {
#define DM_DEV_SET_GEOMETRY	_IOWR(DM_IOCTL, DM_DEV_SET_GEOMETRY_CMD, struct dm_ioctl)

#define DM_VERSION_MAJOR	4
#define DM_VERSION_MINOR	13
#define DM_VERSION_MINOR	14
#define DM_VERSION_PATCHLEVEL	0
#define DM_VERSION_EXTRA	"-ioctl (2007-10-18)"
#define DM_VERSION_EXTRA	"-ioctl (2008-04-23)"

/* Status bits */
#define DM_READONLY_FLAG	(1 << 0) /* In/Out */