Table des matières

LVM et PV shrink

Réduire un “Physical Volume” LVM afin de faire de la place sur son disk , pour ultérieurement, créer de nouvelles partitions…

C'est un peu plus compliqué qu'il n'y parait, parce que les outils “LVM” ne prévoient pas de moyen simple et automatique pour défragmenter un volume.

~~READMORE~~

PV defrag

:!: Avant de poursuivre, se placer dans un “screen” ou un “tmux” : Les commandes peuvent mettre du temps a s'exécuter et un arrêt impromptu peut être fatal !

En effet, un “Physical Volume” (“PV”) peut être fragmenté au fur et a mesure de la création, du redimensionnement et de l'effacement des “Logical Volume” (“LV”).

''pvresize'' en échec

Exemple de tentative de réduction qui ne fonctionne pas:

# pvresize --setphysicalvolumesize 100G /dev/sda2
/dev/sda2: cannot resize to 25599 extents as later ones are allocated.
0 physical volume(s) resized / 1 physical volume(s) not resized

Fragments

Exemple de fragmentations:

# pvdisplay -v -m  
  Scanning for physical volume names
--- Physical volume ---
PV Name               /dev/sda2
VG Name               vg0
PV Size               135,93 GiB / not usable 4,01 MiB
Allocatable           yes 
PE Size               4,00 MiB
Total PE              34798
Free PE               17438
Allocated PE          17360
PV UUID               xxxxxxxx
   
--- Physical Segments ---
Physical extent 0 to 2383:
  FREE
Physical extent 2384 to 4767:
  Logical volume      /dev/vg0/reload_sys
  Logical extents     0 to 2383
Physical extent 4768 to 4895:
  Logical volume      /dev/vg0/videostream1-me-ga-swap
  Logical extents     0 to 127
Physical extent 4896 to 7455:
  Logical volume      /dev/vg0/videostream1-me-ga-disk
  Logical extents     0 to 2559
Physical extent 7456 to 7711:
  Logical volume      /dev/vg0/reload_swap
  Logical extents     0 to 255
Physical extent 7712 to 11551:
  Logical volume      /dev/vg0/warez-disk
  Logical extents     0 to 3839
Physical extent 11552 to 14623:
  Logical volume      /dev/vg0/mp3-me-ga-disk
  Logical extents     0 to 3071
Physical extent 14624 to 14917:
  FREE
Physical extent 14918 to 16249:
  Logical volume      /dev/vg0/databank-me-ga-disk
  Logical extents     3316 to 4647
Physical extent 16250 to 18807:
  FREE
Physical extent 18808 to 22123:
  Logical volume      /dev/vg0/databank-me-ga-disk
  Logical extents     0 to 3315
Physical extent 22124 to 27321:
  FREE
Physical extent 27322 to 27793:
  Logical volume      /dev/vg0/databank-me-ga-disk
  Logical extents     4648 to 5119
Physical extent 27794 to 34797:
  FREE

Par exemple: on voit que le “volume logique” /dev/vg0/databank-me-ga-disk est en 3 fragments :

Logical extents Physical extents
0 to 3315 22124 to 27321
3316 to 4647 16250 to 18807
4648 to 5119 27794 to 34797
# lvs /dev/vg0/databank-me-ga-disk 
LV                  VG   Attr   LSize  Origin Snap%  Move Log Copy%  Convert
databank-me-ga-disk vg0  -wi-a- 20,00g

Ce qu'on retrouve approximativement: 4MB * 5120 extents = 20GB

Défragmenter

Le plus ennuyeux, ce sont les fragments “FREE” qui sont eparpillés dans le “Physical Volume”.

Pour l'exemple ci-dessus, il est obligatoire de défragmenter si on veut réduire le “PV”.

En clair: Il faut mettre le plus gros fragment “FREE” possible à la fin du “Physical Volume”.

Pour cela, il faut déplacer à la main les fragments en utilisant , correctement , la commande pvmove .

