Convert a single-drive LVM volume to a striped volume across 3 drives

5,879

I finally found a trick way.

The setup: Let's say our original drive is /dev/sda (PV is /dev/sda1) and our two new drives are /dev/sdb and /dev/sdc. All drives are 100 MB big.

The idea: Because all our data can fit on half of sdb and sdc, we can temporarily put our data there and in the meanwhile, create a striped mirror of our LV across the 3 other halves of the drives. Then, get rid of the original side of the (temporary) mirror and extend our striped LV to full size.

This wonderful piece of art should explain better:

original state:

   sda       sdb       sdc
 _______   _______   _______
|       | |       | |       |
|       | |       | |       |
|lv_orig| | empty | | empty |
|       | |       | |       |
|       | |       | |       |
|       | |       | |       |
|       | |       | |       |
|_______| |_______| |_______|


partition sdb & sdc, pvmove, then partition sda:

   sda       sdb       sdc
 _______   _______   _______
|       | |       | |       |
| sda1  | | sdb1  | | sdc1  |
| empty | | empty | | empty |
|_______| |_______| |_______|
|       | |       | |       |
| sda2  | |lv_orig| |lv_orig| <= linear on 2 drives
| empty | |half 1 | |half 2 |
|_______| |_______| |_______|


add sda{1,2,3} to vg, mirror the LV on this in striped mode:

   sda       sdb       sdc
 _______   _______   _______
|lv_orig| |lv_orig| |lv_orig|
|mirror | |mirror | |mirror |  <= striped!
|stripe1| |stripe2| |stripe3|
|_______| |_______| |_______|
|       | |       | |       |
| sda2  | |lv_orig| |lv_orig|
| empty | |half 1 | |half 2 |
|_______| |_______| |_______|



get rid of the sd{b,c}2 side of the mirror:

   sda       sdb       sdc
 _______   _______   _______
|       | |       | |       |
|lv_orig| |lv_orig| |lv_orig|  <= still striped!
|stripe1| |stripe2| |stripe3|
|_______| |_______| |_______|
|       | |       | |       |
| sda2  | | sdb2  | | sdc2  |
| empty | | empty | | empty |
|_______| |_______| |_______|


delete sd{a,b,c}2 partitions to extend sd{a,b,c}1 on the whole disk,
finally, extend the lv:

   sda       sdb       sdc
 _______   _______   _______
|       | |       | |       |
| sda1  | | sdb1  | | sdc1  |
|       | |       | |       |
|lv_orig| |lv_orig| |lv_orig|  <= definitely striped!
|       | |       | |       |
|bigger&| |bigger&| |bigger&|
|striped| |striped| |striped|
|_______| |_______| |_______|

Here is how to proceed :

