new file mode 100644
@@ -0,0 +1,15 @@
+dm-ram
+======
+
+Device-Mapper's "ram" target provides a mapping to RAM.
+This is comparible to a loop device mapped to a tmpfs
+file but has less overhead, hence higher IOPS and bandwidth.
+
+dm-ram has no target-specific parameters.
+
+Example:
+
+dmsetup create ramdisk --table "0 $((2048*1024*2)) ram"
+
+This will create a 2GiB ramdisk /dev/mapper/ramdisk and
+will suceed presuming more than 2GiB free RAM are available.
@@ -397,6 +397,13 @@ config DM_LOOP
A target that redirects IOs to a backing file.
E.g. useful in testing.
+config DM_RAM
+ tristate "RAM disk target (EXPERIMENTAL)"
+ depends on BLK_DEV_DM
+ ---help---
+ A target that redirects IO to RAM.
+ E.g. useful in testing.
+
config DM_MULTIPATH
tristate "Multipath target"
depends on BLK_DEV_DM
@@ -58,6 +58,7 @@ obj-$(CONFIG_DM_MIRROR) += dm-mirror.o dm-log.o dm-region-hash.o
obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
obj-$(CONFIG_DM_LOOP) += dm-loop.o
+obj-$(CONFIG_DM_RAM) += dm-ram.o
obj-$(CONFIG_DM_RAID) += dm-raid.o
obj-$(CONFIG_DM_THIN_PROVISIONING) += dm-thin-pool.o
obj-$(CONFIG_DM_VERITY) += dm-verity.o
new file mode 100644
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2018 Red Hat GmbH
+ *
+ * Ram disk target.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/device-mapper.h>
+#include <linux/module.h>
+
+static int ram_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+ int r;
+
+ if (argc) {
+ ti->error = "No arguments required";
+ return -EINVAL;
+ }
+
+ /* Allocation will fail anyway for the time being, but... */
+ if (ti->len != to_sector(to_bytes(ti->len))) {
+ ti->error = "Invalid target length";
+ return -EINVAL;
+ }
+
+ r = dm_set_target_max_io_len(ti, min(ti->len, (sector_t) UINT_MAX));
+ if (r)
+ return r;
+
+ ti->private = vmalloc(to_bytes(ti->len));
+ if (!ti->private) {
+ ti->error = "Cannot allocate ram disk";
+ return -ENOMEM;
+ }
+
+ ti->num_discard_bios = 1;
+ ti->discards_supported = true;
+
+ return 0;
+}
+
+static void ram_dtr(struct dm_target *ti)
+{
+ vfree(ti->private);
+}
+
+static int ram_map(struct dm_target *ti, struct bio *bio)
+{
+ struct bio_vec bvec;
+
+ switch (bio_op(bio)) {
+ case REQ_OP_READ:
+ bio_for_each_segment(bvec, bio, bio->bi_iter)
+ memcpy(page_address(bvec.bv_page) + bvec.bv_offset,
+ ti->private + to_bytes(bio->bi_iter.bi_sector), bvec.bv_len);
+ break;
+ case REQ_OP_WRITE:
+ bio_for_each_segment(bvec, bio, bio->bi_iter)
+ memcpy(ti->private + to_bytes(bio->bi_iter.bi_sector),
+ page_address(bvec.bv_page) + bvec.bv_offset, bvec.bv_len);
+ break;
+ case REQ_OP_DISCARD:
+ memset(ti->private + to_bytes(bio->bi_iter.bi_sector), 0, bio_cur_bytes(bio));
+ break;
+ default:
+ return DM_MAPIO_KILL;
+ }
+
+ bio_endio(bio);
+
+ return DM_MAPIO_SUBMITTED;
+}
+
+static struct target_type ram_target = {
+ .name = "ram",
+ .version = {1, 0, 0},
+ .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE,
+ .module = THIS_MODULE,
+ .ctr = ram_ctr,
+ .dtr = ram_dtr,
+ .map = ram_map
+};
+
+static int __init dm_ram_init(void)
+{
+ return dm_register_target(&ram_target);
+}
+
+static void __exit dm_ram_exit(void)
+{
+ dm_unregister_target(&ram_target);
+}
+
+/* Module hooks */
+module_init(dm_ram_init);
+module_exit(dm_ram_exit);
+
+MODULE_DESCRIPTION(DM_NAME " ram disk target");
+MODULE_AUTHOR("Heinz Mauelshagen <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com> --- Documentation/device-mapper/ram.txt | 15 ++++++ drivers/md/Kconfig | 7 +++ drivers/md/Makefile | 1 + drivers/md/dm-ram.c | 101 ++++++++++++++++++++++++++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 Documentation/device-mapper/ram.txt create mode 100644 drivers/md/dm-ram.c