LVM procedures

Introduction

This page describes various procedures related to LVM.

Procedures

Closing open LVs

LVs must be deactivated before removal, although lvremove can do both at the same time, but only if the volume is already closed. “Closed” means not mounted, not held open by an application (typically it is database applications which hold open storage devices without filesystems). But sometimes it can be a little more complicated.

  1. Verify that the LV really is open by running:
    lvdisplay /dev/<vgname>/<lvname>

    (‘1’ means it is open, ‘0’ means it is closed), as in this example:

    spaghetti# lvdisplay /dev/vg0/pubvol | grep open
      # open                 1
    spaghetti#
  2. Try each of the following steps and then re-check if the LV is still open; if it is then there is no need to continue to the next step.
    1. Refresh the cache of LV statuses by running:
      lvscan
    2. If the LV has a filesystem on it, verify that the LV is not mounted by running the following command and reviewing the output:
      mount 
    3. Verify no process is holding the device open by running:
      lsof | grep <lvname>
    4. If the LV has partitions on it (as might be the case if the LV is presented as a disk to a VM) and you scanned the LV for partitions (using partprobe or kpart) then kernel will “acquainted” with these partitions and and that “acquaintment” keeps the container LV open. You can verify if this is the case by looking under /dev for names of devices containing the LV name, as in this example:
      spaghetti# find /dev -ls | grep pubvol
      121092188    0 lrwxrwxrwx   1 root     root           38 Apr 14 09:06 /dev/vg0/pubvol -> /dev/mapper/vg0-pubvol
      120827538    0 brw-rw----   1 root     disk              Apr 13 16:55 /dev/mapper/vg0-pubvol
      120828929    0 brw-rw----   1 root     disk              Apr 13 16:04 /dev/mapper/vg0-pubvolp1
      spaghetti#

      Serverfault says that the kernel can be “unacquainted” with these partitions by running:

      kpartx -dv /dev/<vgname>/<lvname>
    5. Since the above output shows that device mapper was involved in the management, I wondered if the device mapper was holding the container LV open. I ran:
      dmsetup deps | grep <lvname>

      and this showed that the device mapper understood that the partition depended on the container LV, as in this example:

      spaghetti# dmsetup deps | grep pubvol
      vg0-pubvolp1: 1 dependencies    : (253, 128)
      vg0-pubvol: 1 dependencies      : (253, 2)
      spaghetti#

      By looking in /dev/mapper for devices with listed minor numbers, it is possible to establish what depends on what. In the above example, “(253, 128)” means that vg0-pubvolp1 depends on vg0-pubvol, which could explain why vg0-pubvol is being held open. So then I just asked the device mapper to delete the the “child” in this dependency relation ship with:

      dmsetup remove /dev/mapper/<vgname>-<lvname>p*

      After that I reran dmsetup deps, which now showed:

      spaghetti# dmsetup deps | grep copy
      vg0-pubvol: 1 dependencies      : (253, 2)

      (I.e. nothing depends upon this device any more.)

Creating, splitting and rejoining LVM RAID 10 volumes

