[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [dm-devel] [RFC] File backed target for device-mapper



Am Mi, 2003-07-23 um 01.17 schrieb Christophe Saout:

> Well, a /dev/zero-like target is very easy (attached).

Damn...

--
Christophe Saout <christophe saout de>
Please avoid sending me Word or PowerPoint attachments.
See http://www.fsf.org/philosophy/no-word-attachments.html
/*
 * Copyright (C) 2001 Sistina Software (UK) Limited.
 *
 * This file is released under the GPL.
 */

#include "dm.h"

#include <linux/module.h>
#include <linux/init.h>
#include <linux/bio.h>

/*
 * Returns the minimum that is _not_ zero, unless both are zero.
 */
#define min_not_zero(l, r) (l == 0) ? r : ((r == 0) ? l : min(l, r))

/*
 * Combine the io_restrictions with the default restrictions
 */
static void combine_default_restrictions(struct io_restrictions *rs)
{
	rs->max_sectors =
		min_not_zero(rs->max_sectors, (unsigned short)MAX_SECTORS);

	rs->max_phys_segments =
		min_not_zero(rs->max_phys_segments, (unsigned short)MAX_PHYS_SEGMENTS);

	rs->max_hw_segments =
		min_not_zero(rs->max_hw_segments, (unsigned short)MAX_HW_SEGMENTS);

	rs->hardsect_size =
		max(rs->hardsect_size, (unsigned short)(1 << SECTOR_SHIFT));

	rs->max_segment_size =
		min_not_zero(rs->max_segment_size, (unsigned int)MAX_SEGMENT_SIZE);

	rs->seg_boundary_mask =
		min_not_zero(rs->seg_boundary_mask, (unsigned long)0xffffffff);
}

/*
 * Construct a dummy mapping that only returns zeroes
 */
static int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
	if (argc != 0) {
		ti->error = "dm-zero: No arguments required";
		return -EINVAL;
	}

	/*
	 * FIXME: Since we don't call dm_get_device, we
	 * have to combine the device limits ourself
	 */
	combine_default_restrictions(&ti->limits);

	return 0;
}

/*
 * Fills the bio pages with zeroes
 */
static void zero_fill_bio(struct bio *bio)
{
	unsigned long flags;
	struct bio_vec *bv;
	int i;

	bio_for_each_segment(bv, bio, i) {
		char *data = bvec_kmap_irq(bv, &flags);
		memset(data, 0, bv->bv_len);
		bvec_kunmap_irq(bv, &flags);
	}
}

/*
 * Return zeroes only on reads
 */
static int zero_map(struct dm_target *ti, struct bio *bio,
		      union map_info *map_context)
{
	switch(bio_rw(bio)) {
	case READ:
		zero_fill_bio(bio);
		break;
	case READA:
		/* readahead of null bytes only wastes buffer cache */
		return -EIO;
	case WRITE:
		/* writes get silently dropped */
		break;
	}

	bio_endio(bio, bio->bi_size, 0);

	/* accepted bio, don't make new request */
	return 0;
}

static struct target_type zero_target = {
	.name   = "zero",
	.module = THIS_MODULE,
	.ctr    = zero_ctr,
	.map    = zero_map,
};

int __init dm_zero_init(void)
{
	int r = dm_register_target(&zero_target);

	if (r < 0)
		DMERR("zero: register failed %d", r);

	return r;
}

void dm_zero_exit(void)
{
	int r = dm_unregister_target(&zero_target);

	if (r < 0)
		DMERR("zero: unregister failed %d", r);
}

/*
 * module hooks
 */
module_init(dm_zero_init)
module_exit(dm_zero_exit)

MODULE_AUTHOR("Christophe Saout <christophe saout de>");
MODULE_DESCRIPTION(DM_NAME " dummy target returning zeroes");
MODULE_LICENSE("GPL");

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]