Pour notre cas, la syntaxe de la commande est :

pvmove <pv_device>:<start_src-end_src> <pv_device>:<start_dst-end_dst> --alloc anywhere

En partant de l'exemple vu précédement, on a alors:

<pv_device> /dev/sda2

Par exemple, si on veut déplacer un fragment de “databank-me-ga-disk” , on peut d'abord voir que:

:!: ce n'est qu'un exemple: Il y a des façons plus intelligentes que d'autres pour ré-organiser des fragments !

Allons-y :

# pvmove /dev/sda2:27322-27793 /dev/sda2:0-2383 --alloc anywhere
/dev/sda2: Moved: 1,9%
/dev/sda2: Moved: 9,5%
...
/dev/sda2: Moved: 97,2%
/dev/sda2: Moved: 100,0%
#

Quelques minutes plus tard, on peut vérifier.

# pvdisplay -v -m  
  Scanning for physical volume names
--- Physical volume ---
PV Name               /dev/sda2
.....
  --- Physical Segments ---
Physical extent 0 to 471:
  Logical volume      /dev/vg0/databank-me-ga-disk
  Logical extents     4648 to 5119
Physical extent 472 to 2383:
  FREE
.....
Physical extent 22124 to 34797:
FREE

Un petit “fsck” peut confirmer que la partition “LV” est toujours valide. ( Ouf ! )

On note que les fragments “FREE” ce concatène (heureusement), et donc, dans notre cas, on a un plus gros fragment FREE à la fin: 22124 to 34797 .

A la fin

Au fur et a mesure, on va défragmenter et avoir un gros fragment “FREE” à la fin, par exemple:

# pvdisplay -v -m  
  Scanning for physical volume names
--- Physical volume ---
PV Name               /dev/sda2
.....
  --- Physical Segments ---
.....
Physical extent 17360 to 34797:
FREE

Et enfin, à la fin du fin, on peut réduire le “Physical Volume” par la commande qui échouait initialement:

# pvresize --setphysicalvolumesize 100G /dev/sda2
Physical volume "/dev/sda2" changed
1 physical volume(s) resized / 0 physical volume(s) not resized
# pvs
PV         VG   Fmt  Attr PSize   PFree 
/dev/sda2  vg0  lvm2 a-   100,00g 32,18g

Partitions

Mais il faut encore réduire la partition “disk” , avec “fdisk” ou “parted”. C'est ce dernier utilitaire qui a ma préférence et qui sera utilisé.

On va utiliser un autre volume pour illustrer le partitionnement.

Le voici avec ces fragments:

# pvdisplay -m /dev/sda1
--- Physical volume ---
PV Name               /dev/sda1
VG Name               vg1
PV Size               9,09 TiB / not usable 3,97 MiB
Allocatable           yes 
PE Size               4,00 MiB
Total PE              2382079
Free PE               817919
Allocated PE          1564160
PV UUID               xxxxxxxxxx
   
--- Physical Segments ---
Physical extent 0 to 760064:
  Logical volume      /dev/vg1/x-storage-1-data
  Logical extents     804095 to 1564159
Physical extent 760065 to 1564159:
  Logical volume      /dev/vg1/x-storage-1-data
  Logical extents     0 to 804094
Physical extent 1564160 to 2382078:
  FREE

Sur lequel il n'y qu'un “Logical Volume”, mais un gros:

# lvs /dev/vg1/x-storage-1-data 
LV               VG   Attr   LSize Origin Snap%  Move Log Copy%  Convert
x-storage-1-data vg1  -wi-ao 5,97t

PV Math

Pour la suite, on va n'effectuer les calculs qu'en unité “SECTEUR” .

Ce qui donne par exemple:

# pvs  --units s /dev/sda1
PV         VG   Fmt  Attr PSize        PFree      
/dev/sda1  vg1  lvm2 a-   19513991168S 6700392448S

