Writing Your Own Device Mapper Target

Gaurav Mahajan
5 min readSep 24, 2019

--

Concept of Device Mapper Target

Every storage system/ file system / administrator requires viewing the underlying data devices in their own way.

For example

  1. There are four data disks available on Linux machine and the system wants to create mirroring over them.
  2. concatenate them and view them as a single big device.
  3. if there is one disk, then a particular system may want to encrypt all the data that is going to be stored on that disk.

All such systems want a logical layer of block devices on the top of existing underlying block devices and map the requests on this logical layer to underlying layer after doing particular processing(encryption/decryption) at this layer. This facility is provided by device mapper in Linux kernel.

Device mapper can be defined as a generic way to add required functionality in the storage stack by creating virtual layer of block devices and mapping them to existing block devices.

It create virtual layers of block devices that can do different things on top of existing underlying block devices like striping, concatenation, mirroring, snapshot, etc. The Device Mapper is a modular kernel driver that provides a generic framework for volume management. It has been introduced in the kernel version 2.6. The device-mapper is used by the LVM2 and EVMS 2.x tools. LVM(Logical Volume Manager) is a tool which allows creating and managing partitions on a Linux system. The first version of LVM is in kernel 2.4 where there is no concept of device mapper. So, all the management of logical layer was the responsibility of LVM. But, due to the concept of device mapper in kernel 2.6, the logical layer management is done by device mapper and the code of LVM2 has been simplified to a great extent. This also brings modularity and re usability in the kernel.

The concept of device mapper target

As stated in introduction, we can create various logical layers through device mapper to carry out the required functionality. Each such layer is created by defining “a device mapper target” for that layer. There is one to one correspondence between a virtual layer at device mapper layer and the DM(Device mapper) target for that layer. The particular DM target contains the code which does the task of implementing functionality which the virtual layer intends to do. For example, a device mapper target can be written to implement mirroring over existing block devices. This DM target shows a virtual layer to upper layers which does the task of mirroring. Currently eight such features have been added to device mapper through seven device mapper targets. The device mapper targets are as following

  1. Linear
    This DM target allows us to concatenate number of disks to view them as a single big device or to view a part of disk as an individual logical disk. Thus, it creates a linear logical device on the top of existing block devices.
  2. RAID-0 / Striped
    The striped DM target is designed to handle striping across physical volumes i.e. to carry out well known RAID-0 functionality.
  3. RAID-1 / Mirrored RAID
    The mirrored DM target is designed to handle mirroring across number of disks. It carries out one of most famous RAID level functionality by creating and maintaining number of mirrors of data which all contain same data to improve reliability and speed of operations through load balancing.
  4. Snapshot
    This dm target carries out the functionality of snapshot and allows accessing the older versions of all files along with the latest one.
  5. DM-Crypt
    The dm-crypt device mapper target does the task of providing security through encryption and decryption of all the data that gets stored on the disk.
  6. Multipath
    In order to provide higher reliability for accessing the disks, this dm target provides a functionality of multipath so that in case of failure of path to disk, data on the disk can be accessed through alternative path.
  7. Zero
    The zero DM target returns all the data as zero for all the operations on the disk. Generally it is used for testing and to fill the gaps in new logical device.
  8. Error
    The error DM target causes any I/O to the mapped disk to fail. This also is useful for defining gaps in the new logical device.

Such device mapper target can be inserted into the kernel as a module and removed as per wish of the user. It can also be inserted into the kernel by creating its patch. Device mapper creates a logical layer of block devices and maps all the I/O requests on this logical layer to underlying existing block devices. For such mapping, device mapper uses a data structure called device mapper table. This table tells us how each and every sector (of size 512 bytes) of a logical layer is mapped to a sector on underlying disk. Thus, each target carries out its functionality by doing I/O mapping using its corresponding device mapper table.

So last but not least, Device mapper target represents a type of block device.
Now the “ ability to define the type of block device is provided by device mapper” so that is why it is generic layer.

So when we want to provide a new type of block device with some advance functionality like snapshots, de-duplication. we create new device mapper target, we write logic of the new functionality into that device mapper target. And we can create block devices of that device mapper target. (i.e new type of device )

Lets get started with code now…

Our device mapper target is going to be a kernel module. Lets say we call our dm target as ‘basic_target’. We will create 2 files.

  1. basic_target.c — This file will have all the code for the device mapper target.
basic_target.c

2. Makefile — This file will be used to compile the basic target module.

Compilation

To compile basic_target module runt “make” command.

make

This will generate a kernel module executable named “basic_target.ko”

Load basic target module.

We need to load the compiled Linux kernel module in kernel before we can start using it. To insert the module run following command.

insmod basic_target.ko

This command will load the module in kernel and kernel can start using it now. To validate that the module is loaded successfully run following command

lsmod | grep basic_target

If you see the basic target in “lsmod” output then the module has been loaded successfully.

Setup

Lets create a temp file of 2GB for device.

dd if=/dev/zero of=/tmp/disk1 bs=512 count=20000

Attach loop device to this file.

losetup /dev/loop6 /tmp/disk1

Lets create device with ‘basic_target’

echo 0 20000 basic_target /dev/loop6 0|dmsetup create my_basic_target_device

You can see the constructor getting called in /var/log/messages.

A new device is created at ‘/dev/mapper/my_basic_target_device’

Test

We can create the File system on my_basic_target_device but that will trigger many IO on device and will fill out the logs.

So lets try writing the 1 sector on our device using dd command.

dd if=/dev/zero of=/dev/mapper/my_basic_target_device bs=512 seek=10 count=1

Now you should see a write request for your device having starting sector as 10 and size 512 bytes.

Congratulations ! you now understand how to write and test your own device mapper target.

Cheers!

--

--

Gaurav Mahajan
Gaurav Mahajan

Written by Gaurav Mahajan

Software Engineer @DDN Storage | Interests in Distributed Storage systems, File Systems, Linux Kernel, C, C++, Go, Rust