5

A couple of years ago I upgraded my netbook with a larger hard drive. I wanted to retain the contents of the old hard drive in case there was anything I still wanted off it.

So I copied the the old hard-drive into a file on the new one:

dd if=/dev/sdd5 of=~/fw-disk-image/fw-sdd5-linux-lvm-partition.raw

and I wrote/copied a script for mounting the lvms on that partition as read-only file-systems:

losetup -r /dev/loop1 ~/fw-disk-image/fw-sdd5-linux-lvm-partition.raw

pvscan
vgscan
vgchange -a y fw

cd /mnt/fw
for i in root tmp usr var home
  do
    mount -o ro /dev/fw/$i $i
  done

Now this worked for a long time and now suddenly it fails at the vgchange -a y fw command:

# vgchange -a y fw
  Error writing device /dev/loop1 at 4096 length 512.
  bcache_invalidate: block (4, 0) still dirty
  Failed to write mda header to /dev/loop1 fd -1
  Failed to update old PV extension headers in VG fw.
  Volume group "fw" not found
  Cannot process volume group fw

I'm guessing that since I created a read-only loop-back device, vgchange is not happy that it can't write to it. I think that the file-system was dirty when last the disk was used but I want to ignore that.

My current system is currently running:

Linux fw 4.19.0-8-686-pae #1 SMP Debian 4.19.98-1 (2020-01-26) i686 GNU/Linux

$ vgchange --version
vgchange --version
  LVM version:     2.03.02(2) (2018-12-18)
  Library version: 1.02.155 (2018-12-18)
  Driver version:  4.39.0
  Configuration:   ./configure --build=i686-linux-gnu --prefix=/usr --includedir=${prefix}/include --mandir=${prefix}/share/man --infodir=${prefix}/share/info --sysconfdir=/etc --localstatedir=/var --disable-silent-rules --libdir=${prefix}/lib/i386-linux-gnu --libexecdir=${prefix}/lib/i386-linux-gnu --runstatedir=/run --disable-maintainer-mode --disable-dependency-tracking --exec-prefix= --bindir=/bin --libdir=/lib/i386-linux-gnu --sbindir=/sbin --with-usrlibdir=/usr/lib/i386-linux-gnu --with-optimisation=-O2 --with-cache=internal --with-device-uid=0 --with-device-gid=6 --with-device-mode=0660 --with-default-pid-dir=/run --with-default-run-dir=/run/lvm --with-default-locking-dir=/run/lock/lvm --with-thin=internal --with-thin-check=/usr/sbin/thin_check --with-thin-dump=/usr/sbin/thin_dump --with-thin-repair=/usr/sbin/thin_repair --enable-applib --enable-blkid_wiping --enable-cmdlib --enable-dmeventd --enable-dbus-service --enable-lvmlockd-dlm --enable-lvmlockd-sanlock --enable-lvmpolld --enable-notify-dbus --enable-pkgconfig --enable-readline --enable-udev_rules --enable-udev_sync

Is there some way that I can (again) mount the LVs on this partition while remaining strictly read-only?

Adrian Pronk
  • 527
  • 3
  • 10

2 Answers2

2

Below is a workaround: given LVM wants a read-write block device, we create one with an overlay block device based on the read-only block device (see this other question).

As root:

  1. Create a sparse file with the same size as the read-only block device
    truncate -s`blockdev --getsize64 /dev/loop1` '/tmp/overlay.bin'
    
    (even if larger than the current filesystem)
  2. Create the overlay block device
    loop=`losetup -f --show -- '/tmp/overlay.bin'`
    size=`blockdev --getsz /dev/loop1`
    printf '%s\n' "0 $size snapshot /dev/loop1 $loop P 8" | dmsetup create 'overlayloop1'
    
  3. To avoid LVM to complain about duplicate PV with the same UUID, edit /etc/lvm/lvm.conf to exclude the original /dev/loop1: either devices { scan = [ "/dev/mapper" ] } either devices { filter = [ "r|/dev/loop1|" ] } (see this FAQ on LVM wiki)
  4. Now vgchange -a y fw works.

During the use, the file /tmp/overlay.bin should be monitored, although it should not increase particularly if the filesystem of the LV is mounted read-only.

To close the loop device:

  1. vgchange -a n fw
  2. dmsetup remove /dev/mapper/overlayloop1
  3. rm /tmp/overlay.bin
  4. losetup -d /dev/loop1
Seb35
  • 144
  • 5
  • 1
    I searched to disable metadata, or disable locking, or the option --readonly in vgchange, but nothing worked. Perhaps vgmerge could be an option. I do not know enough LVM and its advanced config to have a better answer. – Seb35 Dec 22 '21 at 19:45
  • I needed to set up the filter in lvm.conf *before* I ran `losetup -r /dev/loop1 ...` otherwise a `/dev/old-name` directory is created and pvscan complains that the entries are pointing to the wrong block-device. I wasn't sure it if was ok to simply delete that directory so I rebooted. It worked well. And a good exercise in setting up an overlay-fs: that's sure to be useful. – Adrian Pronk Dec 24 '21 at 04:03
1

Not the filesystem was dirty (it may have been but that is not the problem here) but the LVM bcache structure. I guess some defaul setting has been changed and that is the reason it does not work any more.

Suggestions:

  1. Set up the loop device in rw mode once. That should fix the problem. After the successful vgchange you can destroy the loop device and set it up again ro. Without having mounted the filesystem.
    You can even try whether that solves the problem without making the loopdev rw: You can create another loopdev over a 100M file and create a snapshot. Unfortunately you would have to do that manually with dmsetup. Then you can have the LVM tools scan the snapshot. All changes would be written to the snapshot.

  2. Try vgchange -a y --readonly fw

Hauke Laging
  • 88,146
  • 18
  • 125
  • 174