Raspberry Pi, Raspbian i problemy z kartami microSD

Jakieś siedem tygodni temu pisałem, że padła mi karta microSD (Kingston) w Raspberry Pi. Wymieniłem na nową (Goodram). Zamontowana oszczędnie, tj. bez journala i z symlinkiem /var/lib/transmission-daemon/info kierującym na dysk twardy. Wczoraj robię aktualizację systemu, a tu nagle:

Preparing to replace libssl1.0.0:armhf 1.0.1e-2+rvt+deb7u7 (using .../libssl1.0.0_1.0.1e-2+rvt+deb7u10_armhf.deb) ...
Unpacking replacement libssl1.0.0:armhf ... dpkg: error processing /var/cache/apt/archives/libssl1.0.0_1.0.1e-2+rvt+deb7u10_armhf.deb (--unpack):
error creating directory `./usr/share/doc/libssl1.0.0': Input/output error
Segmentation fault Segmentation fault -bash: mbrtowc.c:92: __mbrtowc: Assertion `status == __GCONV_OK || status == __GCONV_EMPTY_INPUT || status == __GCONV_ILLEGAL_INPUT || status == __GCONV_INCOMPLETE_INPUT || status == __GCONV_FULL_OUTPUT' failed.

Piękne, prawda? Oczywiście kluczowy jest input/output error. Fsck, są błędy, naprawiony filesystem. Coś mnie tknęło i sprawdziłem badblocks (badblocks -sv). Tak jest, błędy w okolicy 90% karty (dead link). Sztuk prawie 30. Wygląda, że karta Goodram wytrzymała w komfortowych warunkach raptem 7 tygodni. Masakra.

Z tego wszystkiego zacząłem sprawdzać, co pisze na dysk (iotop -ao). Wyniki (sortowane po ilości zapisów, czas działania kilka godzin) są ciekawe:

3192 be/4 root 8.00 K 4.03 M 0.00 % 0.00 % rsyslogd -c5
2184 be/4 root 240.00 K 880.00 K 0.00 % 0.00 % nmbd -D
3341 be/4 ntp 248.00 K 188.00 K 0.00 % 0.00 % ntpd -p /var/run/ntpd.pid -g -u 102:104
5256 be/4 root 0.00 B 160.00 K 0.00 % 0.00 % [kworker/u2:2]
2911 be/4 root 208.00 K 88.00 K 0.00 % 0.00 % -bash

Jak widać, głównie rsyslog. I raczej nie ma tego wiele.

I tu zaczyna się część najciekawsza. Pamiętacie uszkodzoną kartę Kingstona? Przygotowałem się do pozbycia się jej, poleciał shred. Stwierdziłem, że uruchomię badblocks na niej. I… niespodzianka. Teraz nie zgłasza błędów. Ani w teście odczytu (domyślny), ani w niedestrukcyjnym teście zapisu (badblocks -nvs). Naprawiło się?

Zaczynam podejrzewać jakiegoś buga z przejściówką microSD -> SD (ale są dwie różne, bo każda karta miała swoją), gniazdem w rpi (ale działało OK, poza tym i badblocks, i fsck robię w laptopie). Zagadka.

Ostatecznie zmniejszyłem rozmiar partycji ext4 na karcie Kingstona i działa do tej pory bez problemu. Czyli jakieś 3 tygodnie bezproblemowego działania, bo wpis zacząłem tworzyć 12 czerwca.

UPDATE: Zwariowałem. Goodram, który ewidentnie miał błędy, bo nie tylko badblocks je wykazywał, ale nawet shred puszczony przed wyrzuceniem powodował błędy IO i nie mógł dobrnąć do końca (a próbowałem nie raz), teraz działa. Nagrałem Raspbiana dla Banana Pi, test badblockiem i… czysto. WTF?

Pamięci flash, czyli pendrive, microSD itd.

