Linux z dyskiem SSD za pan brat

Nikt nie lubi wlec się w ogonie postępu, dlatego co jakiś czas nachodzi człowieka nieprzemożona ochota na uaktualnienie konfiguracji swojego komputera. Nachodzi go jeszcze gwałtowniej, gdy taka zmiana niesie za sobą wymierne skutki w jakości pracy, oszczędności energii i poziomu decybeli jakie wydobywają się z naszego cyfrowego kompana. Tym razem wybór padł na dysk SSD – uzasadniony tym, że technologia ta osiągnęła już stan miarę dojrzały, pojemności takich dysków przekroczyły już dawno żartobliwe 32GB, w zamian otrzymujemy niebotyczne osiągi transferu, szybkość startu systemu i aplikacji, jak też pozbywamy się ‘zgrzytania’ dysku talerzowego. Minusem jest przypadłość takich dysków wynikają ze specyfiki nośnika – innymi słowy, im więcej i częściej na tym dysku zapisujemy, tym bardziej skracamy ich żywotność. Ale bez obaw, przypuszczalnie nikomu nie uda się ‘zajeździć’ takiego dysku do czasu wymiany na nowszy model. Ale czy da się coś zrobić, aby Linux był bardziej przyjazny dla dysków SSD? Oczywiście, że się da, nawet mamy do wyboru kilka wariantów postępowania.

0. Trochę teoretyzowania i plan działania

Z uwagi na wrażliwość i ew. ograniczenia żywotności w odniesieniu do częstotliwości zapisu na takim nośniku, logicznym wydaje się przeznaczyć go do takiej roli w naszym pudle, aby zminimalizować występowanie zapisu na dysk Solid State Drive. I o ile można się spierać, czy ma to jakieś uzasadnienie ekonomiczne i wytrzymałościowe, o tyle użytkownicy laptopów i systemów mobilnych nie mają takiego problemu – zwykle mogą wsadzić do urządzenia tylko jeden taki dysk i musi on pełnić rolę pełnoprawnego nośnika. Posiadacze desktopów ‘kombinowanych’ mają większe pole do popisu. W moim przypadku dysk SSD został przeznaczony tylko i wyłącznie na partycje systemowe (mam trzy, bo i potestować dystrybucje lubię). Pozostałe dane – a zatem katalog domowy /home, partycje z danymi, itp., z racji częstego kopiowania, przenoszenia, zapisywania lub kasowania na nich przeróżnych danych, zostały na dysku talerzowym (bo na taki komfort mogłem sobie pozwolić).

1. Ulokowanie dysku w maszynie i systemie

Obecne dyski SSD wyposażone są standardowo w interfejs SATAII lub SATAIII (zgodny w dół). Zatem podpięcie dysku do płyty głównej wymaga posiadanie takowego interfejsu, jak też zwrócenie uwagi w BIOSie, aby kontroler obsługiwał taki dysk w trybie AHCI. Instalacja Linuksa na takim dysku? Jeżeli ktoś nie ma jakiś dziwacznych problemów z kontrolerem (?), to po prostu dysk podpina, uruchamia instalator Linuksa i instaluje. Bez żadnej magii, tak po prostu. Jedyną rzeczą na którą należy zwrócić uwagę, to system plików jaki użyjemy na partycjach naszego dysku SSD. Aby wykorzystać specyfikę SSD z funkcją TRIM, powinniśmy użyć systemu plików który wspiera TRIM – zatem wybieramy pomiędzy standardowym Ext4, Btrfs, XFS lub GFS2. Ambitni mogą (a nawet powinni) zainteresować się wyrównaniem tworzonych partycji tak, by w pełni wykorzystały specyfikę dysków SSD.

2. Podstawowe podstawy – TRIM