Mais aussi:

# lvs --units s /dev/vg1/x-storage-1-data 
LV               VG   Attr   LSize        Origin Snap%  Move Log Copy%  Convert
x-storage-1-data vg1  -wi-ao 12813598720S

Un secteur valant 512B , on a bien: 12813598720 * 512 ⇒ 5.97 TB

Et aussi:

# pvdisplay --units s /dev/sda1
--- Physical volume ---
PV Name               /dev/sda1
VG Name               vg1
PV Size               19513999293 Se / not usable 8125 Se
Allocatable           yes 
PE Size               8192 Se
Total PE              2382079
Free PE               817919
Allocated PE          1564160
PV UUID               xxxx

Vérification: 19513999293 * 512 ⇒ 9.08 TB

Ce qui est bien la taille totale du “PV”.

Avec

# pvdisplay -m --units s /dev/sda1
...
Physical extent 1564160 to 2382078:
FREE

On voit bien le fragment “FREE” à la fin.

pvresize

# pvresize --setphysicalvolumesize 12813598720s /dev/sda1
/dev/sda1: cannot resize to 1564159 extents as 1564160 are allocated.
0 physical volume(s) resized / 1 physical volume(s) not resized

Oups ! Trop juste ! On a ajoute 8192 secteurs (qui correspond a 1 PE):

# pvresize --setphysicalvolumesize 12813606912s /dev/sda1
Physical volume "/dev/sda1" changed
1 physical volume(s) resized / 0 physical volume(s) not resized

Voila !

# pvs /dev/sda1
PV         VG   Fmt  Attr PSize PFree
/dev/sda1  vg1  lvm2 a-   5,97t    0

ou bien:

# pvs --unit s /dev/sda1
PV         VG   Fmt  Attr PSize        PFree
/dev/sda1  vg1  lvm2 a-   12813598720S    0S

ou bien:

# pvdisplay /dev/sda1
--- Physical volume ---
PV Name               /dev/sda1
VG Name               vg1
PV Size               5,97 TiB / not usable 3,81 MiB
Allocatable           yes (but full)
PE Size               4,00 MiB
Total PE              1564160
Free PE               0
Allocated PE          1564160
PV UUID               xxxxxx

“but full” :-)

Parted

Maintenant, le plus délicat: redimensionner la partition !

Calcul

Ce qu'en dit parted a ce stade:

# parted /dev/sda print
Model: DELL PERC H800 (scsi)
Disk /dev/sda: 9991GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start   End     Size    File system  Name     Flags
 1      17,4kB  9991GB  9991GB               primary  lvm

ou bien en secteur:

# parted /dev/sda unit s print
Model: DELL PERC H800 (scsi)
Disk /dev/sda: 19513999360s
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start  End           Size          File system  Name     Flags
 1      34s    19513999326s  19513999293s               primary  lvm

On remarque que la taille “19513999293s” correspond exactement à celle retourné par “pvdisplay” avant la réduction. Pour mémoire:

PV Size               19513999293 Se / not usable 8125 Se
:!: Ce n'est pas forcément toujours le cas. Etre trés prudent dans les calculs !

Maintenant, voila ce que ça nous retourne:

# pvdisplay --unit s /dev/sda1
......
PV Size               12813606528 Se / not usable 7808 Se

On va appliquer un arrondi d'un block “PE” , soit 8192 Secteurs, ce qui nous donne un nombre de secteurs de :

12813606528 + 8192 => 12813614720

On a vu que Parted nous dit, pour l'instant, en secteurs toujours:

Start: 34s
  End: 19513999326s

On va devoir changé “End” en la valeur calculé suivante:

34 + 12813614720 - 1

Soit:

  End: 12813614753s

Ce qui devrait nous donner, à la fin du fin (on y est pas encore):

Number  Start  End           Size          File system  Name     Flags
 1      34s    12813614753s  12813614720s               primary  lvm

