initrd, lvm, ошибка активации lv с включенным cache [SOLVED]

Доброго времени суток.

У меня возникла проблема с активацией lvm в initrd.

Что было:
несколько hdd, разбивка следующая: 1 раздел - основные данные, 2 раздел - boot, 3 раздел - efi
raid: md1 - raid5 (первые разделы на всех дисках), md2 - raid1 (вторые разделы),
lvm: pv - md1, vg - vgmain (в которую входит только один pv - md1), lv - их несколько, в том числе и root.
в качестве загрузчика использовал grub2.
initrd - самописный, пользовался, кажется, руководством https://wiki.gentoo.org/wiki/Custom_Initramfs
все это благополучно настроил много лет назад, все работало, все устраивало.
сейчас захотел прикрутить к root lvm cache на ssd, т.к. полностью переносить систему на ssd нехочу из соображений надежности (да, возможно предрассудки, но это мои предрассудки).
столкнулся с несколькими проблемами.
1. текущий initrd содержит старую версию lvm:

  LVM version:     2.02.97(2) (2012-08-07)
  Library version: 1.02.76 (2012-08-07)
  Driver version:  4.39.0

которая не понимает что такое lvm cache,
не беда, обновил до той, что сейчас установлена в системе (бинарник брал, естественно, статический):

  LVM version:     2.02.184(2) (2019-03-22)
  Library version: 1.02.156 (2019-03-22)
  Driver version:  4.39.0

2. для работы lvm cache нужно утилита cache_check.
добавил её в initrd.
3. этого оказалось мало. изменилось поведение lvm.
старый init для активации lvm выполнял следущие действия:

activate_lvm(){
    lvm vgscan --mknodes &&
    lvm vgchange -ay
}

их было достаточно, чтобы в /dev/mapper/ появились block device (имя формата vgname-lvname),
но с новой версии lvm такого не происходит, создаются только /dev/dm-[0-9]*, это не большая проблема, всего-то пройтись по uuid и найти нужный. это я решил.
4. не работает активация lv с включенным cache'ем (опцию --sysinit пробовал добавлять в качестве теста, что с ней, что без неё - результат одниковый):

/ # lvm vgchange -ay --sysinit
  WARNING: Failed to connect to lvmetad. Falling back to device scanning.
modprobe: chdir(4.19.97-gentoo): No such file or directory
  /sbin/modprobe failed: 1
modprobe: chdir(4.19.97-gentoo): No such file or directory
  /sbin/modprobe failed: 1
  /dev/mapper/vgtest-lvt--cache_cmeta: open failed: No such file or directory
  0 logical volume(s) is volume group "vgtest" now active
[   81.111886] lvm (1140) used greatest stack depth: 13952 bytes left

как побороть ошибку *_cmeta я так и не нашел.

это вывод из тестового стенда, конфиг lvm, которого повторяет мою проблему (а именно включение lvm cache ломает активацию lv на этапе initrd):

# pvdisplay  -m
  --- Physical volume ---
  PV Name               /dev/vdb1
  VG Name               vgtest
  PV Size               <5,00 GiB / not usable 3,00 MiB
  Allocatable           yes (but full)
  PE Size               4,00 MiB
  Total PE              1279
  Free PE               0
  Allocated PE          1279
  PV UUID               zvOsLX-em4a-tqck-ZYSv-OjW4-Fjio-rzQDok
   
  --- Physical Segments ---
  Physical extent 0 to 1278:
    Logical volume      /dev/vgtest/lvt-test_corig
    Logical extents     0 to 1278
   
  --- Physical volume ---
  PV Name               /dev/vde
  VG Name               vgtest
  PV Size               1,00 GiB / not usable 4,00 MiB
  Allocatable           NO
  PE Size               4,00 MiB
  Total PE              255
  Free PE               0
  Allocated PE          255
  PV UUID               avPvww-1DKk-IySB-iA5F-N5B0-aeSL-1BSoQk
   
  --- Physical Segments ---
  Physical extent 0 to 1:
    Logical volume      /dev/vgtest/lvol0_pmspare
    Logical extents     0 to 1
  Physical extent 2 to 3:
    Logical volume      /dev/vgtest/lvt-cache_cmeta
    Logical extents     0 to 1
  Physical extent 4 to 254:
    Logical volume      /dev/vgtest/lvt-cache_cdata
    Logical extents     0 to 250

# vgdisplay 
  --- Volume group ---
  VG Name               vgtest
  System ID             
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  52
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                1
  Open LV               0
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               5,99 GiB
  PE Size               4,00 MiB
  Total PE              1534
  Alloc PE / Size       1534 / 5,99 GiB
  Free  PE / Size       0 / 0   
  VG UUID               4sYlbf-HZAZ-BhYs-D9AK-bQnr-p7mh-cUCmYe
   
