Device mapper (dm) — подсистема (модуль) ядра Linux, позволяющая создавать виртуальные блочные устройства (ВБУ). При обращении к таким устройствам выполняется ряд действий, в число которых обычно входит чтение/запись данных с других блочных устройств (БУ). Подсистема используется для реализации менеджера логических томов LVM, программного RAID, системы шифрования дисков dm-crypt. Одной из возможностей подсистемы является создание снимков файловой системы

Как работает?

Юзерспейс приложения для взаимодействия с device-mapper используют библиотеку libdevmapper.so (Она работает через ioctl). Так же существует утилита dmsetup. С ее помощью можно вручную создавать, изменять, удалять dm-устройства. Это в общем по части конфигурации.

А вот сама работа dm в целом выглядит так. Блоки виртуального устройства ставятся в соответсвие блокам целевого устройства (или устройств) основываясь на таблице соответствия и типе преобразования.

Виртуальное устройство. Это новое виртуальное устройство, которое создает dm.

Целевое устройство или устройства. Это те устройства, на которые маппится виртуальное устройство.

Таблица соответсвия (Mapping table). В ней описываются параметры маппинга, с какого по какой сектор маппить и т.д.

 

Тип преобразования (Mapping target). При мэппинге происходит преобразование, например:

-linear - собственно ничего не преобразуется, просто блоки одного устройства мэппятся ну другие.

-error - эмулируются ошибки ввода-вывода.

-zero - просто возвращает нули. В этом случае целевого устройства как такового нет.

-snapshot - для реализации механизма copy-on-write.

-Полный список целей можно посмотреть в документации ядра.

-После того как все настроено, новое виртуальное появляется в каталоге /dev/mapper.

 

dmsetup

Теперь обсудим как пользоваться утилитой dmsetup и как писать те самые таблицы.

 

Создаются новые устройства так:

# dmsetup create DEVICE_NAME --table ’тут пишем таблицу’

Смотрим:

# dmsetup ls

Удаляем:

# dmsetup remove DEVICE_NAME

++++++++++++++++++++++++++++++++-

 

Таблицы соответствия

Таблицу представляет собой текстовые строки, разделенные символом переноса строки \n.

 

Формат строки таблицы следующий:

start_sector sectors_length mapping_target target_parameters

start_sector - начальный сектор для мэппинга

sectors_length - длинна в секторах

mapping_target - тип мэппинга (linear, zero, snaphot и т.д.)

target_parameters - параметры, необходимые для mapping_target. Они уже у каждого target’а свои, например у linear надо указать путь до устройства, на которое будет происходить мэппинг (список аргументов для каждого target’а см. в документации к соответствующему модулю).

 

Для dmsetup таблицу можно указывать несколькими способами.

Например если это одна строка, можно так:

# dmsetup create new_device --table ’0 2048 zero’

Если таблица состоит из нескольких строк, то можно передать пайпом:

# echo -e '0 2048 linear /dev/loop0 0'\\n'

2048 2048 linear /dev/loop1 0'\\n'

4096 2048 linear /dev/loop2 0' | dmsetup create disks

И еще есть способ указать файл с таблицей. Это, и все остальные подробности о dmsetup хорошо описаны в man 8 dmsetup.

Теперь у нас есть полная картина и можно рассмотреть несколько примеров.

++++++++++++++++++++++++++++++++-

 

Объединяем несколько блочных устройств в одно

 

Создадим 3 файла под диски, которые будем объединять и сделаем из них loopback устройства (С таким же успехом можем брать «настоящие» устройства, например /dev/{sda,sdb,sdc,...})

# dd if=/dev/zero of=disk0.img bs=1M count=1

# dd if=/dev/zero of=disk1.img bs=1M count=1

# dd if=/dev/zero of=disk2.img bs=1M count=1

# losetup /dev/loop0 disk0.img

# losetup /dev/loop1 disk1.img

# losetup /dev/loop2 disk2.img

Создаем новое устройство disks:

# echo -e '0 2048 linear /dev/loop0 0'\\n'2048 2048 linear /dev/loop1 0'\\n'4096 2048 linear /dev/loop2 0' | dmsetup create disks

В таблице мы указали, что устройство loop0 будет маппиться на устройство disks с 0-го сектора и будет иметь длинну 2048 секторов, loop2 c 2048-го сектора, loop3 с 4096-го сектора. Итого последовательно замэппили 3 устройства на одно.

Последний параметр 0, после пути до устройства - это смещение, но так как мы хотим объединять устройства от начала до конца, то указываем 0.

 

Посмотрим созданное устройство:

# dmsetup ls

Так как объединяли 3 устройства по мегабайту - disks должен иметь размер 3Мб:

# fdisk -l /dev/mapper/disks

Почистим за собой:

# dmsetup remove disks

# losetup -d /dev/loop{0,1,2}

# rm -f disk{0,1,2}.img

++++++++++++++++++++++++++++++++-

 

Эмуляция ошибок ввода/вывода

 

Теперь создадим устройство, которое будет эмулировать ошибку ввода/вывода при обращении к определенному сектору:

# echo -e '0 995 linear /dev/loop0 0'\\n'

995 5 error'\\n'

1000 1048 linear /dev/loop0 995' | dmsetup create disks

С 0-го по 995-й сектор мэппим на loop0

С 995-го пять секторов у нас будут сбойными

Начиная с 1000-го продолжаем обычный мэппинг, пропуская 995 секторов

В итоге получается устройство размеров 2048 секторов с 5-ю сбойными 995-1000

 

# cat /dev/mapper/disks > test

cat /dev/mapper/disks: Input/output error

 

Материалы:

http://fl47l1n3.net/2015/05/25/using-device-mapper/

https://wiki.gentoo.org/wiki/Device-mapper#Create