5

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
4

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...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.