# lvdisplay 
  --- Logical volume ---
  LV Path                /dev/vgtest/lvt-test
  LV Name                lvt-test
  VG Name                vgtest
  LV UUID                620xp0-coGe-fykI-nQGV-I79l-KMG6-OIViQe
  LV Write Access        read/write
  LV Creation host, time localhost, 2020-03-07 09:26:43 +0200
  LV Cache pool name     lvt-cache
  LV Cache origin name   lvt-test_corig
  LV Status              available
  # open                 0
  LV Size                <5,00 GiB
  Cache used blocks      0,11%
  Cache metadata blocks  2,83%
  Cache dirty blocks     0,00%
  Cache read hits/misses 328 / 136
  Cache wrt hits/misses  0 / 0
  Cache demotions        0
  Cache promotions       0
  Current LE             1279
  Segments               1
  Allocation             inherit
  Read ahead sectors     auto
  - currently set to     256
  Block device           252:3
   

содержимое init из initrd:

#!/bin/busybox sh

rescue_shell() {
    echo "Something went wrong. Dropping you to a shell."
    busybox --install -s
    exec /bin/sh
}

load_modules() {
    MOD_PATH="/lib/modules"
    MODULES=`ls ${MOD_PATH}`
    for MODULE in ${MODULES} ; do
        insmod -f ${MOD_PATH}/${MODULE}
    done
}

activate_lvm(){
    lvm vgscan --mknodes &&
    lvm vgchange -ay
}

uuidlabel_root() {
    for cmd in $(cat /proc/cmdline) ; do
        case $cmd in
        root=*)
            dev=${cmd#root=}
            type=${dev%%=*}
            if [ $type = "LABEL" ] || [ $type = "UUID" ] ; then
                mount -o ro $(findfs "$dev") /mnt/root || rescue_shell
            else
                mount -o ro ${dev} /mnt/root || rescue_shell
            fi
            ;;
        esac
    done
}

mount -t proc none /proc || exit
mount -t sysfs none /sys
mount -t devtmpfs none /dev

load_modules || rescue_shell

rescue_shell
# Mount the root filesystem.
mdadm --assemble --scan /dev/md1 || rescue_shell
activate_lvm || rescue_shell
uuidlabel_root || rescue_shell

# Clean up.
umount /proc
umount /sys
umount /dev

# Boot the real thing.
exec switch_root /mnt/root /sbin/init

конфиг ядра (опции lvm находятся в device drivers -> Multiple devices driver support (RAID and LVM), в сами названия начинаются на CONFIG_DM):

# CONFIG_DM_MQ_DEFAULT is not set
# CONFIG_DM_DEBUG is not set
CONFIG_DM_BUFIO=y
# CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set
CONFIG_DM_BIO_PRISON=y
CONFIG_DM_PERSISTENT_DATA=y
# CONFIG_DM_UNSTRIPED is not set
CONFIG_DM_CRYPT=m
CONFIG_DM_SNAPSHOT=m
CONFIG_DM_THIN_PROVISIONING=m
CONFIG_DM_CACHE=y
CONFIG_DM_CACHE_SMQ=y
CONFIG_DM_WRITECACHE=y
# CONFIG_DM_ERA is not set
CONFIG_DM_MIRROR=m
CONFIG_DM_LOG_USERSPACE=m
CONFIG_DM_RAID=m
CONFIG_DM_ZERO=y
CONFIG_DM_MULTIPATH=m
CONFIG_DM_MULTIPATH_QL=m
CONFIG_DM_MULTIPATH_ST=m
CONFIG_DM_DELAY=m
# CONFIG_DM_UEVENT is not set
CONFIG_DM_FLAKEY=m
CONFIG_DM_VERITY=m
# CONFIG_DM_VERITY_FEC is not set
# CONFIG_DM_SWITCH is not set
# CONFIG_DM_LOG_WRITES is not set
# CONFIG_DM_INTEGRITY is not set

т.е. то, что мне нужно собрано в ядре (а не модулем), и в должно работать. на загруженной системе (стенд), lv с cache подхватывается и его можно использовать (тестовый lv, root не на нем), а вот на этапе initrd ошибка.

я уже попробовал подсмотреть что делает initrd который собирает genkernel, если убрать лишнее, то вот команды:

lvm vgscan 2>&1
lvm vgchange -ay --sysinit 2>&1
lvm vgmknodes --ignorelockingfailure

но она тоже результата не дают - vgchange возвращает ту же ошибку.

буду благодарен за свежие идеи, ибо мои уже закончились.

