Differences

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

Link to this comparison view

so2:teme:tema3 [2017/04/09 16:27]
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''​)
-  * dispozitivul virtual (''​LOGICAL_DISK_NAME''​ - ''/​dev/​ssr''​) va avea capacitatea de ''​LOGICAL_DISK_SECTORS''​ (folosiți [[http://lxr.free-electrons.com/​source/​include/​linux/​genhd.h?v=4.9#L451 | set_capacity]] pe structura [[http://lxr.free-electrons.com/​source/​include/​linux/​genhd.h?v=4.9#L180 | struct gendisk]]). +  * 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]]) 
-  * cele două discuri sunt reprezentate de dispozitivele ''/​dev/​vda'',​ respectiv ''/​dev/​vdb'',​ definite prin intermediul macro-urilor ''​PHYSICAL_DISK1_NAME'',​ respectiv ''​PHYSICAL_DISK2_NAME''​ +  * 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 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]]. +  * 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 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 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]] 
-  * 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]]. +  * rutina de tipul [[https://elixir.bootlin.com/linux/v4.19/​source/​include/​linux/​blkdev.h#L315 make_request_fn]] poate fi apelată în paralel 
-  * 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. +  * î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 
-  * 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. +  * 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]] 
-  * 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 ​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]] 
-  * î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''​) 
-  * 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 și a aștepta încheierea acesteia, puteți utiliza funcția [[https://​elixir.bootlin.com/​linux/​v4.19/​source/​block/​bio.c#L922 | submit_bio_wait]] 
-  * 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]]. +  * 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 ​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> +  * 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 
-bio->bi_idx = 0; +  * macrodefinițiile utile se găsesc în [[http://​elf.cs.pub.ro/​so2/​res/​teme/​ssr.h|header-ul de suport al temei]] 
-bio_for_each_segment(bv, ​bio, i) { +  * **recomandăm** != **este obligatoriu** ​(orice rezolvare care respectă cerințele temei este acceptată)
- __free_page(bv->​bv_page);​ +
-} +
-bio_put(bio);​ +
-</code> +
-  * **recomandăm** != **este obligatoriu**orice rezolvare care respectă cerințele temei este acceptată.+
  
  
 <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.1491744459.txt.gz · Last modified: 2017/04/09 16:27 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