Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so2:laboratoare:lab08:exercitii [2017/04/10 16:48]
octavian.purdila
so2:laboratoare:lab08:exercitii [2018/04/18 09:36] (current)
ionel.ghita [5. [0.5p] Înregistrare și deînregistrare sistem de fișiere minfs]
Line 1: Line 1:
 ====== Laborator 8: Exerciții ====== ====== Laborator 8: Exerciții ======
  
-Pentru desfășurarea laboratorului ​pornim ​de la [[http://​elf.cs.pub.ro/so2/res/laboratoare/lab08-tasks.zip|arhiva ​de sarcini a laboratorului]]. Descărcăși decomprimăm arhiva în directorul ''​so2/'' ​din directorul home al utilizatorului ''​student''​ de pe sistemul de bază (stația ''​mjolnir''​):<code bash> +===== Pregătirea laboratorului ===== 
-student@mjolnir:​~$ cd so2/ + 
-student@mjolnir:​~/​so2$ wget http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab08-tasks.zip +Pentru rezolvarea laboratorului,​ vom lucra în același director din care pornim ​mașina virtuală (''​~/so2/linux/tools/labs''​). 
-student@mjolnir:​~/​so2$ unzip lab08-tasks.zip + 
-student@mjolnir:​~/​so2tree lab08-tasks+Pașii ​de rezolvare sunt următorii: 
 +  * pregătirea scheletului de laborator 
 +  * compilarea modulelor de Kernel 
 +  * copierea modulelor pe mașina virtuală 
 +  * pornirea mașinii virtuale ​și testarea modulelor 
 + 
 +==== Pregătirea scheletului de laborator ==== 
 + 
 +Scheletul de laborator este generat din sursele din directorul ''​tools/labs/​templates''​. Putem genera scheletele pentru toate laboratoarele folosind următoarea comanda: 
 + 
 +<code bash> 
 +tools/labs make skels
 </​code>​ </​code>​
-În cadrul directorului ''​lab08-tasks/''​ se găsesc resursele necesare pentru dezvoltarea exercițiilor de mai jos: fișiere schelet de cod sursă, fișiere Makefile și Kbuild, scripturi și programe de test. 
  
-Vom dezvolta exercițiile pe sistemul ​de bază (stația ​''​mjolnir''​) și apoi le vom testa pe [[:so2:​resurse:​masini-virtuale|mașina virtuală QEMU]]. După editarea și compilarea unui modul de kernel îl vom copia în directorul dedicat pentru mașina virtuală QEMU folosind o comandă de forma<code bash> +Pentru a genera scheletul pentru un singur laborator, vom folosi variabila ​de mediu ''​LABS'':​ 
-student@mjolnir:​~/so2cp /​path/​to/​module.ko ~/​so2/​qemu-so2/​fsimg/​root/​modules/​ + 
-</code> unde ''/​path/​to/​module.ko''​ este calea către fișierul obiect aferent modulului de kernel. Apoi vom porni, din directorul ''​~/​so2/​qemu-so2/''​ mașina virtuală QEMU folosind comanda<code bash> +<code bash> 
-student@mjolnir:​~/​so2/​qemu-so2$ ​make+tools/labs make clean 
 +tools/labs $ LABS=<lab name> make skels
 </​code>​ </​code>​
  
-După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU pentru a încărca și descărca modulul de kernel:<code+<note important
-# insmod modules/​module-name.ko +Numele laboratorului curent este ''​filesystems''​
-# rmmod module/module-name +</note> 
-</codeunde ''​module-name'' ​este numele modulului de kernel.+ 
 +Similar, putem genera și scheletul pentru un singur exercițiu, atribuind valoarea ''​<lab_name>​/<​task_name>'' ​variabilei ''​LABS''​.
  
 <​note>​ <​note>​
-Pentru dezvoltarea laboratorului, ​este recomandat să folosim trei terminale sau, mai bine, trei tab-uri de terminal. Pentru a deschide un nou tab de terminal folosim combinația de taste ''​Ctrl+Alt+t''​. ​Cele trei tab-uri de terminal îndeplinesc următoarele roluri: +Scheletul ​este generat în directorul ​''​tools/​labs/​skels''​. 
-  - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtaulă QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului. +</​note>​ 
-  - În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/​descărcare modul, rulare teste. Lucrăm în directorul ​aferent mașinii virtuale: ​''​~/​so2/​qemu-so2/​''​. + 
-  - În al treilea tab de terminal pornim [[:​so2:​laboratoare:​lab02#​minicom|minicom]] sau un server UDP care să primească [[:​so2:​laboratoare:​lab02#​netconsole|mesajele de netconsole]]. Nu contează în ce director ne aflăm. Folosim comanda<code bash> +==== Compilarea modulelor ==== 
-student@mjolnir:~$ netcat ​-lup 6666+ 
 +Comanda ''​make build''​ compilează toate modulele din directorul ''​skels''​. 
 + 
 +<code bash> 
 +student@eg106:~/​so2/​linux/​tools/​labsmake build 
 +echo "# autogenerated,​ do not edit " > skels/​Kbuild 
 +echo "​ccflags-y += -Wno-unused-function -Wno-unused-label -Wno-unused-variable " >> skels/​Kbuild 
 +for i in ./​filesystems/​minfs/​kernel ./​filesystems/​myfs;​ do echo "obj-m += $i/" >> skels/​Kbuild;​ done
 </​code>​ </​code>​
 +
 +==== Copierea modulelor pe mașina virtuală ====
 +
 +Putem copia modulele generate pe mașina virtuală folosind target-ul ''​copy''​ al comenzii make, atunci când mașina virtuală este oprită.
 +
 +<code bash>
 +student@eg106:​~/​so2/​linux/​tools/​labs$ make copy
 +student@eg106:​~/​so2/​linux/​tools/​labs$ make boot
 +</​code>​
 +
 +Alternativ, putem copia fișierele prin ''​scp'',​ pentru e evita repornirea mașinii virtuale. Pentru detalii despre folosirea interacțiunea prin rețea cu mașina virtuală citiți [[https://​ocw.cs.pub.ro/​courses/​so2/​resurse/​masini-virtuale#​interactiunea_cu_masina_virtuala|Interacțiunea cu mașina virtuală]].
 +
 +==== Testarea modulelor ====
 +
 +Modulele generate sunt copiate pe mașina virtuală în directorul ''/​home/​root/​skels/<​lab_name>''​.
 +
 +<code bash>
 +root@qemux86:​~/​skels/​filesystems#​ ls
 +minfs  myfs
 +root@qemux86:​~/​skels/​filesystems#​ ls myfs/
 +myfs.ko ​      ​test-myfs.sh
 +</​code>​
 +
 +După pornirea mașinii virtuale QEMU vom putea folosi comenzi în fereastra QEMU (sau în ''​minicom''​) pentru a încărca și descărca modulul de kernel:<​code>​
 +root@qemux86:​~#​ insmod skels/<​lab_name>/<​task_name>/<​module_name>​.ko ​
 +root@qemux86:​~#​ rmmod skels/<​lab_name>/<​task_name>/<​module_name>​.ko ​
 +</​code> ​
 +
 +<​note>​
 +Pentru dezvoltarea laboratorului,​ este recomandat să folosim trei terminale sau, mai bine, trei tab-uri de terminal. Pentru a deschide un nou tab de terminal folosim combinația de taste ''​Ctrl+Shift+t''​. Cele trei tab-uri de terminal îndeplinesc următoarele roluri:
 +  - În primul tab de terminal dezvoltăm modulul de kernel: editare, compilare, copiere în directorul dedicat pentru mașina virtuală QEMU. Lucrăm în directorul aferent rezultat în urma decomprimării arhivei de sarcini a laboratorului.
 +  - În al doilea tab de terminal pornim mașina virtuală QEMU și apoi testăm modulul de kernel: încărcare/​descărcare modul, rulare teste. Lucrăm în directorul aferent mașinii virtuale: ''​~/​so2/​linux/​tools/​labs''​.
 +  - În al treilea tab de terminal accesăm directorul ''​~/​so2/​linux/''​ cu sursele nucleului unde putem folosi [[:​so2:​laboratoare:​lab01#​cscope|Vim și cscope]] pentru parcurgerea codului sursă.
 +student@eg106-pc:​~$ netcat -lup 6666
 +</​code>​
 +
 +Pentru buna desfășurare a laboratorului recomandăm să aveți deschise trei tab-uri de browser:
 +  - În primul tab să fie deschis [[:​so2:​laboratoare:​lab08|breviarul laboratorului]].
 +  - În al doilea tab să fie deschisă [[:​so2:​laboratoare:​lab08:​exercitii|pagina curentă]].
 +  - În al treilea tab să fie deschisă [[https://​elixir.bootlin.com/​linux/​v4.15/​source|pagina LXR]] pentru parcurgerea codului sursă din nucleu.
 +
 +</​note>​
 +
 +<note warning>
 +Citiți cu atenție toate precizările unui exercițiu înainte de a începe rezolvarea acestuia.
 +</​note>​
 +
 +<note important>​
 +Înainte de începerea rezolvării laboratorului,​ rulați comanda ''​%%git pull --rebase%%''​ in directorul ''​~/​so2/​linux'',​ pentru a obține ultima versiune a scheletului de laborator.
 </​note>​ </​note>​
  
Line 33: Line 101:
 Pentru început ne propunem să ne acomodăm cu interfața expusă de nucleul Linux și de componenta VFS (//Virtual File System//). De aceea, pentru început vom lucra cu un sistem de fișiere simplu, virtual (adică fără suport fizic pe disc). Sistemul de fișiere poartă denumirea ''​myfs''​. Pentru început ne propunem să ne acomodăm cu interfața expusă de nucleul Linux și de componenta VFS (//Virtual File System//). De aceea, pentru început vom lucra cu un sistem de fișiere simplu, virtual (adică fără suport fizic pe disc). Sistemul de fișiere poartă denumirea ''​myfs''​.
  
-Pentru aceasta vom accesa subdirectorul ''​myfs/''​ din [[http://​elf.cs.pub.ro/​so2/​res/​laboratoare/​lab08-tasks.zip|arhiva ​de sarcini a laboratorului]]. Vom implementa în cadrul acestui laborator operațiile pe superbloc, iar [[:​so2:​laboratoare:​lab09|laboratorul viitor]] vom continua cu operațiile pe inode.+Pentru aceasta vom accesa subdirectorul ''​myfs/''​ din scheletul ​de laborator. Vom implementa în cadrul acestui laborator operațiile pe superbloc, iar [[:​so2:​laboratoare:​lab09|laboratorul viitor]] vom continua cu operațiile pe inode.
  
 ==== 1. [1.5p] Înregistrare și deînregistrare sistem de fișiere myfs ==== ==== 1. [1.5p] Înregistrare și deînregistrare sistem de fișiere myfs ====
Line 42: Line 110:
  
 <note tip> <note tip>
-În cadrul structurii de sistem de fișiere, pentru completarea superbloculului (efectuată la montare) folosiți funcția ''​myfs_mount'',​ prezentă în scheletul de cod. În cadrul funcției ''​myfs_mount''​ apelați funcția specifică unui sistem de fișiere fără suport pe disc (vedeți secțiunea [[:​so2:​laboratoare:​lab08#​functiile_mount_kill_sb|Funcțiile mount, kill_sb]]; este vorba de funcția [[http://lxr.free-electrons.com/​source/​fs/​super.c?v=4.9#L1110|mount_nodev]]). Ca argument pentru funcția de mount specifică folosiți funcția de tipul [[:​so2:​laboratoare:​lab08#​functia_fill_super|funcția fill_super]] definită în scheletul de cod.+În cadrul structurii de sistem de fișiere, pentru completarea superbloculului (efectuată la montare) folosiți funcția ''​myfs_mount'',​ prezentă în scheletul de cod. În cadrul funcției ''​myfs_mount''​ apelați funcția specifică unui sistem de fișiere fără suport pe disc (vedeți secțiunea [[:​so2:​laboratoare:​lab08#​functiile_mount_kill_sb|Funcțiile mount, kill_sb]]; este vorba de funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​super.c#​L1155|mount_nodev]]). Ca argument pentru funcția de mount specifică folosiți funcția de tipul [[:​so2:​laboratoare:​lab08#​functia_fill_super|funcția fill_super]] definită în scheletul de cod.
  
-Pentru distrugerea superblocului (efectuată la demontare) folosiți funcția [[http://lxr.free-electrons.com/​source/​fs/​super.c?v=4.9#L948|kill_litter_super]],​ funcție specifică, de asemenea, unui sistem de fișiere fără suport pe disc.+Pentru distrugerea superblocului (efectuată la demontare) folosiți funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​super.c#​L997|kill_litter_super]],​ funcție specifică, de asemenea, unui sistem de fișiere fără suport pe disc.
 </​note>​ </​note>​
  
-După completarea secțiunilor marcate cu ''​TODO 1'',​ compilați modulul, copiați-l ​în directorul dedicat pentru ​mașina virtuală QEMU și porniți mașina virtuală. Încărcați modulul în kernel și apoi verificați prezența sistemului de fișiere ''​myfs''​ în cadrul fișierului ''/​proc/​filesystems''​.+După completarea secțiunilor marcate cu ''​TODO 1'',​ compilați modulul, copiați-l ​pe mașina virtuală QEMU și porniți mașina virtuală. Încărcați modulul în kernel și apoi verificați prezența sistemului de fișiere ''​myfs''​ în cadrul fișierului ''/​proc/​filesystems''​.
  
 Pe moment sistemul de fișiere este doar înregistrat,​ nu expune operații de utilizare a acestuia. Dacă încercăm să-l montăm, operația va eșua. Pentru a încerca montarea, creăm punctul de montare ''/​mnt/​myfs/''<​code>​ Pe moment sistemul de fișiere este doar înregistrat,​ nu expune operații de utilizare a acestuia. Dacă încercăm să-l montăm, operația va eșua. Pentru a încerca montarea, creăm punctul de montare ''/​mnt/​myfs/''<​code>​
Line 85: Line 153:
 Inode-ul rădăcină este inode-ul aferent directorului rădăcină al sistemului de fișiere (adică ''/''​). Inițializarea sa se face la montare. Funcția ''​myfs_fill_super'',​ apelată la montare, este cea care apelează funcția ''​myfs_get_inode''​ care creează și inițializează un inode. În mod obișnuit, funcția este folosită pentru crearea și inițializarea tuturor inode-urilor;​ în acest exercițiu, însă, vom crea doar inode-ul rădăcină. Inode-ul rădăcină este inode-ul aferent directorului rădăcină al sistemului de fișiere (adică ''/''​). Inițializarea sa se face la montare. Funcția ''​myfs_fill_super'',​ apelată la montare, este cea care apelează funcția ''​myfs_get_inode''​ care creează și inițializează un inode. În mod obișnuit, funcția este folosită pentru crearea și inițializarea tuturor inode-urilor;​ în acest exercițiu, însă, vom crea doar inode-ul rădăcină.
  
-[[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L604 | Inode-ul]] este alocat în cadrul funcției ''​myfs_get_inode''​. Este vorba de variabila locală ''​inode'',​ alocată cu ajutorul apelului [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L900|new_inode]].+[[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L570 | Inode-ul]] este alocat în cadrul funcției ''​myfs_get_inode''​. Este vorba de variabila locală ''​inode'',​ alocată cu ajutorul apelului [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L901|new_inode]].
  
-Pentru a definitiva cu succes montarea sistemului de fișiere, va trebui să completați funcția ''​myfs_get_inode''​. Urmăriți indicațiile marcate cu ''​TODO 3''​. Un punct de plecare este funcția [[http://lxr.free-electrons.com/​source/​fs/​ramfs/​inode.c?v=4.9#L53|ramfs_get_inode]].+Pentru a definitiva cu succes montarea sistemului de fișiere, va trebui să completați funcția ''​myfs_get_inode''​. Urmăriți indicațiile marcate cu ''​TODO 3''​. Un punct de plecare este funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​ramfs/​inode.c#​L61|ramfs_get_inode]].
  
 <note tip> <note tip>
-Pentru inițializarea ''​uid'',​ ''​gid'',​ ''​mode'',​ puteți folosi funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L1993|inode_init_owner]] așa cum este folosită și în funcția [[http://lxr.free-electrons.com/​source/​fs/​ramfs/​inode.c?v=4.9#L53|ramfs_get_inode]]. Când apelați funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L1999|inode_init_owner]] folosiți ''​NULL''​ ca al doilea parametru, întrucât nu există director părinte pentru inode-ul creat.+Pentru inițializarea ''​uid'',​ ''​gid'',​ ''​mode'',​ puteți folosi funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L1997|inode_init_owner]] așa cum este folosită și în funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​ramfs/​inode.c#​L61|ramfs_get_inode]]. Când apelați funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L1997|inode_init_owner]] folosiți ''​NULL''​ ca al doilea parametru, întrucât nu există director părinte pentru inode-ul creat.
  
-Inițializați câmpurile ''​i_atime'',​ ''​i_ctime''​ și ''​i_mtime''​ ale inode-ului VFS la valoarea [[http://lxr.free-electrons.com/​source/​include/linux/time.h?v=4.9#L154|CURRENT_TIME]].+Inițializați câmpurile ''​i_atime'',​ ''​i_ctime''​ și ''​i_mtime''​ ale inode-ului VFS la valoarea ​întoarsă de funcția ​[[https://elixir.bootlin.com/linux/v4.9/​source/​fs/​inode.c#L2104|current_time]].
  
 Va trebui să inițializați operațiile pentru inode-ul de tip director. Pentru aceasta urmați pașii: Va trebui să inițializați operațiile pentru inode-ul de tip director. Pentru aceasta urmați pașii:
-  - Verificați dacă este vorba de inode de tip director folosind macro-ul [[http://lxr.free-electrons.com/​source/​include/​uapi/​linux/​stat.h?v=4.9#L21|S_ISDIR]].+  - Verificați dacă este vorba de inode de tip director folosind macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​uapi/​linux/​stat.h#​L23|S_ISDIR]].
   - Pentru câmpurile, ''​i_op''​ și ''​i_fop'',​ folosiți funcţii din kernel deja implementate:​   - Pentru câmpurile, ''​i_op''​ și ''​i_fop'',​ folosiți funcţii din kernel deja implementate:​
-    * pentru ''​i_op'':​ [[http://lxr.free-electrons.com/​source/​fs/​libfs.c?v=4.9#L226| simple_dir_inode_operations]]. +    * pentru ''​i_op'':​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​libfs.c#​L227| simple_dir_inode_operations]]. 
-    * pentru ''​i_fop'':​ [[http://lxr.free-electrons.com/​source/​fs/​libfs.c?v=4.9#L216|simple_dir_operations]] +    * pentru ''​i_fop'':​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​libfs.c#​L217|simple_dir_operations]] 
-  - Incrementați numărul de link-uri pentru director folosind funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L336|inc_nlink]].+  - Incrementați numărul de link-uri pentru director folosind funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L330|inc_nlink]].
 </​note>​ </​note>​
  
Line 134: Line 202:
 ./​test-myfs.sh ./​test-myfs.sh
 </​code>​ </​code>​
-Statisticile afişate pentru sistemul de fişiere sunt minimale, întrucât informaţiile sunt furnizate de către funcţia [[http://lxr.free-electrons.com/​source/​fs/​libfs.c?v=4.9#L33 | simple_statfs]]. ​+Scriptul este copiat pe mașina virtuală folosind comanda ''​make copy''​ doar dacă este executabil:​ 
 +<code bash> 
 +student@workstation:​~/​so2/​linux/​tools/​labs$ chmod +x skels/​filesystems/​myfs/​test-myfs.sh 
 +</​code>​ 
 +Statisticile afișate pentru sistemul de fișiere sunt minimale, întrucât informațiile sunt furnizate de către funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​libfs.c#​L34 | simple_statfs]]. ​
 </​note>​ </​note>​
  
Line 141: Line 213:
 În continuare vom implementa bazele unui sistem de fișiere foarte simplu, denumit ''​minfs'',​ cu suport pe disc. Vom folosi un disc din cadrul mașinii virtuale pe care îl vom formata și monta cu sistemul de fișiere ''​minfs''​. În continuare vom implementa bazele unui sistem de fișiere foarte simplu, denumit ''​minfs'',​ cu suport pe disc. Vom folosi un disc din cadrul mașinii virtuale pe care îl vom formata și monta cu sistemul de fișiere ''​minfs''​.
  
-Pentru aceasta vom accesa directorul ''​minfs/''​ din archiva de sarcini a laboratorului și vom folosi scheletul de cod ''​minfs.c''​. La fel ca la ''​myfs''​ nu vom implementa operații de lucru cu inode-urile,​ limitându-ne doar la operațiile de lucru cu superblocul și, așadar, la montare. Restul operațiilor le vom implementa în [[:​so2:​laboratoare:​lab09|laboratorul următor]].+Pentru aceasta vom accesa directorul ''​minfs/​kernel''​ din scheletul ​laboratorului și vom folosi scheletul de cod ''​minfs.c''​. La fel ca la ''​myfs''​ nu vom implementa operații de lucru cu inode-urile,​ limitându-ne doar la operațiile de lucru cu superblocul și, așadar, la montare. Restul operațiilor le vom implementa în [[:​so2:​laboratoare:​lab09|laboratorul următor]].
  
 Urmăriți diagrama de mai jos pentru a clarifica rolul structurilor din cadrul sistemului de fișiere ''​minfs''​. Urmăriți diagrama de mai jos pentru a clarifica rolul structurilor din cadrul sistemului de fișiere ''​minfs''​.
Line 147: Line 219:
  
 ==== 5. [0.5p] Înregistrare și deînregistrare sistem de fișiere minfs ==== ==== 5. [0.5p] Înregistrare și deînregistrare sistem de fișiere minfs ====
 +
 +<note important>​
 +Înainte de rezolvarea exercițiului,​ este necesar să adaugăm un disc la mașina virtuală. Pentru aceasta, generați un fișier pe care îl vom folosi ca imaginea discului folosind comanda <​code>​dd if=/​dev/​zero of=qemu/​mydisk.img bs=1M count=100</​code>​ și adăugați argumentul ''​-drive file=qemu/​mydisk.img,​if=virtio,​format=raw''​ comenzii ''​qemu'',​ în fișierul ''​qemu/​Makefile''​ (în variabila ''​QEMU_OPTS''​). Noul argument pentru comanda ''​qemu''​ trebuie sa fie adăugat după cel corespunzător discului existent (''​YOCTO_IMAGE''​).
 +</​note>​
  
 Pentru înregistrarea și deînregistrarea sistemului de fișiere va trebui să completați,​ în fișierul ''​minfs.c'',​ structura ''​minfs_fs_type''​ și funcția ''​minfs_mount''​. Urmăriți indicațiile marcate cu ''​TODO 1''​. Pentru înregistrarea și deînregistrarea sistemului de fișiere va trebui să completați,​ în fișierul ''​minfs.c'',​ structura ''​minfs_fs_type''​ și funcția ''​minfs_mount''​. Urmăriți indicațiile marcate cu ''​TODO 1''​.
  
 <note tip> <note tip>
-În cadrul structurii de sistem de fișiere, pentru montare folosiți funcția ''​minfs_mount''​ prezentă în scheletul de cod. În cadrul acestei funcții apelați funcția aferentă pentru montarea unui sistem de fișiere cu suport de disc (vedeți secțiunea [[:​so2:​laboratoare:​lab08#​functiile_mount_kill_sb|Funcțiile mount, kill_sb]]; este vorba de funcția [[http://lxr.free-electrons.com/​source/​fs/​super.c?v=4.9#L1020|mount_bdev]]).+În cadrul structurii de sistem de fișiere, pentru montare folosiți funcția ''​minfs_mount''​ prezentă în scheletul de cod. În cadrul acestei funcții apelați funcția aferentă pentru montarea unui sistem de fișiere cu suport de disc (vedeți secțiunea [[:​so2:​laboratoare:​lab08#​functiile_mount_kill_sb|Funcțiile mount, kill_sb]]; este vorba de funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​super.c#​L1065|mount_bdev]]).
  
-Alegeți funcția cea mai potrivită pentru distrugerea superblocului (efectuată la demontare); țineți cont de faptul că este un sistem de fișiere cu suport pe disc. Este vorba de funcția [[http://lxr.free-electrons.com/​source/​fs/​super.c?v=4.9#L1095|kill_block_super]].+Alegeți funcția cea mai potrivită pentru distrugerea superblocului (efectuată la demontare); țineți cont de faptul că este un sistem de fișiere cu suport pe disc. Este vorba de funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​super.c#​L1140|kill_block_super]].
  
 Inițializați câmpul ''​fs_flags''​ al structurii ''​minfs_fs_type''​ cu valoarea corespunzătoare pentru un sistem de fișiere cu suport pe disc. Vedeți secțiunea [[:​so2:​laboratoare:​lab08#​inregistrarea_si_deinregistrarea_sistemelor_de_fisiere|Înregistrarea și deînregistrarea sistemelor de fișiere]]. Inițializați câmpul ''​fs_flags''​ al structurii ''​minfs_fs_type''​ cu valoarea corespunzătoare pentru un sistem de fișiere cu suport pe disc. Vedeți secțiunea [[:​so2:​laboratoare:​lab08#​inregistrarea_si_deinregistrarea_sistemelor_de_fisiere|Înregistrarea și deînregistrarea sistemelor de fișiere]].
Line 160: Line 236:
 </​note>​ </​note>​
  
-După completarea secțiunilor marcate cu ''​TODO 1'',​ compilați modulul, copiați-l în directorul dedicat pentru ​mașina virtuală QEMU și porniți mașina virtuală. Încărcați modulul în kernel și apoi verificați prezența sistemului de fișiere ''​minfs''​ în cadrul fișierului ''/​proc/​filesystems''​.+După completarea secțiunilor marcate cu ''​TODO 1'',​ compilați modulul, copiați-l în mașina virtuală QEMU și porniți mașina virtuală. Încărcați modulul în kernel și apoi verificați prezența sistemului de fișiere ''​minfs''​ în cadrul fișierului ''/​proc/​filesystems''​.
  
-Pentru a putea testa montarea sistemului de fișiere va trebui să formatăm discul cu structura acestuia. Formatarea necesită utilitarul de formatare ''​mkfs.minfs'' ​compilabil ​din fișierul ​''​mk_minfs.c'' ​folosind ​comanda<​code bash> +Pentru a putea testa montarea sistemului de fișiere va trebui să formatăm discul cu structura acestuia. Formatarea necesită utilitarul de formatare ''​mkfs.minfs''​din directorul ​''​minfs/user''​. Utilitarul se compilează automat la comanda <code bash>​make ​build</​code> ​și se copiază pe mașina virtuală ​la <code bash>​make copy</​code>​.
-student@mjolnir:​~so2/​lab08-tasks/​minfs$ ​make -f Makefile.format +
-</​code>​ +
-În urma compilării rezultă executabilul ''​mkfs.minfs''​ care trebuie copiat, împreună cu modulul de kernel, în mașina virtuală.+
  
-După compilare, copiere și pornirea mașinii virtuale, formatăm discul ''/​dev/​sdb''​ folosind utilitarul de formatare:<​code>​ +După compilare, copiere și pornirea mașinii virtuale, formatăm discul ''/​dev/​vdb''​ folosind utilitarul de formatare:<​code>​ 
-# ./​mkfs.minfs /dev/sdb+# ./​mkfs.minfs /dev/vdb
 </​code>​ </​code>​
  
Line 176: Line 249:
 # mkdir -p /mnt/minfs/ # mkdir -p /mnt/minfs/
 </​code>​ și montăm sistemul de fișiere<​code>​ </​code>​ și montăm sistemul de fișiere<​code>​
-# mount -t minfs /dev/sdb /mnt/minfs/+# mount -t minfs /dev/vdb /mnt/minfs/
 </​code>​ </​code>​
 Operaţia eşuează din cauză că inode-ul rădăcină nu este iniţializat. Operaţia eşuează din cauză că inode-ul rădăcină nu este iniţializat.
 +
 ==== 6. [2.5] Completare superbloc minfs ==== ==== 6. [2.5] Completare superbloc minfs ====
  
-Pentru a putea monta sistemul de fișiere va trebui să completați superblocul (adică o structură de tip ''​struct super_block''​) în cadrul funcției ''​minfs_fill_super'';​ este vorba de argumentul ''​s''​ al funcției. Structura de operații pe superbloc este definită: ''​minfs_ops''​. Urmăriți indicațiile marcate cu ''​TODO 2''​. Puteți urmări implementarea funcției [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#​L158|minix_fill_super]].+Pentru a putea monta sistemul de fișiere va trebui să completați superblocul (adică o structură de tip ''​struct super_block''​) în cadrul funcției ''​minfs_fill_super'';​ este vorba de argumentul ''​s''​ al funcției. Structura de operații pe superbloc este definită: ''​minfs_ops''​. Urmăriți indicațiile marcate cu ''​TODO 2''​. Puteți urmări implementarea funcției [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L158|minix_fill_super]].
  
 <note tip> <note tip>
Line 188: Line 262:
 Pentu informații legate de lucrul cu buffere, parcurgeți secțiunea [[:​so2:​laboratoare:​lab08#​buffer_cache-ul|Buffer cache-ul]]. Pentu informații legate de lucrul cu buffere, parcurgeți secțiunea [[:​so2:​laboratoare:​lab08#​buffer_cache-ul|Buffer cache-ul]].
  
-Citiți primul bloc de pe disc (**blocul cu indexul 0**). Pentru a citi blocul, folosiți funcția [[http://lxr.free-electrons.com/​source/​include/​linux/​buffer_head.h?v=4.9#L298|sb_bread]]. Convertiți datele citite (câmpul ''​b_data''​ din ''​struct buffer_head''​) la structura de tip informație de superbloc de pe disc: ''​struct minfs_super_block'',​ definită în fișierul cod sursă.+Citiți primul bloc de pe disc (**blocul cu indexul 0**). Pentru a citi blocul, folosiți funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​buffer_head.h#​L304|sb_bread]]. Convertiți datele citite (câmpul ''​b_data''​ din ''​struct buffer_head''​) la structura de tip informație de superbloc de pe disc: ''​struct minfs_super_block'',​ definită în fișierul cod sursă.
  
 Structura ''​struct minfs_super_block''​ deține informații specifice sistemului de fișiere, care nu se regăsesc în structura generică ''​struct super_block''​ (în cazul de față doar versiunea). Acele informații suplimentare (care se găsesc în ''​struct minfs_super_block''​ (disc) dar nu în ''​struct super_block''​ (VFS)) vor fi stocate în structura ''​struct minfs_sb_info''​. Structura ''​struct minfs_super_block''​ deține informații specifice sistemului de fișiere, care nu se regăsesc în structura generică ''​struct super_block''​ (în cazul de față doar versiunea). Acele informații suplimentare (care se găsesc în ''​struct minfs_super_block''​ (disc) dar nu în ''​struct super_block''​ (VFS)) vor fi stocate în structura ''​struct minfs_sb_info''​.
Line 198: Line 272:
 ==== 7. [1.5p] Creare și distrugere inode-uri minfs ==== ==== 7. [1.5p] Creare și distrugere inode-uri minfs ====
  
-Pentru montare avem nevoie de inițializarea inode-ului rădăcină,​ iar pentru inițializarea inode-ului rădăcină avem nevoie de implementarea funcțiilor de lucru cu inode-uri. Adică trebuie să implementați funcțiile ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​. Urmăriții indicațiile marcate cu ''​TODO 3''​. Puteți folosi ca model funcțiile [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#​L62|minix_alloc_inode]] și [[http://lxr.free-electrons.com/​source/​fs/​minix/​inode.c?v=4.9#​L77|minix_destroy_inode]].+Pentru montare avem nevoie de inițializarea inode-ului rădăcină,​ iar pentru inițializarea inode-ului rădăcină avem nevoie de implementarea funcțiilor de lucru cu inode-uri. Adică trebuie să implementați funcțiile ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​. Urmăriții indicațiile marcate cu ''​TODO 3''​. Puteți folosi ca model funcțiile [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L62|minix_alloc_inode]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​minix/​inode.c#​L77|minix_destroy_inode]].
  
 În implementare urmăriți macro-urile și structurile din fișierul ''​minfs.h''​. În implementare urmăriți macro-urile și structurile din fișierul ''​minfs.h''​.
  
 <note tip> <note tip>
-Pentru alocarea/​dezalocarea de memorie în cadrul funcțiilor ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​ recomandăm folosirea [[http://lxr.free-electrons.com/​source/​include/​linux/​slab.h?v=4.9#L629|kzalloc]] și [[http://lxr.free-electrons.com/​source/​mm/​slab.c?v=4.9#L3804|kfree]].+Pentru alocarea/​dezalocarea de memorie în cadrul funcțiilor ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​ recomandăm folosirea [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​slab.h#​L682|kzalloc]] și [[https://elixir.bootlin.com/​linux/​v4.15/​source/​mm/​slab.c#​L3780|kfree]].
  
 În funcția ''​minfs_alloc_inode''​ alocați inode-uri de tip ''​minfs_inode_info'',​ dar returnați doar structuri de tip ''​struct inode'',​ adică cele date de câmpul ''​vfs_inode''​. În funcția ''​minfs_alloc_inode''​ alocați inode-uri de tip ''​minfs_inode_info'',​ dar returnați doar structuri de tip ''​struct inode'',​ adică cele date de câmpul ''​vfs_inode''​.
  
-În funcția de ''​minfs_alloc_inode''​ apelați funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L359|inode_init_once]] pentru inițializarea inode-ului.+În funcția de ''​minfs_alloc_inode''​ apelați funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L365|inode_init_once]] pentru inițializarea inode-ului.
  
-În funcția ''​destroy_inode''​. să puteți accesa structura de tip ''​struct minfs_inode_info''​ folosiți macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​kernel.h?v=4.9#L828|container_of]].+În funcția ''​destroy_inode''​. să puteți accesa structura de tip ''​struct minfs_inode_info''​ folosiți macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​kernel.h#​L922|container_of]].
 </​note>​ </​note>​
  
Line 218: Line 292:
  
 Inițializarea inode-ului rădăcină este necesară pentru montarea sistemului de fișiere. Pentru aceasta va trebui să completați structura ''​minfs_ops''​ cu funcțiile ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​ și să completați funcția ''​minfs_iget''​. Funcția ''​minfs_iget''​ este funcția apelată pentru alocarea unui inode de tip VFS (adică ''​struct inode''​) și completarea acestuia cu informații specifice inode-ului ''​minfs''​ de pe disc (adică ''​struct minfs_inode''​). Urmăriții indicațiile marcate cu ''​TODO 4''​. Inițializarea inode-ului rădăcină este necesară pentru montarea sistemului de fișiere. Pentru aceasta va trebui să completați structura ''​minfs_ops''​ cu funcțiile ''​minfs_alloc_inode''​ și ''​minfs_destroy_inode''​ și să completați funcția ''​minfs_iget''​. Funcția ''​minfs_iget''​ este funcția apelată pentru alocarea unui inode de tip VFS (adică ''​struct inode''​) și completarea acestuia cu informații specifice inode-ului ''​minfs''​ de pe disc (adică ''​struct minfs_inode''​). Urmăriții indicațiile marcate cu ''​TODO 4''​.
-Completați câmpurile ''​alloc_inode''​ și ''​destroy_inode''​ ale structurii [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L1786 | struct super_operations]] cu funcțiile implementate la pasul anterior.+Completați câmpurile ''​alloc_inode''​ și ''​destroy_inode''​ ale structurii [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1803 | struct super_operations]] cu funcțiile implementate la pasul anterior.
  
 Informațiile despre inode-ul rădăcină se găsesc în al doilea bloc de pe disc (**inode-ul cu indexul 1**). Realizați, în cadrul funcției ''​minfs_iget''​ citirea inode-ului rădăcină de tip ''​minfs''​ de pe disc (''​struct minfs_inode''​) și completarea inode-ului VFS (''​struct inode''​). Informațiile despre inode-ul rădăcină se găsesc în al doilea bloc de pe disc (**inode-ul cu indexul 1**). Realizați, în cadrul funcției ''​minfs_iget''​ citirea inode-ului rădăcină de tip ''​minfs''​ de pe disc (''​struct minfs_inode''​) și completarea inode-ului VFS (''​struct inode''​).
Line 225: Line 299:
  
 <note tip> <note tip>
-Pentru ​a citi un bloc folosiți funcția [[http://lxr.free-electrons.com/​source/​include/linux/buffer_head.h?v=4.9#L298|sb_bread]]. Convertiți datele citite (câmpul ''​b_data''​ al structurii ''​struct buffer_head''​) la inode-ul de tip ''​minfs''​ de pe disc (''​struct minfs_inode''​).+Pentru ​implementarea funcției ''​minfs_iget''​ urmăriți implementarea ​funcției [[https://elixir.bootlin.com/​linux/​v4.15/source/fs/minix/inode.c#L460|V1_minix_iget]].
  
-Câmpurile ​''​i_uid''​''​i_gid''​, ''​i_mode'',​ ''​i_size''​ le completați în cadrul inode-ului VFS cu valorile din inode-ul de pe disc. Pentru initializarea câmpurilor ​''​i_uid'' ​și ''​i_gid'',​ folosiți funcțiile ''​i_uid_write'',​ și, respectiv, ​''​i_gid_write''​. ​+Pentru a citi un bloc folosiți funcția [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​buffer_head.h#​L304|sb_bread]]. Convertiți datele citite (câmpul ​''​b_data'' ​al structurii ​''​struct buffer_head''​) la inode-ul de tip ''​minfs'' ​de pe disc (''​struct minfs_inode''​).
  
-Inițializați câmpurile ''​atime'',​ ''​ctime''​ și ''​mtime''​ ale inode-ului VFS la valoarea [[http://lxr.free-electrons.com/​source/​include/linux/time.h?v=4.9#L154|CURRENT_TIME]].+Câmpurile ''​i_uid'',​ ''​i_gid'',​ ''​i_mode'',​ ''​i_size''​ le completați în cadrul inode-ului VFS cu valorile din inode-ul de pe disc. Pentru initializarea câmpurilor ''​i_uid''​ și ''​i_gid'',​ folosiți funcțiile [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1461|i_uid_write]],​ și, respectiv, [[https://​elixir.bootlin.com/​linux/​v4.15/​source/​include/​linux/​fs.h#​L1466|i_gid_write]].  
 + 
 +Inițializați câmpurile ''​i_atime'',​ ''​i_ctime''​ și ''​i_mtime''​ ale inode-ului VFS la valoarea ​întoarsă de funcția ​[[https://elixir.bootlin.com/linux/v4.15/​source/​fs/​inode.c#L2107|current_time]].
  
 Va trebui să inițializați operațiile pentru inode-ul de tip director. Pentru aceasta urmați pașii: Va trebui să inițializați operațiile pentru inode-ul de tip director. Pentru aceasta urmați pașii:
-  - Verificați dacă este vorba de inode de tip director folosind macro-ul [[http://lxr.free-electrons.com/​source/​include/​uapi/​linux/​stat.h?v=4.9#L21|S_ISDIR]].+  - Verificați dacă este vorba de inode de tip director folosind macro-ul [[https://elixir.bootlin.com/​linux/​v4.15/​source/​include/​uapi/​linux/​stat.h#​L23|S_ISDIR]].
   - Pentru câmpurile, ''​i_op''​ și ''​i_fop'',​ folosiți funcții din kernel deja implementate:​   - Pentru câmpurile, ''​i_op''​ și ''​i_fop'',​ folosiți funcții din kernel deja implementate:​
-    * pentru ''​i_op'':​ [[http://lxr.free-electrons.com/​source/​fs/​libfs.c?v=4.9#L226| simple_dir_inode_operations]]. +    * pentru ''​i_op'':​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​libfs.c#​L227| simple_dir_inode_operations]]. 
-    * pentru ''​i_fop'':​ [[http://lxr.free-electrons.com/​source/​fs/​libfs.c?v=4.9#L216|simple_dir_operations]] +    * pentru ''​i_fop'':​ [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​libfs.c#​L217|simple_dir_operations]] 
-  - Incrementați numărul de link-uri pentru director folosind funcția [[http://lxr.free-electrons.com/​source/​fs/​inode.c?v=4.9#L336|inc_nlink]].+  - Incrementați numărul de link-uri pentru director folosind funcția [[https://elixir.bootlin.com/​linux/​v4.15/​source/​fs/​inode.c#​L330|inc_nlink]].
  
 </​note>​ </​note>​
Line 253: Line 329:
 Alternativ, pentru testarea întregii funcționalității puteți folosi scriptul ''​test-minfs.sh'':<​code>​ Alternativ, pentru testarea întregii funcționalității puteți folosi scriptul ''​test-minfs.sh'':<​code>​
 # ./​test-minfs.sh # ./​test-minfs.sh
 +</​code>​
 +Scriptul este copiat pe mașina virtuală la rularea comenzii ''​make copy''​ doar dacă este executabil.
 +<code bash>
 +student@workstation:​~/​so2/​linux/​tools/​labs$ chmod +x skels/​filesystems/​minfs/​user/​test-minfs.sh ​
 </​code>​ </​code>​
 </​note>​ </​note>​
so2/laboratoare/lab08/exercitii.1491832089.txt.gz · Last modified: 2017/04/10 16:48 by octavian.purdila
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0