единственная догадка - это изменилось поведение lvm и те команды, которыми я пользовался ранее, уже не создают нужные мне /dev/mapper/vgname-lvname либо /dev/vgname/lvname block device (либо symlink'и на /dev/dm-[0-9]*), а на этапе инициализации lv с включенным cache выполняется запуск check_cache, которому в качестве аргумента передается путь к lv:

# strace -f -s 1024 lvm vgchange -ay  2>&1|grep execve
[pid  3422] execve("/sbin/modprobe", ["/sbin/modprobe", "dm-cache-smq"], 0x7ffeee8ebef8 /* 30 vars */) = 0
[pid  3439] execve("/sbin/cache_check", ["/sbin/cache_check", "-q", "--clear-needs-check-flag", "/dev/mapper/vgtest-lvt--cache_cmeta"], 0x7ffeee8ebef8 /* 30 vars */) = 0

к слову тут же видно и с какими параметрами выполняется modprobe (но я не понимаю на кой он нужен, если ядро собрано с CONFIG_DM_CACHE_SMQ=y).

ради интереса попробовал (для теста разумеется) заменить /sbin/cache_check на /bin/true дабы пропустить его проверку, но вывод ошибки, которая возникает на этапе initrd не меняется, значит до его запуска даже не доходит.

lvm cache не сама цель. в конечном итоге хочу получить кеширование нескольких lv на ssd и в моей текущей конфигурации его внедрение было вроде самой легкой задачей.
bcache попросит переформатировать разделы, и как поведет себя после смерти ssd я не знаю.
переводить lvm на zfs нет возможности.

Что-то ты не так делаешь!

Может доки недочитал?
Вот тут ещё пару сайтов, где для домохозяек на пальцах объясняют, как надо делать:
https://lukas.zapletalovi.com/2019/05/lvm-cache-in-six-easy-steps.html
https://ahelpme.com/linux/lvm/ssd-cache-device-to-a-hard-disk-drive-using-lvm/

в целов да, arch доки не

в целов да, arch доки не читал, нашел другую.
но ведь не в этом проблема - создание lvm cache прошло у меня успешно.
проблема в том, что не работает его активация на этапе initrd, тогда как в загруженной системе все ок.
cache примерно так и создавал:

vgextend vgtest /dev/vde
lvcreate --type cache-pool -l 100%FREE -n lvt-cache vgtest /dev/vde
lvconvert --type cache --cachepool vgtest/lvt-cache vgtest/lvt-test

он создается и работает, но перезагрузку система не пережила.

тут нашел упоминание об

тут нашел упоминание об genkernel-next
попробовал, он генерирует те же команды активации lvm что и genkernel, которые не работает с lvm cache.

нашел способ воспроизвести на

нашел способ воспроизвести на загруженной системе:

localhost ~ # /etc/init.d/udev status
 * status: stopped
localhost ~ # /etc/init.d/lvm status
 * status: stopped
localhost ~ # /etc/init.d/lvmetad status
 * status: stopped
localhost ~ # vgchange -ay --sysinit
  WARNING: Failed to connect to lvmetad. Falling back to device scanning.
  /dev/mapper/vgtest-lvt--cache_cmeta: open failed: Нет такого файла или каталога
  0 logical volume(s) in volume group "vgtest" now active
localhost ~ # /etc/init.d/udev start
 * Starting udev ...                                                                                                                                                                                                                                                       [ ok ]
localhost ~ # vgchange -ay 
  WARNING: Failed to connect to lvmetad. Falling back to device scanning.
  1 logical volume(s) in volume group "vgtest" now active

но только где же я в initrd возьму udev то(

в initrd можно включить все,

в initrd можно включить все, что угодно! Читай теорию...

та да, уже тоже нашел

та да, уже тоже нашел упоминание, что в arch он по-умолчанию включен в initrd,
и более того в initrd сгенерированном genkernel/genkernel-next он есть, что объясняет почему там работают команды активации.
вангую что через 20 лет в initrd будет полноценный stage3, только для того чтобы примонтировать root(.
такого подвоха от lvm я не ожидал... Поттеринг их покусал чтоли)

А что тут не так? Разберись

А что тут не так? Разберись как работает система, и все станет понятно и логично!
Очевидно же, что при запуске системы нужно при себе иметь все, что использует при этом.
Для того и придумали initrd (а это и есть статическая минисистема!), чтобы не подключать все нужные ресурсы статически в ядро и/или утилиты, как это сделал ты! ;)
И, в отличие от твоего костыля, при правильном использовании initrd нет ненужного разбазаривания ресурсов - ведь твой lvm будет жрать больше памяти всегда - и при нормальной работе системы тоже! А то что initrd стал больше - кого это волнует, ибо он используется только при запуске, а с флоппиков давно уже никто не грузится... :)

эм, а чем костыль?и почему

эм, а чем костыль?
и почему "ведь твой lvm будет жрать больше памяти всегда"?

я в ядро запихнул все что нужно для работы моей системы (raid, lvm, еще там по мелочи), что позволило не пересобирать initrd после каждого обновления ядра.
lvm с нужными флагами собрал единожды чтобы получить бинарник, который положил в initrd, затем пересобрал с предидущими use-флагами.

что не учел?

[SOLVED]

USE="static-libs static -udev" emerge -1Nav sys-fs/lvm2

полностью решает мою проблему. на выходе получается бинарник, который активирует lvm cache в initrd без udev.

Настройки просмотра комментариев

Выберите нужный метод показа комментариев и нажмите "Сохранить установки".