Opracował:
Tomasz Socha
XFS to 64-bitowy system plików zaprojektowany przez firmę Silicon Graphics Inc. z przeznaczeniem do użycia go w systemie operacyjnym IRIX (wersja UNIX-a firmy SGI). Aktualnie jest dostępna również jego implementacja dla systemu Linux rozwijana przez SGI jako projekt na licencji wolnego oprogramowania.
XFS loguje wszystkie zmiany strukturalne do metadanych systemu plików zanim dane użytkownika zostaną przesłane na dysk. Dokładniej mówiąc, zapisywane są: i-węzły, bloki katalogów, bloki drzewa wolnych ekstentów, bloki drzewa alokacji i-węzłów, bloki mapy ekstentów plików, bloki nagłówkowe grup alokacji i superblok. XFS nie zapisuje danych użytkownika w dzienniku. Kronikowanie nowych kopii zmodyfikowanych elementów powoduje, że dziennik XFS jest niezależny od rozmiaru i złożoności systemu plików. Odzyskanie struktur danych wymaga jedynie odtworzenia obrazów bloków oraz i-węzłów z dziennika do systemu plików. Algorytm odtwarzający nawet nie wie, że odtwarza B+ drzewo. Wie tylko tyle, że przywraca najnowsze wersje pewnych bloków w systemie plików.
Tradycyjny schemat kronikowania zapisu z wyprzedzeniem (write ahead) zapisuje synchronicznie dziennik na dysku zanim zadeklaruje zakończenie transakcji i odblokowanie jego zasobów. Z jednej strony, takie rozwiązanie daje solidną gwarancję trwałości zapisu danych, ale z drugiej strony, ogranicza wydajność systemu plików do wydajności z jaką może pisać dziennik. XFS dostarcza tryb do synchronicznego zapisu zmian, używany podczas eksportu systemu plików przez NFS (Network File System), ale normalnym trybem pracy dla XFS jest użycie asynchronicznie zapisywanego dziennika. XFS nadal zapewnia zgodność z protokołem zapisu wprzód w ten sposób, że zmodyfikowane dane nie mogą zostać wysłane na dysk dopóty, dopóki dyskowy dziennik nie zostanie zapisany. Jednak zamiast trzymać zmodyfikowane zasoby „pod kluczem” do czasu, aż transakcja zostanie wysłana na dysk, zasoby są odblokowywane i oznaczane w pamięci do czasu gdy zakończenie transakcji zostanie wpisane do dyskowego dziennika. Zasoby mogą zostać odblokowane w momencie, gdy transakcja zostanie zapisana do buforów dziennika w pamięci, ponieważ sam dziennik utrzymuje kolejność zmian w systemie plików.
XFS zyskuje dwie rzeczy dzięki asynchronicznemu pisaniu dziennika. Po pierwsze, wiele zmian może zostać wpisanych podczas jednego zapisu dziennika. Zwiększa to wydajność dziennika w stosunku do fizycznej warstwy – dysku. Po drugie, tempo zmian w metadanych jest niezależne od szybkości fizycznych dysków. Ta niezależność jest co prawda ograniczona przez rozmiar bufora logu, ale jest i tak o wiele lepsza niż synchroniczne zmiany w starszych systemach plików.
W sytuacjach, gdy zmiany metadanych są bardzo częste, dziennik może być przechowywany na osobnym urządzeniu, takim jak specjalny dysk czy jakieś urządzenie z trwałą pamięcią. Jest to szczególnie przydatne, gdy system plików jest eksportowany przez NFS, co wymaga synchronicznego wykonywania wszystkich transakcji.
XFS potrafi zaalokować pojedyncze ekstenty wielkości aż do 2 milionów bloków i używa B+ drzew do zarządzania wolnym miejscem, dzięki czemu szybko można znaleźć ekstenty odpowiedniego rozmiaru. Dodatkowo, XFS używa opóźnionej alokacji, aby zapewnić, że za każdym razem są alokowane największe możliwe ekstenty.
Zamiast alokować konkretny blok dla pliku, gdy jest on zapisywany do bufora, XFS po prostu rezerwuje blok w systemie plików dla danych zbuforowanych w pamięci. Fizyczne bloki są alokowane dla wirtualnych ekstentów jedynie wtedy, gdy zbuforowane dane są zapisywane na dysk. Opóźnienie decyzji który i ile bloków zaalokować dla pliku gdy jest on pisany daje alokatorowi dużo lepszą wiedzę na temat ewentualnego rozmiaru pliku podczas podejmowania decyzji. Gdy cały plik może być zbuforowany w pamięci, oznacza to zazwyczaj, że może również zmieścić się w pojedynczym ekstencie. Dla plików, które nie mogą być całe zbuforowane w pamięci, opóźniona alokacja pozwala na przydzielenie tych plików do dużo większych ekstentów niż byłoby to możliwe w innym przypadku.
Dzięki opóźnionej alokacji pliki tymczasowe często nawet nie uzyskują przydziału fizycznych, dyskowych bloków. Nawet pliki, które są zapisywane w sposób przypadkowy, takie jak pliki mapujące pamięć, często mogą być zapisane w jednym spójnym kawałku, właśnie dzięki opóźnionej alokacji.
Mając plik zaalokowany w jednym ciągłym kawałku, zarządca I/O systemu XFS musi wykonywać operacje odczytu i zapisu na dysk, tak aby ograniczyć spadki wydajności związane z fizyczną warstwą systemu. XFS używa kombinacji łańcuchowania (clustering), odczytu z wyprzedzeniem (read ahead), opóźnionego zapisu (write behind) i zrównoleglania żądań aby maksymalnie wykorzystać możliwości fizycznych dysków.
Aby osiągnąć maksymalną możliwą wydajność sekwencyjnych odczytów, XFS używa dużych buforów odczytu i wielu buforów odczytu z wyprzedzeniem. Dla sekwencyjnych odczytów, używa dużego minimalnego rozmiaru bufora I/O (zazwyczaj 64 kilobajty). Oczywiście rozmiar ten jest zmniejszany aby dopasować się do plików o rozmiarze mniejszym niż minimalny rozmiar bufora. Użycie dużych minimalnych rozmiarów I/O zapewnia, że nawet gdy aplikacja rozkazuje odczyt w małych jednostkach, system plików wysyła żądania odczytu z dysku tak duże, by zoptymalizować wydajność I/O. Dla dużych odczytów, XFS zwiększa rozmiar bufora aby sprostać wymaganiom aplikacji.
XFS używa wielu buforów odczytu z wyprzedzeniem, aby zwiększyć możliwość równoczesnego dostępu do fizycznej warstwy systemu. Tradycyjne Uniksowe systemy plików miały tylko jeden bufor odczytu z wyprzedzeniem naraz. Dla odczytów sekwencyjnych, XFS opóźnia wykonanie dwóch czy trzech żądań tego samego rozmiaru co główny bufor I/O. Wiele żądań odczytu z wyprzedzeniem naraz jest wysyłanych do dysków, aby miały co robić, podczas gdy aplikacja przetwarza odczytywane dane. Większa liczba buforów odczytu z wyprzedzeniem zapewnia, że większa liczba fizycznych dysków pracuje w danym momencie.
Aby przyspieszyć wydajność operacji zapisu, XFS stosuje agresywne „łączenie żądań zapisu” (write clustering). Dane pliku oznaczone jako „dirty” są buforowane w pamięci w kawałkach po 64 kilobajty, a kiedy kawałek zostanie wybrany do zrzucenia z pamięci, zostaje przyczepiony do innych kawałków, tworząc większe żądanie I/O. Te łańcuchy (clusters) I/O są zapisywane na dysk asynchronicznie, więc gdy dane są zapisywane do pliku, wiele takich łańcuchów zostanie wysłanych na fizyczne dyski współbieżnie. Dzięki temu dyski są zajęte ciągłym strumieniem dużych żądań zapisu.
Mechanizm opóźnionego zapisu (write behind) używany przez XFS jest ściśle powiązany z mechanizmem opóźnionej alokacji opisanym wcześniej. Im więcej „brudnych” danych zbuforowanych w pamięci dla nowo zapisywanego pliku, tym lepsza będzie alokacja dla tego pliku. Jest to rozwiązanie balansujące potrzeby ochrony pamięci przed zawaleniem brudnymi stronami z potrzebą wysyłania ciągłego strumienia żądań do fizycznych dysków.
Ciekawostka: XFS osiągnął podczas testów przepustowość rzędu 7 GB/s. Maksymalna osiągnięta prędkość zapisu dla tego systemu plików: 4 GB/s. Maksymalna prędkość oczytu jest również rzędu 4 GB/s.
Najbardziej unikalną właściwością XFS jest Gwarantowana Wydajność I/O (GRIO = Guaranteed Rate I/O), która pozwala aplikacjom na zarezerwowanie pasma do lub z systemu plików. XFS wylicza dostępną wydajność i gwarantuje, że żądany poziom wydajności zostanie zapewniony przez określony czas. To uwalnia programistę od konieczności przewidywania wydajności, która może być zmienna, a proces jej wyliczania - bardzo złożony. Taka funkcjonalność jest wymagana dla systemów udostępniania mediów wysokiej rozdzielczości, takich jak Video-on demand czy systemy satelitarne, które muszą przetwarzać informacje z pewną prędkością. Domyślnie, XFS zapewnia 4 (współbieżne) strumienie GRIO. Ilość strumieni można zwiększyć do 40 po zakupieniu opcji High Performance GRIO-5-40 lub opcji Unlimited Streams :)
XFS ma także interfejs migracji danych (Data Migration API, DMAPI). Dzięki użyciu tego interfejsu, aplikacje takie jak Data Migration Facility firmy Silicon Graphics mogą wykorzystać zaawansowane hierarchiczne zarządzanie nośnikami. Dane mogą łatwo migrować z dysków on-line na nośniki near-line lub off-line. Pozwala to na łatwe zarządzanie zbiorami danych o dużo większej pojemności niż pojemność dysków on-line.