Całe zamieszanie z funkcją TRIM w dyskach SSD wynika właśnie z potrzeby ograniczenia ilości zapisów na dysku, jak też polepszenie ogólnej wydajności podczas zapisu. Nie uwierzycie ile w dysku SSD jest ceregieli, aby zapisać dane do strony (na jakie podzielony jest nośnik, a które zgrupowane są w bloki). Panaceum na te zawiłości ma być TRIM w połączeniu z Garbage Collection. Zatem – w dobrym tonie leży korzystać z TRIM, ale jak? Pierwszy krok już uczyniliśmy – nasz system plików wspiera TRIM (Ext4, Btrfs, XFS, GFS2). Lecz domyślnie jego obsługa jest wyłączona. Wymagane jest poprawienie pliku /etc/fstab i dodanie odpowiednich parametrów przy naszej partycji dysku SSD. Dlatego najpierw wykonujemy kopię pliku fstab, a następnie otwieramy go do edycji:

sudo cp /etc/fstab /etc/fstab.bak
sudo gedit /etc/fstab

Odnajdujemy wpis naszej partycji (u mnie /) i przy opcjach dodajemy ‘noatime,discard’:

UUID=(...) / ext4 noatime,discard,errors=remount-ro 0 1

‘Discard’ włączy obsługę TRIM, ‘noatime’ poprawni nieco wydajność.

3. Usprawniania ciąg dalszy – Deadline w miejsce CFQ

Generalnie na włączeniu obsługi funkcji TRIM możemy zakończyć nasze zmagania z mediacjami pomiędzy Linuksem a Solid State Drive. Skoro jednak system pozwala nam na kolejne optymalizacje, dlaczego by więc z tego nie skorzystać. Pierwszym takim niuansem w przypadku dysków SSD pod Linuksem jest zarządca (scheduler) kolejkowania procesów I/O. Domyślnie Linux wykorzystuje CFQ, który jest zoptymalizowany pod zwykłe, talerzowe napędy. W przypadku SSD, który jest kawałkiem pamięci, najprościej mówiąc, nie ma konieczności wymyślnego kolejkowania danych, bo czas dostępu do wszystkich sektorów-stron pamięci jest taki sam. Dlatego zastosowanie najprostszego rozwiązania zwiększy dodatkowo wydajność SSD. A tym rozwiązaniem jest scheduler Deadline (lub Noop). Łatwo sprawdzimy, jaki zarządca jest obecnie w użyciu, wydając komendę (dla SSD pod sda):

sudo cat /sys/block/sda/queue/scheduler

A otrzymamy w rezultacie:

noop deadline [cfq]

Teraz musimy tylko pouczyć system, by dla dysku sda użył Deadline:

echo deadline > /sys/block/sda/queue/scheduler

Jak zrobić, aby działo się to samoczynnie przy starcie systemu? W przypadku Ubuntu 12.04 i przyszłego 12.10 oraz pochodnych (w tym Mint 13 i kolejny), Deadline jest już domyślnym zarządcą kolejkowania. W dystrybucjach, które nadal korzystają z CFQ, musimy odpowiednio spreparować plik /etc/rc.local, wklejąc na końcu (po wcześniejszym sudo gedit /etc/rc.local), zamieniając sda na nasz dysk:

echo deadline > /sys/block/sdX/queue/scheduler
exit 0

Nie wszędzie jest jednak tak łatwo i przyjemnie. Dystrybucje korzystające z nowego zarządcy usług systemd (Archlinux, Manjaro, itp), który nie bierze pod rozwagę /etc/rc.local, wymuszają na nas zmianę tego parametru na poziomie udev. Tworzymy zatem plik:

sudo gedit /etc/udev/rules.d/50-schedulers.rules

… i wklejamy:

# set deadline scheduler for non-rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="deadline"

# set cfq scheduler for rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="cfq"

Ten sposób jest o tyle wygodny, że nie musimy w przyszłości pamiętać, że zmieniła się np. nazwa naszego dysku (z sda na sdb).

4. Korzystamy z SSD, ale nie korzystamy – swap, /tmp i inne

