Mondi su mondi, sistemi di sistemi.

LVM

Cos’è LVM

LVM sta per Logical Volume Manager e consente di gestire lo storage in modo più fles­sibile introducendo uno strato intermedio tra i dischi (fisici) e i file system.

Senza LVM avremmo:

  1. dischi;
  2. partizioni: ogni partizione può occupare al mas­simo un disco;
  3. file system: ogni file system può occupare al mas­simo una partizione.

Con LVM abbiamo:

  1. dischi fisici, quelli veri ;-);
  2. dischi fisici (PV);
  3. volume group (VG): associa i PV ai volumi logici;
  4. volumi logici (LV);
  5. file system.

I PV corrispondono alle partizioni così come le conosciamo nel mondo Mac ed è al di sopra di questi che LVM aggiunge quel livello d’indirezione che consente ai LV di essere definiti in termini di “somma” di PV.

Una limitazione di LVM è data dal fatto che una partizione LVM non può essere usata per il boot. Inoltre, il fatto che sia neces­sario smontare il file system per ridimensionarlo, complica leggermente la pianificazione delle partizioni: è meglio pre­vedere almeno due partizioni non LVM, una di boot e una di root. In questo modo le operazioni di manutenzione non richiederanno il riavvio da un boot alternativo.

Attenzione, non è obbligatorio che la partizione di root non usi LVM; è solo che diventa una complicazione inutile se tanto il file system non verrà mai allargato. Il problema diventerà evidente più avanti.

Un case study

Questo case study è lo scenario in cui mi sono realmente trovato e che mi ha portato ad approfondire questo software. Si trattava di una macchina con Fedora Core, nella quale si voleva riutilizzare il secondo dei due dischi interni per altri scopi.

Quello che segue è una replica abbastanza fedele di quello che è stato fatto.

Scopo del case study

Lo scenario di partenza è il seguente:

  • due dischi fisici, l’uno grande il doppio dell’altro;
  • un solo VG;
  • due PV;
  • due LV, uno di root e l’altro di swap.

Quello di arrivo è:

  • un LV di root composto da un solo PV;
  • un LV di root composto dal secondo PV a scopo di backup.

Ambiente di test

Useremo Debian 4, sotto Parallels, per illustrare i passi e il contesto delle decisioni prese. Alcune operazioni saranno dettate dalla situazione particolare dell’ambiente di test e terranno conto di elementi non strettamente collegati a LVM; tuttavia penso che questi elementi di contorno rendano il case study più realistico. I tutorial sono neces­sati per capire l’uso di un dato strumento ma, sul campo, bisogna saper incrociare elementi diversi per arrivare all’obbiettivo.

La virtual machine è configurata in questo modo:

  • il disco di boot, da 32GB (il default) sul bus IDE 0:0 e mappato sotto /dev/hda;
  • il secondo disco, da 16GB sul bus IDE 1:0 e mappato sotto /dev/hdc;
  • un disco di backup, da 32GB sul bus IDE 1:1 e mappato sotto /dev/hdd;

Sistema operativo

Debian 4 propone 4 tipi di partizioni:

  1. un disco intero;
  2. un disco intero, con LVM;
  3. un disco intero, con LVM criptato;
  4. manuale.

Sceglieremo la seconda opzione, con una sola partizione, aggiungendo manualmente il secondo disco in un secondo momento. Il nome di default per il VG è uguale al nome dell’host, in questo caso debian4lvm e il bootloader usato è GRUB. Ad installazione terminata abbiamo:


# vgdisplay
  --- Volume group ---
  VG Name               debian4lvm
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               31.01 GB
  PE Size               4.00 MB
  Total PE              7938
  Alloc PE / Size       7938 / 31.01 GB
  Free  PE / Size       0 / 0
  VG UUID               K1SsHH-eJv3-cDir-j0HQ-JXaz-qPvn-zRCytB

# pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda5
  VG Name               debian4lvm
  PV Size               31.01 GB / not usable 0
  Allocatable           yes (but full)
  PE Size (KByte)       4096
  Total PE              7938
  Free PE               0
  Allocated PE          7938
  PV UUID               fOw6Im-tcAV-oBbH-9yt3-gMfQ-zW2I-sME5bq

