18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (C) 2003 Jana Saout <jana@saout.de>
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is released under the GPL.
58c2ecf20Sopenharmony_ci */
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ci#include <linux/device-mapper.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <linux/module.h>
108c2ecf20Sopenharmony_ci#include <linux/init.h>
118c2ecf20Sopenharmony_ci#include <linux/bio.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define DM_MSG_PREFIX "zero"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * Construct a dummy mapping that only returns zeros
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_cistatic int zero_ctr(struct dm_target *ti, unsigned int argc, char **argv)
198c2ecf20Sopenharmony_ci{
208c2ecf20Sopenharmony_ci	if (argc != 0) {
218c2ecf20Sopenharmony_ci		ti->error = "No arguments required";
228c2ecf20Sopenharmony_ci		return -EINVAL;
238c2ecf20Sopenharmony_ci	}
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	/*
268c2ecf20Sopenharmony_ci	 * Silently drop discards, avoiding -EOPNOTSUPP.
278c2ecf20Sopenharmony_ci	 */
288c2ecf20Sopenharmony_ci	ti->num_discard_bios = 1;
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	return 0;
318c2ecf20Sopenharmony_ci}
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci/*
348c2ecf20Sopenharmony_ci * Return zeros only on reads
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_cistatic int zero_map(struct dm_target *ti, struct bio *bio)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	switch (bio_op(bio)) {
398c2ecf20Sopenharmony_ci	case REQ_OP_READ:
408c2ecf20Sopenharmony_ci		if (bio->bi_opf & REQ_RAHEAD) {
418c2ecf20Sopenharmony_ci			/* readahead of null bytes only wastes buffer cache */
428c2ecf20Sopenharmony_ci			return DM_MAPIO_KILL;
438c2ecf20Sopenharmony_ci		}
448c2ecf20Sopenharmony_ci		zero_fill_bio(bio);
458c2ecf20Sopenharmony_ci		break;
468c2ecf20Sopenharmony_ci	case REQ_OP_WRITE:
478c2ecf20Sopenharmony_ci		/* writes get silently dropped */
488c2ecf20Sopenharmony_ci		break;
498c2ecf20Sopenharmony_ci	default:
508c2ecf20Sopenharmony_ci		return DM_MAPIO_KILL;
518c2ecf20Sopenharmony_ci	}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	bio_endio(bio);
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	/* accepted bio, don't make new request */
568c2ecf20Sopenharmony_ci	return DM_MAPIO_SUBMITTED;
578c2ecf20Sopenharmony_ci}
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic struct target_type zero_target = {
608c2ecf20Sopenharmony_ci	.name   = "zero",
618c2ecf20Sopenharmony_ci	.version = {1, 1, 0},
628c2ecf20Sopenharmony_ci	.module = THIS_MODULE,
638c2ecf20Sopenharmony_ci	.ctr    = zero_ctr,
648c2ecf20Sopenharmony_ci	.map    = zero_map,
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_cistatic int __init dm_zero_init(void)
688c2ecf20Sopenharmony_ci{
698c2ecf20Sopenharmony_ci	int r = dm_register_target(&zero_target);
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci	if (r < 0)
728c2ecf20Sopenharmony_ci		DMERR("register failed %d", r);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	return r;
758c2ecf20Sopenharmony_ci}
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistatic void __exit dm_zero_exit(void)
788c2ecf20Sopenharmony_ci{
798c2ecf20Sopenharmony_ci	dm_unregister_target(&zero_target);
808c2ecf20Sopenharmony_ci}
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cimodule_init(dm_zero_init)
838c2ecf20Sopenharmony_cimodule_exit(dm_zero_exit)
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jana Saout <jana@saout.de>");
868c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DM_NAME " dummy target returning zeros");
878c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
88