Wspomniany strach przed częstym zapisywaniem danych na naszym nowiutkim SSD ciągnie się ciągle za nami. Nieco podleczyliśmy tę fobie pozostawiając /home na dysku tradycyjnym. Jednak są miejsca w systemie, gdzie zapis jest przeprowadzany równie często co w naszym katalogu domowym, jak nie częściej. Takim miejscem jest… Nie, nie swap (o nim za chwilę), ale np. katalog /tmp. Skoro jednak dokupiliśmy do naszej konfiguracji sprzętowej dysk SSD, zatem przypuszczalnie mamy również zamontowane sporo pamięci. Dlaczego nie wykorzystać by jej na potrzeby plików tymczasowych? W ten sposób odciążymy SSD od częstego zapisu (w /tmp przewija się nasza codzienna działalność – i tak codziennie, od nowa). Ponownie zatem edytujemy plik /etc/fstab i wklejamy (o ile już takiej linijki tam nie ma – bo Archlinux i Manjaro na pewno ją posiadają).

tmpfs   /tmp       tmpfs   defaults,noatime,mode=1777   0  0

A co ze swapem? Ponownie – użytkownicy laptopów i urządzeń mobilnych nie mają wyjścia, jeżeli chcą używać hibernacji – swap musi być (co najmniej odpowiadający ilości zainstalowanej pamięci RAM) i to nawet na SSD (plusem jest, że hibernacja i powrót będzie sprawniejsza). Jeżeli natomiast mamy stacjonarny desktop i pamięci w okolicach 4GB i więcej – swap zapewne nigdy nie będzie u nas wykorzystany. Mamy zatem dwa rozwiązania – pominąć swap, albo ponownie wspomóc się dyskiem tradycyjnym lub pamięcią RAM (zram i swap w pamięci). Jeżeli jednak zdecydujemy się na swap na SSD, to by zminimalizować jego wykorzystanie możemy poinstruować system, by korzystał z niego w ostateczności. Wykorzystamy albo /etc/rc.local, albo /etc/sysctl.conf:

# rc.local, przed exit 0
echo 1 > /proc/sys/vm/swappiness

… lub:

# sysctl.conf, dopisujemy linijkę
vm.swappiness=1

A co z innymi katalogami systemowymi, gdzie coś często się dzieje? Można zastosować trick z tmpfs – np. /var/cache/apt/archives to tymczasowy katalog na pobierane pakiety aktualizacji. Dlaczego by nie miały wylądować chwilowo w pamięci?

tmpfs /var/cache/apt/archives tmpfs defaults,noatime 0 0

5. Ostatnie maźnięcia po klawiaturze – journaling systemu plików

Gdy już tak majstrujemy przy systemie, warto przypomnieć sobie o starym tricku zwiększającym wydajność tradycyjnych dysków – mianowicie sposobie księgowania (journaling). Standardowo nasz system plików (np. ext4) na wypadek awarii bardzo skrupulatnie księguje wszelkie zmiany, co siłą rzeczy zmniejsza nieco wydajność operacji I/O. Ponadto taka asekuracja w przypadku dysków SSD zwiększa częstotliwość zapisu na nośniku – a tego nie lubimy. Aby całkiem nie pozbawiać się ochrony, przestawimy (zamiast wyłączyć) księgowanie na metodę writeback (metadane pliku), zamiast ordered (metadane pliku + dane). W tym celu musimy najpierw zmienić pewien parametr partycji:

sudo tune2fs -o journal_data_writeback /dev/sdXX

Gdzie sdXX to nasza partycji na dysku SSD, np. sda1.

Dalej jest nieco gorzej. Ponieważ na SSD mamy główny system plików, a w przypadku zmiany księgowania dodanie odpowiedniego parametru do /etc/fstab jest zwodnicze i niepewne, dlatego pouczymy od razu kernel jakim księgowaniem posługuje się partycja / (root). W tym celu edytujemy nasz /etc/default/grub (sudo gedit /etc/default/grub) i odnajdujemy linijkę GRUB_CMDLINE_LINUX_DEFAULT (to zapewni nam dodawanie parametru dla każdej partycji systemowej, także po aktualizacji), dodając na końcu jej parametrów rootflags=data=writeback:

