resize de lvm peste luks
De ceva vreme ma tot plang ca nu mai am spatiu pe laptop si nu prea-mi vine sa sterg mare lucru. Ceva mai devreme am constatat insa ca am 15 GB neocupati, mosteniti de pe vremea cand intentionam sa pun windows pe laptop (dupa ce am incercat cu 3 cd-uri diferite si n-a vrut nici macar sa porneasca installerul, probabil din cauza partitiilor de linux, am renuntat). Booon, toate bune si frumoase, numai ca spatiul liber e intre partitii si eu il vreau utilizabil sub forma de fisiere, diferenta care in cazul laptopului meu inseamna cateva bariere logice: partitia, peste care este device LUKS, peste care este un PV, peste care este un VG, peste care exista niste LV-uri, fiecare cu filesystemul lui (si toate pline pe la 80-90% cu date). Dupa o intrebare pe rlug, mi s-a confirmat de catre wolfy atat pe lista cat si pe #mumu ca nu-i nici o capcana si am purces la treaba.
Mai intai o descriere a situatiei:
Discul este /dev/hda si avea partitiile /dev/hda1 de vreo 250MB, /dev/hda2 de vreo 63GB si spatiu liber de vreo 15GB, asezate exat in ordinea asta pe disc. /dev/hda2 este folosit ca suport pentru LUKS, asta inseamna mai pe romaneste ca in /etc/cryptsetup se specifica ca /dev/hda2 e transformat de dev-mapper folosind modulul dm-crypt in /dev/mapper/hda2_crypt (alt nume al device-ului este /dev/dm-0 pentru ca e primul vazut de devmapper dupa boot, dar mai safe e primul). Acesta la randul lui este folosit de LVM2 ca PV (physical volume). Layerul de LVM defineste un VG (volume group) numit /dev/argos (atentie, calea nu e block device, este un director) care e format doar din acest PV (daca aveam mai multe discuri sau partitii dedicate LVM, puteam defini pe fiecare cate un PV pe care sa le combin in unul sau mai multe VG-uri, dupa plac). De ce argos? Asta era numele laptopului pe vremea cand l-am instalat, cred ca a fost inspirat de un pasaj din Cryptonomicon; intre timp am schimbat numele laptopului dar era prea mare bataia de cap sa redenumesc VG-ul, asa ca l-am lasat asa. In acest VG exista niste LV-uri (logical volumes) care sunt folosite drept suport pentru cele cateva sisteme de fisiere (sau ca swap device). La momentul actual am /boot pe partitia hda1 (desi am inteles ca grub2 stie sa booteze de pe lvm, nu stie si de dm-crypt, si oricum e bine sa ai la indemana un mediu de recovery Just In Case), swap, /, /opt si /home ca LV-uri. /opt e folosit ca depozit de "chestii", in timp am mai mutat diverse directoare de la mine din home acolo, pastrand doar cate un symlink. Utilitatea acestei scheme de partitionare este ca am de introdus o singura cheie de LUKS la boot si asigur confidentialitatea datelor de pe tot sistemul - cu exceptia /boot (care pentru paranoia totala poate fi mutat pe un stick usb de exemplu). Toti expertii in domeniu recomanda inclusiv criptarea swapului, intrucat poate contine zone sensibile de memorie care pot fi citite "la rece" de pe discul oprit. Ca bonus, ma pot folosi de avantajele LVM: resize usor de fs-uri, snapshoturi samd. Surpinzator, toata chestia asta are un impact minim de performanta, overheadul de procesor simtindu-se doar in conditii de I/O sustinut cu discul, cand de obicei am alte probleme oricum
Dar sa revenim la oile noastre, si anume procedura urmata pentru exploatarea acelor 15GB "rataciti".
Primul pas a fost refacerea partitiei /dev/hda2: cfdisk /dev/hda, stearsa partitia veche, refacuta cu noua dimensiune. Aici e foarte importnt faptul ca noua partitie incepe din acelasi loc cu cea veche si se termina mai departe decat inainte, astfel incat pozitia relativa a tuturor sectoarelor cu date din filesystem ramane la fel pe noul blockdevice. Inainte de iesirea din cfdisk, se salveaza tabela de partitii si nu e foarte surprinzator faptul ca da o eroare la recitirea ei, recomandan un reboot (explicatia imediat). Pentru completitudine, am rulat dupa iesirea din cfdisk un "blockdev --rereadpt /dev/hda" ceea ce ar face aceeasi chestie. Iarasi nu ma surprinde mesajul de eroare asa ca dau reboot.
Pana rebooteaza, o explicatie: la accesarea unui block device care e o partitie a altui device, kernelul citeste tabela de partitii din device-ul parinte, ca sa stie cat de lung este device-ul (dat fiind ca un blockdevice poate fi citit aleator si nu secvential, marimea acestuia e importanta la crearea structurilor de date care il acceseaza). Aceasta informatie este disponibila in /proc/partitions (foarte util pentru momentele cand constati ca ti-ai sters din greseala tabela de partitii si n-ai backup). In general kernelul refuza sa actualizeze aceste informatii daca risca sa contrazica starea curenta a blockdevice-urilor in uz, ca atare e nevoie sa se demonteze toate partitiile de pe discul respectiv (in cazul in care e si partitia de root pe acolo, reboot e cam singura sansa de a face acest lucru).
Acum ca a bootat sistemul, se constata ca tabela de partitii e vazuta corect de kernel. dar si o surpriza noua: si modulul dm-crypt a sesizat noua dimensiune a partitiei si a redimensionat in consecinta /dev/mapper/hda2_crypt. Cum se verifica asta? cryptsetup status hda2_crypt afiseaza campurile 'size' si 'offset' (cel din urma fiind de obicei 2056 de sectoare). Suma acestor doua numere ar trebui sa fie exact cat spune sfdisk -d /dev/hda | grep hda2 (sau alt partition manager care vorbeste in sectoare si nu bytes, blocks, clusters, etc., desi se poate tine cont ca un sector e 512 bytes). Daca nu faceam reboot (sa zicem din cauza ca in loc de hda2 aveam vreun LUN nepartitionat pe un SAN pe care tocmai l-am largit si ca atare nu era nevoie de tot circul cu rereadpt), probabil era nevoie de cryptsetup resize sau dmsetup reload pentru a forta devmapper sa vada noua dimensiune a device-ului.
Boon, acum spatiul liber este pe hda2, in hda2_crypt, dar in afara PV-ului, VG-ului si a oricarui LV. Pasul urmator e sa extind PV-ul, folosind pur si simplu pvresize /dev/mapper/hda2_crypt (sau /dev/dm-0 pentru lenesi, cu amendamentul sa fie primul device al dev-mapper). Operatia se face instant, intrucat tot ce se intampla e informarea LVM-ului ca maparea in extents (unitatile de date cu care lucreaza LVM, de obicei un numar de sectoare pe disc) a PV-ului s-a extins la noua dimensiune. pvdisplay ar trebui sa afiseze acum spatiu liber (free PE inseamna free physical extents). Surprinzator (sau nu) si vgdisplay sesizeaza acum noii extents, deoarece VG-ul contine in intregime PV-ul (poate avea mai multe, dar nu si fractiuni).
Ca atare acum spatiul liber e disponibil pentru alocare in interiorul VG-ului. De aici sunt 3 optiuni: crearea unui nou LV, crearea unui snapshot al unui LV existent (ambele variante se fac cu lvcreate, pagina de manual contine exemple pentru ambele cazuri) sau extinderea unui LV existent. Acest caz e putin mai complicat, asa ca il explic in continuare.
Mai intai se face extinderea LV-ului cu lvextend. Asta va informa driverul LVM sa prezinte ca LV un blockdevice mai mare, dar noul spatiu inca nu e utilizat de structurile filesystemului. In cazul ext2 sau ext3 cum folosesc eu, redimensionarea acestuia se face (dupa un obligatoriu fsck) cu ext2resize. Unele FS-uri permit redimensionarea "online" (in timp ce sunt montate) altele "offline". Nu toate permit redimensionarea in ambele sensuri. Atentie foarte mare la aceste detalii intrucat este extrem de usor sa se corupa iremediabil filesystemul si sa se piarda datele de pe el.
Alt lucru asupra caruia trebuie sa atrag atentia este ca ordinea operatiilor descrisa aici se aplica la marirea volumului/PV-ului/partitiei. Pentru micsorare, ordinea operatiilor este aproximativ invers, urmarindu-se eliberarea spatiului pentru redimensionarea unui container logic in interiorul sau in cazul micsorarii, nu in exterior. Pare evident, dar e foarte usor de trecut cu vederea.
Ca fapt divers, dupa ce am terminat de executat toate operatiile, am gasit pe net postul asta, care descrie exact situatia mea (si pe care il citisem la vremea respectiva, intrucat il am in Google Reader prin intermediul Debian Planet). Eh, sper sa fie de folos si altcuiva povestile de mai sus, ca vad ca m-am cam lungit. Ochii-n paispe si spor la treaba!