# lvdisplay
  --- Logical volume ---
  LV Name                /dev/debian4lvm/root
  VG Name                debian4lvm
  LV UUID                SylknN-CQxH-2mv6-32Dc-FLDg-frIG-zdQ3gA
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                30.27 GB
  Current LE             7750
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:0

  --- Logical volume ---
  LV Name                /dev/debian4lvm/swap_1
  VG Name                debian4lvm
  LV UUID                PXaaOb-yl4Y-J9NR-6q73-2cqw-8zjd-3JlfiP
  LV Write Access        read/write
  LV Status              available
  # open                 2
  LV Size                752.00 MB
  Current LE             188
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:1

Secondo disco

Aggiungiamo il secondo disco, dopo averlo formattato con fdisk:


# fdisk /dev/hdc
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-2039, default 1):<RETURN>
Using default value 1
Last cylinder or +size or +sizeM or +sizeK (1-2039, default 2039): <RETURN>
Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): 8e
Changed system type of partition 2 to 8e (Linux LVM)
Command (m for help): w

per poi aggiungerlo al VG creata all’inizio:


# pvcreate /dev/hdc1
# vgextend debian4lvm /dev/hdc1

Adesso avremo:


# pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda5
  VG Name               debian4lvm
  PV Size               31.01 GB / not usable 0
  Allocatable           yes (but full)
  PE Size (KByte)       4096
  Total PE              7938
  Free PE               0
  Allocated PE          7938
  PV UUID               fOw6Im-tcAV-oBbH-9yt3-gMfQ-zW2I-sME5bq

  --- Physical volume ---
  PV Name               /dev/hdc1
  VG Name               debian4lvm
  PV Size               15.62 GB / not usable 0
  Allocatable           yes
  PE Size (KByte)       4096
  Total PE              3998
  Free PE               3998
  Allocated PE          0
  PV UUID               2dWjqG-Z9nS-t56H-4PZo-ubwg-psId-BnKpVj

# vgdisplay
  --- Volume group ---
  VG Name               debian4lvm
  System ID
  Format                lvm2
  Metadata Areas        2
  Metadata Sequence No  4
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               2
  Max PV                0
  Cur PV                2
  Act PV                2
  VG Size               46.62 GB
  PE Size               4.00 MB
  Total PE              11936
  Alloc PE / Size       7938 / 31.01 GB
  Free  PE / Size       3998 / 15.62 GB
  VG UUID               K1SsHH-eJv3-cDir-j0HQ-JXaz-qPvn-zRCytB

# lvdisplay
  --- Logical volume ---
  LV Name                /dev/debian4lvm/root
  VG Name                debian4lvm
  LV UUID                SylknN-CQxH-2mv6-32Dc-FLDg-frIG-zdQ3gA
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                30.27 GB
  Current LE             7750
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:0

  --- Logical volume ---
  LV Name                /dev/debian4lvm/swap_1
  VG Name                debian4lvm
  LV UUID                PXaaOb-yl4Y-J9NR-6q73-2cqw-8zjd-3JlfiP
  LV Write Access        read/write
  LV Status              available
  # open                 2
  LV Size                752.00 MB
  Current LE             188
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:1

Ovvero, vediamo il nuovo PV e la capacità mas­sima del VG è diventata di circa 46GB mentre i LV sono rimasti invariati.

Adesso pos­siamo allargare il LV: il nuovo PV è grande 15.62GB ma dobbiamo ridurre di 0.01GB per errori di arrotondamento (almeno credo… se usas­simo i blocchi potremmo essere più precisi):


# lvextend -L+15.61G /dev/debian4lvm/root

adesso abbiamo:


  --- Logical volume ---
  LV Name                /dev/debian4lvm/root
  VG Name                debian4lvm
  LV UUID                SylknN-CQxH-2mv6-32Dc-FLDg-frIG-zdQ3gA
  LV Write Access        read/write
  LV Status              available
  # open                 1
  LV Size                45.89 GB
  Current LE             11747
  Segments               2
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:0

  --- Logical volume ---
  LV Name                /dev/debian4lvm/swap_1
  VG Name                debian4lvm
  LV UUID                PXaaOb-yl4Y-J9NR-6q73-2cqw-8zjd-3JlfiP
  LV Write Access        read/write
  LV Status              available
  # open                 2
  LV Size                752.00 MB
  Current LE             188
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           254:1
Estensione del file system

Per poter allargare il file system, dobbiamo smontarlo. Tuttavia, dato che la partizione di root è una sola dobbiamo fare il boot da un altra unità. Abbiamo due pos­sibilità: a) usare un CD di recupero; b) aggiungere un secondo disco di dimensioni adeguate e usarlo come boot alternativo e, nello stesso tempo, come backup per il disco principale.