# GRUB_CMDLINE_LINUX_DEFAULT ->  rootflags=data=writeback
GRUB_CMDLINE_LINUX_DEFAULT = "(...) rootflags=data=writeback"

… i wykonujemy sudo update-grub.

6. Mowa końcowa

Dla laika powyższe wywody wyglądają dramatycznie. Dlatego jak wspomniałem, zakończyć zabawę można już po włączeniu obsługi TRIM. A nawet i bez tego, dysk SSD będzie działał. Po prostu.

Dla oczekujących szybkich komend i błyskotliwych porad, powyższe nudziarstwo może być nie do przełknięcia – lecz różnorodność jaką stwarzają dystrybucje Linuksa wymaga paru słów szerszego opisu kontekstu i genezy działania.

Dla fachowców – temat został ledwie liźnięty.

Poza tym, sprawa jest rozwojowa – obsługa SSD zapewne za jakiś czas nieco się zmieni – nadejdą nowe technologie, rozwiązania w kernelu, poprawki w dystrybucjach, itp. Jedyne co nam pozostaje, to być świadomymi faktu, że zawsze jakoś nad technologią możemy spróbować zapanować.

PS. Równaj do megabajta

W związku z trafnymi uwagami w komentarzach, że pominąłem zupełnie kwestię wyrównania partycji, parę słów nt. co to takiego i dlaczego jest tak istotne dla żywotności i sprawności nośników SSD.

Temat wyrównywania partycji wynikł ze sposobu w jaki elektronika dysków SSD obsługuje dane. Otóż w tych napędach najmniejsza porcja informacji to strona (4KB), natomiast 128 takich stron tworzy blok (512KB) i to właśnie tutaj rozmiar ma znaczenie. Operacje kasowania/czyszczenia elektronika SSD potrafi przeprowadzać tylko angażując cały blok (czyli 512KB – Erase Block Size). Wyrównanie partycji polega na takim dobraniu ilości głowic i sektorów, aby cylindry (stara nomenklatura w służbie nowoczesnej technologii) szły ręka w rękę z porcjami danych, które przerabia SSD. Dlatego pilnujemy, aby nasze partycje zaczynały się od sektorów będących krotnością liczby 512 (przy czym pierwszy partycja powinna zawsze zaczynać min. od 1024 sektora – kwestia kompatybilności z MS-DOS). A co z głowicami, sektora i cylindrami? Domyślnie Linux produkuje partycje oparte o schemat 255 głowice i 63 sektory 512bajtowe (i to wszystko tworzy cylinder o pojemności 255*63*512). Zaleca się jednak stosowania geometrii 32 głowic i sektorów. Aby ją uzyskać, należy posiłkować się poleceniem fdisk i nim stworzyć partycje (gparted nie umożliwia określenia geometrii). Całość rozpoczniemy poleceniem:

sudo fdisk -H 32 -S 32 /dev/sdX

Jak sprawdzić, czy przynajmniej początki partycji mamy dobrze wyrównane?

sudo fdisk -l /dev/sdX

Urządzenie Rozruch   Początek      Koniec   Bloków   ID  System
/dev/sda1   *        2048    81922047    40960000   83  Linux
/dev/sda2        81922048   163841969    40959961   83  Linux
/dev/sda3       163842048   250068991    43113472   83  Linux

Wartości z kolumny ‘Początek’ powinny być podzielne przez 512 bez reszty. Niektóre porady jakie można spotkać, zalecają stosowanie wyrównania do bloków 128KB (geometria 244 głowic, 56 sektorów) – do tego należy jednak posiłkować się danymi producenta dysku SSD i rozmiarem stosowanego przez niego Erase Block Size.