Signed-off-by: Heinz Mauelshagen <[email protected]>
---
 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

diff --git a/Documentation/device-mapper/ram.txt 
b/Documentation/device-mapper/ram.txt
new file mode 100644
index 000000000000..4358fbf57cae
--- /dev/null
+++ b/Documentation/device-mapper/ram.txt
@@ -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.
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig
index 1d80783b9ee8..abea7b8771f4 100644
--- a/drivers/md/Kconfig
+++ b/drivers/md/Kconfig
@@ -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
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 68baf79c5536..f404223629ab 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -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
diff --git a/drivers/md/dm-ram.c b/drivers/md/dm-ram.c
new file mode 100644
index 000000000000..9ef1a8516e1a
--- /dev/null
+++ b/drivers/md/dm-ram.c
@@ -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 <[email protected]>");
+MODULE_LICENSE("GPL");
-- 
2.14.3

--
dm-devel mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/dm-devel

Reply via email to