Seguiamo la seconda soluzione, ispirata a questo HOWTO, usando il disco sotto /dev/hdd. Esso dovrà essere formattato in modo da poter essere usato come disco di boot alternativo (senza usare LVM).

Dobbiamo creare tre partizioni: una di boot da 247MB, una di swap da 752MB e il resto lo dedichiamo alla partizione di root. Le dimensioni delle prime due partizioni sono desunte da quelle in uso. Dato che usiamo sempre fdisk, rimando ancora a questo HOWTO per i dettagli.

Formattiamo le partizioni:


# mkfs.ext3 /dev/hdd1
# mkfs.ext3 /dev/hdd3
# mkswap /dev/hdd2

Creiamo una directory di mount per il nuovo disco e montiamolo:


# mkdir /new-hd
# mount -t ext3 /dev/hdd3 /new-hd
# mkdir /new-hd/boot
# mount -t ext3 /dev/hdd1 /new-hd/boot

Prima di copiare i dati, mettiamoci in single user mode:


# /sbin/telinit 1

Per copiare i dati ci sono diverse pos­sibilità. Le più semplice consiste nell’usare cp:


# cp -ax / /new-hd

Il flag -a cerca di pre­servare ogni carattertistica dei file, mentre il flag -x evita che la copia “attraversi” i file system, in modo che new-hd non venga copiato.
Un’altra pos­sibilità è quella di usare rsync (che può non essere installato, dipende dalle opzioni scelte all’inizio):


# rsync -ax --delete --force --exclude /new-hd / /new-hd
# rsync -ax --delete --force --exclude /new-hd /boot /new-hd/boot

in questo caso useremo quest’ultima.

Il disco di backup non sarebbe disponibile per il boot, a causa della sua posizione sul bus IDE, per cui scambiamo la sua posizione con quella occupata dal CD.
Questo ha due implicazioni: 1) /dev/hdb, prima usato per il CD, adesso fa riferimento al nuovo disco; 2) l’fstab è disallineato, dato che indica /dev/hdb come device per il mount dei CD.
Quindi modifichiamo l’/etc/fstab sotto /new-hd. Il disco hdd diventa hdb e il CD-ROM diventa hdd:

/dev/hdb3    /            ext3 …
/dev/hdb1    /boot        ext3 …
/dev/hdb2    none         swap …
/dev/hdd     /media/cdrom udf,iso9660 …
…

Per eseguire il boot dal disco di backup, dopo averne scambiato la posizione con il lettore, usiamo GRUB, pas­sandogli questi parametri:


root(hd1,0)
kernel /vmlinux-2.6.18-4-686 root=/dev/hdb3 ro single
initrd /initrd.img-2.6.18-4-686

A boot avvenuto, espandiamo la partizione di root:


fsck.ext3 -f /dev/debian4lvm/root
resize2fs /dev/debian4lvm/root

da notare che senza nes­suna indicazione l’espansione del volume occuperà tutto il LV.

Distacco del secondo hd

A questo punto abbiamo replicato lo scenario di partenza: un disco di boot composto da due volumi logici. Adesso, per poter sganciare il secondo disco dovremo semplicemente fare queste operazioni:

  1. Ridurre le dimensioni del file system montato sul LV:
    
    # fsck.ext3 -f /dev/debian4lvm/root
    # resize2fs /dev/debian4lvm/root 25G
    
  2. Ridurre le dimensioni del LV:
    
    # lvreduce -L26G /dev/debian4lvm/root
    
  3. Rimuovere il disco fisico dal VG:
    
    # vgreduce debian4lvm /dev/hdc1
    
  4. Rimuovere il PV:
    
    # pvremove /dev/hdc1
    

Forse prima avete notato che ho usato una dimensione molto inferiore a quella mas­sima disponibile. Questo è stato fatto per assicurarsi che il secondo PV fosse libero. Ovviamente, un approccio del genere è pos­sibile solo se si ha spazio a sufficienza sul primo PV.

Per riutilizzare di nuovo tutto il PV usiamo lvextend specificando un numero di LE ricavato da pvdisplay:


# lvextend -l +1094 /dev/debian4lvm/root

È tutto!

Appendice 1. Link utili

Questi sono i link agli articoli che ho usato come riferimento nell’intervento e nella stesura del case study.

Appendice 2. ZFS

Dato che ZFS è un file system che probabilmente verrà usato anche sotto Mac OS X ed è implementato, in forma ancora sperimentale, su FreeBSD 7, pensavo sarebbe stato utile qualche accenno a ZFS.

I link che seguono dovrebbero dare un’idea più pre­cisa delle sue peculiarità: