Differences

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

Link to this comparison view

so2:teme:tema3 [2017/04/09 16:13]
adrian.stanciu [Detalii de implementare]
so2:teme:tema3 [2020/04/12 23:05] (current)
lucian.teodorescu [Sfaturi]
Line 1: Line 1:
 ====== Tema 3 - Software RAID ====== ====== Tema 3 - Software RAID ======
  
-Termen de predare: **Marți26 aprilie 2016, ora 23:00**+  * Termen de predare: **Duminică3 Mai 2020, ora 23:00**
  
 ===== Scopul temei===== ===== Scopul temei=====
Line 18: Line 18:
 Să se scrie un modul de kernel care să implementeze funcționalitatea de software RAID. [[http://​en.wikipedia.org/​wiki/​RAID#​Software-based_RAID|Software RAID]] oferă o abstractizare între dispozitivul logic și dispozitivele fizice. Implementarea va utiliza schema [[http://​en.wikipedia.org/​wiki/​RAID#​Standard_levels|RAID1]]. Să se scrie un modul de kernel care să implementeze funcționalitatea de software RAID. [[http://​en.wikipedia.org/​wiki/​RAID#​Software-based_RAID|Software RAID]] oferă o abstractizare între dispozitivul logic și dispozitivele fizice. Implementarea va utiliza schema [[http://​en.wikipedia.org/​wiki/​RAID#​Standard_levels|RAID1]].
  
-Mașina virtuală dispune de două hard disk-uri care vor reprezenta dispozitivele fizice: ''/​dev/​vda''​ și ''/​dev/​vdb''​. Sistemul de operare va oferi un dispozitiv logic (de tip bloc) care va interfața accesul din user space. Cererile de scriere în dispozitivul logic vor rezulta în două scrieri, câte una pentru fiecare hard disk. Hard disk-urile **nu** sunt partiționate. Se va considera că fiecare hard disk are o singură partiție ce acoperă întregul disk.+Mașina virtuală dispune de două hard disk-uri care vor reprezenta dispozitivele fizice: ''/​dev/​vdb''​ și ''/​dev/​vdc''​. Sistemul de operare va oferi un dispozitiv logic (de tip bloc) care va interfața accesul din user space. Cererile de scriere în dispozitivul logic vor rezulta în două scrieri, câte una pentru fiecare hard disk. Hard disk-urile **nu** sunt partiționate. Se va considera că fiecare hard disk are o singură partiție ce acoperă întregul disk.
  
 Fiecare partiție va stoca un sector împreună cu o sumă de control asociată ([[http://​en.wikipedia.org/​wiki/​Cyclic_redundancy_check|CRC32]]) pentru a asigura recuperarea din eroare. La fiecare citire se citesc informațiile aferente de pe **ambele** partiții. Dacă un sector al primei partiții deține date corupte (valoarea CRC este greșită) atunci se va citi sectorul de pe cea de-a doua partiție; în acelasi timp se va corecta sectorul primei partiții. Similar în cazul unei citiri a unui sector corupt de pe a doua partiție. În cazul în care un sector are valori CRC greșite pe ambele partiții, se va returna un cod de eroare corespunzător. Fiecare partiție va stoca un sector împreună cu o sumă de control asociată ([[http://​en.wikipedia.org/​wiki/​Cyclic_redundancy_check|CRC32]]) pentru a asigura recuperarea din eroare. La fiecare citire se citesc informațiile aferente de pe **ambele** partiții. Dacă un sector al primei partiții deține date corupte (valoarea CRC este greșită) atunci se va citi sectorul de pe cea de-a doua partiție; în acelasi timp se va corecta sectorul primei partiții. Similar în cazul unei citiri a unui sector corupt de pe a doua partiție. În cazul în care un sector are valori CRC greșite pe ambele partiții, se va returna un cod de eroare corespunzător.
Line 32: Line 32:
 </​code>​ </​code>​
  
-''​C1'',​ ''​C2'',​ ''​C3''​ sunt valorile CRC pentru sectoarele ''​sector1'',​ ''​sector2'',​ ''​sector3''​. Zona CRC-urilor se regăsește imediat după ''​LOGICAL_DISK_SIZE''​ octeți ai partiției.+unde ''​C1'',​ ''​C2'',​ ''​C3''​ sunt valorile CRC pentru sectoarele ''​sector1'',​ ''​sector2'',​ ''​sector3''​. Zona CRC-urilor se regăsește imediat după ''​LOGICAL_DISK_SIZE''​ octeți ai partiției.
  
 Ca //seed// pentru CRC folosiți ''​0''​ (zero). Ca //seed// pentru CRC folosiți ''​0''​ (zero).
Line 40: Line 40:
   * modulul de kernel va avea numele **ssr.ko**   * modulul de kernel va avea numele **ssr.ko**
   * dispozitivul logic va fi accesat ca un dispozitiv de tip bloc cu majorul ''​SSR_MAJOR''​ și minorul ''​SSR_FIRST_MINOR''​ sub numele ''/​dev/​ssr''​ (prin macro-ul ''​LOGICAL_DISK_NAME''​)   * dispozitivul logic va fi accesat ca un dispozitiv de tip bloc cu majorul ''​SSR_MAJOR''​ și minorul ''​SSR_FIRST_MINOR''​ sub numele ''/​dev/​ssr''​ (prin macro-ul ''​LOGICAL_DISK_NAME''​)
-  * cele două discuri sunt reprezentate de dispozitivele ''/​dev/​vda'',​ respectiv ''/​dev/​vdb'',​ definite prin intermediul macro-urilor ''​PHYSICAL_DISK1_NAME'',​ respectiv ''​PHYSICAL_DISK2_NAME''​ +  ​* dispozitivul virtual (''​LOGICAL_DISK_NAME''​ - ''/​dev/​ssr''​) va avea capacitatea de ''​LOGICAL_DISK_SECTORS''​ (folosiți [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​genhd.h#​L445 | set_capacity]] pe structura [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​genhd.h#​L174 | struct gendisk]]) 
-  * pentru lucrul cu structura [[http://lxr.free-electrons.com/​source/​include/​linux/​fs.h?v=4.9#L457 | struct block_device]] asociată unui dispozitiv fizic, puteți utiliza funcțiile [[http://lxr.free-electrons.com/​source/​fs/​block_dev.c?v=4.9#L1467 | blkdev_get_by_path]] și [[http://lxr.free-electrons.com/​source/​fs/​block_dev.c?v=4.9#L1619 | blkdev_put]]. +  ​* cele două discuri sunt reprezentate de dispozitivele ''/​dev/​vdb'',​ respectiv ''/​dev/​vdc'',​ definite prin intermediul macro-urilor ''​PHYSICAL_DISK1_NAME'',​ respectiv ''​PHYSICAL_DISK2_NAME''​ 
-  * pentru tratarea cererilor din user-space, recomandăm să nu vă folosiți de o coadă de cereri, ci să faceți prelucrare la nivel de bio; puteți înregistra o rutină corespunzătoare folosind apelul [[http://lxr.free-electrons.com/​source/​block/​blk-settings.c?v=4.9#L136 | blk_queue_make_request]]. +  * pentru lucrul cu structura [[https://elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​fs.h#​L432 | struct block_device]] asociată unui dispozitiv fizic, puteți utiliza funcțiile [[https://elixir.bootlin.com/​linux/​v4.19/​source/​fs/​block_dev.c#​L1685 | blkdev_get_by_path]] și [[https://elixir.bootlin.com/​linux/​v4.19/​source/​fs/​block_dev.c#​L1814 | blkdev_put]] 
-  * pentru a transmite o cerere către un dispozitiv ​de tip bloc, puteți utiliza funcția [[http://lxr.free-electrons.com/​source/​block/bio.c?v=4.9#L863 submit_bio_wait]]+  * pentru tratarea cererilor din user space, recomandăm să nu vă folosiți de o coadă de cereri, ci să faceți prelucrare la nivel de structuri [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​blk_types.h#​L144 | struct ​bio]]; puteți înregistra o rutină corespunzătoare folosind apelul [[https://elixir.bootlin.com/​linux/​v4.19/​source/​block/​blk-settings.c#​L163 | blk_queue_make_request]] 
-  * folosiți [[http://lxr.free-electrons.com/​source/​block/​bio.c?v=4.9#L1734 bio_endio]] pentru a semnala terminarea prelucrării unei structuri bio. +  * rutina de tipul [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​blkdev.h#​L315 | make_request_fn]] poate fi apelată în paralel 
-  * pentru ​calculul CRC32 puteți utiliza ​macro-ul [[http://lxr.free-electrons.com/​source/​include/​linux/​crc32.h?v=4.9#L66 crc32]] pus la dispoziție de kernel+  * întrucât sectoarele ​de date sunt separate de sectoarele de CRC-uri va trebui să construiți structuri bio separate pentru date și pentru valorile CRC 
-  * când generați o structură bio, luați în considerare că aceasta trebuie să aibă dimensiunea multiplu de dimensiunea sectorului de disc (''​KERNEL_SECTOR_SIZE''​). +  * pentru alocarea unui bio pentru discurile fizice puteți folosi ​[[https://elixir.bootlin.com/​linux/​v4.19/source/include/​linux/bio.h#L435|bio_alloc]]; pentru adăugarea de pagini de date în bio folosiți [[https://elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​gfp.h#​L524|alloc_page]] și [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​block/​bio.c#​L818|bio_add_page]] 
-  * întrucât sectoarele de date sunt separate de sectoarele de CRC-uri va trebui să construițstructuri bio separate pentru date și pentru valorile CRC+  * pentru ​eliberarea spațiului alocat de un bio este nevoie să eliberați paginile alocate bio-ului (folosind ​macro-ul [[https://elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​gfp.h#L554 __free_page]]) și să apelați [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​block/​bio.c#​L558|bio_put]] 
-  * Dispozitivul virtual (''​LOGICAL_DISK_NAME''​ - ''/​dev/​ssr''​) va avea capacitatea de ''​LOGICAL_DISK_SECTORS''​ (folosind ​[[http://lxr.free-electrons.com/source/include/linux/genhd.h?v=3.13#L449 set_capacity]] pe structura ​[[http://lxr.free-electrons.com/​source/​include/​linux/​genhd.h?v=3.13#L165 struct gendisk]]). +  * când generați o structură bio, luați în considerare că aceasta trebuie să aibă dimensiunea multiplu de dimensiunea sectorului de disc (''​KERNEL_SECTOR_SIZE''​) 
-  * macrodefinițiile utile se găsesc în [[http://​elf.cs.pub.ro/​so2/​res/​teme/​ssr.h|header-ul de suport al temei]]. +  * pentru a transmite o cerere către un dispozitiv de tip bloc șa aștepta încheierea acesteia, putețutiliza funcția [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​block/​bio.c#​L922 | submit_bio_wait]] 
-  * **recomandăm** != **este obligatoriu**orice rezolvare care respectă cerințele temei este acceptată+  * folosiți ​[[https://elixir.bootlin.com/linux/v4.19/source/block/bio.c#L1740 bio_endio]] pentru a semnala terminarea prelucrării unei structuri bio 
-  * Pentru alocarea unui bio nou pentru discurile fizice puteți folosi [[http://​lxr.free-electrons.com/​source/​include/​linux/​bio.h?​v=3.13#​L235|bio_alloc]] sau, mai direct, [[http://​lxr.free-electrons.com/​source/​include/​linux/​bio.h?​v=3.13#​L240|bio_clone]] pornind de la bio-ul pentru discul fizic. Pentru adăugarea de pagini de date în bio folosiți [[http://​lxr.free-electrons.com/​source/​include/​linux/​gfp.h?​v=3.13#​L345|alloc_page]] și [[http://​lxr.free-electrons.com/​source/​fs/​bio.c?​v=3.13#​L738|bio_add_page]]. +  * pentru calculul CRC32 puteți utiliza macro-ul ​[[https://elixir.bootlin.com/​linux/​v4.19/​source/​include/​linux/​crc32.h#L66 crc32]] pus la dispoziție de kernel 
-  * Pentru eliberarea spațiului alocat de un bio este nevoie să eliberați paginile alocate de bio și să apelați [[http://​lxr.free-electrons.com/​source/​fs/​bio.c?​v=3.13#​L488|bio_put]]. O secvență posibilă este cea de mai jos:<​code c> +  * macrodefinițiile utile se găsesc în [[http://​elf.cs.pub.ro/​so2/​res/​teme/​ssr.h|header-ul de suport al temei]] 
-bio->​bi_idx = 0; +  * **recomandăm** != **este obligatoriu** ​(orice rezolvare care respectă cerințele temei este acceptată)
-bio_for_each_segment(bv,​ bio, i+
- __free_page(bv->​bv_page);​ +
-+
-bio_put(bio);​ +
-</​code>​+
  
  
 <note important>​ <note important>​
-O singură funcție de prelucrare a cererilor pentru dispozitive de tip bloc poate fi activă la un moment dat în cadrul unei stive de apeluri (mai multe detalii [[http://lxr.free-electrons.com/​source/​block/​blk-core.c?v=4.9#L2003 | aici]]). Va trebui să submiteți cererile pentru dispozitivele fizice dintr-un kernel thread; recomandăm folosirea [[http://​ocw.cs.pub.ro/​courses/​so2/​laboratoare/​lab06#​workqueues | workqueues]].+O singură funcție de prelucrare a cererilor pentru dispozitive de tip bloc poate fi activă la un moment dat în cadrul unei stive de apeluri (mai multe detalii [[https://elixir.bootlin.com/​linux/​v4.19/​source/​block/​blk-core.c#​L2404 | aici]]). Va trebui să submiteți cererile pentru dispozitivele fizice dintr-un kernel thread; recomandăm folosirea [[http://​ocw.cs.pub.ro/​courses/​so2/​laboratoare/​lab06#​workqueues | workqueues]].
 </​note>​ </​note>​
  
 <note important>​ <note important>​
-[[http://​lxr.free-electrons.com/​source/​include/​linux/​bio.h?​v=3.13#​L240|bio_clone]] clonează bio-ul inițial astfel încât noul bio cât și cel inițial sunt mapate peste aceleași pagini de memorie fizică. Dacă modificați datele dintr-un bio (fie cel inițial fie cel nou) modificările se vor întâmpla și în celălalt bio. +Pentru o rulare rapidă a temei, folosiți un singur bio pentru a trimite în batch cererea de citire/​scriere a valorilor ​CRC pentru sectoare adiacente. De exemplu, dacă trebuie să trimiteți cereri pentru CRC-urile ​sectoarelor 0, 1, ..., 7, folosiți un singur bio, nu 8 bio-uri.
- +
-Folosiți [[http://​lxr.free-electrons.com/​source/​include/​linux/​bio.h?​v=3.13#​L240|bio_clone]] doar în cazul în care în nu modificați datele. Dacă vreți să modificați datele într-un dintre cele două bio-uri (inițial sau nou) fără că aceste modificări să fie vizibile în celălalt bio, atunci folosiți [[http://​lxr.free-electrons.com/​source/​include/​linux/​bio.h?​v=3.13#​L235|bio_alloc]],​ [[http://​lxr.free-electrons.com/​source/​include/​linux/​gfp.h?​v=3.13#​L345|alloc_page]] și [[http://​lxr.free-electrons.com/​source/​fs/​bio.c?​v=3.13#​L738|bio_add_page]]. +
-</​note>​ +
- +
-<note important>​ +
-Pentru o rulare rapidă a temei, folosiți un singur bio pentru a trimite în batch CRC-urile ​pentru sectoare adiacente. De exemplu, dacă trebuie să trimiteți cereri pentru CRC-urile ​pentru sectoarele ​1, 2, ..., 8, folosiți un singur bio, nu 8 bio-uri.+
 </​note>​ </​note>​
  
 ===== Testare ===== ===== Testare =====
  
-Pentru simplificarea procesului de corectare a temelor, dar și pentru a reduce greșelile temelor trimise, corectarea temelor se va face automat cu ajutorul ​unor [[http://elf.cs.pub.ro/so2/res/teme/3-ssr.zip|teste publice]]. Indicații despre utilizarea suitei de teste se găsesc ​în fișierul ''​README''​ din cadrul arhivei.+Pentru simplificarea procesului de corectare a temelor, dar și pentru a reduce greșelile temelor trimise, corectarea temelor se va face automat cu ajutorul ​testelor publice care se găsesc în noua infrastructură. Pentru testarea locală folosiți următoarele comezi: 
 +<code bash> 
 +$ git clone https://github.com/linux-kernel-labs/linux.git 
 +$ cd linux/tools/​labs 
 +$ LABS=assignments/3-raid make skels  
 +# dezvoltarea temei se va efectua ​în directorul 3-raid/ 
 +$ make build 
 +$ make copy 
 +$ make boot 
 +</​code>​
  
 Dacă, în urma procesului de testare, sectoarele de pe ambele discuri conțin date nevalide, rezultând în erori de citire ce fac imposibilă funcționarea modulului, va trebui să refaceți cele două discuri în cadrul mașinii virtuale folosind comenzile: Dacă, în urma procesului de testare, sectoarele de pe ambele discuri conțin date nevalide, rezultând în erori de citire ce fac imposibilă funcționarea modulului, va trebui să refaceți cele două discuri în cadrul mașinii virtuale folosind comenzile:
 <​code>​ <​code>​
-dd if=/​dev/​zero of=/dev/vda bs=1M 
 dd if=/​dev/​zero of=/dev/vdb bs=1M dd if=/​dev/​zero of=/dev/vdb bs=1M
 +dd if=/​dev/​zero of=/dev/vdc bs=1M
 </​code>​ </​code>​
  
Line 89: Line 87:
 rm disk{1,​2}.img;​ make rm disk{1,​2}.img;​ make
 </​code>​ </​code>​
 +
 +<note important>​
 +în cazul în care corupeți ''/​dev/​vda''​ corespunzător yocto, va trebui să ștergeți imaginea de pe local ''​core-image-minimal-qemux86.ext4''​ pentru ca scriptul [[https://​github.com/​linux-kernel-labs/​linux/​blob/​master/​tools/​labs/​qemu/​Makefile|qemu]] să o refacă.
 +</​note>​
  
 ==== Sfaturi ==== ==== Sfaturi ====
  
-Pentru a vă mări șansele de a obține nota maximă, citiți și respectați coding style-ul kernelului Linux descris din documentul [[http://lxr.free-electrons.com/​source/​Documentation/​process/​coding-style.rst | Coding Style]].+Pentru a vă mări șansele de a obține nota maximă, citiți și respectați coding style-ul kernelului Linux descris din documentul [[https://elixir.bootlin.com/​linux/​v4.19/​source/​Documentation/​process/​coding-style.rst | Coding Style]].
  
 De asemenea, folosiți următoarele tool-uri de analiza statică pentru a verifica codul: De asemenea, folosiți următoarele tool-uri de analiza statică pentru a verifica codul:
Line 123: Line 125:
 ===== Resurse ====== ===== Resurse ======
  
-  * implementarea de [[http://lxr.free-electrons.com/​source/​drivers/​md/?​v=4.9 ​| software RAID]] din nucleul Linux.+  * implementarea de [[https://elixir.bootlin.com/​linux/​v4.19/​source/​drivers/​md | software RAID]] din nucleul Linux.
  
 <note important>​ <note important>​
so2/teme/tema3.1491743615.txt.gz · Last modified: 2017/04/09 16:13 by adrian.stanciu
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