Defragmentace dat na pevném disku

Transkript

Defragmentace dat na pevném disku
Na tomto místě bude oficiální
zadání vaší práce
• Toto zadání je podepsané děkanem a vedoucím katedry,
• musíte si ho vyzvednout na studiijním oddělení Katedry počítačů na Karlově náměstí,
• v jedné odevzdané práci bude originál tohoto zadání (originál zůstává po obhajobě na
katedře),
• ve druhé bude na stejném místě neověřená kopie tohoto dokumentu (tato se vám vrátí
po obhajobě).
i
ii
České vysoké učení technické v Praze
Fakulta elektrotechnická
Katedra počítačů
Diplomová práce
Defragmentace dat na pevném disku
Bc. Tomáš Dosoudil
Vedoucí práce: Ing. Ivan Šimeček, Ph.D.
Studijní program: Elektrotechnika a informatika, strukturovaný, Navazující
magisterský
Obor: Výpočetní technika
30. prosince 2010
iv
v
Poděkování
Mé velké díky patří rodičům, kteří mě nikdy nepřestali podporovat a vždy ve mně věřili
a také mé přítulkyni Lucce, která mi byla vždy oporou. V neposlední řadě bych také rád
poděkoval vedoucímu práce Ing. Ivanu Šimečkovi, Ph.D., díky kterému mohla tato práce
vzniknout.
vi
vii
Prohlášení
Prohlašuji, že jsem práci vypracoval samostatně a použil jsem pouze podklady uvedené
v přiloženém seznamu.
Nemám závažný důvod proti užití tohoto školního díla ve smyslu §60 Zákona č. 121/2000
Sb., o právu autorském, o právech souvisejících s právem autorským a o změně některých
zákonů (autorský zákon).
V Praze dne 31. 12. 2010
.............................................................
viii
Abstract
The main goal of this thesis is to describe problems of data fragmentation and how modern
file systems deal with. The second part of this thesis is focused on UFS file system and deal
with an implementation of a tool for defragmentation.
Abstrakt
Cílem této práce je popsat problematiku fragmentace dat na pevném disku a také to, jak
se jí moderní souborové systémy snaží předcházet. Druhá část práce se věnuje konkrétně
souborovému systému UFS a zabývá se implementací programu na odstranění fragmentace
v tomto souborovém systému.
ix
x
Obsah
1 Úvod
1
2 Projekt OpenBSD
2.1 Historie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.2 Přednosti operačního systému . . . . . . . . . . . . . . . . . . . . . . . . . . .
3
3
3
3 Souborový systém UFS
3.1 Historie . . . . . . . . . . . . . . . . . .
3.2 Naformátování nového diskového oddílu
3.3 Vnitřní struktura . . . . . . . . . . . . .
3.3.1 Boot block . . . . . . . . . . . .
3.3.2 Super-block . . . . . . . . . . . .
3.3.3 Cylinder group block . . . . . . .
3.3.3.1 Bitmapa . . . . . . . .
3.3.4 Inode block . . . . . . . . . . . .
3.3.5 Data block . . . . . . . . . . . .
3.3.6 Alokace nového inodu . . . . . .
3.3.7 Alokace nového datového bloku .
4 Fragmentace
4.1 Co je fragmentace . . . . . . . .
4.2 Stárnutí souborového systému . .
4.2.1 Vytváření nového souboru
4.2.2 Zvětšování souboru . . . .
4.2.3 Mazání souboru . . . . .
5 Pevný disk
5.1 Geometrie pevného disku
5.2 Hlava . . . . . . . . . . .
5.2.1 Settle time . . . .
5.2.2 Latency . . . . . .
5.2.3 Track-to-Track . .
5.2.4 Positioning . . . .
5.2.5 Full stroke . . . . .
5.3 Access time . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
xi
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
5
. 5
. 5
. 6
. 6
. 6
. 8
. 9
. 9
. 10
. 10
. 12
.
.
.
.
.
.
.
.
.
.
15
15
16
16
17
17
.
.
.
.
.
.
.
.
19
19
20
20
20
21
21
21
21
.
.
.
.
.
.
.
.
xii
6 Předcházení fragmentace
6.1 Variabilita velikosti uložených dat
6.2 Rezerva volného místa . . . . . . .
6.3 Před-alokování . . . . . . . . . . .
6.4 Zpožďování alokace . . . . . . . . .
6.5 Extents . . . . . . . . . . . . . . .
6.6 Souborový systém UFS . . . . . .
6.6.1 Rezerva volného místa . . .
6.6.2 Skupiny cylindrů . . . . . .
6.6.3 Fronta přístupů na disk . .
OBSAH
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
23
23
24
24
25
25
25
25
26
26
7 Analýza a návrh řešení
7.1 Defragmentace oblasti Inode block . . . . . . .
7.2 Defragmentace oblasti Data block . . . . . . . .
7.3 Identifikace bloků . . . . . . . . . . . . . . . . .
7.3.1 Úvaha o velkém počtu malých souborů .
7.3.2 Úvaha o malém počtu velkých souborů .
7.3.3 Nejhorší stav pro identifikaci bloků . . .
7.4 Seřazení bloků . . . . . . . . . . . . . . . . . .
7.4.1 Optimalizace na souvislost . . . . . . . .
7.4.2 Optimalizace na počet přesunů . . . . .
7.4.3 Optimalizace na fragmenty . . . . . . .
7.5 Využití paměti . . . . . . . . . . . . . . . . . .
7.6 Přesuny bloků . . . . . . . . . . . . . . . . . . .
7.6.1 Bez možnosti ztráty dat . . . . . . . . .
7.6.2 Možnost ztráty jednoho souboru . . . .
7.6.3 Možnost ztráty celé skupiny cylindrů . .
7.7 Algoritmy pro přesun bloků . . . . . . . . . . .
7.7.1 Naivní algoritmus . . . . . . . . . . . .
7.7.2 Algoritmus úplného seřazení . . . . . . .
7.7.3 Algoritmus bez zbytečných přesunů . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
27
27
28
28
29
29
30
30
31
31
32
32
33
33
34
34
34
34
35
36
8 Implementace
8.1 Vstupní parametry a inicializace . . . . . . . . . . . . . . .
8.2 Namapování skupiny cylindrů do paměti . . . . . . . . . . .
8.2.1 Paměťové nároky . . . . . . . . . . . . . . . . . . . .
8.3 Identifikace bloků . . . . . . . . . . . . . . . . . . . . . . . .
8.3.1 Paměťové nároky . . . . . . . . . . . . . . . . . . . .
8.4 Seřazení bloků . . . . . . . . . . . . . . . . . . . . . . . . .
8.5 Výpis informací . . . . . . . . . . . . . . . . . . . . . . . .
8.6 Přístup k datům . . . . . . . . . . . . . . . . . . . . . . . .
8.6.1 Přímý přístup k blokům . . . . . . . . . . . . . . . .
8.6.2 Přístup k blokům s namapovanou skupinou cylindrů
8.7 Přesun bloků . . . . . . . . . . . . . . . . . . . . . . . . . .
8.7.1 Vyhledání volného bloku . . . . . . . . . . . . . . . .
8.7.2 Příprava přesouvaných bloků . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
39
40
41
42
42
44
45
45
46
46
46
47
47
48
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
OBSAH
8.8
xiii
8.7.3 Triple sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
8.7.4 Hop sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
Uvolnění prostředků . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
9 Testování funkčnosti
9.1 Testování defragmentace .
9.2 Testování konzistence dat
9.3 Velikost diskového oddílu
9.4 Testovaná data . . . . . .
9.5 Testovací nástroje . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
53
53
53
54
54
54
10 Měření
10.1 Měření 1 . . . . . . . . . . . . . . . . . . . . . . .
10.2 Měření 2 . . . . . . . . . . . . . . . . . . . . . . .
10.3 Měření 3 . . . . . . . . . . . . . . . . . . . . . . .
10.4 Zrychlení souborového systému po defragmentaci
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
55
55
55
56
56
.
.
.
.
59
59
59
60
60
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
11 Závěr
11.1 Fragmentace souborových systémů
11.2 Vlastní implementace . . . . . . .
11.2.1 Potenciální vylepšení . . . .
11.3 Výsledky defragmentace . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
A Seznam použitých zkratek
63
B Nástroj fragfile.sh
65
C Nástroj autofrag.sh
67
D Ukázka programu
71
E BSD licence
75
F Obsah přiloženého CD
77
xiv
OBSAH
Seznam obrázků
3.1
3.2
3.3
Rozložení souborového systému. . . . . . . . . . . . . . . . . . . . . . . . . . . 7
Princip adresace pomocí přímých a nepřímých odkazů. . . . . . . . . . . . . . 11
Struktura bloku na disku, fragmentu a UFS bloku. . . . . . . . . . . . . . . . 12
4.1
4.2
4.3
4.4
Rozmístění fragmentů jednoho souboru. . . . . . . . . . . . . . .
Rozdělení nového souboru z důvodu fragmentace volného místa. .
Rozdělení stávajícího souboru po jeho zvětšení. . . . . . . . . . .
Fragmentace v rámci oblasti. . . . . . . . . . . . . . . . . . . . .
5.1
Geometrie disku. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
7.1
7.2
7.3
Pohled na souborový systém po smazání jednoho ze souborů. . . . . . . . . . 32
Průběh zpracování u naivního algoritmu. . . . . . . . . . . . . . . . . . . . . . 36
Průběh zpracování u algoritmu bez zbytečných přesunů. . . . . . . . . . . . . 38
8.1
8.2
8.3
8.4
8.5
Průchod programem. . . . . . . . .
Vazba mezi polem blockap a slink.
Určení cílové pozice bloku. . . . . .
Model funkcí pro přístup k datům.
Přesun bloků metodou Triple sort.
.
.
.
.
.
xv
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
16
17
17
18
39
43
45
46
50
xvi
SEZNAM OBRÁZKŮ
Seznam tabulek
3.1
Přednastavené hodnoty pro UFS. . . . . . . . . . . . . . . . . . . . . . . . . .
6
7.1
Počet přístupů na disk.
8.1
8.2
8.3
Hodnoty kterých může nabývat proměnná flags ve struktuře GLBVAL. . . . . . 41
Hodnoty kterých může nabývat proměnná flags ve struktuře BLOCKARRS. . . . 44
Hodnoty kterých může nabývat proměnná flags ve struktuře SWPDATA. . . . . 48
10.1
10.2
10.3
10.4
Naměřené hodnoty při defragmentaci 1050 souborů. . . . . . . . . . . . . .
Naměřené hodnoty při defragmentaci 850 souborů. . . . . . . . . . . . . . .
Naměřené hodnoty při defragmentaci bloků, které jsou adresovány nepřímo.
Rychlost čtení souborů v závislosti na velikostech fragmentů. . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
xvii
.
.
.
.
56
56
56
58
xviii
SEZNAM TABULEK
Kapitola 1
Úvod
Tato práce se zabývá problémem fragmentace uložených dat na souborovém systému. Snaží
se vysvětlit co vlastně fragmentace je, a z jakých důvodů k ní dochází. To, jakým způsobem
se data na pevném disku fragmentují, silně závisí na souborovém systému. Pro tuto práci
jsem zvolil souborový systém UFS. Jedním z důvodů této volby bylo to, že se jedná o starší
souborový systém, který je jednak implementován v řadě unixů a bsd systémů, ale také
mnoho modernějších souborových systému funguje na podobných principech.
Součástí práce je i program, který se do jisté míry snaží fragmentaci odstranit. Program
je programovaný v souladu s normou ANSI C a využívá systémových hlaviček operačního
systému OpenBSD. Výsledný zdrojový kód bude poskytnut komunitě pod licencí BSD.
Kapitola 1: Seznámení se záměrem této práce.
Kapitola 2: Seznámení s projektem OpenBSD, pro který je nástroj pro odstranění fragmentace implementován.
Kapitola 3: Popis souborového systému UFS. Jelikož součástí této práce je implementace
defragmentace, je naprosto nezbytné seznámit se s konkrétním souborovým systémem.
Kapitola 4: Obecné vlastnosti fragmentace. Definice fragmentace a vysvětlení, proč nám
fragmentace vadí.
Kapitola 5: Popis pevného disku a princip vystavení čtecí a zapisovací hlavy disku. Rozdíly
v časech u jednotlivých typů vystavení hlavy disku a vliv fragmentace.
Kapitola 6: Jak se v praxi souborové systémy brání fragmentaci.
Kapitola 7: Tato kapitola popisuje analýzu problému a současně navrhuje několik způsobů
řešení.
Kapitola 8: Samotná implementace defragmentace pro UFS. Obsahuje již konkrétní řešení,
která byla navržena v předchozí kapitole.
Kapitola 9: Testování funkčnosti programu a způsoby testování.
Kapitola 10: Měření rychlosti defragmentace a zrychlení souborového systému po defragmentaci.
1
2
KAPITOLA 1. ÚVOD
Kapitola 11: Zhodnocuje výsledky implementace. Současně shrnuje nedostatky implementace a návrhy na jejich zlepšení.
Kapitola 2
Projekt OpenBSD
Jelikož se většina této práce zabývá souborovým systémem UFS a konkrétně implementací
pod operačním systémem OpenBSD, tak si v této kapitole projekt stručně popíšeme.
2.1
Historie
Operační systém BSD se začal vyvíjet v 70. letech na Kalifornské univerzitě v Berkley.
Jednalo se o jakýsi protipól tehdejšího Unixu. Poslední verze, která byla pod záštitou univerzity vydána, byla 4.4BSD. Díky licenci BSD, která umožňovala v podstatě libovolné
využití zdrojových kódů, zde mohli začít vznikat komunitní projekty.
Za přímé následníky verze 4.3BSD a 4.4BSD se mohou považovat komunitní projekty
FreeBSD a NetBSD. V roce 1995 se díky neshodám v komunitě NetBSD část vývojářů
rozhodla tento projekt opustit a v čele s Theo de Raadtem zakládají nový projekt OpenBSD.
V době psaní této práce vyšla nová verze OpenBSD 4.8, která podporuje 17 architektur,
jako např. alpha, amd64, i386, sqi, sparc, vax atd.
2.2
Přednosti operačního systému
Celý projekt je zaměřen především na bezpečnost, která jde často na úkor uživatelské přívětivosti. Díky této filozofii, „Secure by default“ jak ji vývojáři často nazývají, zde za posledních 10 let byly jen dvě chyby, které umožňovaly vzdálené převzetí kontroly nad operačním
systémem.
Jelikož hlavní servery projektu jsou umístěny v Kanadě, tak se na ně nevztahuje restriktivní omezení tykající se šíření kryptografických materiálů jako na podobné projekty, které
mají servery v USA. To vedlo k tomu, že součástí systému vždy byly pokročilé šifrovací
metody.
Součástí operačního systému OpenBSD je projekt OpenSSH, který slouží pro vzdálené
přístupy, a který byl později naportován i do většiny linuxových systémů.
Domovská stránka projektu je http://www.openbsd.org
3
4
KAPITOLA 2. PROJEKT OPENBSD
Kapitola 3
Souborový systém UFS
3.1
Historie
Souborový systém UFS doslova znamená Unix File Sytem a patří mezi jedny z nejstarších
unixových souborových systémů. Do operačního systému BSD, konkrétně do verze 4.2BSD,
byl poprvé implementován v roce 1984. O implementaci, a současně i o jeho dnešní podobu,
se značně zasadil Marshall Kirk McKusick [5].
Za jednu z novodobých nevýhod se ukázala 32 bitová adresace bloků. Za předpokladu
použití nejmenšího datového bloku, tj. 512 B, může být maximální kapacita souborového
systému 2 TB. To se v dnešní době ukázalo jako nedostatečné, a proto se v roce 2003 přišlo
se UFS2 souborovým systémem, který mimo jiné používá 64 bitovou adresaci.
3.2
Naformátování nového diskového oddílu
V BSD systémech se souborový systém vytváří pomocí příkazu newfs. Oproti jiným souborovým systémům se neformátuje přímo diskový oddíl. Disk, resp. diskový oddíl, je ještě třeba
rozdělit pomocí nástroje disklabel. V rámci jednoho disku je možné provést rozdělení až na
15 oddílů značících se a-p, kde c reprezentuje celý disk a nelze jej modifikovat. Po rozdělení
jsou jednotlivé oddíly zpřístupněny v adresáři /dev. Například první oddíl značící se a na
prvním pevném disku, který je připojený pomocí rozhraní PATA, bude zpřístupněn jako
/dev/wd0a.
Po vytvoření oddílu lze vybraný oddíl naformátovat již zmíněným nástrojem newfs.
Formátování lze ovlivnit několika parametry. Jedním z parametrů, který do značné míry
ovlivňuje výkonnost celého souborového systému, je velikost bloku, kde blok je uvažován
v kontextu souborového systému. Nejedná se tedy o diskový blok typické velikosti 512 B.
Minimální velikost bloku je 4096 B. Tato velikost byla zvolena z toho důvodu, aby soubor
o velikosti 232 B mohl být adresovatelný nanejvýše dvěma stupni indirekce. Blok se dále dělí
na fragmenty. Fragment je nejmenší adresovatelná jednotka v rámci souborového systému
a jeho minimální velikost je 512 B, což současně odpovídá typicky nejmenší adresovatelné
jednotce pevného disku. Počet fragmentů v bloku může být 2, 4 nebo 8.
Během formátování nového oddílu, se oddíl rozdělí na několik dalších skupin po sobě
jdoucích cylindrů. V terminologii UFS se tyto skupiny cylindrů nazývají cylinder groups.
5
6
KAPITOLA 3. SOUBOROVÝ SYSTÉM UFS
Parametr
Velikost bloku
Velikost fragmentu
Počet fragmentů
Velikost skupiny cylindrů
Počet inodů na skupinu cylindrů
Typ UFS
Hodnota
16384 B
2048 B
8
12958 bloků
25984
UFS1
Tabulka 3.1: Přednastavené hodnoty pro UFS.
Vždy musí být vytvořeny alespoň 4 skupiny cylindrů. Shora je počet omezen jen maximální
velikostí souborového systému.
Tabulka 3.1 shrnuje hodnoty nejdůležitějších parametrů, které jsou přednastaveny, a
nebo jsou typické pro většinu pevných disků. Pokud nebude řečeno jinak, tak se budou
v následujícím textu u výpočtů uvažovat tyto hodnoty.
3.3
Vnitřní struktura
Obrázek 3.1 znázorňuje rozložení souborového systému UFS [6] na pevném disku, kterým se
v této kapitole budeme podrobněji zabývat. Souborový systém se skládá z několika skupin
cylindru, tj. cylinder groups, a na prvním z nich se nachází Boot block, který obsahuje informace potřebné k zavedení systému. Za ním následuje Super-block, který je umístěn stejně
jako Boot block na pevně dané adrese, resp. offsetu, od začátku oddílu. Za Super-blockem
následuje již rozložení, které se bude opakovat na všech ostatních skupinách cylindrů, tj.
Cylinder group block, Inode block a Data block. Informace týkající se základního rozložení
a struktury jednotlivých bloků lze nalézt v hlavičkovém souboru src/sys/ufs/ffs/fs.h.
3.3.1
Boot block
Jak již bylo řečeno, Boot block obsahuje potřebné informace k zavedení systému. Jedná se
v podstatě o program napsaný v assembleru, který je umístěn na prvních 512 B diskového
oddílu. Tomuto programu, resp. fázi bootování, se říká first-stage. Úkolem této fáze je načíst
fázi dvě, tedy second-stage, která již načte kernel. Drobná komplikace v načítání kernelu
je ta, že druhá fáze stále nerozumí souborovému systému. Řešení je takové, že kořenový
adresář pro daný souborový systém má číslo inodu vždy 2. Inode se nachází na první skupině
cylindrů, před kterou je pouze Super-block, který má ovšem svou velikost a pozici pevně
danou.
3.3.2
Super-block
Super-block se nachází na první skupině cylindrů a primárně je jeho offset 8192 B, resp.
65536 B, dle typu UFS. Jelikož obsahuje několik kritických informací, jako např. geometrie
disku nebo rozložení souborového systému, tak je současně nakopírován do skupin cylindrů,
a to z důvodu prevence proti poškození. Většina těchto kritických informacích se zapíše
3.3. VNITŘNÍ STRUKTURA
7
Obrázek 3.1: Rozložení souborového systému.
během vytváření souborového systému a pozdější změny již nejsou možné. Super-block ovšem
obsahuje i řadu informací, které jsou během užívání operačním systémem nastavovány, jako
např. počet souborů a adresářů. Některé lze také nastavit pomocí nástroje tunefs. Veškeré
informace obsažené v bloku jsou popsány strukturou struct fs. Mezi nejdůležitější položky
patří:
• fs_cblkno - Offset do prvního Cylinder group bloku.
• fs_iblkno - Offset do prvního bloku inodů.
• fs_dblkno - Offset do prvního datového bloku.
• fs_cgoffset - Offset mezi skupinou cylindrů.
• fs_ffs1_time - Čas posledního zápisu.
• fs_ncg - Počet skupin cylindrů.
• fs_bsize - Velikost bloku v bytech.
8
KAPITOLA 3. SOUBOROVÝ SYSTÉM UFS
• fs_fsize - Velikost fragmentu v bytech.
• fs_minfree - Minimální počet volných bloků v procentech.
• fs_frag - Počet fragmentů v bloku.
• fs_cgsize - Velikost skupiny cylindrů v bytech.
• fs_ncyl - Počet cylindrů.
• fs_cpg - Počet cylindrů na skupinu.
• fs_ipg - Počet inodů na skupinu cylindrů.
• fs_fpg - Celkový počet fragmentů na skupinu cylindrů.
• fs_clean - Clean flag.
• fs_magic - Magic číslo1 pro UFS.
Jedna z položek struktury, která přímo ovlivňuje fragmentaci, je fs_minfree. Ta udává
minimální počet volných bloků v procentech. Defaultně je nastavena na 5%, což se považuje
jako minimum, nicméně se doporučuje hodnotu nastavit alespoň mezi 10-15%. Uvažujeme-li
5% hodnotu, tak po vyčerpání 95% všech bloků již běžný uživatel nemůže dál vytvářet nové
soubory na disku, resp. alokovat nové bloky. Pouze uživatel root může dál alokovat nové
bloky. Toto omezení je zde právě kvůli omezení fragmentace souborů, jelikož po překročení
určité meze alokovaných bloků, je již velmi obtížné nalézt souvislý úsek bloků na disku.
Nutno poznamenat, že volný blok znamená, že v našem případě všech 8 fragmentů
v bloku je nealokovaných. Pokud je alespoň jeden fragment obsazený, tak se již nejedná
o volný blok, ačkoliv zbývajících 7 fragmentů může být volných. Tento fakt může vést např.
k situaci, kdy nám operační systém hlásí, že je disk zaplněn, přestože nám např. příkaz df
ukazuje, že je na něm stále dostatek místa. Teoreticky je možné, že po zaplnění pouze 1/8
datové oblasti souborového systému nám operační systém nedovolí vytvořit nový soubor
o velikosti bloku z důvodu, že je již zaplněn. Tato situace může nastat, pokud se systém
zaplní velkým počtem souborů, které jsou nanejvýš 2048 B velké, tj. o velikosti fragmentu.
Pokud se následně konkrétní soubory smažou tak, že vždy v rámci jednoho bloku 7 souborů
odstraníme a jeden zůstane, pak přestože bude souborový systém ze 7/8 volný, nebude možné
vytvořit nový soubor o velikosti alespoň jednoho bloku.
3.3.3
Cylinder group block
Cylinder group block je rozdělen na tři části, a to na datovou strukturu struct cg a dvě
bitmapy. Struktura obsahuje kromě konkrétních informací pro danou skupinu cylindrů také
několik duplicitních informací, které již obsahuje Super-block. Mezi nejdůležitější položky
patří:
• cg_time - Čas posledního zápisu.
1
Magic číslo pro UFS2 je 0x19540119 a jedná se o „zakódované“ datum narození Marshalla Kirk McKusicka, tedy 19.1.1954.
3.3. VNITŘNÍ STRUKTURA
9
• cg_cgx - Číslo skupiny cylindrů.
• cg_ncyl - Počet cylindrů ve skupině.
• cg_niblk - Počet inodů.
• cg_ndblk - Počet datových bloků.
• cg_cs - Jedná se o strukturu shrnující počet adresářů, bloků, fragmentů atd.
• cg_iusedoff - Offset na bitovou mapu idnodů.
• cg_freeoff - Offset na bitovou mapu volných fragmentů.
Každá skupina cylindrů si současně shromažďuje informace o svém stavu alokovaných
jednotek. Tyto informace jsou uloženy ve struktuře struct csum a obsahuje tyto položky:
• cs_ndir - Počet adresářů nacházejících se na skupině cylindrů.
• cs_nbfree - Počet volných bloků.
• cs_nifree - Počet volných inodů.
• cs_nffree - Počet volných fragmentů.
3.3.3.1
Bitmapa
Ve stejném bloku za strukturou struct cg, je umístěna bitová mapa použitých inodů.
V bitové mapě je použitý inode nastaven na 1. Za mapou inodů je bitová mapa volných
fragmentů, kde volný fragment je v bitové mapě nastaven na 1.
Velikost skupiny cylindrů je mimo jiné limitována tím, že se struktura struct cg, bitová
mapa inodů a především bitová mapa volných fragmentů, musí společně vejít do jednoho
bloku.
3.3.4
Inode block
Inode block obsahuje tabulku inodů. Inode, neboli index node, je datová struktura uchovávající metadata o konkrétním souboru. Inode může mít dvě podoby, a to buď inode, který
je v operační paměti nebo inode uložený na disku. Nás bude zajímat druhá varianta, tedy
inode na disku, jemuž se také říká dinode. Velikost dinodu se odvíjí od verze UFS a je 128
B, resp. 256 B a popsána strukturou struct ufs1_dinode, resp. struct ufs2_dinode.
Je třeba mít na paměti, že z důvodu velikosti dinodu není možné každý dinode přímo
adresovat, ať už přímo na pevném disku nebo v rámci souborového systému. Pro přístup
k jednotlivým dinodům je zapotřebí načíst celý blok, resp. fragment. Ofset fragmentu se
vypočítá pomocí makra:
#define ino_to_fsbo(fs, x)
((x) % INOPB(fs))
10
KAPITOLA 3. SOUBOROVÝ SYSTÉM UFS
Kde fs je odkaz na struct fs a x je číslo požadovaného inodu. INOPB je počet dinodu
na blok.
Mezi nejdůležitější položky dinodu ve struktuře struct ufs1_dinode patří:
• di_size - Velikost souboru.
• di_db[NDADDR] - Přímé odkazy na datové bloky.
• di_ib[NIADDR] - Nepřímé odkazy.
• di_uid - UID vlastníka souboru.
• di_gid - GID vlastníka souboru.
Počet přímých odkazů je 12. Pokud soubor přesáhne velikost 192 kB, tak je třeba použít
nepřímé odkazy. Tyto odkazy jsou celkem 3, a to odkazy první, druhé a třetí úrovně. V případě první nepřímé úrovně odkaz di_ib[0] ukazuje na datový blok, který místo samotných
dat souboru, obsahuje odkazy na datové bloky a teprve tyto bloky obsahují data patřící
souboru. Princip adresace pomocí přímých a nepřímých odkazů je zobrazen na Obrázku 3.2.
To, kolik odkazů se vejde do bloku u nepřímé adresace, záleží jednak na velikosti bloku,
a pak na velikosti, resp. datovém typu samotného odkazu. Pro UFS1 je velikost 4 B a pro
UFS2 je to 8 B. Pro výpočet lze použít vzorec 3.1. V našem případě na jeden blok připadá
4096 odkazů.
odkazu_v_bloku = velikost_bloku/velikost_odkazu
(3.1)
Informace týkající se dinodu jsou v hlavičkovém souboru src/sys/ufs/ufs/dinode.h.
3.3.5
Data block
Skládá se z bloků, které slouží k uložení dat ze souboru, nebo bloků obsahující nepřímé odkazy. V datové oblasti by alokovaný blok, resp. fragment, měl být pevně svázán s konkrétním
inodem pomocí odkazu. To znamená, že pokud nedojde k chybě v systému, tak ke každému
bloku, resp. fragmentu, bychom měli být schopni dohledat inode, který na něj ukazuje.
Struktura bloku na disku, fragmentu a bloku UFS je znázorněna na Obrázku 3.3.
3.3.6
Alokace nového inodu
Alokaci nového inodu má na starosti funkce ffs_inode_alloc. Jejím prvním úkolem je zjistit, zda inode bude typu adresář či ne. Při výběru skupiny cylindrů a následného vhodného
umístění, se bere v potaz řada parametrů. Jedná se o preference inodu na jeho umístění.
Následující rutina je použita pro alokaci inodu typu soubor. Pokud v konkrétním bodě není
možné požadavky uspokojit, přechází se na další.
1. Alokuj preferovaný inode.
2. Alokuj inode na stejné skupině cylindrů, kde je umístěn nadřazený adresář.
3.3. VNITŘNÍ STRUKTURA
11
Obrázek 3.2: Princip adresace pomocí přímých a nepřímých odkazů.
3. Zvol jinou skupinu cylindrů pomocí kvadratické hashe a pokus se alokovat nový inode.
Pokud inode alokovat nelze, pokračuj ve výběru dalších skupin cylindrů.
Jestliže je výběr nového inodu bez preferencí na umístění, pak bude použit tento postup:
1. Alokuj inode na první skupině cylindrů.
2. Zvol jinou skupinu cylindrů pomocí kvadratické hashe a pokus se alokovat nový inode.
Pokud inode alokovat nelze, pokračuj ve výběru dalších skupin cylindrů.
Kvadratická hash se používá z důvodu její rychlosti naléznutí nepoužitého pole v téměř
zaplněné tabulce. Pokud má souborový systém nastavenou alespoň 10 % rezervu, tak se
použije jen zřídka. Pokud zde není žádná rezerva a souborový systém je téměř zaplněn, tak
alokace probíhá spíše náhodně [4].
Pokud nový inode bude typu adresář, bude zavolána funkce ffs_dirpref, která bude
mít na starost vybrat vhodnou skupinu cylindrů. Pří výběru se bere v úvahu několik kritérií.
12
KAPITOLA 3. SOUBOROVÝ SYSTÉM UFS
Obrázek 3.3: Struktura bloku na disku, fragmentu a UFS bloku.
• Vyber stejnou skupinu cylindrů, jako nadřazený adresář.
• Skupina cylindrů musí obsahovat dostatek místa pro následující soubory adresářů.
• Zohledni počty adresářů na skupině cylindrů.
• Omez počet adresářů, které by byly na skupinu cylindrů umístěny hned za sebou.
• Pokud se jedná o první stupeň adresáře, umísti ho v jiné skupině cylindrů.
Zmiňované funkce jsou umístěné v src/sys/ufs/ffs/ffs_alloc.c.
3.3.7
Alokace nového datového bloku
Při každém požadavku na alokaci nového bloku či fragmentu, je použita funkce ffs_alloc.
Podobně jako při výběru nového inodu, tak i zde mohou být součástí výběru různá preferenční kritéria, podle kterých rozhodnou jaký blok vybrat. Kritériem je např. umístění inodu,
umístění jiných bloků inodu nebo počet alokovaných bloků na konkrétní skupině cylindrů.
Výběr vhodného bloku nastane v jednom z následujících kroků:
1. Alokuj požadovaný blok.
2. Alokuj blok na stejném cylindru.
3. Alokuj blok na stejné skupině cylindrů.
4. Zvol jinou skupinu cylindrů pomocí kvadratické hashe. Pokud nelze blok alokovat,
pokračuj ve výběru dalších skupin cylindrů.
Pokud je výběr bloku bez preferencí na umístění, pak bude použit tento postup:
1. Alokuj blok na stejné skupině cylindrů jako je inode.
2. Zvol jinou skupinu cylindrů pomocí kvadratické hashe. Pokud nelze blok alokovat,
pokračuj ve výběru dalších skupin cylindrů.
3.3. VNITŘNÍ STRUKTURA
13
Součástí kroku 2 bývala i podmínka, aby byl blok vzhledem k rotaci disku optimálně
umístěn od předchozího bloku. Ačkoliv se v dokumentacích, a i v komentáři ve zdrojových
kódech, tato podmínka často vyskytuje, tak již není pravdivá. Při alokaci bloku se rotace
disku nezohledňuje2 .
2
Dle CVS byla tato vlastnost odstraněna v revizi 1.60.
14
KAPITOLA 3. SOUBOROVÝ SYSTÉM UFS
Kapitola 4
Fragmentace
V kapitole o fragmentaci si vysvětlíme co fragmentace vlastně je, jak je chápána v modernějších souborových systémech a jaký má vliv na výkonnost souborového systému [2].
Fragmentaci si budeme popisovat nezávisle na konkrétním typu souborového systému.
4.1
Co je fragmentace
Již ze samotného slova fragmentace je patrné, že se jedná o jakési fragmenty, tzn. menší části
z celku. V kontextu souborového systému fragmentace souboru znamená jeho rozdělení na
několik menších částí. Nejprve se pokusme definovat soubor, který není fragmentovaný.
Definice 4.1.1. Soubor není fragmentovaný, pokud je zapsaný v jedné sekvenční posloupnosti na disku.
Soubory, které této definici nevyhovují, jsou fragmentované. Za fragmentované soubory
můžeme ve většině případů považovat i takové soubory, které sice jsou zapsány souvisle
v jedné oblasti, ale nejsou zapsány sekvenčně. Příkladem může být soubor s přehozenými
fragmenty na obrázku 4.1. Pro načtení druhého fragmentu je třeba překonat fragmenty 3,
4, 6, 5. Pokud budou fragmenty dostatečně veliké, např. větší než jeden cylindr, tak se již
nebudou číst, ale přeskočí se. Záměrně se již bavíme o fragmentech, a ne o blocích, jelikož
fragment se může skládat z několika bloků.
Vyhovět definici 4.1.1 nejspíš mohly jen jedny z prvních souborových systémů. Modernější souborové systémy, jako např. popsaný UFS v kapitole 3, záměrně své datové oblasti
rozdělují do menších částí. Jiné souborové systémy např. po určitém počtu bloků vkládají
blok s meta-informacemi. To se provádí buď z důvodu snížení budoucí fragmentace, nebo
kvůli jiným optimalizacím.
S ohledem na modernější souborové systémy, již nemá smysl zabývat se fragmentací
definovanou v 4.1.1, jelikož ta pro větší soubory nastane vždy. Budeme-li tedy brát v potaz
nové trendy ve vývoji souborových systémů, a než samotnou fragmentací se budeme zabývat jen fragmentací, která má negativní vliv na výkon, pokusme se opět nejprve definovat
fragmentaci, která nemá negativní vliv na výkonnost souborového systému.
15
16
KAPITOLA 4. FRAGMENTACE
Obrázek 4.1: Rozmístění fragmentů jednoho souboru.
Definice 4.1.2. K soubor, který je fragmentovaný a neovlivňuje negativně výkonnost souborového
systému, by měl být přístup z pohledu souborového systému stejně rychlý, jako k souboru nefragmentovanému.
Jinými slovy, pokud např. čteme fragmentovaný soubor, tak čas potřebný k vystavení
čtecí hlavy disku na začátek následujícího fragmentu, by neměl ovlivnit dobu celkového čtení
souboru.
Tato podmínka nemusí být za všech okolností splněna. Například u UFS předem neznáme
velikost segmentu na skupině cylindrů, a čas pro přístup na jinou skupinu cylindrů je závislý
na vzdálenosti této skupiny. Nicméně definice 4.1.2 se pro naše účely defragmentace zdá být
postačující.
Z definice mimo jiné vyplývá, že jedním z úkolů defragmentace je buď úplně odstranit,
nebo alespoň minimalizovat čas potřebný na přechody mezi fragmenty.
4.2
Stárnutí souborového systému
Stárnutí souborového systému, je pojmem pro aktivně používaný souborový systém [9]. Stárnutím se myslí sled událostí, jako např. přidávání, upravování a mazání souborů. Opomenemeli fakt, kdy fragmentaci vytváří samotný souborový systém, tak právě tyto události vytvářejí
fragmentaci, kterou můžeme nazvat jako nežádoucí. V následujících podkapitolách si popíšeme
tři nejčastější způsoby, jak během stárnutí souborového systému, fragmentace vzniká.
4.2.1
Vytváření nového souboru
Vytvořením nového souboru, na minimálně zaplněném souborovém systému, vzniká jen fragmentace, která je úmyslně vytvořená tímto systémem. Představme si ale situaci, kdy se
na již používaném systému snažíme vytvořit nový soubor. Tento soubor chceme umístit
do adresáře, obsahujícího několik menších souborů, z nichž několik bylo v nedávné době
smazaných. Situace je vyobrazena na obrázku 4.2. Zd je vidět, že nový soubor se bude
muset rozdělit na několik menších fragmentů, aby mohl být zapsán do volných pozic.
4.2. STÁRNUTÍ SOUBOROVÉHO SYSTÉMU
17
Obrázek 4.2: Rozdělení nového souboru z důvodu fragmentace volného místa.
4.2.2
Zvětšování souboru
V tomto případě uvažujeme již uložený soubor. V podstatě nás nezajímá, jestli je, či není
fragmentovaný. Podstatné je, že pokud za určitou dobu od jeho vytvoření budeme chtít
soubor rozšířit, tak se již za posledním blokem nemusí nacházet volná pozice. Tuto novou
část budeme tedy muset uložit jako samostatný fragment, viz obrázek 4.3.
Obrázek 4.3: Rozdělení stávajícího souboru po jeho zvětšení.
4.2.3
Mazání souboru
Mazáním souborů vzniká fragmentace volného místa [10], jako je na obrázku 4.4. To samo
o sobě nemá negativní vliv na výkonnost souborového systému, avšak následné ukládání
nových dat již může způsobit fragmentaci těchto dat. V podstatě se jedná o kombinaci dvou
předchozích způsobů, kdy se buď nový soubor může uložit do jedné volné pozice, ale pro
následné zvětšení již nebude dostatek místa v pozici, nebo nelze celý soubor do volné pozice
umístit, a musí být fragmentován hned při ukládání.
Fragmentace volného místa je zajímavá ještě z jiného hlediska, a to z hlediska, kdy častou
obranou před fragmentací je určitá rezerva volného místa. Představme si nyní minimálně
zaplněný souborový systém, kde v adresáři vytváříme několik souborů A o velikosti SA .
Pro velikost SA platí, že SA << Sf rag , kde Sf rag je maximální velikost souvislé oblasti dat
jakou povoluje souborový systém, aniž by byl soubor nuceně fragmentován a fragment tedy
uložen na jinou pozici. Současně se zvyšováním počtu souborů A se nám na disku začne
vytvářet oblast, např. v terminologii UFS můžeme uvažovat skupinu cylindrů, která bude
oproti zbytku značně zaplněná. Pokud se smaže několik souborů A a vytvoří se nový soubor
B o velikosti SB , kde pro SB platí, že SA << SB <= Sf rag , pak soubor B bude nutně
18
KAPITOLA 4. FRAGMENTACE
Obrázek 4.4: Fragmentace v rámci oblasti.
fragmentovaný. S počtem adresářů podobných tomuto, poroste i počet takto zaplněných
oblastí, kde podobné soubory B budou vždy fragmentované.
0 >S
Uvažme nyní situaci, kdy se soubor B zvětší do velikosti SB
f rag . Pak původní data,
0
0 −S
o velikosti SB , budou stále fragmentovaná, ale zbytek, o velikosti SBZ
= (SB
f rag ), bude
umístěn do jiné oblasti. V případě minimálně zaplněného souborového systému bude zbytek,
0 , umístěn souvisle. Pokud by platilo, že S 0
o velikosti SBZ
BZ > Sf rag , tak se sice bude dále
fragmentovat, ale již se bude jednat o úmyslnou fragmentaci.
Předpokládáme-li stále, že je na disku dostatek místa, tak z výše uvedených faktů vyplývá, že velké soubory mají menší tendenci k fragmentaci, než malé soubory, kde za malé
soubory uvažujeme soubory o velikosti menší než Sf rag . Tuto úvahu potvrzuje studie [9].
Pro zvětší části zaplněné souborové systémy to již platit nebude, jelikož zbytek o velikosti
0 , se již může rozdělit do více fragmentů o velikosti menší než S
SBZ
f rag .
Kapitola 5
Pevný disk
V této kapitole si popíšeme některé části pevného disku a také to, jak fragmentace ovlivňuje
práci disku. Hlavním důvodem, proč se budeme zabývat pevným diskem, tedy HDD a ne
např. SSD diskem či USB flash diskem, je jednak princip jakým přistupuje k datům, ale také
i to, že se stále jedná o nejčastější typ úložiště. Oproti SSD či USB flash disku je součástí
pevného disku čtecí a zápisová hlava, která se vždy musí vystavit na začátek požadovaného
bloku a v případě fragmentace, čím více je soubor fragmentován, tím vícekrát se bude
muset hlava zbytečně přesouvat. V následném popisu pevného disku nebudeme zabíhat
do technologických detailů, ale budeme se držet jen takových součástí, které jsou pro nás
z hlediska fragmentace zajímavé, a to jsou zejména:
Plotna: Jedná se o skleněnou či kovovou rotující desku pokrytou magnetickou vrstvou, pro
uložení dat. Její velikost je typicky 2,5“ či 3,5“ a rychlost rotace u osobních počítačů
bývá 4900 ot/min až 10000 ot/min. Plotna může mít dva povrchy.
Hlava: Hlava slouží k čtení a zápisu dat. S hlavou pohybuje vystavovací mechanizmus a
tím je buď krokový motor nebo lineární motor. V kombinaci s pohybem hlavy a pod
ní rotující plotnou, může hlava přistoupit na kteroukoliv část plotny. Počet hlav závisí
na počtu povrchů.
Vyrovnávací paměť: Je integrovaná v pevném disku a nejen že vyrovnává rozdíly mezi
rychlostmi všech zúčastněných složek, ale především uchovává před-načtená data.
5.1
Geometrie pevného disku
Každá plotna je rozdělena do několika dílčích částí, které jsou zobrazeny na obrázku 5.1.
Stopa: Stopy neboli tracks jsou soustředné kružnice na plotně. Plotna obsahuje stopy v řádu
tisíců. Jejich číslování je rostoucí od 0, kde směr číslování je od vnější stopy k vnitřní.
Cylindr: Stopy, které jsou umístěny nad sebou se nazývají cylindr. Stopy jsou nad sebou
právě proto, že všechny plotny v disku mají stejnou geometrii.
Sektor: Nejmenší adresovatelný úsek je sektor a typicky je velký 512 B.
19
20
KAPITOLA 5. PEVNÝ DISK
Obrázek 5.1: Geometrie disku.
5.2
Hlava
Ať už má pevný disk jednu hlavu či více hlav, tak na rychlosti přístupu k datům se podílí
dvě složky. Jednou je rychlost otáčení plotny, která je typicky u stolních počítačů 7200
ot/min. Druhá složka je rychlost hlavy, resp. čas potřebný k vystavení halvy. Tento čas
potřebný k vystavení hlavy není konstantní, jelikož nejenže záleží o jak velký kus budeme
hlavu posouvat, ale také se zde projeví např. latence a čas potřebný k ustálení hlavy.
Jelikož v české literatuře nejsou všechny následující názvy ustáleny, tak použiji anglické
názvy tak, jak jsou popisovány v [7].
5.2.1
Settle time
Settle time je čas potřebný k ustálení hlavy. Při každém pohybu se hlava nepatrně rozkmitá
a po přesunutí na požadovanou stopu je nutné vyčkat, než se ustálí. Typickým časem pro
ustálení je méně než 0.1 ms.
5.2.2
Latency
Jelikož se plotny soustavně otáčejí, tak po přesunu na konkrétní stopu není zaručeno, že se
požadovaná data budou nacházet zrovna pod hlavou. To znamená, že je ve většině případů
nutné vyčkat až se požadované data pod hlavu dostanou. V nejhorším případě hlava vyčkává
po dobu jedné otáčky plotny. Pro výpočet průměrné hodnoty se používá vzorec 5.1.
prum_latence =
1
∗
2
1
rpm_disku
60
∗ 1000 [ms]
(5.1)
Jak z rovnice vyplývá, ovlivňujícím faktorem je počet otáček disku za minutu. Průměrná
latence bývá 3-8 ms.
5.3. ACCESS TIME
5.2.3
21
Track-to-Track
V tomto případě se již jedná o pohyb hlavy a konkrétně o přechod na vedlejší stopu. Typický
čas bývá 2,5 ms, včetně doby pro ustálení hlavy.
5.2.4
Positioning
Jedná se o pohyb hlavy na libovolně vzdálenou stopu. Tento čas hraje důležitou roli např.
u aplikací, které nepřistupují k datům sekvenčně, jako jsou např. databáze. Typický čas je
10 ms.
5.2.5
Full stroke
Full stroke je čas potřebný k přesunu hlavy přes celou šíři plotny, tedy přesun z první na
poslední stopu. V reálných případech tento pohyb hlavy není nejběžnější, ale výrobci jej často
uvádějí. Důvodem je nejspíš i to, že společně s Track-to-Track tvoří meze pro positioning.
Typický čas je 17 ms.
5.3
Access time
Z předchozí podkapitoly je zřejmé, že fragmentace, resp. z pohledu pevného disku zbytečný
pohyb hlavy, bude mít negativní vliv na celkovou dobu přístupu. Tu lze pomocí vzorce 5.2
snadno vypočítat [1].
Taccess = Tseek + Tlatency + Tsettle + Trw
(5.2)
Poslední tři časy, včetně času pro zápis či čtení Trw , nelze z pohledu souborového systému
nijak ovlivnit, ale čas Tseek může být ovlivněn alespoň částečně. Čas Tseek je čas potřebný
pro samotný pohyb hlavy, tedy jeden z typů Track-to-Track, Positioning nebo Full stroke.
To, o jaký typ se bude jednat, lze ovlivnit mírou fragmentace.
Budeme-li např. číst soubor bez fragmentace, tak se hlava bude pohybovat po stopách,
tedy Track-to-Track.
Jedna z optimalizací pevných disků je tzv. read-ahead [3]. To znamená před načítání
dat, která budeme potenciálně v budoucnu potřebovat. V případě čtení libovolného úseku
se zároveň před načte i několik dalších sektorů, či případně celá stopa. Pokud máme tedy
fragmentovaný soubor v rámci před načtených dat, či např. přistupujeme k menším fragmentům v rámci jedné před načtené oblasti, tak se čtení provede jen jednou. Následné čtení
se bude provádět z vyrovnávací paměti disku.
Další optimalizací, která současně minimalizuje dopad fragmentace, je tzv. zero-latency.
V předchozí podkapitole bylo popsáno, že čtecí hlava musí vyčkat, v nejhorším případě
po dobu jedné otáčky plotny, než se požadovaná data dostanou pod hlavu. Princip zerolatency spočívá v tom, že čtecí hlava začne číst hned v momentě, kdy je přesunuta nad
požadovanou stopu. Během jedné otáčky se přečte celá stopa, která se poté v paměti disku
logicky přerovná. Dle vzorce 5.1 vychází, že v případě čtení více jak půl stopy se tato technika
vždy vyplatí.
22
KAPITOLA 5. PEVNÝ DISK
Kapitola 6
Předcházení fragmentace
V této kapitole si popíšeme obecné principy, a to jak moderní souborové systémy předcházejí
fragmentaci a případně jak se s ní vypořádají. Z předchozí kapitoly 4 víme, že v některých
případech fragmentaci souboru nelze zabránit. Nicméně, jak již bylo zmíněno, fragmentace
souboru je pro nás negativním aspektem až v momentě, kdy ovlivňuje výkonnost práce
s tímto souborem. Z toho mimo jiné vyplývá, že práci s fragmentovanými soubory značně
ovlivňují i parametry pevného disku popsané v kapitole 5. Těmito parametry jsou především
velikost vyrovnávací paměti, rychlost otáčení plotny a doba potřebná k vystavení čtecí a
zapisovací hlavy.
Jak jednotlivé souborové systémy předcházejí fragmentaci, lze jen těžko popsat obecně,
avšak existují zde určité techniky, které buď přímo slouží k minimalizaci fragmentace, nebo
je to jejich vedlejší efekt.
6.1
Variabilita velikosti uložených dat
Nejedná se ani tak o techniku, ale spíše o vlastnost ukládaných dat. Onou vlastností je, že
fragmentace je do jisté míry úměrná variabilitě velikostí uložených souborů. Co to znamená,
si ukážeme na třech případech, kdy budeme postupně uvažovat ukládání velkých a malých
souborů, a poté jejich kombinaci.
1. Pokud souborový systém obsahuje pouze velké soubory, tak při jejich postupném ukládání je snaha o co největší souvislost. Pokud je soubor úmyslně fragmentován, tak
fragmenty budou ukládány o své maximální velikosti, kterou definuje každý souborový
systém zvlášť. Pouze poslední fragment souboru může mít rozdílnou velikost v závislosti na celkové velikosti souboru. V případě stárnutí souborového systému, jak bylo
popsáno v podkapitole 4.2, se fragmentace projeví jen minimálně, jelikož kromě posledního fragmentu souboru, mají všechny stejnou velikost.
2. Podobně je to i s větším množstvím pouze malých souborů, ačkoliv oproti prvnímu
případu, zde dochází k fragmentaci v daleko větší míře. V daleko větší míře dochází i
k fragmentaci volného místa, ale jelikož ukládáme jen malé soubory, tak to nezpůsobuje
takové komplikace, jako v následujícím případě.
23
24
KAPITOLA 6. PŘEDCHÁZENÍ FRAGMENTACE
3. Nejhorší, a také bohužel nejčastější varianta, je kombinace malých a velkých souborů.
V momentě stárnutí souborového systému se začnou postupně malé soubory ukládat
do volných míst, kde byly dříve fragmenty velkých souborů. Tím se postupně začne
fragmentovat volné místo, což v tomto případě začne být komplikace pro velké soubory,
které budou muset být rozděleny na více fragmentů o menší velikosti.
Obecně tedy souborové systémy, resp. jejich alokační mechanizmy, nemají potíže s první
variantou, a to i přes to, že souborový systém má malou rezervu volného místa. Důvodem
je to, že fragmenty mají téměř konstantní velikost.
Druhá varianta je poněkud komplikovanější v tom, že jsme si jasně nedefinovali velikost souborů. Předpokladem malých souborů můžeme tedy rozumět velikost menší, než
velikost maximálního fragmentu. Ovšem, ne každý souborový systém musí soubory ukládat
po fragmentech, či fragmentech tak malých, jako např. UFS. V tom případě musíme předpokládat velikost souboru mnohonásobně menší, než celkovou velikost souborového systému.
Omezením velikosti jsme do jisté míry omezili i onu variabilitu velikostí souborů, avšak to
nezabrání fragmentaci. Mnohem důležitější podmínkou je omezení samotné variability velikostí. Čím více si velikosti souborů budou podobné, tím více se bude tato varianta podobat
první variantě.
V posledním případě budou alokaci velkých souborů ztěžovat malé soubory. S touto
situací si již alokační mechanizmy moc neporadí, jelikož jejich hlavním úkolem je výběr
vhodného místa. Na řadu by tedy mohly přijít přesuny malých souborů, resp. fragmentů, na
vhodnější místo. To ovšem vede k redundantním zápisům, a proto se tato technika ve většině
souborových systémů nepoužívá. Na řadu tedy přicházejí offline defragmentovací nástroje.
6.2
Rezerva volného místa
Minimální rezerva volného místa, či případně jen dostatek volného místa, obecně minimalizuje fragmentaci. Alokátor nemá problémy s výběrem nového vhodného místa. Jedinou
překážkou v alokaci velkých souvislých fragmentů, může být větší počet malých souborů.
6.3
Před-alokování
Před-alokování, neboli preallocation je technika, která alokuje dopředu více bloků, než je
skutečně potřeba. Důvodem je minimalizace volání metody starající se o alokaci bloků, a
současně snaha mít více bloků pohromadě. Fragment tedy bude mít velikost minimálně
takovou, jako je velikost před-alokovaného úseku.
Například, budeme-li uvažovat souborový systém Ext3, který má bloky o velikosti 4
kB a nebude používat techniku před-alokování3 , tak pro zapsání 100 MB souboru se bude
muset 25600 krát zavolat metoda starající se o alokaci bloků. V případě před-alokování by
se musela volat jen 3200 krát a minimální velikost fragmentu by byla 32 kB4 . Nevýhoda
z toho plynoucí je případná alokace nepotřebných bloků, které se opět musejí uvolnit. Proto
3
Skutečnost je taková, že souborový systém Ext3 má implementováno před-alokování, stejně jako jeho
předchůdce Ext2. Nicméně kvůli nekompatibilitě s žurnálem jej nelze používat.
4
Přednastavená hodnota na před-alokování je 8 bloků.
6.4. ZPOŽĎOVÁNÍ ALOKACE
25
zde nutně musí existovat jisté omezení, aby se souborový systém nezahltil před-alokovanými
bloky, které později nebudou potřebné. Tímto omezením, např. u Ext3, resp. Ext2 je, že
každý inode může mít jen jedno před-alokované místo.
6.4
Zpožďování alokace
Zpožďování alokace, neboli delayed allocation [11] je technika, která se začala využívat
v souborových systémech jako např. ZFS, XFS, Ext4. Bez použití této techniky se v momentě, kdy aplikace zavolá write(), ihned vyhledá a alokuje potřebné místo na disku, kam
se budou data ukládat. K tomu dojde i přesto, že k zápisu nedochází bezprostředně, a data
jsou po nějakou dobu ve vyrovnávací paměti. To je ovšem nevýhodné v případě, kdy dochází
k soustavnému zapisování, a tím i zvětšování cílového souboru, jelikož za vybraným místem
již nemusí byt dostatek prostoru a bude muset dojít k fragmentaci. Zpožďování alokace
vybere vhodné místo pro data až v momentě, kdy jsou opravdu zapisována na disk.
6.5
Extents
Extents je další technika, jejímž úkolem není primárně zabránit fragmentaci, ale přesto je
to jedna z jejích vlastností. Jak bylo vysvětleno v kapitole 3, tak ve většině případů jsou
data na disku uložena po blocích, jejichž konkrétní velikost definuje souborový systém, a
na každý tento blok je v inodu odkaz. Extents je v podstatě sloučení několika souvislých
bloků, na který je v inodu pouze jeden odkaz. Jinými slovy se jedná o fragment, na který je
v inodu jeden odkaz. Tato technika se většinou používá společně se zpožďováním alokace.
6.6
Souborový systém UFS
Souborový systém UFS neobsahuje žádné komplexní metody, které se přímo zabývají předcházením, či odstraňováním fragmentace. Nicméně UFS bylo navrhováno s ohledem na fragmentaci a obsahuje několik mechanismů, které zde sice nejsou primárně kvůli fragmentaci,
ale přesto fragmentaci jistým způsobem pozitivně ovlivňují.
6.6.1
Rezerva volného místa
Jedná se o jedinou konkrétní zmínku, resp. parametr, který je určen pouze k minimalizaci
fragmentace. Doporučená minimální hodnota je 10% volného místa. Důležité je, že rezerva je
počítána z celého disku, a ne např. jen z konce disku, což by nám nijak nepomohlo. Počítání
rezervy z celého disku znamená, že na každé skupině cylindrů máme teoreticky také rezervu.
V případě alokace nového úseku máme tedy šanci, že se úsek nebude dělit na více fragmentů
v rámci skupiny.
Pokud se ale jednou skupina cylindru zaplní, tak následující zápisy do této skupiny
budou většinou znamenat fragmentaci, nehledě na celkovou rezervu volného místa. Proto je
u UFS nejen velmi důležité mít rezervu volného místa, ale pokud možno tak tuto hranici
10% volného místa na disku nikdy nedosáhnout. Jakmile se jednou disk zcela zaplní, tak i
26
KAPITOLA 6. PŘEDCHÁZENÍ FRAGMENTACE
po následném uvolnění, např. z 30%, nebudeme mít přehled o fragmentaci volného místa na
jednotlivých skupinách cylindrů.
Pokud skutečně k fragmentaci volného místa dojde, tak v rámci UFS neexistuje opravný
mechanismus, jak tuto fragmentaci odstranit.
6.6.2
Skupiny cylindrů
Samotný souborový systém UFS je navržen tak, že při formátování nového oddílu bude
oddíl rozdělen do několika skupin cylindrů. To následně sice vede k nucené fragmentaci
při vytváření větších souborů, ale snižuje to fragmentaci volného místa. Tím, že je soubor
rozdělen do několika skupin cylindrů, se minimalizuje fragmentace v případě jeho smazání.
Pokud bychom uvažovali, že by byl soubor souvislý, tak po jeho smazání by vzniklo volné
místo, jakési okno o velikosti tohoto souboru. Následné vytváření souborů o velikosti menší,
než volné místo v okně a průběžné mazaní, by mělo dříve či později za následek fragmentaci
volného místa v tomto okně. Tím, že je ale soubor úmyslně rozdělen do několika skupin
cylindrů, tak po jeho smazání zbyde oněch oken mnohem více a o menší velikosti. Sice stále
může docházet k fragmentaci volného místa v jednotlivých oknech, ale celkový dopad bude
méně znatelnější a je mnohem pravděpodobnější, že okno bude alokováno celé.
6.6.3
Fronta přístupů na disk
Jak bylo popsáno v kapitole 5, tak při požadavku na určitý soubor se nejprve musí vystavit
čtecí a zapisovací hlava disku. K disku se obecně nepřistupuje s každým požadavkem, ale
po určitých intervalech, kde jednotlivé požadavky na fragmenty, resp. bloky, jsou uloženy
do fronty, a poté uspokojeny naráz. V případě velké fragmentace souboru, či požadavků na
navzájem vzdálené bloky, by zde docházelo ke zbytečnému pohybu čtecí a zapisovací hlavy.
Proto se k optimalizaci pohybu hlavy používá one-way scan algoritmus. Princip spočívá
v tom, že se nejprve požadavky setřídí dle umístění bloků. Následně se rozdělí fronta na dvě
části. Na bloky s vyšší adresou než je aktuální pozice hlavy disku, a na bloky s nižší adresou.
Poté se již hlava disku postupně přesouvá, nejprve na bloky s vyšší adresou, a poté na ty,
které měly adresu nižší než pozice hlavy.
Implementace algoritmu není vždy zcela v rámci souborového systému UFS. V projektu
FreeBSD tomu tak je, ale např. v OpenBSD je algoritmus implementován v části ovladače
obsluhujícího pevný disk.
Kapitola 7
Analýza a návrh řešení
Z kapitoly 3 zabývající se UFS, bychom nyní měli brát na zřetel alespoň to, že souborový
systém je rozdělen do několika skupin cylindrů. Každá skupina obsahuje oblast Data block,
která se skládá z bloků, a ty dále z fragmentů. Oblastí našeho zájmu bude Data block,
který obsahuje data souborů. Všechny ostatní oblasti s výjimkou Inode block, jsou pro nás
z hlediska defragmentace nezajímavé, jelikož mají pevně danou strukturu.
7.1
Defragmentace oblasti Inode block
V této podkapitole vysvětlím, proč se nedefragmentuje Inode block, přestože inody mohou
být roztroušeny po celém souborovém systému, což z hlediska vystavování čtecí hlavy disku
nemusí být vždy výhodné. V prvním případě by přesun inodu z jedné pozice do druhé
znamenalo, že se pro daný soubor změní jeho inode číslo. To by ještě nemuselo znamenat
vážný problém, ale se změnou inode čísla by se současně musel upravit inode adresář, ve
kterém je tento soubor umístěn. Tento inode ve svých datových blocích obsahuje jména
souborů v něm obsažených a toto jméno je svázáno právě s číslem inodu.
Druhý důvod, a to daleko závažnější, vychází ze způsobu jakým se vybírá nepoužitý inode při vytváření nového souboru. Kritériem výběru je především, ve které skupině cylindrů
se nachází inode adresáře, v kterém bude soubor umístěn. Dále jsou to shrnující informace v rámci každé skupiny cylindrů, která obsahuje počet použitých inodů uvnitř skupiny.
V úvahu se bere i celkový počet již alokovaných datových bloků ve skupině.
Pokud bychom tedy začali přesouvat jednotlivé inody, bylo by to spíše proti logice
samotného UFS a jeho optimalizačním metodám. V úvahu může přicházet pouze přesun inodů z více zaplněné skupiny cylindrů, do méně zaplněné skupiny, kde zaplněnost
se samozřejmě myslí v oblasti Inode block. Současně by se muselo pamatovat vždy na hierarchii podadresářů. Ovšem tyto přesuny by se spíše než fragmentací, zabývaly optimalizací
vyváženosti mezi zaplněností v jednotlivých Inode blocích.
Díky vyrovnávací paměti, v které se uchovávají naposledy použité inody, algoritmu pro
výběr nového inodu a i snadnému přístupu k inodům, by jejich přesuny byly z pohledu
optimalizace spíše sporadické.
27
28
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
7.2
Defragmentace oblasti Data block
Oproti Inode block je Data block tou správnou oblastí, kterou defragmentovat. Je jasné, že
po defragmentaci by ideální případ byl takový, že každý inode by měl datové bloky, na které
odkazuje v jediné sekvenční posloupnosti a stejně by tomu bylo i s bloky neobsazenými. To
samozřejmě z hlediska architektury UFS není vždy možné.
Defragmentaci souborového systému lze rozdělit do několika vrstev dle toho, jak budeme
vnímat datovou oblast.
1. Za datovou oblast budeme považovat Data blocky ze všech skupin cylindrů, tzn. jako
jeden sekvenční úsek.
2. Datovou oblastí je jen Data block z konkrétní skupiny cylindrů.
3. Datovou oblastí je jeden, resp. více bloků souborového systému, a defragmentují se jen
fragmenty uvnitř bloku.
V prvním případě by taková defragmentace v podstatě znamenala odstranění skupin
cylindrů, jelikož po jejím skončení by první skupiny byly zaplněné, kdežto poslední skupiny
souborového systému by byly prázdné. To by ovšem bylo v rozporu s principem UFS, jelikož
je zde snaha o to, aby všechny skupiny cylindrů byly zaplněny stejnoměrně.
V úvahu tedy připadají jen poslední dvě možnosti. Defragmentovat datovou oblast jen
v rámci konkretní skupiny cylindrů, resp. na úrovni fragmentů jednotlivých bloků, ale opět
jen v rámci jedné skupiny cylindrů. To, proč stačí defragmentovat jen skupinu cylindrů, je
dáno principem UFS.
7.3
Identifikace bloků
Než se vůbec s defragmentací začne, je třeba zjistit, v jakém stavu se Data block nachází.
Pomocí bitové mapy můžeme zjistit které bloky, resp. fragmenty, jsou obsazené a které volné.
U obsazených bloků, resp. fragmentů, musíme dále zjistit, ke kterému inodu patří. Důležité je
uvědomit si, že tento krok je naprosto nezbytný, jelikož pokud chceme dále bloky přesouvat
na jiné pozice, musíme vědět, ke kterému inodu náleží, abychom mohli změnit odkaz v inodu
na novou pozici bloku. Problém tohoto hledání se skrývá v tom, že ze samotných bloků, resp.
fragmentů, tuto informaci nezjistíme. Jediné řešení jak určit, zda blok k inodu patří je ta,
že se prohledají všechny odkazy konkrétního inodu a nalezne se tam takový, který ukazuje
na tento blok.
Pokud tedy potřebujeme ke každému bloku v oblasti Data block zjistit, ke kterému inodu
patří, musíme v nejhorším případě prohledat všechny inody, které se nacházejí v souborovém
systému. Všechny inody se prohledávají z toho důvodu, že umístění datového bloku na
konkrétní skupině cylindrů nám nic nevypovídá o tom, na které skupině cylindrů se nachází
inode, který na tento blok odkazuje.
Ačkoliv se na první pohled může zdát, že toto vyhledávání je časově velmi náročné, tak
následující protichůdné úvahy ukáží, že tomu tak ve většině případů není. V obou úvahách
předpokládáme nejčastější hodnoty souborového systému, tedy že skupina cylindrů obsahuje
12958 bloků a 25984 inodů.
7.3. IDENTIFIKACE BLOKŮ
7.3.1
29
Úvaha o velkém počtu malých souborů
Předpokládejme, že souborový systém obsahuje pouze velký počet malých souborů, takže
počet využitých inodů se přiblížil k celkovému počtu všech inodů na skupině cylindrů.
Z poměru bloků a inodů vyplývá, že mohou nastat tři situace:
• Počet inodů je shodný s počtem bloků, tzn. každý inode ukazuje právě na jeden blok.
• Počet inodů je vyčerpán, tj 25984 inodů je použito. Za předpokladu, že každý blok
obsahuje 8 fragmentů připadají na každý inode necelé 4 fragmenty5 .
• Kombinace obou předchozích případů. Důležité je si uvědomit, že v momentě, kdy je
pro inode potřeba alokovat nový fragment a celkový počet fragmentů v inodu stoupne
na 8, se tyto fragmenty automaticky překopírují do prázdného bloku tak, aby mohly
tvořit jeden souvislý blok. Tím se i počet odkazů v inodu sníží ze 7 na jeden odkaz.
Shrneme-li všechny tři situace, tak nám z nich vyplývá, že ať již bude počet inodů zcela
vyčerpán, či se jejich počet bude pohybovat v rozmezí počtu bloků, tak všechny odkazy na
bloky, resp. fragmenty, budou přímé.
Budeme-li uvažovat tu horší variantu, že všechny inody jsou na skupině cylindrů použity,
tak se nám nabízí dvě možnosti jak inody prohledat.
1. Celou oblast Inode block můžeme naráz načíst, resp. namapovat do paměti. Následný
čas potřebný k přístupu k jednotlivým položkám inodu bude již zanedbatelný. Za
předpokladu velikosti inodu 128 B a 25984 inodů bude třeba použít 3248 kB paměti.
Samozřejmě v rámci optimalizace lze uvažovat i o načítání menších úseků.
2. Čtení jednotlivých bloků s inody. Předpokládáme-li, že se do bloku vejde celkem 128
inodů, tak bude třeba 203 přístupů na disk.
7.3.2
Úvaha o malém počtu velkých souborů
Opačná úvaha se zabývá malým počtem velkých souborů. Po vyčerpání 12ti přímých odkazů
je inode nucen začít používat nepřímé odkazy. To pro nás mimo jiné znamená, že musíme
načíst nový blok obsahující tyto odkazy. Jeden blok může pojmout 4096 odkazů, z čehož
plyne, že tyto necelé 4 bloky mohou pokrýt celou oblast Data block.
Pokud by se uvažoval pouze jeden inode, tzn. soubor zhruba o velikosti 202 MB, tak by
bylo nutné provést celkem 6 čtení z disku.
• Načíst inode.
• Načíst blok z první nepřímé úrovně.
• Načíst blok z druhé nepřímé úrovně.
5
Jedná se samozřejmě o zaokrouhlení (12958 * 8) / 25984. Nezapomínejme, že fragment je nejmenší
adresovatelná oblast souborového systému.
30
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
• Načíst zbývající 3 bloky, jejichž adresu získáme z bloku ze 3 čtení.
Tyto úvahy nám ukázaly dvě protichůdné situace, které mohou nastat při hledání odkazů
na bloky v inodech. Z pohledu rychlosti vyhledávání a počtu přístupů na disk, by pro nás
bylo výhodné, kdyby soubory patřily jen do jedné skupiny. Nicméně ve většině reálných
souborových systémů jsou soubory jak malé, tak i velké, ale vždy když začne dominovat
jedna skupina, tak je to na úkor druhé.
7.3.3
Nejhorší stav pro identifikaci bloků
Nejhorším stavem který může nastat je právě situace, kdy soubory svojí velikostí nepaří do
skupiny malých a ani velkých souborů. To znamená stav, kdy je zde velký počet inodů ve
skupině cylindrů, a současně každý z nich používá adresování pomocí nepřímé úrovně.
Konkrétně jedna z nejhorších situací nastane, když každý inode ukazuje právě na 13
bloků, resp. 12 bloků a alespoň jeden fragment, ale pro jednoduchost výpočtu berme v úvahu
13 bloků. V takovém případě je prvních 12 bloků adresováno přímo a 13 blok nepřímo,
k čemuž je nutné použít další blok pro adresaci. To ale znamená, že je nutné provést další
přístup k disku. Celkem tedy tento inode zabere 14 bloků. Pokud je tedy na skupině cylindrů
12958 bloků, tak je možné, že zde bude cca 925 takovýchto inodů. To znamená, že nehledě
na to jak se bude načítat oblast Inode block, tak zde bude dalších 925 přístupů na disk.
7.4
Seřazení bloků
V této fázi, která následuje po identifikaci bloků, již máme ke každému bloku informaci, zda
je obsazený či ne. U obsazených bloků známe číslo inodu, který na ně ukazuje a i pořadí,
v kterém na bloky ukazuje. Všechny tyto informace nám vytvářejí jakousi mapu oblasti Data
block. Z této mapy můžeme nejen určit volné a zaplněné místa, ale i oblasti, kde jsou data
souvislá či fragmentovaná.
V této podkapitole se budeme zabývat tím, jak bloky vhodně uspořádat. Nicméně ve fázi
řazení nebudeme bloky stále fyzicky přesouvat, budeme jen vypočítávat jejich budoucí pozici.
Podobně jako jsme si vytvořili mapu oblasti Data block, která reprezentuje aktuální stav,
tak si vytvoříme mapu, která nám bude reprezentovat oblast Data block po defragmentaci.
Hlavním důvodem proč nepřesouvat bloky již v této fázi, bylo oddělit algoritmus řazení od
samotných přesunů.
Ideálním řešením by bylo, kdybychom měli funkci, které předáme aktuální mapu Data
blocku, a ta by nám vrátila novou mapu, která by reprezentovala oblast po defragmentaci.
Takový postup nám samozřejmě v budoucnu dovolí snadnou modifikaci algoritmu.
Pokud bychom se zabývali řazením libovolných objektů v operační paměti, tak by postup
byl vcelku zřejmý. Problém ovšem nastává s tím, že naše objekty jsou uloženy na pevném
disku. To jest na médiu řádově pomalejším, odkud je vždy musíme načíst a poté na jinou
pozici uložit. Proto nás kromě výsledného uspořádání bude zajímat i to, kolik přesunů bude
třeba provést. V úvahu přicházejí tři způsoby jak bloky uspořádat.
1. Všechny bloky konkrétního inodu budou na skupině cylindrů uloženy souvisle.
7.4. SEŘAZENÍ BLOKŮ
31
2. Bude brán zřetel na souvislost, ale současně i na počet nutných přesunů nutných
k dosažení souvislosti.
3. Přesuny fragmentů k dosažení maximálního počtu neobsazených bloků.
V následujících podkapitolách si jednotlivé varianty probereme. Některé z nich je možné
kombinovat, jako např 1 a 3 některé se zas navzájem vylučují. Ve fázi řazení nicméně nebudeme bloky stále fyzicky přesouvat, budeme jen vypočítávat jejich budoucí pozici.
7.4.1
Optimalizace na souvislost
Při této optimalizaci se snažíme dosáhnout toho, aby inode měl bloky na skupině cylindrů
v co největších souvislých úsecích. Optimální stav je takový, když je zde jen jedna souvislá
posloupnost bloků pro každý inode. Pokud jsou tyto posloupnosti umístěny za sebou, tak
se současně zabraňuje fragmentaci volného místa. Vytvářejí-li se posloupnosti postupně od
začátku datové oblasti, pak na konci datové oblasti vzniká souvislý úsek nepoužitých bloků.
Tato optimalizace se snaží odstranit fragmentaci v největší míře a výsledný stav by měl
být velice podobný stavu těsně po instalaci operačního systému, resp. po nakopírování dat
na nově naformátovaný souborový systém.
Nevýhodou je nutnost přesunutí velkého počtu bloků, který se často blíží počtu celkových
bloků na skupině cylindrů.
7.4.2
Optimalizace na počet přesunů
Za ideální řešení by se mohl považovat jeden, či více větších souvislých úseků pro jeden inode,
k čemuž by se došlo z minimálního počtu přesunutých bloků. Problémem je, že pokud je
souborový systém fragmentovaný a z větší části zaplněn, tak se musí volit kompromis mezi:
• Počtem přesunů.
• Souvislostí bloků.
• Fragmentací volného místa.
Dalším problémem je to, jak určit, jestli je souvislý úsek již dostatečně velký. To znamená,
nalezení takového úseku bloků, kdy po rozšíření o následující bloky již rychlost čtení nebude
ovlivněna. Taková hodnota by se musela určit experimentálně u každého systému zvlášť,
jelikož její hodnoty by se jistě lišily dle použitého hardwaru.
Uvažujme zjednodušenou situaci, kdy jsme vytvořili současně tři soubory. Soubory byly
nezávisle na sobě zvětšovány o rozdílný počet bloků. Poté byl jeden ze souborů smazán.
Obrázek 7.1. zobrazuje teoretický stav, ve kterém by se souborový systém mohl nacházet.
Defragmentace, která by se snažila o vytvoření co největších souvislých úseků společně
s minimem přesunů, by musela volit mezi jedním z kompromisů:
32
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
Obrázek 7.1: Pohled na souborový systém po smazání jednoho ze souborů.
• Pokud S1 = A2 je možné přesunout A2 na pozici S1 . Současně ale rozhodni, zda je BK
dostatečně velký úsek. Pokud ne, pak rozhodni, jestli není výhodnější přesunout blok
BK−1 na pozici S1 , za předpokladu že BK−1 = S1 . Pokud je BK−1 < S1 , ale současně
je i BK−1 << A2, stále může být přesun výhodnější i za cenu potenciálního vzniku
fragmentace volného místa.
• Pokud S1 < A2 je možné přesunout A1 a A2 do SF . Cenou bude počet přesunů
rovnající se velikosti obou úseků. Druhou možností je rozdělit A2 na A2a a A2b . A2a
o velikosti S1 by se přesunula do S1 a zbývající část A2b by se musela sloučit s A3 ,
samozřejmě pokud by sama A2b nebyla dostatečně velký úsek.
• Pokud S1 > A2 , pak lze A2 přesunout do S1 , ale rozdíl S1 − A2 bude volné místo F.
Pokud F nebude tvořit dostatečně velký úsek a BK se nebude přesouvat, pak bude
obtížné F odstranit. Podaří se to jen v případě, že nalezneme soubor o velikosti F nebo
minimalizovat F, pokud nalezneme dostatečný počet souborů, které budou přesunuty
do F. Budeme muset volit mezi zbytečnými přesuny malých souborů, nebo fragmentací
volného místa.
7.4.3
Optimalizace na fragmenty
Optimalizovat přesuny na fragmenty lze prakticky z jediného důvodu, a to z důvodu uvolnění bloku. Jelikož víme, že jeden inode může mít nanejvýš 7 fragmentů, které musejí být
umístěny v jednom bloku, tak je zbytečné řešit souvislost fragmentů. Nicméně v jednom
případě je užitečné přesouvat fragmenty, a to z důvodu uvolnění bloku. Může se stát, že
souborový systém bude obsahovat mnoho malých souborů, např. o velikosti 2 fragmentů
a zbytek bloku bude nevyužit. To povede nejen k velké fragmentaci volného místa, ale i
k problémům při následné alokaci celých bloků.
Tuto optimalizaci je možné zkombinovat s předešlými dvěmi. Stále ale platí, že se zvolený
cílový blok snažíme fragmenty zaplnit a zdrojový blok uvolnit. Naopak následné přesuny
takového bloku mohou být velmi nevýhodné, a to co se přístupu na disk týče. Uvědomíme-li
si, že v bloku může být až 8 fragmentů z 8 inodů, tak přesun takového bloku by znamenal
až potenciálních 18 přístupů na disk.
7.5
Využití paměti
Ačkoliv ještě nemáme jasně definované datové struktury programu, již bychom se měli zamyslet nad tím, kolik operační paměti bude naše implementace vyžadovat.
V předchozích podkapitolách jsme si definovali jakousi mapu datové oblasti, která bude
obsahovat potřebné informace o blocích. V tomto okamžiku ještě nemůžeme říct, kolik informací o jednom bloku budeme uchovávat a ani kolik místa zaberou. Můžeme ale dle velikosti
7.6. PŘESUNY BLOKŮ
33
skupiny cylindrů odhadnout, že velikost mapy bude nanejvýš 12958. Tato hodnota se poté
vynásobí velikostí datových typů, které budou uchovávat informace o jednotlivých blocích
a výsledek bude velikost potřebné paměti v bajtech.
Dále budeme potřebovat načítat jednotlivé inody. Ty lze načíst minimálně po fragmentech, ale rozhodně bude výhodnější je číst po celých blocích, tj. o velikosti 16 kB. Jelikož
úpravy v inodech budeme provádět velmi často, lze i uvažovat o načtení celého Inode blocku.
Pokud uvažujeme 25984 inodů, kde každý má velikost 128 B, tak budeme potřebovat okolo
3.17 MB. To stále nemusí být dostatečné, jelikož Data block může obsahovat i bloky inodů,
které nejsou ve stejné skupině cylindrů.
Při přesunech bloků budeme potřebovat v paměti prostor minimálně pro dva bloky.
Jelikož ale budou přesuny hlavní náplní programu, můžeme i uvažovat o načtení celé skupiny
cylindrů do paměti. Pro celou skupinu cylindrů bychom potřebovali okolo 202 MB. Můžeme
polemizovat, jestli je to v dnešní době mnoho či ne, nicméně neoddiskutovatelnou výhodou
by bylo, že čtení by prakticky proběhlo v nejrychlejší možné míře. Nehledě na algoritmus
pro přesuny bloků, musí se pamatovat na to, že pro přesun jednoho bloku musíme načíst
jak samotný blok, tak i inode. V případě nepřímé adresace i bloky s adresami.
7.6
Přesuny bloků
V této podkapitole si popíšeme možnosti při přesunech bloků a rizika jsou s tím spojená.
Efektivitu můžeme z velké části ovlivnit buď zvětšením rizika ztráty souboru, nebo zvětšením
paměťových nároků.
V momentě, kdy začneme s přesunem bloků, tak v podstatě začneme narušovat integritu
souborů. V případě nečekaného ukončení programu mohou nastat tři varianty, v kterých se
souborový systém bude nacházet. Ty jsou především závislé na stupni optimalizace zápisu.
7.6.1
Bez možnosti ztráty dat
Chceme-li se vyvarovat ztráty dat za všech okolností, tak musíme přesouvat bloky následujícím způsobem. V příkladě se uvažuje prohození dvou bloků b1 a b2 , dvou rozdílných inodů
i1 a i2 , které jsou adresované přímo. V případě nepřímé adresace by se navíc musel uvažovat
blok s adresou.
1. Načtení inodů a bloků. Celkem se jedná o 4 přístupy na disk. V případě, že jsou inody
v jednom bloku, tak jen 3 přístupy.
2. Nyní se nahraje např. b1 do libovolného nevyužitého bloku.
3. Upraví se inode i1 a uloží se.
4. Nakopíruje se b2 na starou pozici b1 .
5. Upraví se inode i2 a uloží se.
6. Nakopíruje se b1 na starou pozici b2 .
7. Upraví se inode i1 a uloží se.
34
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
Celkem se tedy musí po prvních 4 čtení a 6 zápisech, provést 10 přístupů na disk.
Výhodou této metody je ovšem to, že program může být ukončen v kterýkoliv okamžik, a
to bez rizika ztráty dat.
7.6.2
Možnost ztráty jednoho souboru
Podstoupíme-li riziko ztráty jednoho souboru, tak můžeme uvažovat i zde příklad z předchozí
podkapitoly. Rozdíl bude jen v tom, že v 2 a 3 kroku nebudeme blok a inode ukládat do
dočasné pozice, ale ponecháme je jen v operační paměti a uložíme je v kroku 6 a 7. Pokud
ovšem po kroku 4 nastane nečekané ukončení programu, bude soubor s inodem i1 ztracen.
Toto riziko potrvá až do dokončení kroku 7.
7.6.3
Možnost ztráty celé skupiny cylindrů
V tomto případě uvažujeme, že jsme načetli celou skupinu cylindrů do paměti. Pokud bychom přesuny prováděli jen v rámci operační paměti, celý proces by se značně urychlil, a to
díky jednomu čtení a po seřazení jednoho zápisu. Jen jedno čtení a zápis je za předpokladu,
že není nutné přistupovat na jinou skupinu cylindrů kvůli inodům nebo nepřímých blokům.
Pokud bychom přistupovali na jinou skupinu cylindrů, tak po první změně na této skupině
by v případě náhlého ukončení programu došlo k poškození všech souborů, které byly na
této skupině upravovány.
Jestliže bychom nepotřebovali jiná data, než která jsou jsou již v paměti, tak by poškození
souborů mohlo nastat jen v momentě, kdyby se skupina cylindrů kopírovala z operační
paměti zpět na disk. V tomto případě by ovšem mohlo být ztraceno mnohem více dat.
7.7
Algoritmy pro přesun bloků
V této podkapitole budou popsány tři algoritmy pro přesouvání bloků. Jejich společnou
charakteristikou je, že bloky, resp. veškerá potřebná data, se v jednom průchodu algoritmem,
načtou z disku jen jednou. Počet přístupů na disk z důvodu ukládání je závislý na riziku,
které jsme ochotni podstoupit v případě neplánovaného ukončení programu, viz podkapitola
o přesunech bloků 7.6. V algoritmech budeme uvažovat, z pohledu přístupů na disk, tu
nejnáročnější variantu, tedy bez možnosti ztráty dat. Abychom takto mohli bloky přesouvat,
musíme mít kdekoliv na disku jeden blok neobsazený.
Počet přístupů na disk, z důvodu načtení bloků, je závislý na způsobu jeho adresace. Pro
názornost budeme v algoritmech předpokládat přímou adresaci. V případě nepřímé adresace
by se musely načítat i bloky s adresami. Zápis by se ale nezměnil, jelikož místo upravených
inodů, by se ukládaly upravené bloky s adresami. V nejhorším případě se tedy počet přístupů
na disk zvetší o tři čtení na jeden požadovaný blok.
7.7.1
Naivní algoritmus
Jedná se o jednoduchý algoritmus, který prochází postupně inody ve skupině cylindrů a jejich
odkazy na bloky, viz Obrázek 7.2. Pokud se bloky nacházejí na aktuální skupině cylindru,
tak se budou přesouvat.
7.7. ALGORITMY PRO PŘESUN BLOKŮ
35
Algoritmus:
1. Nastav ukazovátko na začátek oblasti Data block.
2. Pro všechny obsazené inody ve skupině cylindrů.
3. Načti inode.
4. V inodu pro všechny odkazy na bloky jenž se nacházejí ve skupině cylindrů.
• Pokud žádný blok není, pokračuj v bodě 3.
5. Načti blok na který ukazuje.
6. Načti blok na který ukazuje ukazovátko.
7. Proveď výměnu.
8. Zvětši ukazovátko a pokračuj v bodě 4.
Pokud je pozice, na kterou ukazuje ukazovátko prázdná, tak se prázdný blok nekopíruje,
jen se přenastaví bitmapa.
Výhody:
+ Není třeba fáze řazení popsané v 7.4.
+ Aktuální inode a nepřímé bloky se načtou jen jednou a pak se zpracovávají.
Nevýhody:
- Bloky inodů mimo skupinu cylindrů nejsou seřazeny.
- Při výměně bloků je většinou jeden z nich umístěn na pozici, z které bude dále
přesouván.
7.7.2
Algoritmus úplného seřazení
Pro tento algoritmus je již nezbytné znát cílové pozice pro všechny bloky na skupině cylindru.
Toho se docílí řazením, viz. podkapitola 7.4. Postupně se pak procházejí všechny seřazené
bloky a dle informací o jejich cílové pozici se přesouvají.
Pokud je cílová pozice prázdná, tak se prázdný blok nekopíruje, jen se přenastaví bitmapa.
Výhody:
+ Seřadí všechny bloky na skupině cylindrů bez ohledu na to, kde se nachází inode.
Nevýhody:
- Při výměně bloků je většinou jeden z nich umístěn na pozici, z které bude dále
přesouván.
- Nepřesunou se všechny bloky inodu na jedno načtení inodu, případně bloku s nepřímými adresami.
36
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
Obrázek 7.2: Průběh zpracování u naivního algoritmu.
Algoritmus:
1. Pro všechny obsazené datové bloky v mapě.
2. Načti informace o bloku.
3. Zjisti jestli je blok již na cílové pozici.
• Pokud ano, přejdi na následující blok.
• Pokud ne, načti informace o bloku, který je na cílové pozici.
4. Načti oba bloky a proveď výměnu.
5. Pokračuj v bodě 2.
7.7.3
Algoritmus bez zbytečných přesunů
Nevýhodou předchozích algoritmů byly jejich zbytečné přesuny. Ve většině případů se na
požadovanou pozici dostal jen jeden ze dvou bloků. Druhý blok se přesouval na svou cílovou
pozici až tehdy, když na něj přišla řada. To nejen znamená, že se musí do operační paměti
načíst inode a poté blok, který již v paměti jednou byl, ale musí se i znovu přesouvat a poté
zapsat. Bylo by tedy vhodné nalézt takový způsob přesunu, aby se blok, který se jednou
načte, uložil vždy na svou cílovou pozici.
Problém tohoto požadavku je, že obecně dva bloky nelze navzájem přesunout s tím, aby
oba byly na cílové pozici. Řešením se z části ukázalo zahrnutí třetího bloku do přesunů.
Algoritmus si popíšeme na konkrétním příkladě tří bloků A, B, C, přesunovaných ve
dvou fázích, viz. Obrázek 7.3. V první fázi se přesune B na svou cílovou pozici a v druhé
fázi se přesune A na svou cílovou pozici. Při přesunech budou cílové pozice bloků obsazeny.
7.7. ALGORITMY PRO PŘESUN BLOKŮ
Operace
Načtení A,B,C
Ulož dočasně A
Ulož B
Ulož dočasně C
Ulož A
37
Čtení
6
Zápis
2
2
2
2
Tabulka 7.1: Počet přístupů na disk.
Vstupem algoritmu je blok, který se nenachází na cílové pozici, a současně je třeba znát
cílové pozice bloků. Po ukončení algoritmu je vždy jeden či více bloku na cílové pozici. Počet
bloků, které se přesunou není předem znám, záleží vždy na jejich cílových pozicích.
Algoritmus:
1. Vstupem je blok B.
2. Načteme informace o bloku a přejdeme k jeho cílové pozici.
3. Na této pozici se nachází blok A, načteme jeho informace.
• V případě, že je pozice prázdná, přesune se blok B a skončíme.
4. Blok A má svou cílovou pozici obsazenou C, přesouvá se tedy do neobsazené pozice.
• Pokud by A měl cílovou pozici volnou, přesunul by se a vrátili bychom se k přesunu bloků B a algoritmus by skončil.
5. Cílová pozice B je nyní volná a blok se přesouvá. Práce s blokem B končí.
6. Blok C se přesouvá do nové volné pozice po B.
• Pokud by cílová pozice C byla prázdná, blok by se na ni přesunul a práce s blokem
C by se ukončila.
7. Blok A se může přesunout do své cílové pozice.
8. Nyní jsou minimálně blok A a B na cílových pozicích. Za předpokladu, že C není na
cílové pozici, přecházíme do bodu 2 s blokem C, ale již nemusíme z disku nic načítat.
Výhoda, která nemusí být na první pohled zřejmá je, že čtení inodů a bloků A, B, C
proběhne jen jednou. Při opakovaných přesunech z dočasného umístění již nemusíme bloky
ani inody znovu načítat.
Celkový počet přístupů na disk při prvním průchodem algoritmu je v tabulce 7.1
Celkový počet přístupů na disk je tedy 14. V porovnání s předchozími algoritmy, které
měly jen 10 přístupů na disk na jeden průchod algoritmem, jsme si znatelně pohoršili.
Nicméně při všech dalších průchodech již nebudeme muset znovu načítat C, jen A a B,
tudíž počet přístupů nám klesne na 12. Hlavním rozdílem ale je, že po jednom průchodu
38
KAPITOLA 7. ANALÝZA A NÁVRH ŘEŠENÍ
Obrázek 7.3: Průběh zpracování u algoritmu bez zbytečných přesunů.
algoritmem budou 2 bloky na cílové pozici, kdežto v předchozích algoritmech to ve většině
případů byl jen jeden blok.
Pokud zanedbáme první načtení C, které se již dále nebude provádět, tak se počet
přístupů na disk zefektivní až o 40%.
Výhody:
+ Dva bloky se vždy přesunou na cílovou pozici.
+ Možnost přesunutí až tří bloků na cílovou pozici.
Nevýhody:
- Nepřesunou se všechny bloky inodu na jedno načtení inodu, případně bloku
s nepřímými adresami.
Kapitola 8
Implementace
V této kapitole si popíšeme vlastní implementaci programu na odstranění defragmentace,
pro který jsem zvolil název udef, což je odvození z UFS defragmentation. Na obrázku 8.1
je znázorněn zjednodušený úspěšný průchod programem. Pro implementaci byl zvolen programovací jazyk C a program byl rozdělen do sedmi souborů.
Obrázek 8.1: Průchod programem.
39
40
KAPITOLA 8. IMPLEMENTACE
udef.c Obsahuje funkci main() a hlavní náplní je zpracování parametrů a poté volání jednotlivých funkcí v závislosti na vstupních parametrech.
io.c Zajišťuje ukládání a načítání bloků a inodů buď z paměti nebo z pevného disku. Přepočítává relativní adresu bloku na absolutní adresu. Jedná se v podstatě o nejnižší
vrstvu programu obsahující systémové funkce jako pread() a pwrite().
cgmmap.c Stará se o namapování skupiny cylindrů do paměti pomocí funkce mmap().
V případě namapování skupiny cylindrů se stará o ukládání a načítání bloků.
udefcg.h Alokuje potřebnou paměť pro pole reprezentující skupinu cylindrů. Identifikuje
jednotlivé bloky a určí jejich cílovou pozici.
udef_stat.c Výpis souhrnných informací o skupině cylindrů a o blocích nacházejících se
na ní.
sortcg.c Zajišťuje přesouvání bloků. To mimo jiné znamená veškerou přípravu s tím spojenou, jako příprava zdrojové a cílové pozice a dále zpřístupnění bloků s adresami a
nastavení bitmapy. Obsahuje metodu Triple sort pro přesouvání bloků.
hop_sort.c Obsahuje jedinou funkci starající se o přesun bloků pomocí metody Hop sort.
8.1
Vstupní parametry a inicializace
Program definuje 8 přepínačů, které mohou být uživatelem nastaveny. Jeden z nich vyžaduje
argument, a to číslo skupiny cylindrů. Syntaxe příkazu je následující:
udef [-pbsmrih -c ncyl] device
Vstupní parametry:
-c Definuje číslo skupiny cylindrů a požaduje tedy argument. Výchozí hodnota bez použití
parametru je 0.
-p Vypiš informace o blocích na skupině cylindrů a jejich cílové pozice po provedení defragmentace.
-b Vypiš bitmapu bloků na skupině cylindrů.
-s Vypiš pořadí, v jakém budou bloky přesouvány.
-m Namapuj skupinu cylindrů do paměti.
-r Spusť defragmentaci.
-i Jako metodu pro přesun bloků použij Hop sort.
-h Vypiš nápovědu.
8.2. NAMAPOVÁNÍ SKUPINY CYLINDRŮ DO PAMĚTI
Parametr
GLBCGISMMAP
GLBRUNINSEC
41
Popis
Využívá se mapování do paměti.
Použije se metoda Hop sort pro přesun bloků.
Tabulka 8.1: Hodnoty kterých může nabývat proměnná flags ve struktuře GLBVAL.
Po zpracování vstupních parametrů se zavolá funkce open_disk(), pomocí které se
otevře zařízení. Současně se přečte Super-block a uloží do jediné globální proměnné afs.
Následně se načte hlavička skupiny cylindrů a inicializuje se proměnná glb. Proměnná glb je
typu GLBVAL, což je struktura obsahující klíčové informace, které se využívají v jednotlivých
částech programu.
typedef struct {
int
fd;
void
**blockap;
void
**slink;
int
slink_size;
void
memcg;
struct cg *acg;
uint32_t flags;
} GLBVAL;
Položky struktury GLBVAL jsou:
fd File descriptor pro otevřené zařízení.
blockap Pole ukazatelů reprezentuje mapu bloků na aktuální skupině cylindrů.
slink Pole které ukazuje na stejné položky jako blockap, ale ukazatelé jsou v pořadí,
v jakém se budou postupně zpracovávat.
slink_size Velikost pole slink, tzn. počet bloků, které se budou přesouvat.
memcg V případě, že se mapovala celá oblast skupiny cylindrů do paměti, tak obsahuje
ukazatel na začátek této paměti.
flags Obsahuje bitové hodnoty některých parametrů, popsaných v tabulce 8.1.
8.2
Namapování skupiny cylindrů do paměti
Pokud bylo parametrem vynuceno mapovaní skupiny cylindrů do paměti, tak se tak učiní
ve funkci cgmmap(). Samotné mapování se provede pomocí systémové funkce mmap(), která
mimo jiné má jako parametr velikost mapované oblasti. Velikost se musí získat z hlavičky
42
KAPITOLA 8. IMPLEMENTACE
konkrétní skupiny cylindrů, která se načte funkcí read_cgblock_ft(). Součástí namapování
je i volání funkce pre_read(), která vynutí načtení všech bloků z disku do paměti.
Pro přístup k blokům se v případě namapování skupiny cylindrů používají funkce
cgm_read_fs_block() a cgm_write_fs_block(). Zápis bloků, tj. překopírování z paměti,
je uskutečněn pomocí funkce memcpy(). Skutečný zápis z namapované oblasti na disk je
z důvodu optimalizace přenechán na operačním systému, proto tedy nelze zcela přesně určit,
kdy se změněný blok skutečně zapíše.
8.2.1
Paměťové nároky
Paměťové požadavky na namapování celé skupiny cylindrů závisí pouze na velikosti a počtu
bloků. Uvažujeme-li tedy výchozích hodnoty, pak skupina cylindrů obsahuje 12958 bloků,
kde každý blok má velikost 16 kB. K namapování skupiny cylindrů bude tedy zapotřebí 203
MB operační paměti.
8.3
Identifikace bloků
Identifikace bloků, tak jak byla popsána v podkapitole 7.3, se spustí funkcí udefcg(). Ta
obsahuje volání několika dalších funkcí spojených s identifikací bloků. Jedna z prvních funkcí,
která se musí zavolat, je alokace pole ukazatelů reprezentující mapu skupiny cylindrů, tedy
blockap. Ta se provede ve funkci allock_blockap(). Následuje alokace pole ukazatelů
slink, která ukazuje na stejné položky jako blockap, ale již v pořadí, v jakém se budou
postupně přesouvat.
Hlavními funkcemi, které slouží k identifikaci bloků, jsou fill_array(), fill_array_inode()
a fill_array_dbib(). Funkce fill_array() se skládá ze dvou vnořených cyklů, kde vnější
cyklus prochází všechny skupiny cylindrů na disku a vnitřní postupně načítá všechny inody
na skupině cylindrů.
Načtený inode, resp. dinode, se předá funkci fill_array_inode(). Ta má za úkol předat pole s přímými adresami bloků funkci fill_array_dbib(). V případě přímé adresace se
předá jen pole di_db, které je součástí každého dinodu a obsahuje prvních 12, resp. NDADDR
odkazů. První stupeň indirekce předává blok přímých odkazů, který se načte z adresy obsažené v di_ib[0] a obsahuje NINDIRS odkazů. Druhý a třetí stupeň indirekce funguje
na podobném principu, kdy se přes di_ib[1], resp. di_ib[2], postupně načítají bloky
s nepřímými odkazy až do okamžiku, kdy se načte blok s přímými odkazy, který se předá
funkci fill_array_dbib().
Ve funkci fill_array_dbid() se postupně projdou všechny odkazy z předaného bloku
a provede se kontrola, zda-li tyto odkazy ukazují do aktuální skupiny cylindrů. Pokud ano,
tak se vytvoří nová proměnná typu BLOCKARRS a vloží se do pole blockap na pozici, která
koresponduje s umístěním bloku na aktuální skupině cylindrů. Současně se přidá odkaz na
položku do pole slink. Vazba mezi polem slink a blockap je zobrazena na obrázku 8.2.
Pole slink v podstatě reprezentuje frontu a dle toho se i plní. Důvodem, proč bylo pro
reprezentaci fronty zvoleno pole a ne např. spojový seznam, je menší náročnost na paměť.
V případě spojového seznamu bychom museli použít ukazatel na následující prvek, čímž
by se velikost z původního jednoho ukazatele zdvojnásobila. Pokud by následně skupina
8.3. IDENTIFIKACE BLOKŮ
43
cylindrů byla zaplněna více jak z poloviny, což se u fragmentace v celku předpokládá, tak
by potom spojový seznam zabíral více paměti než pole ukazatelů.
Obrázek 8.2: Vazba mezi polem blockap a slink.
typedef struct blockarrs {
ino_t
ino;
uint32_t apindx;
uint32_t blkindx;
uint32_t blkdest;
uint32_t flags;
FRAGARRS *frag;
} BLOCKARRS;
Položky struktury BLOCKARRS jsou:
ino Číslo inodu.
apindx Index, resp. relativní adresa bloku od začátku skupiny cylindrů.
blkindx Index datového bloku. Jedná se o absolutní hodnotu, tedy 0 až N, kde N je celkový
počet bloků patřící inodu.
blkdest Index, resp. relativní adresa cílové pozice. Ta se určí až během řazení bloků.
flags Obsahuje bitové hodnoty některých parametrů, popsaných v tabulce 8.2.
frag Odkaz na spojový seznam obsahující jednotlivé fragmenty.
V případě, že je blok rozdělen do více fragmentů na které ukazují rozdílné inody, tak
se pro jednotlivé další fragmenty využije spojový seznam, kde každá položka je datový typ
FRAGARRS.
44
KAPITOLA 8. IMPLEMENTACE
Parametr
BLCKFREE
BLCKNOMOVE
BLCKLAST
BLCKALONE
Popis
Neobsazený blok.
Nepřesunutelný blok.
Poslední blok inodu.
Blok byl alokován celý, tzn. není fragmentován.
Tabulka 8.2: Hodnoty kterých může nabývat proměnná flags ve struktuře BLOCKARRS.
typedef struct fragarrs {
ino_t
ino;
int8_t
fragoff;
struct fragarrs *frag;
} FRAGARRS;
Položky struktury FRAGARRS jsou:
ino Číslo inodu.
fragoff Umístění fragmentu v bloku.
frag Odkaz na další položku spojového seznamu.
Poslední volaná funkce zabývající se identifikací bloků je fill_array_restblocks().
Ta pro každý ukazatel z blockap, který je NULL, zkontroluje příslušné bity v bitmapě bloků.
Pokud je blok dle bitmapy neobsazený, tak se ponechá v blockap hodnota NULL. Pokud je
dle bitmapy obsazený, tak se alokuje nová položka a vloží se do blockap. Současně se její
proměnná flags nastaví na hodnotu BLCKNOMOVE a z bloku se stane nepřesunutelný blok.
8.3.1
Paměťové nároky
Když již známe všechny struktury a datové typy, které budou použity k identifikaci bloků
na skupině cylindrů, tak můžeme vypočítat potřebné paměťové nároky, a to pomocí vzorce
8.1.
blockap_mem = (blks ∗ ps) + (blks − hs) ∗ ss
(8.1)
Vysvětlivky:
blks Počet bloků na skupině cylindrů, resp. velikost pole blockap.
blkh Počet bloků které zabírá hlavička skupiny cylindrů.
ps Velikost ukazatele v bytech na konkrétní architektuře.
ss Velikost jedné položky pole blockap v bytech.
Pokud budeme uvažovat 64 bitovou architekturu, kde je velikost ukazatele do paměti
8 bytů a současně bloky nejsou dále dělené na fragmenty, tak budeme potřebovat 449 KB
operační paměti.
8.4. SEŘAZENÍ BLOKŮ
8.4
45
Seřazení bloků
Seřazení bloků v našem kontextu znamená určení cílové pozice pro každý přesunutelný blok.
Seřazení se provádí ve funkci valid_blocks_order() a její hlavní náplní je přiřadit každému
bloku, resp. položce, v poli blockap cílovou pozici. Pozice se ukládá do proměnné blkdest.
Princip určení cílové pozice je vysvětlen pomocí obrázku 8.3. Nejprve se zvolí dvě ukazovátka do polí. Do pole slink ukazovátko spos a do pole blockap ukazovátko apindx.
Ukazovátko spos ukazuje na první prvek pole slink a apindx na pozici v blockap, která
reprezentuje počátek datové oblasti. Poté se v cyklu postupně inkrementuje spos, a tím se
prochází pole slink. V cyklu se pro každou přesunutelnou položku z pole slink na pozici
spos zkontroluje, zda-li je položka z pole blockap na pozici apindx také přesunutelná nebo
neobsazená. Pokud tomu tak je, tak se z pozice na kterou ukazuje apindx, stane cílová pozice
pro blok, resp. položku, na kterou ukazuje spos. Pokud tomu tak není, tak se inkrementuje
apindx a spos zůstane pro následující iteraci nezměněn.
Obrázek 8.3: Určení cílové pozice bloku.
8.5
Výpis informací
Součástí programu je i stručný výpis vybraných informací. Lze vypsat některé parametry
z hlavičky na konkrétní skupině cylindrů pomocí funkce print_cgblock(). Informace o inodech a informace o umístění datových bloků se vypisují pomocí funkcí print_inodes()
a print_inodes_ib(). Dále je zde výpis pole blockap funkcí print_blockap(), který zobrazí aktuální pozici bloku, cílovou pozici, číslo inodu a index bloku. Funkce print_slink()
vypíše pole slink a přepínačem lze také vynutit vypsání bitmapy bloků, které se provádí
ve funkci print_bmap().
46
KAPITOLA 8. IMPLEMENTACE
8.6
Přístup k datům
Funkce pro přístup k datům lze rozdělit na tři skupiny, kde každá skupina obsahuje vždy
čtecí a zapisovací funkci.
1. Přístup k hlavičce skupiny cylindrů. Funkcemi jsou reat_cgblock(), read_cgblock_ft()
a write_cgblock().
2. Přístup k inodům. Funkcemi jsou read_inodes_block() a write_inodes_block().
3. Přístup k blokům. Funkcemi jsou read_fs_block() a write_fs_block().
Jelikož jsou data uložená po blocích a po blocích se jak načítají, tak i ukládají, tak na
nejnižší úrovni jsou vždy volány funkce pro přístup k blokům. První dvě skupiny tedy slouží
jen jako mezistupeň, jak je vidět na obrázku 8.4. Funkce vyšší vrstvy z předaných parametrů
vypočítají konkrétní adresu bloku a ten je dále dle potřeby načten či uložen pomocí funkcí
přistupujících k blokům. V následujících dvou podkapitolách si popíšeme postup, jak se
přistupuje k blokům, ať už s namapovanou či nenamapovanou skupinou cylindrů.
Obrázek 8.4: Model funkcí pro přístup k datům.
8.6.1
Přímý přístup k blokům
V případě, že nemáme namapovanou skupinu cylindrů do paměti, tak je situace poměrně
snadná. Uvažujeme-li např. čtení bloku, tak se zavolá funkce read_fs_block() a jako
parametry jsou jí předány číslo boku a úložiště, kam se blok načte. Číslo bloku se poté
převede na konkrétní adresu a pomocí systémové funkce pread() se načte požadovaný blok.
8.6.2
Přístup k blokům s namapovanou skupinou cylindrů
V případě, že je skupina cylindrů namapovaná do paměti, tak se situace nepatrně změní.
Budeme-li opět uvažovat čtení bloku, tak se nejprve zavolá funkce read_fs_block(). Ta
pomocí funkce is_blockinmem() rozhodne, zda se požadovaný blok nachází v namapované
oblasti či ne. To je nutné z toho důvodu, že ačkoliv je skupina cylindrů namapovaná do
8.7. PŘESUN BLOKŮ
47
paměti, tak zde stále mohou být požadavky na bloky, které se nacházejí na jiné skupině,
tedy nenamapované. Jedná se o bloky s inody či bloky s nepřímými adresami.
Pokud se blok nenachází v namapované oblasti, tak se pokračuje obdobně, jak bylo
popsáno v 8.6.1. V případě, že se nachází v namapované oblasti, tak se zavolá funkce
cgm_read_fs_block() a předají se jí stejné parametry, jako funkci read_fs_block(). Jedním z parametrů je úložiště, kam se blok načítá. Oním úložištěm je konkrétněji ukazatel na
ukazatel ukazující na úložiště. Ve funkci cgm_read_fs_block() se již jen přepočítá adresa
bloku na adresu do namapované oblasti a změní se ukazatel předaný parametrem. Ten bude
ukazovat na požadovaný blok v namapované oblasti.
Pseudokód:
char *buf;
char st_buf[SIZE];
buf = st_buf;
read_fs_block(..., &buf, ...);
/* dále již používám buf bez ohledu na to, do jaké části paměti ukazuje */
Výhody které z tohoto postupu plynou jsou ty, že pro načítání bloků se stále volá
jedna funkce, a to read_fs_block(). Po návratu z funkce se používá předávaný ukazatel na úložiště stále stejným způsobem, nehledě na to, do jaké paměti ukazuje. Není potřeba
kopírovat blok do jiného úložiště pomocí memcpy(), když se již v paměti nachází, tj. v namapované oblasti.
Na podobném principu funguje i zápis bloků, kde se blok buď pomocí systémové funkce
pwrite() zapíše na disk, nebo pomocí memcpy() překopíruje do namapované oblasti.
8.7
Přesun bloků
Pro přesuny bloků jsou implementovány dvě rozdílné metody, které jsem nazval Triple sort a
Hop sort. Obě metody mohou přesouvat bloky s využitím, či bez využití namapování skupiny
cylindrů. Metodu Triple sort lze považovat za bezpečnou z hlediska konzistence dat při
neočekávaném ukončení programu. To platí ovšem jen v případě, že není použito namapování
skupiny cylindrů do paměti, viz podkapitola . Přesouvání bloků je implementováno jen pro
bloky, které jsou v poli blockap označeny jako BLCKALONE. Nepřesouvají se tedy např.
nepřímé bloky s adresami či fragmentované bloky.
Metody se postupně volají z funkce sortcg(), která postupně prochází pole slink a pro
každý blok, který se ještě nenachází na cílové pozici, zavolá příslušnou metodu.
8.7.1
Vyhledání volného bloku
V případě metody Triple sort je potřeba před spuštěním přesunů vyhledat jeden volný blok.
Ten bude sloužit jako dočasné úložiště přesouvaného bloku a musí se nacházet na jiné než
aktuální skupině cylindrů. Vyhledání volného bloku má na starosti funkce find_freeblk(),
která postupně prochází okolní skupiny cylindrů. Nejprve vždy vybere nejbližší předchozí
48
KAPITOLA 8. IMPLEMENTACE
Parametr
SWPDB
SWPIB
ZERODESTINO
Popis
Blok je adresován přímo.
Blok je adresován nepřímo.
Blok cílové pozice je neobsazený.
Tabulka 8.3: Hodnoty kterých může nabývat proměnná flags ve struktuře SWPDATA.
skupinu cylindrů a při neúspěchu vybere nejbližší následující. Ve funkci find_freeblk_cg()
se poté z bitmapy bloků vyhledá volný blok.
8.7.2
Příprava přesouvaných bloků
Při přesunech bloků je vždy jeden z bloků považován za zdrojový, tj. src, a druhý za cílový, tj.
dest. Zdrojový blok src se vždy přesouvá na pozici dest. Pro snadnější předávání parametrů
mezi funkcemi jsou k oběma blokům vytvořeny proměnné typu SWPDATA. Jména proměnných
jsou swpsrc a swpdest, či pokud pracujeme jen s jednou proměnnou ve funkci, tak jen swp.
typedef struct swpdata {
ino_t
ino;
uint32_t apindx;
uint32_t blkindx;
void
*buf;
uint32_t addr;
uint8_t
flags;
} SWPDATA;
ino Číslo inodu.
apindx Index do blockap, resp. relativní adresa bloku od začátku skupiny cylindrů.
blkindx Index datového bloku. Index je relativní k bloku s adresami. V případě nepřímé
adresace je to tedy index do pole buf.
buf Ukazatel na úložiště. Pokud je blok adresován pomocí přímé adresace, tak je v úložišti
blok s inody. Z tohoto bloku se nejprve musí získat konkrétní dinode, a ten již obsahuje
přímé odkazy na datové bloky v položce di_db. Pokud je blok adresován nepřímo, tak
obsahuje blok uchovávající adresy.
addr Pokud je blok adresován nepřímo, tak obsahuje adresu bloku, který je uložen v buf.
U přímé adresace není adresa bloku nutná, jelikož jí snadno získáme z čísla inodu.
flags Může nabývat některých bitových hodnot, popsaných v tabulce 8.3.
Položky blkindx, buf a addr jsou potřebné z toho důvodu, že kromě samotného přesunu
bloku se musí modifikovat i odkaz na tento blok.
Jednotlivé položky v proměnné swpsrc se nastaví ve funkci prepare_swp_src() a v
prepare_swp(). Hodnoty pro swpdest se nastaví v prepare_swp_dest() a prepare_swp().
8.7. PŘESUN BLOKŮ
49
Ve funkci prepare_swp_dest() se kromě nastavení hodnot musí provést kontrola zdrojového a cílového bloku, jelikož mohou nastat dvě situace, které je nutno ošetřit.
• Oba bloky jsou adresovány pomocí přímé adresace a inody jsou uloženy ve stejném
bloku.
• Bloky jsou adresovány pomocí nepřímé adresace, ale současně se jedná o bloky jednoho
inodu a adresy sdílí společný blok.
Pokud jedna z možností nastane, tak musíme změnit ukazatel swpdest.buftak, aby
ukazoval na stejnou oblast jako swpsrc.buf. Pokud by k tomu nedošlo, tak by swpsrc.buf
i swpdest.buf obsahovaly stejné kopie bloků, ale provedené změny v nich by se navzájem
neprojevily. To by vedlo k tomu, že např. při ukládání změněné swpdest.buf paměti bychom
přemazali změny, které byly provedeny v swpsrc.buf.
8.7.3
Triple sort
Jedná se o implementaci algoritmu, popsaného v podkapitole 7.7.3. Algoritmus je definován
ve funkci triple_sort() a skládá ze dvou fází. V první fázi se vždy zdrojový blok přesune
na cílovou pozici. V druhé fázi se blok z cílové pozice stane zdrojovým a přesune se na
svou cílovou pozici. V následujícím textu budeme pro přehlednost uvádět jen src nebo dest,
ale jsou tím myšleny jednak bloky, ale současně i pomocné proměnné, jako např swpsrc a
swpdest.
Triple sort algoritmus:
1. Načti a nastav příslušné src proměnné.
2. Načti a nastav příslušné dest proměnné.
3. Zavolej funkci swap_dest_p1(), a poté swap_src_p1().
4. Pokud je dest na cílové pozici, či dest byl prázdný, tak ukonči cyklus.
5. Nastav dest na src.
6. Načti a nastav příslušné nové dest proměnné.
7. Zavolej funkci swap_dest_p2(), a poté swap_src_p2().
8. Pokud není dest na cílové pozici, tak nastav dest na src a pokračuj v bodě 2.
Funkce swap_dest_p1() má za úkol přesunout blok z pozice A1, viz. obrázek 8.5, přičemž
mohou nastat následující situace:
• Pozice A1 je neobsazená. V tom případě nastav v bitmapě pozici A1 za obsazenou,
jelikož se na ní bude přesouvat src blok.
• Pozice B1 je neobsazená. Nastav v bitmapě pozici B1 na obsazenou a přesuň do ní
dest blok.
50
KAPITOLA 8. IMPLEMENTACE
Obrázek 8.5: Přesun bloků metodou Triple sort.
• Pokud nenastane žádná z výše uvedených situací, tak přesuň dest do D1.
Funkce swap_src_p1() přesune src blok. Cílová pozice je vždy volná. Pokud byl dest
přesunut na svou cílovou pozici, či byl neobsazený, tak se ukončí cyklus a zapíše se bitmapa.
Před uložením bitmapy se ještě musí nastavit v bitmapě pozice C1 na neobsazenou.
Pokud nebyl cyklus ukončen a vstupuje se do druhé fáze, tak se z dest stane src a určí se
nová dest. Ve funkci swap_dest_p2() přesouvá blok z pozice B2. Při přesunu mohou nastat
následující situace:
• Pozice B2 je neobsazená. To mohlo nastat pouze v případě, že v první fázi byla pozice
B1 totožná s C1.
• Pozice E2 je neobsazená. V bitmapě se nastaví pozice E2 na obsazenou a přesune se
blok.
• Pozice E2 je neobsazená, ale současně je E2 totožná s C2. Přesune se pouze blok,
jelikož bitmapa je již nastavená.
Ve funkci swap_src_p2() se přesouvá blok z pozice D2 na pozici B2, která musí byt
v tomto kroku již neobsazená.
Pokud je nyní dest na cílové pozici, či byl prázdný, tak se cyklus ukončí a pomocí funkce
write_cgblock() se zapíše bitmapa. V opačném případě se z dest stane src a pokračuje se
v další iteraci, která v algoritmu začíná bodem 2.
8.8. UVOLNĚNÍ PROSTŘEDKŮ
8.7.4
51
Hop sort
Hop sort je upravený algoritmus popsaný v podkapitole 7.7.2, který se nachází ve funkci
hop_sort(). Jediný rozdíl oproti algoritmu z analýzy je ten, že v bodě 4 nedochází k výměně
bloků, ale místo toho se uloží jen zdrojový blok. Blok z cílové pozice se uloží až v následující
iteraci, kdy se z něj stane blok zdrojový.
Hop sort algoritmus:
1. Nastav proměnnou swpsrc.
2. Načti příslušný src blok do paměti, odeber src položku z pole blockap a nastav pozici
bloku v bitmapě na neobsazeno.
3. Nastav proměnnou swpdest.
(a) Pokud swpdest nemá flag ZERODESTINO, tak načti příslušný dest blok do paměti
a odeber dest položku z pole blockap.
4. Ulož src blok na novou pozici.
5. Vlož src položku do pole blockap.
6. Pokud swpdest nemá flag ZERODESTINO, tak pokračuj v bodě 3 s tím, že všechny dest
proměnné se stanou src.
7. Nastav dest pozici bloku v bitmapě na obsazenou.
8. Ulož bitmapu.
V bodě 2 je potřeba nastavit bitmapa z toho důvodu, že v daný okamžik není jasné,
jestli se na danou pozici bude přesouvat jiný blok, či jestli zůstane neobsazená. V bodě 7 se
nastavuje bitmapa, jelikož cílová pozice byla neobsazena, a proto se ukončil cyklus. Bitmapa
se ukládá jen jednou po ukončení cyklu.
Z algoritmu je patrné, že se každý blok načte a uloží jen jedenkrát.
8.8
Uvolnění prostředků
K uvolnění operační paměti slouží funkce free_blockap(), free_blockapitem()
a free_blockapfrag(), které uvolní prostředky spojené s polem blockap. Funkce free_slink()
uvolní paměť spojenou s polem slink.
Ve funkci cgm_unmap() se zavolá funkce munmap(), která slouží k odmapování souboru
z paměti. Ještě před tím se zavolá funkce msync(), která zapíše všechny změněné bloky.
52
KAPITOLA 8. IMPLEMENTACE
Kapitola 9
Testování funkčnosti
Testování hrálo během vývoje důležitou roli, jelikož v případě chyby, nehrozí jen pád aplikace, ale ve většině případů i ztráta dat. To, jaké množství souborů může být ztraceno,
záleží na mnoha faktorech, ale především na tom, jestli skupina cylindrů byla či nebyla
mapována do paměti. V případě pádů aplikace s namapovanou skupinou cylindrů může dojít ke ztrátě v oblastech, které nebyly ještě zapsány na disk. Ty se samozřejmě nemusejí
týkat jen jednoho souboru.
9.1
Testování defragmentace
Úkolem je zjistit, jestli program defragmentuje správně. Nekontrolují se obsahy jednotlivých
souborů, ale to, jak jsou bloky na disku seřazeny. První test se provede pomocí systémového
nástroje fsck_ffs. Ten ověří, zda-li se na disku nachází správný počet bloků a jestli je
správně nastavena bitmapa bloků. Poté zkontroluje adresy na bloky, a to pro každý inode
na souborovém systému. Ověří případnou duplicitu bloků, pokud by inody ukazovaly na
stejné bloky. U inodů se dále ověří, jestli jejich velikosti korespondují s počtem bloků.
Další test je již pomocí programu udef. Pomocí přepínače se zvolí požadovaná skupina
cylindrů a vypíší se bloky, jenž se na ní nacházejí. Z výpisu je již patrné, jestli jsou bloky
v požadovaném pořadí. V případě fragmentace volného místa, lze pro větší přehlednost
využít i výpis bitmapy bloků.
Pro ověření defragmentace souboru je také možné využít např. nástroj filestat6 . Ten
pro konkrétní inode vypíše na kterých adresách, resp. skupinách cylindrů, se jeho fragmenty
nacházejí a jejich velikosti.
9.2
Testování konzistence dat
Mnohem důležitějším testem je test na konzistenci dat. To znamená, že již neověřujeme
kde jsou data uložená a v jakém pořadí, ale to, jestli se obsahy bloků nezměnily. Asi nejjednodušším způsobem jak to provést je pro každý soubor vypočítat kontrolní součet. Test
6
Program vznikl v průběhu psaní této diplomové práce a je volně ke stažení na
http://code.google.com/p/filestat/. Inspirací mu byl stejnojmenný nástroj pro operační systém Solaris na
architektuře Sparc.
53
54
KAPITOLA 9. TESTOVÁNÍ FUNKČNOSTI
byl tedy prováděn tak, že se před spuštěním defragmentace pro všechny soubory na disku
spočetla hash pomocí algoritmu MD5 a uložila se do souboru. Po skončení defragmentace se
provedlo totéž a pokud se soubory navzájem nelišily, tak byly soubory na disku nezměněny.
9.3
Velikost diskového oddílu
Velikost diskového oddílu, na kterém byly testy prováděny není pro samotné testování
markantní, jelikož defragmentace probíhá vždy v rámci skupiny cylindrů. Podstatné pro
testy bylo, aby se do testování zahrnulo několik skupin cylindrů a mohlo se např. otestovat řazení bloků, jejichž inode či bloky s nepřímými adresami, se nachází na jiné skupině
cylindrů.
9.4
Testovaná data
V rámci testování bylo podstatné mít co nejvíce různorodý obsah souborového systému a
tím pokrýt většinu možných případů, které mohou nastat v reálných systémech. Současně
bylo nutné vytvořit uměle fragmentaci. To bylo z důvodu, že každý test se prováděl na
právě naformátovaném souborovém systému a pouhé překopírování souborů by fragmentaci
nevytvořilo, či ne alespoň fragmentaci takovou, k jaké dochází během stárnutí souborového
systému [9]. Z toho důvodu byly soubory generovány. Při vytváření generovaných dat se
uvažovalo několik případů:
• Obecné generování. Probíhalo tak, že se pomocí skriptu vytvořilo několik souborů.
Počet souborů byl dle potřeby v řádech stovek až tisíců. Ty se poté v různém pořadí
zvětšovaly o určitý počet bloků, a tím docházelo k jejich fragmentaci.
• Testování fragmentace volného místa. Provádělo se tak, že se vygeneroval větší počet
menších fragmentovaných souborů. Několik souborů se poté smazalo, čímž vznikla
fragmentace volného místa.
• Větší soubor na více skupinách cylindrů. K tomu stačilo pouze generovat menší počet
dostatečně velkých souborů.
9.5
Testovací nástroje
Pro usnadnění testování byly vytvořeny dva nástroje fragfile.sh a autofrag.sh. Oba
nástroje jsou vytvořeny pomocí skriptovacího jazyka BASH. První z nich slouží ke generování fragmentovaných souborů. Hlavní parametry nástroje fragfile.sh je počet souborů,
který se má generovat a počet repetic. V každé repetici se všechny soubory postupně zvětší
o požadovanou velikost, což de facto znamená, že každá repetice vytvoří samostatný fragment.
Nástroj autograg.sh obsahuje několik rozdílných testů. Každý test se skládá v podstatě
z několika volaní fragfile.sh s rozdílnými parametry.
Oba nástroje fragfile.sh a autofrag.sh jsou v dodatku B a C.
Kapitola 10
Měření
V první části této kapitoly popíšeme několik testů, které byly provedeny za účelem změření
času potřebného k odstranění fragmentace. Jedná se tedy o měření rychlosti programu.
Čas potřebný k defragmentaci byl měřen na vygenerovaných datech v rámci jedné skupiny
cylindrů, kde vygenerovaná data reprezentovala mezní případy, které mohou na souborovém
systému nastat.
Důvodem proč stačí provést měření jen na jedné skupině cylindrů je to, že se měření
provádí na mezních případech. Proto odstranění fragmentace na každé jiné skupině cylindrů
bude vyžadovat stejný nebo menší počet přesunů bloků, a tedy i stejný nebo kratší čás
potřebný k defragmentaci.
Fragmentace se odstraňovala pomocí obou metod, které program podporuje, tz. pomocí
metody Triple sort 8.7.3 a Hop sort 8.7.4, a to s použitím i bez použití mapování skupiny
cylindrů do paměti.
Měření časů se zajistilo pomocí funkce gettimeofday(), která se zavolala na začátku a
na konci funkce main().
V druhé části této kapitoly si ukážeme zrychlení souborového systému po provedení
defragmentace.
Příklady, jak se data generovala, lze najít v nástroji autofrag.sh v dodatku C.
10.1
Měření 1
V rámci tohoto měření bylo vygenerováno 1050 souborů, kde každý byl o velikosti 192 kB, tj.
12 bloků. K vygenerování souborů se použil nástroj fragfile.sh. Fragmentace se zajistila tak,
že se nejprve vytvořilo 1050 souborů o velikosti jednoho bloku. Poté se každý soubor zvětšil
o jeden blok a takto se zvětšovaly až do velikosti 12 bloků. Naměřené časy jsou v tabulce
10.1.
10.2
Měření 2
Bylo vytvořeno 850 souborů o velikosti 224 kB, tj. 14 bloků. Soubory byly vytvořeny pomocí
nástroje fragfile.sh podobným způsobem, jako v předchozím případě. Jelikož jsou soubory
55
56
KAPITOLA 10. MĚŘENÍ
Metoda
Triple sort
Hop sort
Triple sort s -m
Hop sort s -m
Čas [s]
196.911
166.558
117.952
115.910
Tabulka 10.1: Naměřené hodnoty při defragmentaci 1050 souborů.
Metoda
Triple sort
Hop sort
Triple sort s -m
Hop sort s -m
Čas [s]
192.198
161.459
124.439
122.758
Tabulka 10.2: Naměřené hodnoty při defragmentaci 850 souborů.
větší jak 12 bloků, tak ke každému souboru, resp. inodu, přísluší i jeden blok s adresami.
Všechny bloky jsou uloženy na stejné skupině cylindrů. Naměřené časy jsou v tabulce 10.2.
10.3
Měření 3
V tomto měření se provádělo řazení bloků, které byly adresovány nepřímo. Toho stavu se
dosáhlo tak, že se nejprve vytvořilo 850 souborů o velikosti 224 kB, viz. předchozí případ.
Tím se zaplnila celá jedna skupina cylindrů. Následně se opět všechny soubory zvětšily o 14
bloků. Jelikož na první skupině cylindrů již nebylo místo, tak se bloky začaly ukládat na
druhou skupinu cylindrů. Porovnáním tohoto a předchozího měření, u kterého se defragmentuje stejný počet bloků, je patrné, jak se negativně projeví nepřímá adresace na čase
defragmentace. Naměřené časy jsou v tabulce 10.3.
10.4
Zrychlení souborového systému po defragmentaci
V této podkapitole budeme zkoumat zrychlení souborového systému po provedení defragmentace. Měření probíhalo tím způsobem, že se na souborovém systému vygenerovaly dva
Metoda
Triple sort
Hop sort
Triple sort s -m
Hop sort s -m
Čas [s]
253.140436
210.380257
172.599169
143.696910
Tabulka 10.3: Naměřené hodnoty při defragmentaci bloků, které jsou adresovány nepřímo.
10.4. ZRYCHLENÍ SOUBOROVÉHO SYSTÉMU PO DEFRAGMENTACI
57
fragmentované soubory a na jednom z nich se měřila rychlost čtení. Čtení souboru se zajistilo pomocí nástroje cat a md5. Konkrétně příkaz cat byl spouštěn následovně: time cat
soubor > /dev/null. Celkem se desetkrát změřily časy pomocí nástroje time a poté se
vypočítal jejich průměr. Před každým měřením byl souborový systém odpojen a byl přečten
300 MB soubor. Tím se minimalizoval vliv vyrovnávacích pamětí operačního systému.
Soubory byly generovány pomocí nástroje fragfile.sh, kde jedním z parametrů byla velikost fragmentu. Pro měření byly zvoleny fragmenty o velikosti 1 bloku, 64 bloků, tj. 1
MB a pro větší soubory 640 bloků, tj. 10 MB. Velikost posledního fragmentu byla zvolena
s ohledem na velikosti fragmentů souborového systému. Empiricky bylo zjištěno, že velikost
fragmentu na souborovém systému je cca 60 MB. Po překročení této velikosti je fragment
rozdělen a další bloky se již ukládají na jinou skupinu cylindrů. Defragmentace souboru
většího než 60 MB má tedy smysl pouze tehdy, pokud jsou jeho fragmenty menší než 60
MB.
Velikost souborového systému byla 5 GB, ačkoliv podstatnější pro testy bylo to, že generované soubory nebyly během vytváření limitovány nedostatkem místa.
Celkem se měření provádělo na 5 souborech o velikostech 10 MB, 20 MB, 80 MB, 160
MB a 300 MB. Výsledky měření jsou v tabulce 10.4.
58
KAPITOLA 10. MĚŘENÍ
Velikost souboru [MB]
Velikost fragmentu [blok]
1
10
64
Po defragmentaci
1
20
64
Po defragmentaci
1
80
64
640
Po defragmentaci
1
160
64
640
Po defragmentaci
1
300
64
640
Po defragmentaci
Typ čtení
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
md5
cat
Čas [s]
0.535
0.540
0.335
0.353
0.308
0.308
1.032
1.055
0.701
0.705
0.563
0.536
4.188
4.203
2.713
2.667
2.187
2.205
2.132
2.158
8.398
8.410
5.501
5.306
4.320
4.312
4.218
4.255
15.711
15.664
10.329
10.019
8.126
8.083
7.866
7.907
Tabulka 10.4: Rychlost čtení souborů v závislosti na velikostech fragmentů.
Kapitola 11
Závěr
Závěrečná kapitola obsahuje shrnutí hlavních bodů této práce.
11.1
Fragmentace souborových systémů
Součástí této práce bylo nastudovat a popsat problematiku fragmentace a také to, jak se jí
moderní souborové systémy snaží předcházet. Fragmentace obecně byla popsána v kapitole
4 a popis metod, které se používají k předcházení fragmentace, v kapitole 6. Nicméně na
základě těchto dvou kapitol jsem došel k závěru, že ani v moderních souborových systémech
nelze fragmentaci zabránit. Důvodem je i to, že většina metod popisovaných v kapitole
6 neslouží primárně k zabránění fragmentace jako takové, ale spíše k zlepšení výkonnosti
souborového sytému. Současně, pokud vezmeme v úvahu některé situace popsané v kapitole
4, které mohou nastat, tak bez následných přesunů bloků se fragmentaci zabránit nedá.
11.2
Vlastní implementace
Výsledkem této práce je nástroj na odstranění fragmentace, který byl řádně otestován a lze
jej považovat za funkční. Jelikož pro souborový systém UFS neexistuje žádná jiná podobná
aplikace, tak nelze výsledek práce s ničím jiným porovnat. Již to, že neexistuje žádný jiný
nástroj na odstranění fragmentace, považuji za úspěch. Nicméně jsem si vědom toho, že se
nalezne mnoho míst, které by bylo možné vylepšit. Při vývoji jsem se především zaměřoval
na paměťové nároky celé aplikace, které pokud pomineme mapování skupiny cylindrů do
paměti, jsou na dnešní poměry vcelku minimální, viz. podkapitola 8.3.1. Dále byl kladen
velký důraz na to, aby po spuštění defragmentace nehrozilo žádné riziko ztráty dat, pokud by
byla aplikace náhle ukončena. Tomuto kritériu vyhovuje metoda Triple sort. V neposlední
řadě zde byla snaha na minimalizaci přístupů na disk, což se podařilo pomocí mapování
skupiny cylindrů do paměti, ačkoliv to současně znamená potenciální riziko ztráty dat v případě náhlého ukončení aplikace.
Za velmi přínosné považuji osobně také to, že jsem se podrobně seznámil s implementací
souborového systému UFS, který je popsán v kapitole 3.
59
60
KAPITOLA 11. ZÁVĚR
11.2.1
Potenciální vylepšení
• Od počátku vývoje se počítalo s vícevláknovou variantou a větší část aplikace je tomu
přizpůsobena. Nicméně po prvních testech bylo patrné, že vícevláknová varianta by
nepřinesla výrazné zlepšení výkonu, jelikož většinu času aplikaci zaberou diskové operace.
• Vylepšení, které by mohlo zlepšit výkon, by bylo použití vyrovnávacích pamětí pro již
jednou načtené bloky.
• Výpočet cílové pozice pro jednotlivé bloky by se mohl provádět na základě pozic ostatních bloků, resp. fragmentů.
• Implementovat přesuny všech bloků, tj. např. i bloky obsahující nepřímé adresy.
• V neposlední řadě by zlepšení výkonu bylo možné dosáhnout pomocí přesunů více
bloků najednou.
11.3
Výsledky defragmentace
Z výsledku, které byly naměřeny a nacházejí se v tabulce 10.4 je patrné, že po defragmentaci
vždy dojde k zrychlení při čtení souboru. U souborů, jejichž fragmenty jsou 10 MB, což
je u fragmentovaného souborového systému vcelku reálné, se zrychlení po defragmentaci
pohybuje mezi 2-3%. Otázkou ovšem vždy zůstává, do jaké míry budou data v souborových
systémech fragmentována, aby se vyplatilo spouštět defragmentaci.
Literatura
[1] CLEMENTS, A. Principles of computer hardware. Oxford University Press, 4th edition,
2006.
[2] NIJS, G. et al. The Effects of Filesystem Fragmentation. Proceedings of the Linux
Symposium. 2006.
[3] HARIZOPOULOS, S. Hierarchical Caching and Prefetching for Improving the Performance of Continuous Media Servers. 1998.
[4] LEFFLER, S. J. The Design and implementation of the 4.3 BSD Unix operating system.
Addison-Wesley Publishing Company, 1990.
[5] MARSHALL KIRK MCKUSICK, S. J. L. R. S. F. W. N. J. A Fast File System for
UNIX. 1984.
[6] MCDOUGALL – RICHARD. Solaris internals : Solaris 10 and OpenSolaris kernel
architecture. Prentice Hall, 2nd edition, 2007.
[7] MESSMER, H.-P. The indispensable PC hardware book. Addison-Wesley Publishing
Company, 4th edition, 2002.
[8] Přispěvatelé Wikipedie. BSD licence [online]. [cit. 29. 7. 2010]. Dostupné z: <http:
//cs.wikipedia.org/wiki/BSD_licence>.
[9] SMITH, K. A. – SELTZER, M. I. File System Aging — Increasing the Relevance of
File System Benchmarks. Proceedings of the Linux Symposium. 1997.
[10] SMITH, K. A. – SELTZER, M. I. File Layout and File System Performance.
[11] V, A. K. K. et al. Ext4 block and inode allocator improvements. Proceedings of the
Linux Symposium. 2008.
61
62
LITERATURA
Dodatek A
Seznam použitých zkratek
ANSI American National Standards Institute
ATA Advanced Technology Attachment
BASH Bourne Again Shell
BSD Berkeley Software Distribution
CG Cylinder Group
CVS Concurrent Version System
EXT Extended File System
FS File System
HDD Hard Disk Drive
INODE Index Node
PATA Parallel ATA
SSD Solid State Drive
SSH Secure Shell
UFS Unix File System
USB Universal Serial Bus
ZFS Zettabyte File System
63
64
DODATEK A. SEZNAM POUŽITÝCH ZKRATEK
Dodatek B
Nástroj fragfile.sh
Nástroj fragfile.sh generuje fragmentované soubory. Generovat soubory může buď pomocí
nástroje dd a čtení ze zařízení /dev/urandom či pomocí předgenerovaných souborů.
#!/usr/local/bin/bash
if [ "$1" = "-h" ]; then
echo "Usage: $0 filecount repeated name file"
echo "filecount - # of files, only with rand"
echo "repeated - # of repetition"
echo "name - filename"
echo "dirname - dir of copyed files"
exit 1
fi
if [ $# -lt 3 ]; then
echo "Usage: $0 filecount repeated name [size rand | dirsrc dirdest]"
exit 1
fi
START=1
FCOUNT=$1
REPEATED=$2
NAME=$3
RAND=""
RNDCOUNT=20
DIRSRC=""
DIRDEST=""
if [ "$5" = "rand" ]; then
65
66
DODATEK B. NÁSTROJ FRAGFILE.SH
SIZE=$4
RAND=$5
elif [ "$4" = "big" ]; then
DIRSRC="_big"
DIRDEST=$5
elif [ "$4" = "small" ]; then
DIRSRC="_small"
DIRDEST=$5
elif [ "$4" = "normal" ]; then
DIRDEST="$5"
elif [ "$4" != "" ]; then
DIRSRC="_$4"
fi
if [ "$DIRDEST" != "" ]; then
mkdir /home/filedisk/$DIRDEST
fi
RNDFILES="/home/tomas/Diplomka/udefrag/scripts/genfiles$DIRSRC/gen_"
#RNDFILES=‘dirname $0‘/genfiles_big/gen_
#RNDFILES=‘dirname $0‘/genfiles_small/gen_
while [ $START -le $REPEATED ]
do
FI=1
while [ $FI -le $FCOUNT ]
do
if [ "$RAND" = "" ]; then
cat $RNDFILES$((RANDOM%RNDCOUNT)) >> /home/filedisk/$DIRDEST/$NAME$FI
else
dd if=/dev/urandom of=/tmp/frag bs=$SIZE count=1
cat /tmp/frag >> /home/filedisk/$NAME$FI
fi
FI=‘expr $FI + 1‘
done
START=‘expr $START + 1‘
done
Dodatek C
Nástroj autofrag.sh
Nástroj autofrag.sh obsahuje řadu testů, které byly vykonány, ale také nastavení pro generování souborů, pro které se měřila rychlost defragmentace.
#!/usr/local/bin/bash
DEV=""
mount $DEV /home/filedisk
rm -rf /home/filedisk/*
if [ "$1" == "test1" ]; then
./fragfile.sh 2 20 a_ big
./fragfile.sh 50 20 b_
./fragfile.sh 2 20 a_ big
./fragfile.sh 50 20 c_
./fragfile.sh 10 20 d_ big
./fragfile.sh 50 20 b_
./fragfile.sh 10 20 e_ big
./fragfile.sh 50 20 b_
./fragfile.sh 2 20 a_ big
rm /home/filedisk/b_{5,10,15,20,25}
rm /home/filedisk/c_{5,10,15,20,25}
elif [ "$1" == "test2" ]; then
./fragfile.sh 5 5000 a_
elif [ "$1" == "test3" ]; then
./fragfile.sh 9 20 a_ big
./fragfile.sh 2 20 a_ big
67
68
DODATEK C. NÁSTROJ AUTOFRAG.SH
elif [ "$1" == "test4" ]; then
./fragfile.sh 9 20 a_ big
./fragfile.sh 2 20 b_ big
elif [ "$1" == "test5" ]; then
./fragfile.sh 2 300 a_ big
elif [ "$1" == "test6" ]; then
./fragfile.sh 100 20 a_
./fragfile.sh 100 20 b_
./fragfile.sh 100 20 c_
./fragfile.sh 90 20 a_
./fragfile.sh 90 20 b_
./fragfile.sh 90 20 c_
elif [ "$1" == "test7" ]; then
./fragfile.sh 3 10 a_ small
./fragfile.sh 3 1 b_ small
elif [ "$1" == "test8" ]; then
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
./fragfile.sh 30 50 a_ normal
dir1
dir2
dir3
dir4
dir5
dir6
dir7
elif [ "$1" == "mereni1" ]; then
./fragfile.sh 1050 12 a_
elif [ "$1" == "mereni2" ]; then
./fragfile.sh 850 14 a_
elif [ "$1" == "mereni3" ]; then
./fragfile.sh 850 14 a_
./fragfile.sh 850 14 a_
elif [ "$1" == "zrychleni" ]; then
# 10m
./fragfile.sh 2 640 a_
#./fragfile.sh 2 10 a_ big
# 20m
#./fragfile.sh 2 1280 a_
#./fragfile.sh 2 20 a_ big
69
# 80m
#./fragfile.sh 2 5120 a_
#./fragfile.sh 2 80 a_ big
#./fragfile.sh 2 8 a_ 640b
# 160m
#./fragfile.sh 2 10240 a_
#./fragfile.sh 2 160 a_ big
#./fragfile.sh 2 16 a_ 640b
# 300m
#./fragfile.sh 2 19200 a_
#./fragfile.sh 2 300 a_ big
#./fragfile.sh 2 30 a_ 640b
else
./fragfile.sh 3 10 a_ big
./fragfile.sh 2 12 a_
fi
echo ======================================
md5 /home/filedisk/*
echo ======================================
umount /home/filedisk
70
DODATEK C. NÁSTROJ AUTOFRAG.SH
Dodatek D
Ukázka programu
Souborový systém obsahuje 5 souborů. Každý soubor je o velikosti 5 bloků a fragmentován
je po 1 bloku.
=== Super block ===
SBLOCK=16
DEV_BSIZE=512
ADR #8192
id=4d1a88fcbaecaab8
magic: 00011954
rps=60
fs_bsize=16384
fs_sblkno=8
fs_cblkno=16
fs_iblkno=24
fs_dblkno=1648
ncg = 6, fpg = 103664 ipg = 25984
fs_fragshift = 3
NINDIR = 4096
cgsblock: 8
fsbtodb: 32
inodes at: 96
data at: 6592
<--- Hlavička souborového systému.
=== Cylinder group ===
Cylinder: 0
cgbase 0
cgdmin 1648
cgimin 24
cgsblock 8
cgtod 16
cgstart 0
cgsize=16384
<--- Hlavička na skupině cylindrů.
71
72
DODATEK D. UKÁZKA PROGRAMU
cg_magic: 0x90255
cg_niblk: 25984
cg_ndblk: 103664
cg_iusedoff 174 (#89088)
rotor 1856 irotor 7 frotor 1856
cgimin: 24
csum free block: 12725 inodes: 25976 frags: 14
inodes used:0-7
blks free: 1649-1655, 1657-1663, 1864-103663
=== Inodes ===
2) Adr 24 di_size:
512 di_nlink:
di_db[0] 1656 (#3391488)
db: 1656
3) Adr 24 di_size:
81920 di_nlink:
di_db[0] 1664 (#3407872)
di_db[1] 1704 (#3489792)
di_db[2] 1744 (#3571712)
di_db[3] 1784 (#3653632)
di_db[4] 1824 (#3735552)
db: 1664, 1704, 1744, 1784,
4) Adr 24 di_size:
81920 di_nlink:
di_db[0] 1672 (#3424256)
di_db[1] 1712 (#3506176)
di_db[2] 1752 (#3588096)
di_db[3] 1792 (#3670016)
di_db[4] 1832 (#3751936)
db: 1672, 1712, 1752, 1792,
5) Adr 24 di_size:
81920 di_nlink:
di_db[0] 1680 (#3440640)
di_db[1] 1720 (#3522560)
di_db[2] 1760 (#3604480)
di_db[3] 1800 (#3686400)
di_db[4] 1840 (#3768320)
db: 1680, 1720, 1760, 1800,
6) Adr 24 di_size:
81920 di_nlink:
di_db[0] 1688 (#3457024)
di_db[1] 1728 (#3538944)
di_db[2] 1768 (#3620864)
di_db[3] 1808 (#3702784)
di_db[4] 1848 (#3784704)
db: 1688, 1728, 1768, 1808,
7) Adr 24 di_size:
81920 di_nlink:
di_db[0] 1696 (#3473408)
di_db[1] 1736 (#3555328)
di_db[2] 1776 (#3637248)
<--- Výpis jednotlivých inodů.
2 di_blocks: 4
1 di_blocks: 160
1824
1 di_blocks: 160
1832
1 di_blocks: 160
1840
1 di_blocks: 160
1848
1 di_blocks: 160
73
di_db[3] 1816 (#3719168)
di_db[4] 1856 (#3801088)
db: 1696, 1736, 1776, 1816, 1856
[
0][
0] block
0: 0 (0)
[
1][
0] block
8: 0 (0)
...
<--- Zde se nachází samé 0.
[ 206][
0] block 1648: 0 (0)
[ 207][ 207] block 1656: 2 (0)
<--- Root souborového systému.
[ 208][ 208] block 1664: 3 (0)
[ 209][ 212] block 1672: 4 (0)
[ 210][ 216] block 1680: 5 (0)
[ 211][ 220] block 1688: 6 (0)
[ 212][ 224] block 1696: 7 (0)
[ 213][ 209] block 1704: 3 (1)
[ 214][ 213] block 1712: 4 (1)
[ 215][ 217] block 1720: 5 (1)
[ 216][ 221] block 1728: 6 (1)
[ 217][ 225] block 1736: 7 (1)
[ 218][ 210] block 1744: 3 (2)
[ 219][ 214] block 1752: 4 (2)
[ 220][ 218] block 1760: 5 (2)
[ 221][ 222] block 1768: 6 (2)
[ 222][ 226] block 1776: 7 (2)
[ 223][ 211] block 1784: 3 (3)
[ 224][ 215] block 1792: 4 (3)
[ 225][ 219] block 1800: 5 (3)
[ 226][ 223] block 1808: 6 (3)
[ 227][ 227] block 1816: 7 (3)
[ 228][ 228] block 1824: 3 (4)
[ 229][ 229] block 1832: 4 (4)
[ 230][ 230] block 1840: 5 (4)
[ 231][ 231] block 1848: 6 (4)
[ 232][ 232] block 1856: 7 (4)
^
^
^
^ ^
|
|
|
| |
|
|
|
| +--- Číslo bloku konkrétního inodu.
|
|
|
+------ Číslo inodu.
|
|
+---------- Číslo fs bloku relativně k~CG.
|
+---------------------- Cílová pozice v~poli blockap.
+---------------------------- Aktuální pozice v~poli blockap.
74
DODATEK D. UKÁZKA PROGRAMU
Dodatek E
BSD licence
Překlad licence BSD:1
c
Copyright <ROK>,
<VLASTNÍK PRÁV>. Všechna práva vyhrazena.
Redistribuce a použití zdrojových i binárních forem díla, v původním i upravovaném tvaru,
jsou povoleny za následujících podmínek:
• Šířený zdrojový kód musí obsahovat výše uvedenou informaci o copyrightu, tento seznam podmínek a níže uvedené zřeknutí se odpovědnosti.
• Šířený binární tvar musí nést výše uvedenou informaci o copyrightu, tento seznam
podmínek a níže uvedené zřeknutí se odpovědnosti ve své dokumentaci a/nebo dalších
poskytovaných materiálech.
• Ani jméno vlastníka práv, ani jména přispěvatelů nemohou být použita při podpoře nebo právních aktech souvisejících s produkty odvozenými z tohoto software
bez výslovného písemného povolení.
TENTO SOFTWARE JE POSKYTOVÁN DRŽITELEM LICENCE A JEHO PŘISPĚVATELI „JAK STOJÍ A LEŽÍ“ A JAKÉKOLIV VÝSLOVNÉ NEBO PŘEDPOKLÁDANÉ
ZÁRUKY VČETNĚ, ALE NEJEN, PŘEDPOKLÁDANÝCH OBCHODNÍCH ZÁRUK A ZÁRUKY VHODNOSTI PRO JAKÝKOLIV ÚČEL JSOU POPŘENY. DRŽITEL, ANI PŘISPĚVATELÉ NEBUDOU V ŽÁDNÉM PŘÍPADĚ ODPOVĚDNI ZA JAKÉKOLIV PŘÍMÉ,
NEPŘÍMÉ, NÁHODNÉ, ZVLÁŠTNÍ, PŘÍKLADNÉ NEBO VYPLÝVAJÍCÍ ŠKODY (VČETNĚ, ALE NEJEN, ŠKOD VZNIKLÝCH NARUŠENÍM DODÁVEK ZBOŽÍ NEBO SLUŽEB;
ZTRÁTOU POUŽITELNOSTI, DAT NEBO ZISKŮ; NEBO PŘERUŠENÍM OBCHODNÍ
ČINNOSTI) JAKKOLIV ZPŮSOBENÉ NA ZÁKLADĚ JAKÉKOLIV TEORIE O ZODPOVĚDNOSTI, AŤ UŽ PLYNOUCÍ Z JINÉHO SMLUVNÍHO VZTAHU, URČITÉ ZODPOVĚDNOSTI NEBO PŘEČINU (VČETNĚ NEDBALOSTI) NA JAKÉMKOLIV ZPŮSOBU POUŽITÍ TOHOTO SOFTWARE, I V PŘÍPADĚ, ŽE DRŽITEL PRÁV BYL UPOZORNĚN NA MOŽNOST TAKOVÝCH ŠKOD.
1
Překlad licence byl převzat z [8].
75
76
DODATEK E. BSD LICENCE
Dodatek F
Obsah přiloženého CD
.
|-|-|-|-|-|-|-|-|-|
|
|
|
|
|
|-|-|-|-|-|-|-‘--
Diplomka
Makefile
cgmmap.c
cgmmap.h
hop_sort.c
hop_sort.h
io.c
io.h
scripts
|-- autofrag.sh
|-- fragfile.sh
|-- genfiles
|-- genfiles_640b
|-- genfiles_big
‘-- genfiles_small
sortcg.c
sortcg.h
udef.c
udef.h
udef_stat.c
udef_stat.h
udefcg.c
udefcg.h
Každý adresář genfiles obsahuje 20 souborů s náhodným obsahem. Soubory se jmenují
gen_0 až gen_19 a používají se ke generování náhodných souborů v nástroji fragfile.sh.
Adresář Diplomka obsahuje diplomovou práci.
77