Czasem człowiekowi wydaje się, że coś wie i… no właśnie, wydaje się. Że są różne pendrive’y (czy tam ogólnie pamięci flash), to wiedziałem. Wiedziałem też, że mają klasy i poszczególne klasy odpowiadają różnym prędkościom zapisu. I tyle.

Niedawno od hrw dowiedziałem się, że to nie do końca tak, że parametrów jest znacznie więcej i że w praktyce mają one spore znaczenie przy stosowaniu karty jako nośnika dla systemu Linux. Bo jednak czym innym jest zapis filmu na FAT, a czym innym realne operacje na jakichś linuksowych systemach plików.

Ostatnio uruchomiłem grzejnik na starym pendrive, użyłem ext2 i zdarzyło mi się trochę ponarzekać na μblogu, że wolno działa i w ogóle. Dostałem odpowiedź, że minimalny cluster size dla nośnika flash powinien być 4k. Co przypomniało mi wcześniejszą rozmowę i skłoniło do zadania pytania jak sprawdzić cluster size? Co dość szybko przywiodło mnie do wpisu nt. optymalizacji systemu plików dla pamięci flash.

Zauważyłem, że blog do którego powyżej linkuję ma raptem trzy wpisy i to sprzed roku, więc ryzyko zniknięcia jest spore. Pozwolę sobie zacytować dla pamięci część dotyczącą analizy:

  1. Interesting parts of this result are the diff changes drastically at two places:
    1. from  8388608 (8Mb) to 4194304 (4MB): Based in example readme in flashbench, this indicates that there was no performance overhead reading two blocks over the 4mb boundary, but there was for 8mb boundary. The guess is then that the erasure block is 8mb large on my sd-card
    2. before 8192 and after. I would really like to know why there is a bump at 8k, but times after that are so much lower, so 8k is obviously some sort of boundary point.
  2. From this, I deduce two things,
    1. Ext4 should have a block size of 4k, and the “stride” value should be 2. This will cause ext4 to think that units of 2 blocks (8k) can and should be treated as one.
    2. Ext4 should have the stripe-size set to 1024. This value was calculated by taking 8M (guessed erasure block size) dividing by 8K (size of a stride, 2 times block size (4K)). This will (hopefully) cause Ext4 to try to align writes so that while erasure blocks are written continuously and make it avoid sub-block updates.

Część dotyczącą ustawiania początku partycji w fdisk:

First sector (2048-15759359, default 2048): 16384

Wraz z wyjaśnieniem, skąd to się wzięło:

Fdisk uses blocks of 512 bytes, so that means that we want to start at 8*1024^2/512 = 16384.

No i na koniec część dotycząca tworzenia samego filesystemu ext4:

Reformat the filesystem, this time with Ext4 with block size of 4k, without journaling, but with additional parameters to encourage Ext4 to do the right thing with respect to the erasure block:

mkfs.ext4 -O ^has_journal -E stride=2,stripe-width=1024 -b 4096 -L Fedora14Arm  /dev/mmcblk0p1

Na koniec dwa linki, które autor wpisu podaje jako źródła:

Zachęcam do lektury całego wpisu z którego pochodzą powyższe cytaty, bo powyżej są jedynie najważniejsze wyjątki, które bez kontekstu nie do końca w czymkolwiek pomogą.

Inny, prostszy (ale starszy) wpis o podobnej tematyce: http://linux-howto-guide.blogspot.com/2009/10/increase-usb-flash-drive-write-speed.html

No i dowiedziałem się, że pożyteczne narzędzie to flashbench (pakiet jest w Debianie unstable), że żaden ext2 dla nośników flash, tylko ext4 bez journala, za to z dodatkowymi opcjami, zależnymi od parametrów karty. I że nie tylko w przypadku SSD warto stosować alignment. Różnica prędkości między ext2 a ext4 po tuningu? Wg autora wpisu 8 razy szybciej dla małych plików i dwa szybciej dla dużych. Trochę mi wszystko opadło, ale za to wiem, co będę robić w weekend.