La “size” “12813614720” est bien le nombre de secteurs retourné par “pvdisplay” , +8192 (l'arrondi en PE)

Bon bah, y a pu ka !

Appliquer

:!: On va devoir supprimer et recréer dans la foulée la partition !
:!: Il y aura des warnings “Ignore/Cancel” . Pour ma part, j'ignore toujours !
# parted /dev/sda
GNU Parted 2.3
Using /dev/sda
Welcome to GNU Parted! Type 'help' to view a list of commands.

D'abord , bien vérifier et noter l'état actuel de la partition a modifier:

(parted) print
Model: DELL PERC H800 (scsi)
Disk /dev/sda: 19513999360s
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start  End           Size          File system  Name     Flags
 1      34s    19513999326s  19513999293s               primary  lvm

:!: Virer la partition “1” (c'est la seule) :

(parted) rm 1                                                             
Error: Partition(s) 1 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel? I                                                          

:!: La recréer aussitot avec la nouvelle valeur “End” :

(parted) mkpart primary 34s 12813614753s
Warning: The resulting partition is not properly aligned for best performance.
Ignore/Cancel? I                                                          
Error: Partition(s) 1 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel? I                                                          

:!: Dire que c'est une partition “lvm” :

(parted) set 1 lvm on
Error: Partition(s) 1 on /dev/sda have been written, but we have been unable to inform the kernel of the change, probably because it/they are in use.  As a result, the old partition(s) will remain in use.  You should reboot now before making further changes.
Ignore/Cancel? I                                                          

Verifier d'un regard :

(parted) unit s print                                                     
Model: DELL PERC H800 (scsi)
Disk /dev/sda: 19513999360s
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number  Start  End           Size          File system  Name     Flags
 1      34s    12813614753s  12813614720s               primary  lvm
:!: On a modifié à “chaud” une partition. Le noyau Linux n'aime pas trop ça. Lisez la suite.
(parted) quit

Une fois sortie:

# sync

( Ça sert surement a rien… )

Puis reboot parce que l'OS est surement un peu perdu.
Pour ma part, je ne me risquerai pas a continuer a jouer avec la partition sans être certain que le noyau Linux est informé de l'état de la partition. Donc:

# reboot

Bilan

Ok

Ça a fonctionné ? Pour mon cas: oui.

Un petit e2fsck

# e2fsck -C 0 -f /dev/vg1/x-storage-1-data
e2fsck 1.41.12 (17-May-2010)
Passe 1 : vérification des i-noeuds, des blocs et des tailles
Passe 2 : vérification de la structure des répertoires                         
Passe 3 : vérification de la connectivité des répertoires                      
Passe 4 : vérification des compteurs de référence
Passe 5 : vérification de l'information du sommaire de groupe                  
/dev/vg1/x-storage-1-data : 453/400424960 fichiers (4.9% non contigus), 1146650060/1601699840 blocs

… et quelques *heures* plus tard : Aucune erreur.

Juste pour finasser :

# pvresize /dev/sda1
Physical volume "/dev/sda1" changed
1 physical volume(s) resized / 0 physical volume(s) not resized

Le “PE” en rabe vient d'être ajouté… lol

# pvs /dev/sda1
PV         VG   Fmt  Attr PSize PFree
/dev/sda1  vg1  lvm2 a-   5,97t 4,00m
# pvdisplay /dev/sda1
--- Physical volume ---
PV Name               /dev/sda1
VG Name               vg1
PV Size               5,97 TiB / not usable 3,62 MiB
Allocatable           yes 
PE Size               4,00 MiB
Total PE              1564161
Free PE               1
Allocated PE          1564160
PV UUID               xxxxxxxxx

Tout va bien.

Fail

En cas d'incident, eviter toutes écriture sur le “file system” en péril.

Avec parted (ou fdisk) , remettre en place la partition avec les mêmes paramètres qu'initialement.

Source