See the links below to find out what the device mapper is http://lc.linux.or.jp/lc2009/slide/T-02-slide.pdf https://en.wikipedia.org/wiki/Device_mapper
Personally, I understand that in Linux, where Filesystem is more diverse than other Unixes, it was necessary to cut out and provide functions that should be integrated into Filesystem, such as ZFS.
I started by picking up a simple device mapper target code, building it, and using it.
The environment is as follows CentOS Linux release 7.7.1908 (Core) A virtual machine on VirtualBox built with Vagrant. git clone https://github.com/huwan/dm-target
$ git clone https://github.com/huwan/dm-target.git
Go to the cloned folder
$ make
make -C /lib/modules/3.10.0-957.12.2.el7.x86_64/build M=/home/vagrant/dm-target modules
make[1]:directory`/usr/src/kernels/3.10.0-957.12.2.el7.x86_64'Enter
CC [M] /home/vagrant/dm-target/mapper.o
(Omission)
include/linux/device-mapper.h:160:5:Remarks: expected ‘struct dm_dev **’ but argument is of type ‘sector_t’
int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
^
/home/vagrant/dm-target/mapper.c:85:13:error:Function ‘dm_get_Too many arguments to device ’
dm_table_get_mode(target->table), &mdt->dev)) {
^
In file included from /home/vagrant/dm-target/mapper.c:15:0:
include/linux/device-mapper.h:160:5:Remarks:Declared here
int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
^
(Omitted)
With that feeling, the trouble is that an error occurs on line 85 and the build does not pass. The applicable part is
84 if (dm_get_device(target, argv[0], start, target->len,
85 dm_table_get_mode(target->table), &mdt->dev)) {
86 target->error = "Device lookup failed";
87 goto out;
88 }
The dm_get_device in the if statement is called, but I'm angry when there are too many arguments.
Check device-mapper.h. (Is it easier to see the code online?)
First, check the kernel version
$ uname -a
Linux localhost.localdomain 3.10.0-957.12.2.el7.x86_64 #1 SMP Tue May 14 21:24:32 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
Search device-mapper.h
$ sudo find / -name device-mapper.h
/usr/src/kernels/3.10.0-957.12.2.el7.x86_64/include/linux/device-mapper.h
/usr/src/kernels/3.10.0-1062.18.1.el7.x86_64/include/linux/device-mapper.h
It seems that it refers to the header of 3.10.0-957. Check the contents of the header
[device-mapper.h]
/*
* Constructors should call these functions to ensure destination devices
* are opened/closed correctly.
*/
int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
struct dm_dev **result);
void dm_put_device(struct dm_target *ti, struct dm_dev *d);
The comment says it's a constructor. I read the implementation below (it's easier on the net) https://elixir.bootlin.com/linux/v3.10.95/source/drivers/md/dm-table.c#L462
/*
* Add a device to the list, or just increment the usage count if
* it's already present.
*/
int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
struct dm_dev **result)
Apparently, it adds a new block device to the list of target block devices (and allows duplicates ??). Well I do not know. If it fails, it will return a non-zero value and enter the if statement in mapper.c.
The build failed probably because start and target-> len were extra arguments when dm_get_device was called. Since start is a long long type and target-> len is a sector_t type, it is not in the function declaration. target is the dm_target structure, which is declared in device-mapper.h.
Modify mapper.c
/*
* Add a device to the list, or just increment the usage count if
* it's already present.
*/
int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
struct dm_dev **result)
Make again
$ make
make -C /lib/modules/3.10.0-957.12.2.el7.x86_64/build M=/home/vagrant/dm-target modules
make [1]: Enter the directory `/usr/src/kernels/3.10.0-957.12.2.el7.x86_64'
CC [M] /home/vagrant/dm-target/mapper.o
/home/vagrant/dm-target/mapper.c:122:5: WARNING: Initialization from incompatible pointer type [Enabled by default]
.map = hello_target_map,
^
/home/vagrant/dm-target/mapper.c:122:5: WARNING: (near initialization for ‘hello_target.map’) [enabled by default]
Building modules, stage 2.
MODPOST 1 modules
CC /home/vagrant/dm-target/mapper.mod.o
LD [M] /home/vagrant/dm-target/mapper.ko
make [1]: Exit from the directory `/usr/src/kernels/3.10.0-957.12.2.el7.x86_64'
$ ls
mapper.c# Makefile Module.symvers README.md mapper.c mapper.ko mapper.mod.c mapper.mod.o mapper.o modules.order run-dmtarget.sh
The build passed.
A shell script for setup is enclosed, so try using it.
$ sudo ./run-dmtarget.sh -s
128+0 records in
128+0 records out
134217728 bytes (134 MB) copied, 0.1957 s, 686 MB/s
/home/vagrant/dm-target/mapper.c:122:5: WARNING: Initialization from incompatible pointer type [Enabled by default]
.map = hello_target_map,
^
/home/vagrant/dm-target/mapper.c:122:5: WARNING: (near initialization for ‘hello_target.map’) [enabled by default]
$ sudo dmsetup targets
hello_target v1.0.0 <-this
striped v1.6.0
linear v1.3.0
error v1.5.0
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
└─sda1 8:1 0 40G 0 part /
loop0 7:0 0 128M 0 loop
└─my_device_mapper 253: 0 0 128M 0 dm <-this
It would be helpful for beginners to have a shell script for such experiments. Looking at the contents, ...
dd if=/dev/zero of=/tmp/mydisk bs=1M count=128 # 128MB file
losetup /dev/loop0 /tmp/mydisk # losetup -f
make -s
insmod ./mapper.ko
echo <starting logical sector number> <logical size of device in terms of sector> <target name> <device path> <unsed paramter> | dmsetup create <mapper name>
echo 0 262144 hello_target /dev/loop0 0 | dmsetup create my_device_mapper
Next, try a writing test with dd
sudo ./run-dmtarget.sh -d
16+0 records in
16+0 records out
16384 bytes (16 kB) copied, 0.0399802 s, 410 kB/s
What the process here is doing
dd if=/dev/urandom of=/dev/mapper/my_device_mapper bs=1K count=16
It seems that 16KB of random data is being written.
Next, try formatting the created block device with ext4.
$ sudo ./run-dmtarget.sh -f
copy.txt lost+found test.txt
So what are you doing here?
if [ ! -d /mnt/mapper ]
then
mkdir -p /mnt/mapper
fi
modprobe ext4
mkfs.ext4 -q /dev/mapper/my_device_mapper
mount /dev/mapper/my_device_mapper /mnt/mapper
cd /mnt/mapper
touch test.txt
cp test.txt copy.txt
ls
Check if it is mounted
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 40G 0 disk
└─sda1 8:1 0 40G 0 part /
loop0 7:0 0 128M 0 loop
└─ my_device_mapper 253: 0 0 128M 0 dm / mnt / mapper <-Mounted on / mnt / mapper
$ ls /mnt/mapper/
copy.txt lost+found test.txt
$ cd /mnt/mapper/
$ du -sh
du: cannot read directory ‘./lost+found’: No permission
15K .
$ sudo touch hoge
$ ls
copy.txt hoge lost+found test.txt
It can be used normally as a 16KB folder.
It's a very simple device mapper target, so it's simple.
The members of the instance hello_target of the target_type structure are initialized as follows.
static struct target_type hello_target = {
.name = "hello_target",
.version = {1,0,0},
.module = THIS_MODULE,
.ctr = hello_target_ctr,
.dtr = hello_target_dtr,
.map = hello_target_map,
};
The definition of this structure is declared in device-mapper.h. The function pointer for handling block I / O (bio) is assigned to the map member variable, and the constructor and destructor are assigned to ctr and dtr, respectively. that's all.
The results of the following code reading will be added.
Recommended Posts