UPDATE: Trochę się pobawiłem i wyszło mi, że metoda pomiaru jest średnio dokładna. Albo pendrive zwalnia w miarę używania (w sensie „wykonana ilość zapisów”), albo reboot/hibernacja drastycznie zmieniają wyniki, albo nie wiem co jest grane. Bo zrobiłem test na FAT, potem na ext4 po dopasowaniu partycji (brak zauważalnych różnic), potem zabawa z ustawieniami ext4 i… między pierwszym testem na ext4, a końcowym, na identycznych parametrach ext4 były 4 sekundy różnicy. Przy podstawie 22 sekundy, więc prawie 20% wolniej. Zagadka. A ponieważ nie widzę zysku między FAT a ext4, to chęć do migracji ext2 -> ext4 gwałtownie spadła. Może kiedyś.

UPDATE2: Dodane cytaty z bloga. Bawiłem się trochę w optymalizacje/benchmarki na czterech różnych pendrive’ach. Tylko jeden zareagował pozytywnie na zmianę alignmentu (OK, bez wyliczeń było, po prostu początek partycji na sektorze 16384) i zmianę systemu na ext4. Przy okazji wyszło na jaw, że pendrive, który uznałem za wolny jest ok. 3 razy wolniejszy od pozostałych, niezależnie od ustawień.

Praca na desktopie z małą ilością RAM po raz drugi.

Jakiś czas temu pisałem o pierwszym podejściu do małej ilości RAM na desktopie, więc pora na część drugą. Przejrzałem podrzucone linki nt. optymalizacji działania dekstopu. Dysk był już ustawiony optymalnie, niepotrzebne usługi powyłączane, więc tak naprawdę tylko zmniejszyłem ilość uruchamianych konsol w inittabie. Nie zauważyłem zmiany w ilości zużywanego RAM, ale i tak ich nie potrzebuję – dwie wystarczają z naddatkiem. Swappiness nadal jest ustawione na 0 i IMO działa OK.

Zauważyłem, że spowalnianie występuje głównie na jednym desktopie (tym w pracy, starszy, bardziej zapchany dysk), przy pracy z pakietami (aktualizacja listy, instalacja), co skłania mnie do wniosku, że głównym winowajcą jest fragmentacja filesystemu. W obu przypadkach jest to ReiserFS (zaszłość, kiedyś był najlepszym wyborem, teraz chętnie widziałbym ext4 w tym miejscu), ale w domu z pewnością fragmentacja jest mniejsza – pół dysku zawsze było wolne.

Tak czy inaczej, wydaje mi się, że wypracowałem sposób na drastyczne ograniczenie spowalniania komputera przy pracy z pakietami. Korzystam z niego mniej więcej raz na tydzień. Cudów nie ma, czyli najpierw zamykam programy, które zużywają najwięcej RAM: Iceweasel, czyli Firefox, Icedove, czyli Thunderbird i PSI. Trwa to chwilę, a zwalnia znaczne obszary RAM.

Następnie uruchamiam prosty skrypt, który robi sync na dyskach, opróżnia bufory dyskowe, a następnie wyłącza i ponownie włącza swap.

#!/bin/bash

echo Syncing hard discs
sync
sleep 5
sync

echo Flushing disc buffers
echo 3 > /proc/sys/vm/drop_caches

echo Turning swap off
swapoff -a

echo Turning swap on
swapon -a

Celem jest najpierw zwolnienie jak największego obszaru pamięci, a następnie wymuszenie przerzucenia danych ze swap do RAM. Szybsze od restartu, działa w tle, więc można pracować w tym czasie. Po wykonaniu skryptu można swobodnie uruchomić przeglądarkę, pocztę, komunikator i aktualizować system. Najgorsze co może się wydarzyć, to niewyłączenie swapa, jeśli nie będzie wystarczającej ilości dostępnej pamięci, ale nie jest to krytyczne i zdarza się rzadko (zwł. po wyłączeniu przeglądarki). Wydaje mi się, że po takim zabiegu system działa znacznie lepiej.