This page describes how Alexis Huxley created a test RAID10 volume on LVM, how he split the mirror specifying which disks to remove from the volume, in order to apply firmware upgrades on the two removed disks, and how he re-added the disks afterwards.

  1. Allocate the PVs for LVM usage:
    spaghetti# pvcreate /dev/xvdb
      Physical volume "/dev/xvdb" successfully created
    spaghetti# pvcreate /dev/xvdc
      Physical volume "/dev/xvdc" successfully created
    spaghetti# pvcreate /dev/xvdd
      Physical volume "/dev/xvdd" successfully created
    spaghetti# pvcreate /dev/xvde
      Physical volume "/dev/xvde" successfully created
    spaghetti#
  2. create the VG from them:
    spaghetti# vgcreate vg0 /dev/xvdb /dev/xvdc /dev/xvdd /dev/xvde
      Volume group "vg0" successfully created
    spaghetti#
  3. Create a RAID10 LV from that VG specifying PVs in order:
    <leg0-part0> <leg0-part1> ... <leg1-part0> <leg1-part1> ...

    which for my setup meant running:

    spaghetti# lvcreate --mirrors 1 --name lvol0 --mirrorlog core --extents 510 vg0 \
        /dev/xvdb /dev/xvdc /dev/xvdd /dev/xvde
      Logical volume "lvol0" created
    spaghetti#

    (Note that I first tried to allocate size --size 1e which was impossibly big but told me the number of extents available, which I halved to get 510).

  4. Monitor things with iostat. At first iostat showed:
    Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
    xvda              0.00         0.00         0.00          0          0
    xvdb            198.48     12715.15         0.00      25176          0
    xvdc              0.00         0.00         0.00          0          0
    xvdd            198.99         0.00     12735.35          0      25216
    xvde              0.00         0.00         0.00          0          0
    dm-0            197.98     12670.71         0.00      25088          0
    dm-1            197.98         0.00     12670.71          0      25088
    dm-2              0.00         0.00         0.00          0          0

    and a little bit later it showed:

    Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
    xvda              0.00         0.00         0.00          0          0
    xvdb              0.00         0.00         0.00          0          0
    xvdc             93.47      5981.91         0.00      11904          0
    xvdd              0.00         0.00         0.00          0          0
    xvde             89.45         0.00      5724.62          0      11392
    dm-0             89.45      5724.62         0.00      11392          0
    dm-1             93.47         0.00      5981.91          0      11904
    dm-2              0.00         0.00         0.00          0          0

    and a little bit later still it showed:

    Device:            tps   Blk_read/s   Blk_wrtn/s   Blk_read   Blk_wrtn
    xvda              0.00         0.00         0.00          0          0
    xvdb              0.00         0.00         0.00          0          0
    xvdc              0.00         0.00         0.00          0          0
    xvdd              0.00         0.00         0.00          0          0
    xvde              0.00         0.00         0.00          0          0
    dm-0              0.00         0.00         0.00          0          0
    dm-1              0.00         0.00         0.00          0          0
    dm-2              0.00         0.00         0.00          0          0

    During the first output above lvs --all showed:

    spaghetti# lvs --all
      LV               VG   Attr   LSize Origin Snap%  Move Log Copy%  Convert
      lvol0            vg0  mwi-a- 1.99g                         <less-than-50%>
      [lvol0_mimage_0] vg0  Iwi-ao 1.99g
      [lvol0_mimage_1] vg0  Iwi-ao 1.99g

    and during the second output it showed:

    spaghetti# lvs --all
      LV               VG   Attr   LSize Origin Snap%  Move Log Copy%  Convert
      lvol0            vg0  mwi-a- 1.99g                         <more-than-50%>
      [lvol0_mimage_0] vg0  Iwi-ao 1.99g
      [lvol0_mimage_1] vg0  Iwi-ao 1.99g
  5. In a moment you’ll split the mirror, but to confirm that you’ve removed the devices you want to remove it is useful to run the following command now for comparison purposes later:
    spaghetti# pvs
      PV         VG   Fmt  Attr PSize    PFree
      /dev/xvdb  vg0  lvm2 a-   1020.00m    0
      /dev/xvdc  vg0  lvm2 a-   1020.00m    0
      /dev/xvdd  vg0  lvm2 a-   1020.00m    0
      /dev/xvde  vg0  lvm2 a-   1020.00m    0
    spaghetti#
  6. Split mirror, specifying what to remove:
    spaghetti# lvconvert --mirrors 0 /dev/vg0/lvol0 /dev/xvdb /dev/xvdc
  7. Confirm that you’ve removed the devices you wanted to remove run:
    spaghetti# pvs
      PV         VG   Fmt  Attr PSize    PFree
      /dev/xvdb  vg0  lvm2 a-   1020.00m 1020.00m
      /dev/xvdc  vg0  lvm2 a-   1020.00m 1020.00m
      /dev/xvdd  vg0  lvm2 a-   1020.00m       0
      /dev/xvde  vg0  lvm2 a-   1020.00m       0
    spaghetti#

    (Note that /dev/xvdb and /dev/xvdc are now back in the ‘free’ pool.)

  8. This is the moment to do whatever it is you have to do the the removed PVs (e.g. firmware upgrade on SAN).
  9. Join mirror, specifying what to add again:
    spaghetti# lvconvert --mirrors 1 --mirrorlog core /dev/vg0/lvol0 /dev/xvdb /dev/xvdc

    (Note that without the --mirrorlog option there are not enough extents available on the devices being added because the log will be allocated out of them.)

See also