Disclaimer: I wrote this mostly based on memories, please double check the commands (and edit the post if needed!)

  • create the partitions sdb1 and sdb2, respectively 42 and 58 MB,
  • same thing for sdc,
  • pvcreate /dev/sd{b,c}{1,2},
  • vgextend vg_orig /dev/sdb2 /dev/sdc2,
  • pvmove /dev/sda1 will move all LV data to sdb2 and sdc2,
  • vgreduce vg_orig /dev/sda1 and pvremove /dev/sda1 will make LVM completely stop using sda,
  • create a 42 MB partition /dev/sda1 (erasing the previous one if needed), and pvcreate /dev/sda1, vgextend vg_orig dev/sd{a,b,c}1,
  • lvconvert --type mirror --mirrors 1 --stripes 3 vg_orig/lv_orig /dev/sd{a,b,c}1 will create a stripped mirror of our original LV volume (what we are looking for!), you can check the details with lvdisplay -am,
  • the previous command may fail if the total number of extends in the LV is not a multiple of 3, in which case, you can simply add 1 or 2 extend to the LV like this: lvextend -l +1 vg_orig/lv_orig,
  • with this command, we will get rid of the temporary mirror copy of the data we have in sdb2 and sdc2: lvconvert --type mirror --mirrors 0 vg_orig/lv_orig /dev/sd{b,c}2,
  • remove the sdX2 partitions we don't need anymore: vgreduce vg_orig /dev/sd{b,c}2, pvremove /dev/sd{b,c}2,
  • now we have a striped version of our original data, we still need to make the sd{a,b,c}1 partitions bigger, so delete the sdb2 and sdc2 partitions and recreate the sda1, sdb1 and sdc1, partitions so that they start at the same sector number, but end at a higher sector number (don't be afraid :)),
  • partprobe /dev/sd{a,b,c}1 to refresh the kernel partition table,
  • pvresize /dev/sd{a,b,c}1 to make LVM realize the PVs are bigger,
  • lvextend -l 100%VG vg_orig/lv_orig to make the LV bigger now,
  • resize2fs vg_orig/lv_orig if you have an ext filesystem that you want to grow online.

Here you go!

It is pretty confusing to me that a tool like LVM, supposedly made for this kind of operation is not able to do this task easily in a single (or two) command...

Share:
5,879

Related videos on Youtube

Totor
Author by

Totor

Updated on September 18, 2022

Comments

  • Totor
    Totor almost 2 years

    On my server using LVM, I have a simple linear LV on a single drive (PV). Now, I added 2 more (same size) drives (PVs) to the server.

    I want to convert my existing linear LV to a striped LV (RAID0 like) across the 3 drives, if possible, online. This would allow me to enhance performance, thanks to the striping. I know it is theoretically possible.

    I tried many things, like creating a striped mirror of my LV, based on this website technique, but in my case it is more complicated because I want to keep using the original drive (on the website, it is a migration from a single drive LV to 3 other drives).

    I am becoming more and more familiar with the pvmove, lvconvert and other LVM tools but didn't succeed. Please help. :)

    If needed, I have very few extra space on another drive (about 5% of my original LV size).

    My lvdisplay -m is as follows:

    --- Logical volume ---
    LV Path                /dev/vg_space/vol_space
    LV Name                vol_space
    VG Name                vg_space
    LV Status              available
    # open                 1
    LV Size                260.75 GiB
    Current LE             66752
    Segments               1
    Allocation             inherit
    Read ahead sectors     auto
    - currently set to     256
    Block device           253:0
    
    --- Segments ---
    Logical extent 0 to 66751:
      Type                linear       
      Physical volume     /dev/sda5
      Physical extents    0 to 66751
    
  • Joachim Wagner
    Joachim Wagner about 2 years
    The man page says "In most cases, the mirror type is deprecated and the raid1 type should be used." Is the above a case in which --type mirror is not depreciated? If not, might be worthwhile making a request to the developers to keep this feature for use cases like this one.
  • Joachim Wagner
    Joachim Wagner about 2 years
  • Joachim Wagner
    Joachim Wagner about 2 years
    Replacing --type mirror with type raid1 in above procedure, the mirror is linear over sda{a,b,c}1, not striped.
  • Jeff Schaller
    Jeff Schaller about 2 years
    There may be a little time travel happening here -- just note that this (accepted) answer is just over 5 years old at this point. The deprecation may have happened in that timeframe.
  • Joachim Wagner
    Joachim Wagner about 2 years
    @JeffSchaller Actually, raid1 probably never worked in this scenario and mirror should still work (it only temporarily was rendered unusable in the CLI), reading on the lvm2 bug tracker and unix.stackexchange.com/questions/697364/…
  • Admin
    Admin about 2 years
    Hi @JoachimWagner, did you consider the --type striped or raid0 options of lvconvert? (regarding the deprecation of the mirror type) It's been some time since I dug into this, so, I'm asking not out of knowledge, but out of curiosity ("maybe it works" spirit).
  • Admin
    Admin almost 2 years
    @Tutor: Yes, I tried and it didn't work as it only applies to new allocations. mirror is used here to copy data to the striped set without disrupting users of the volume. If you can accept a downtime you can simple create the striped volume, copy data (filesystem image or individual files), configure your system to use the new volume and then grow it.