Na tomto cvičení pridáte do súborového systému xv6 podporu veľkých súborov a symbolických odkazov.
Predtým, než sa pustíte do písania kódu, prečítajte si kapitolu 8 File system z xv6 knižky a preštudujte si príslušný kód.
Vo svojom repozitári sa prepnite do vetvy fs:
1 2 3 |
$ git fetch $ git switch fs # alebo git checkout fs $ make clean |
Riešenia úloh z tohto cvičenia ukladajte do vetvy fs. Túto vetvu budeme kontrolovať v rámci priebežnej kontroly repozitárov. Viac informácií k hodnoteniu repozitárov nájdete na príslušnej stránke.
V prvej časti cvičenia zvýšite maximálnu podporovanú veľkosť súboru v xv6. Veľkosť súborov v xv6 je aktuálne obmedzená na 268 blokov, teda 268*BSIZE
bajtov (BSIZE
je v xv6 definovaný na 1024). Tento limit je spôsobený tým, že inode v xv6 obsahuje 12 priamych blokových čísel a jedno nepriame blokové číslo, ktoré odkazuje na blok, ktorý obsahuje ďalších 256 blokových čísel, čo je spolu 12+256=268 blokov.
Program bigfile vytvorí súbor s maximálnou možnou veľkosťou a túto veľkosť vypíše:
1 2 3 4 5 |
$ bigfile .. wrote 268 blocks bigfile: file is too small $ |
Test očakáva, že môže zapisovať súbory až do veľkosti 65803 blokov. Najväčší súbor, ktorý je možné vytvoriť v neupravenej xv6 má 268 blokov a preto test zlyhá.
Súborový systém musíte zmeniť tak, aby podporoval dvojito nepriame bloky v každom inode, pričom každý bude obsahovať 256 adries nepriamych blokov, a tie budú obsahovať 256 adries dátových blokov. Celkovo teda bude možné ukladať súbory o veľkosti až 256*256+256+11 blokov (11 namiesto 12, lebo jeden blok sme obetovali na priame čísla blokov dvojito nepriameho bloku).
Program mkfs vytvára súborový systém xv6 a určuje celkový počet blokov súborového systému; táto veľkosť je určená konštantou FSSIZE
v súbore kernel/param.h. Jej hodnota pre tento lab je 200 000 blokov. Vo výstupe make si môžete všimnúť tento riadok:
1 |
nmeta 70 (boot, super, log blocks 30 inode blocks 13, bitmap blocks 25) blocks 199930 total 200000 |
Tento riadok popisuje súborový systém, ktorý program mkfs/mkfs vytvoril: má 70 metadátových blokov (bloky, ktoré popisujú samotný súborový systém) a 199 930 dátových blokov, čo je spolu 200 000blokov.
Ak by ste potrebovali obnoviť stav súborového systému, použite make clean, ktorý obnoví fs.img do pôvodného stavu.
Formát diskového inodu je definovaný v struct dinode
v súbore fs.h. Najviac vás budú zaujímať položky NDIRECT
, NINDIRECT
, MAXFILE
, a addrs[]
štruktúry struct dinode
. Pozrite si tiež obrázok 8.3 z xv6 knižky, v ktorom je zobrazený štandardný inode z xv6.
Kód, ktorý hľadá dáta súboru na disku je vo funkcii bmap()
v fs.c. Prezrite si ju, aby ste pochopili, čo robí. bmap()
je volaná pri čítaní aj zápise do súboru. Počas zápisu bmap()
alokuje dostatočný počet nových blokov podľa potreby, aby sa do nich zmestil obsah súboru a zároveň alokuje nepriamy blok, ak je potrebný na uloženie adries blokov.
bmap()
pracuje s dvoma druhmi čísel blokov. Argument bn
je „logické číslo bloku“ – číslo bloku v súbore relatívne k začiatku súboru. Čísla blokov v ip->addrs[]
a argument bread()
sú čísla blokov na disku. Funkcia bmap()
teda mapuje logické čísla blokov súborov na čísla blokov na disku.
bmap()
, aby implementoval „dvojito nepriame“ bloky spolu s priamymi a nepriamymi blokmi. Musíte použiť iba 11 priamych blokov namiesto 12, aby ste tam zmestili nový „dvojito nepriamy“ blok; nemôžete zmeniť veľkosť inodu na disku. Prvých 11 položiek ip->addrs[]
by mali byť priame bloky; dvanásta bude nepriamy blok (podobne ako doteraz); trinásty bude nový dvojito nepriamy blok. Úloha je hotová, keď bigfile zapíše 65803 blokov a usertesty zbehnú úspešne:
1 2 3 4 5 6 7 8 |
$ bigfile .................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................. wrote 65803 blocks done; ok $ usertests ... ALL TESTS PASSED $ |
bigfile je časovo náročný test, vyhraďte si minimálne minútu a pol na jeho zbehnutie.
Pomôcky:
bmap()
. Zakreslite diagram vzťahov medzi ip->addrs[]
, nepriamym blokom, dvojito nepriamym blokom a nepriamymi blokmi na ktoré ukazuje; a dátovými blokmi. Mali by ste rozumieť tomu, prečo pridanie dvojito nepriameho bloku zväčší maximálnu veľkosť súboru o 256*256 blokov (v skutočnosti o jeden menej, pretože prídete o jeden priamy blok).NDIRECT
, pravdepodobne budete musieť zmeniť deklaráciu addrs[]
v struct inode
v súbore file.h. Presvedčte sa, že struct inode
a struct dinode
majú rovnaký počet položiek vo svojich poliach addrs[]
.NDIRECT
, nezabudnite vytvoriť nový fs.img, pretože mkfs používa konštantu NDIRECT
na zostavenie súborového systému.bread()
pomocou brelse()
.bmap()
.Po úspešnom dokončení úlohy nezabudnite vytvoriť commit!
V druhej časti cvičenia pridáte do xv6 podporu symbolických odkazov. Symbolické odkazy (známe aj ako mäkké odkazy) odkazujú na súbor jeho cestou; keď otvoríte symbolický odkaz, jadro vás nasmeruje na odkazovaný súbor. Symbolické odkazu sú veľmi podobné pevným odkazom. Rozdiel spočíva v tom, že pevné odkazy môžu ukazovať len na súbor, ktorý sa nachádza na tom istom disku (ukazujú na konkrétny inode), zatiaľ čo symbolické odkazy môžu ukazovať na iné diskové zariadenie. Aj keď xv6 nepodporuje viaceré zariadenia, implementácia tohto systémového volania vám umožní lepšie pochopiť ako funguje vyhľadávanie cesty.
Implementujte nové systémové volanie symlink(char *target, char *path)
, ktoré vytvorí nový symbolický odkaz na path, ktorý bude ukazovať na súbor target. Pre viac informácií si pozrite manuálovú stránku funkcie symlink. Na otestovanie pridajte do Makefile program symlinktest a spustite ho. Implementáciu máte korektnú, ak majú testy takýto výstup (vrátane úspechu usertests:
1 2 3 4 5 6 7 8 9 |
$ symlinktest Start: test symlinks test symlinks: ok Start: test concurrent symlinks test concurrent symlinks: ok $ usertests ... ALL TESTS PASSED $ |
Pomôcky:
symlink
, pridajte záznam do user/usys.pl, user/user.h, a definujte prázdnu funkciu sys_symlink()
v súbore kernel/sysfile.c.T_SYMLINK
) do kernel/stat.h, ktorý bude reprezentovať symbolický odkaz.O_NOFOLLOW
) do kernel/fcntl.h, ktorý môže byť použitý v systémovom volaní open
. Všimnite si, že príznaky, ktoré používa open
sa dajú kombinovať pomocou bitového operátora OR, takže váš nový príkaz by nemal prekrývať existujúce príznaky. Po tejto úprave bude možné skompilovať user/symlinktest.c, keď ho pridáte do Makefile.symlink(target, path)
, ktoré vytvorí nový symbolický odkaz umiestnený na path
, ktorý bude ukazovať na súbor target
. Na úspešné vytvorenie odkazu nemusí cieľ existovať. Cestu k cieľu musíte niekde uložiť, napríklad do dátových blokov inodu. Návratová hodnota systémového volania symlink
je v prípade úspechu nulová, v opačnom prípade -1 (podobne ako link
a unlink
).open
, aby správne obslúžilo situáciu, kedy meno súboru ukazuje na symbolický odkaz. Ak súbor neexistuje, open
musí zlyhať. Keď proces nastaví príznak O_NOFOLLOW
vo volaní open
, open
by mal otvoriť priamo symbolický odkaz (nie súbor, na ktorý symbolický odkaz ukazuje).Spustite príkaz make grade, aby ste overili správnosť svojho riešenia. Po úspešnom dokončení úlohy nezabudnite vytvoriť commit! Aby ste prešli posledným testom time, musíte vytvoriť nový súbor time.txt, v ktorom uvediete počet hodín, ktorý ste strávili nad zadaním ako celé číslo. Na záver aj túto zmenu commitnite do repozitára. Týmto je cvičenie ukončené.
Pridajte podporu pre trojito nepriame bloky.
Ďakujeme vyučujúcim predmetu CSEP551 (jeseň 2019) na Univerzite vo Washingtone za cvičenie so symbolickým odkazom.