                              Sozdanie klassa GEOM

  Ivan Voras

   <ivoras@FreeBSD.org>
     

   Izdanie: b55bb8ba3f

   FreeBSD `eto zaregistrirovannaya torgovaya marka FreeBSD Foundation.

   Intel, Celeron, EtherExpress, i386, i486, Itanium, Pentium i Xeon `eto
   torgovye marki ili zaregistrirovannye torgovye marki Intel Corporation ili
   ee dochernih kompanij v Soedinennyh SHtatah i drugih stranah.

   Mnogie iz oboznachenij, ispol'zuemye proizvoditelyami i prodavcami dlya
   oboznacheniya svoih produktov, zayavlyayutsya v kachestve torgovyh marok.
   Kogda takie oboznacheniya poyavlyayutsya v `etom dokumente, i Proektu
   FreeBSD izvestno o torgovoj marke, k oboznacheniyu dobavlyaetsya znak
   <<TM>> ili <<(R)>>.

   2015-05-12 08:03:23 +0000 Taras Korenko.
   Annotaciya

   `Eta stat'ya dokumentiruet nekotorye nachal'nye vykladki v razrabotke
   GEOM-klassov, a takzhe modulej yadra v obschem. Predpolagaetsya, chto
   chitatel' blizko znakom s programmirovaniem na Si v kontekste prostranstva
   pol'zovatel'skih processov (userland).

   [ Po razdelam / Odnim fajlom ]

     ----------------------------------------------------------------------

   Soderzhanie

   1. Vstuplenie

   2. Podgotovka

   3. Programmirovanie v yadre FreeBSD

   4. Programmirovanie v sisteme GEOM

1. Vstuplenie

  1.1. Dokumentaciya

   Dokumentaciya po programmirovaniyu dlya yadra skudnaya, `eto odna iz
   nemnogih oblastej programmirovaniya, gde pochti net horoshih uchebnyh
   posobij, i sovet <<chitaj ishodniki!>> - sohranyaet svoyu spravedlivost'.
   Odnako, suschestvuet neskol'ko statej i knig raznoj aktual'nosti, kotorye
   rekomenduyutsya k izucheniyu pered tem, kak nachat' programmirovat':

     * Rukovodstvo FreeBSD dlya razrabotchikov - chast' Proekta Dokumentacii
       FreeBSD, nichego specifichnogo o programmirovanii yadra v nem net,
       zato est' nemnogo obschej poleznoj informacii.

     * Rukovodstvo po Arhitekture FreeBSD - takzhe yavlyaetsya chast'yu
       Proekta Dokumentacii FreeBSD, soderzhit opisaniya nekotoryh
       nizkourovnevyh sredstv i procedur. Udelite vnimanie razdelu nomer 13 -
       Napisanie drajverov ustrojstv dlya FreeBSD.

     * Neskol'ko interesnyh statej ob ustrojstve yadra mozhno najti na sajte
       FreeBSD Diary.

     * Stranicy iz razdela nomer 9 sistemnogo spravochnika, soderzhat
       vazhnuyu dokumentaciyu po funkciyam yadra.

     * Stranica spravochnika geom(4), a takzhe slajdy Pola-Henninga Kampa -
       obschee predstavlenie o podsisteme GEOM.

     * Stranicy spravochnika g_bio(9), g_event(9), g_data(9), g_geom(9),
       g_provider(9), g_consumer(9), g_access(9), a takzhe drugie, svyazannye
       s vysheupomyanutymi i raskryvayuschie specificheskij funkcional
       podsistemy GEOM.

     * Stranica spravochnika style(9) - dokumentiruet soglasheniya o stile
       oformleniya koda, kotorye obyazany byt' soblyudeny esli vy planiruete
       peredat' vash kod v Subversion repozitorij FreeBSD.

2. Podgotovka

   Dlya togo, chtob zanimat'sya razrabotkami dlya yadra, zhelatel'no imet'
   dva otdel'nyh komp'yutera. Odin iz nih prednaznachen dlya sredy razrabotki
   i ishodnyh kodov, a vtoroj - dlya zapuska testov otlazhivaemogo koda.
   Vtoromu komp'yuteru dlya raboty dostatochno imet' vozmozhnost' vypolnyat'
   nachal'nuyu zagruzku po seti i montirovanie fajlovyh sistem po seti. V
   `etoj situacii, esli otlazhivaemyj kod soderzhit oshibki i vyzovet
   avarijnuyu ostanovku sistemy, to `eto ne povlechet porchu ili uteryu
   ishodnogo koda . Vtoromu komp'yuteru dazhe ne potrebuetsya imet' svoj
   monitor, dostatochno budet soedineniya asinhronnyh portov kabelem RS-232
   ili soedineniya pri pomoschi KVM-ustrojstva.

   No tak kak daleko ne u kazhdogo est' dva ili bolee komp'yuterov pod rukoj,
   est' para sposobov podgotovit' inuyu <<zhivuyu>> sistemu dlya razrabotki
   koda dlya yadra. Odin iz nih - `eto razrabotka v VMWare ili QEmu
   virtual'noj mashine (`eto luchshee iz dostupnogo, posle, konechno-zhe,
   vydelennogo dlya testov komp'yutera).

  2.1. Nastrojka sistemy dlya razrabotki

   Prezhde vsego neobhodimo imet' v yadre podderzhku INVARIANTS. Dobav'te
   sleduyuschie stroki v fajl konfiguracii yadra:

 options INVARIANT_SUPPORT
 options INVARIANTS

   Dlya bol'shej informativnosti pri otladke vklyuchite podderzhku WITNESS,
   kotoraya budet preduprezhdat' vas v sluchae vozniknoveniya
   vzaimoblokirovok:

 options WITNESS_SUPPORT
 options WITNESS

   Takzhe vklyuchite otladochnye simvoly, esli planiruete vypolnyat' otladku
   po dampam avarijnyh otkazov

   makeoptions    DEBUG=-g

   Ustanovka otladochnogo yadra obychnym sposobom (make installkernel) ne
   dast privychnogo rezul'tata: fajl yadra budet nazyvat'sya kernel.debug i
   budet nahodit'sya v /usr/obj/usr/src/sys/KERNELNAME/. Dlya udobstva,
   otladochnoe yadro neobhodimo skopirovat' v /boot/kernel/.

   Takzhe udobno imet' vklyuchennyj otladchik yadra, tak vy smozhete
   issledovat' paniki srazu-zhe posle ih vozniknoveniya. Dlya vklyucheniya
   otladchika dobav'te sleduyuschie stroki v fajl konfiguracii yadra:

 options KDB
 options DDB
 options KDB_TRACE

   Dlya avtomaticheskogo zapuska otladchika yadra posle vozniknoveniya paniki
   mozhet ponadobit'sya ustanovit' peremennuyu sysctl:

   debug.debugger_on_panic=1

   Paniki sistemy budut proishodit', po`etomu udelite vnimanie k`eshu
   fajlovoj sistemy. Obychno, pri vklyuchennom mehanizme softupdates,
   poslednyaya versiya fajla mozhet byt' uteryana esli panika proizoshla
   ran'she sbrasyvaniya k`esha na ustrojstvo hraneniya. Vyklyuchenie
   mehanizma softupdates (posredstvom montirovaniya fajlovoj sistemy s opciej
   <<sync>>) znachitel'no skazyvaetsya na proizvoditel'nosti i, opyat'-zhe,
   ne garantiruet celostnosti dannyh. Kak kompromiss, mozhno sokratit'
   zaderzhki sbrasyvaniya k`esha mehanizma softupdates. Est' tri peremennyh
   sysctl, znacheniya kotoryh neobhodimo izmenit' (luchshe vsego - propisav
   ih v /etc/sysctl.conf):

 kern.filedelay=5
 kern.dirdelay=4
 kern.metadelay=3

   Znacheniya `etih peremennyh - sekundy.

   Dlya otladki panik yadra neobhodimy dampy pamyati. Tak kak panika yadra
   mozhet <<slomat'>> fajlovuyu sistemu, damp snachala sohranyaetsya v
   <<syroj>> razdel. Obychno, `eto svop-razdel. Po`etomu, razmer svop-razdela
   dolzhen byt' ne men'she razmera OZU komp'yutera. Pri posleduyuschej
   zagruzke damp kopiruetsya v obychnyj fajl. `Eto proishodit srazu-zhe posle
   proverki i montirovaniya fajlovyh sistem, no pered aktivirovaniem razdela
   svopa. Takoe povedenie kontroliruetsya sleduyuschimi peremennymi
   /etc/rc.conf:

 dumpdev="/dev/ad0s4b"
 dumpdir="/usr/core"

   Peremennaya dumpdev ukazyvaet na razdel podkachki, a dumpdir soobschaet
   sisteme kuda peremeschat' damp yadra pri sleduyuschej zagruzke.

   Sohranenie dampa yadra - process medlennyj, i, esli u vashego komp'yutera
   mnogo operativnoj pamyati (>256M) i esli paniki sluchayutsya chasto, to
   ozhidanie sohraneniya dampov mozhet nachat' razdrazhat' (vspomnim, chto
   nad dampom proishodit dve operacii: sohranenie v svop-fajl i peremeschenie
   na fajlovuyu sistemu). V takom sluchae mozhet okazat'sya udobnym
   ogranichivanie ob"ema ispol'zuemoj sistemoj pamyati putem ustanovki
   peremennoj v /boot/loader.conf:

   hw.physmem="256M"

   Esli paniki sluchayutsya chasto i razmer fajlovyh sistem bol'shoj (ili zhe
   vy prosto ne doveryaete softupdates i fonovoj proverke fajlovyh sistem),
   rekomenduetsya otklyuchit' fonovuyu proverku fajlovyh sistem posredstvom
   ustanovki peremennoj v /etc/rc.conf:

   background_fsck="NO"

   V `etom sluchae fajlovye sistemy budut proveryat'sya tol'ko pri
   neobhodimosti. Takzhe zamet'te, chto v sluchae ispol'zovaniya fonovoj
   proverki, novaya panika mozhet sluchit'sya v to vremya, kogda
   proveryayutsya diski. Drugimi slovami, naibolee bezopasnyj sposob - ne
   imet' mnogo lokal'nyh fajlovyh sistem, a ispol'zovat' vtoroj komp'yuter v
   kachestve NFS-servera.

  2.2. Nachalo proekta

   Dlya napisaniya novogo klassa GEOM neobhodimo sozdat' poddirektoriyu v
   lyuboj dostupnoj pol'zovatelyu direktorii. Sovsem ne obyazatel'no, chtob
   vash modul' iznachal'no razmeschalsya v /usr/src.

  2.3. Makefile

   Pravilom horoshego tona yavlyaetsya sozdanie Makefile-ov dlya kazhdogo
   netrivial'nogo proekta, primerom kotorogo konechno-zhe yavlyaetsya
   sozdanie modulej yadra.

   Sozdanie Makefile - delo ne slozhnoe blagodarya ischerpyvayuschemu naboru
   vspomogatel'nyh sredstv, predostavlyaemyh sistemoj. V vkratce, vot kak
   dolzhen vyglyadet' Makefile dlya modulya yadra:

 SRCS=g_journal.c
 KMOD=geom_journal

 .include <bsd.kmod.mk>

   `Etot Makefile (s izmenennymi imenami fajlov) podojdet k lyubomu modulyu
   yadra. Klass GEOM mozhet razmeschat'sya v odnom edinstvennom module yadra.
   Esli dlya sborki vashego modulya trebuetsya bol'she, chem odin fajl, to
   perechislite ih imena, razdelennye probel'nymi simvolami, v peremennoj
   SRCS.

3. Programmirovanie v yadre FreeBSD

  3.1. Vydelenie pamyati

   Prochitajte malloc(9) - vydelenie pamyati lish' nemnogo otlichaetsya ot
   svoego `ekvivalenta, ispol'zuemogo v prostranstve pol'zovatel'skih
   processov (userland). Naibolee primetno to, chto malloc() i free()
   prinimayut dopolnitel'nye parametry, kotorye opisany v stranice
   spravochnika.

   Tip <<malloc_type>> neobhodimo ob"yavit' v sekcii deklaracij fajla s
   ishodnym kodom, naprimer:

   static MALLOC_DEFINE(M_GJOURNAL, "gjournal data", "GEOM_JOURNAL Data");

   Dlya togo, chtoby mozhno bylo ispol'zovat' `etot makros, neobhodimo
   vklyuchit' sleduyuschie zagolovochnye fajly: sys/param.h, sys/kernel.h i
   sys/malloc.h

   Suschestvuet esche odin mehanizm vydeleniya pamyati - UMA (Universal
   Memory Allocator), opisannyj v uma(9). `Eto specificheskij metod,
   preimuschestvenno prednaznachennyj dlya bystrogo vydeleniya pamyati pod
   spiski, sostoyaschie iz `elementov odinakovogo razmera (naprimer,
   dinamicheskie massivy struktur).

  3.2. Ocheredi i spiski

   Oznakom'tes' s queue(3) Vo mnozhestve sluchaev vam neobhodimo budet
   organizovyvat' i upravlyat' takoj strukturoj dannyh, kak spiski. K
   schast'yu, `eta struktura dannyh realizovana neskol'kimi sposobami v vide
   makrosov na Si, a takzhe vklyuchena v sistemu. Naibolee gibkij i chasto
   upotreblyaemyj tip spiska - TAILQ. `Etot tip spiska takzhe odin iz
   naibolee trebovatel'nyh k pamyati (ego `elementy - s dvojnymi svyazyami),
   a takzhe - naibolee medlennyj (odnako schet idet na neskol'ko instrukcij
   CPU, po`etomu poslednee utverzhdenie ne sleduet vosprinimat' v vser'ez).

   Esli vazhna skorost' polucheniya dannyh, to voz'mite na vooruzhenie
   tree(3) i hashinit(9).

  3.3. BIOs

   Struktura bio ispol'zuetsya dlya vseh operacij vvoda/vyvoda,
   kasayuschihsya GEOM. Ona soderzhit informaciyu o tom, kakoe ustrojstvo
   ('postavschik geom') dolzhno otvetit' na zapros, tip zaprosa, smeschenie,
   dlinu i ukazatel' na bufer, a takzhe nabor <<opredelennyh pol'zovatelem>>
   flagov i polej .

   Vazhnym momentom yavlyaetsya to, chto bio obrabatyvayutsya asinhronno.
   `Eto znachit, chto vo mnogih chastyah koda net analoga k read(2) i
   write(2) funkciyam iz prostranstva pol'zovatel'skih processov, kotorye ne
   vozvraschayut upravlenie poka ne vypolnitsya sistemnyj vyzov. Skoree, po
   zavershenii obrabotki zaprosa (ili v sluchae oshibki pri obrabotke) kak
   izveschenie vyzyvaetsya opredelennaya pol'zovatelem funkciya.

   Asinhronnaya model' programmirovaniya v chem-to slozhnej, nezheli chasche
   ispol'zuemaya imperativnaya model', ispol'zuemaya v prostranstve
   pol'zovatel'skih processov; v lyubom sluchae, privykanie zajmet nekotoroe
   vremya. V nekotoryh sluchayah mogut byt' ispol'zovany vspomogatel'nye
   funkcii g_write_data() i g_read_data(), no daleko ne vsegda. V chastnosti,
   `eti funkcii ne mogut ispol'zovat'sya kogda zahvachen m'yuteks; naprimer,
   m'yuteks GEOM-topologii ili vnutrennij m'yuteks, uderzhivaemyj v hode
   vypolneniya .start() ili .stop().

4. Programmirovanie v sisteme GEOM

  4.1. Ggate

   Esli maksimal'naya proizvoditel'nost' ne trebuetsya, to bolee prostoj
   sposob sovershat' preobrazovaniya dannyh - `eto vypolnyat' ih v
   prostranstve pol'zovatel'skih processov posredstvom ggate (GEOM gate). K
   nedostatkam sleduet otnesti nevozmozhnost' prostogo perenosa koda v yadro.

  4.2. Klass GEOM

   Klass GEOM vypolnyaet preobrazovaniya dannyh. `Eti preobrazovaniya mogut
   byt' skomponovany drug s drugom v vide dereva. `Ekzemplyar klassa GEOM
   nazyvayut geom.

   V kazhdom klasse GEOM est' neskol'ko <<metodov klassa>>, kotorye
   vyzyvayutsya kogda `ekzemplyara klassa net v nalichii (ili zhe oni ne
   privyazany k konkretnomu `ekzemplyaru klassa).

     * .init vyzyvaetsya togda, kogda sisteme GEOM stanovitsya izvestno o
       klasse GEOM (naprimer, kogda zagruzhaetsya modul' yadra).

     * .fini budet vyzvan v sluchae otkaza GEOM sistemy ot klassa (naprimer,
       pri vygruzke modulya).

     * .taste vyzyvaetsya, kogda v sisteme poyavlyaetsya novyj klass ili
       postavschik geom (<<provider>>). Esli sootvetstvie najdeno, to `eta
       funkciya obychno sozdaet i zapuskaet `ekzemplyar geom.

     * .destroy_geom vyzyvaetsya pri neobhodimosti razrushit' `ekzemplyar
       geom.

     * .ctlconf budet vyzvan, kogda pol'zovatel' zaprosit izmenenie
       konfiguracii suschestvuyuschego `ekzemplyara geom

   Takzhe opredeleny funkcii sobytij GEOM, kotorye kopiruyutsya v `ekzemplyar
   geom.

   Pole .geom v strukture g_class - `eto spisok (LIST) `ekzemplyarov geom,
   realizovannyh iz klassa.

   `Eti funkcii vyzyvayutsya iz g_event potoka yadra.

  4.3. Softc

   <<softc>> - `eto ustarevshij termin dlya <<privatnyh dannyh drajvera>>
   (<<driver private data>>). Nazvanie veroyatnej vsego proishodit ot
   ustarevshego termina <<software control block>>. V sisteme GEOM softc `eto
   struktura (tochnee: ukazatel' na strukturu) kotoraya mozhet byt'
   prisoedinena k `ekzemplyaru geom i mozhet soderzhat' privatnye dannye
   `ekzemplyara. U bol'shinstva klassov GEOM est' sleduyuschie chleny:

     * struct g_provider *provider : <<postavschik geom>> predostavlyaemyj
       dannym `ekzemplyarom geom

     * uint16_t n_disks : Kolichestvo potrebitelej geom (<<consumer>>),
       obsluzhivaemyh dannym `ekzemplyarom geom

     * struct g_consumer **disks : Massiv struct g_consumer*. (Nevozmozhno
       obojtis' odinarnym ukazatelem, potomu chto sistema GEOM sozdaet dlya
       nas struktury struct g_consumer*)

   Struktura softc soderzhit sostoyanie `ekzemplyara geom. U kazhdogo
   `ekzemplyara est' svoj softc.

  4.4. Metadannye

   Format metadannyh v toj ili inoj mere zavisit ot konkretnogo klassa, no
   obyazan nachinat'sya s:

     * 16-bajtnogo bufera dlya podpisi - stroki s zavershayuschim nulem
       (obychno `eto imya klassa)

     * uint32 identifikatora versii

   Podrazumevaetsya, chto klassy geom znayut kak obraschat'sya s metadannymi
   s identifikatorami versij nizhe, chem ih sobstvennye.

   Metadannye razmeschayutsya v poslednem sektore postavschika geom (po`etomu
   obyazany celikom umeschat'sya v nem).

   (Vse `eto zavisit ot realizacii, no ves' suschestvuyuschij kod rabotaet
   podobno opisannomu i podderzhivaetsya bibliotekami.)

  4.5. Markirovanie/sozdanie `ekzemplyara geom

   Posledovatel'nost' sobytij sleduyuschaya:

     * pol'zovatel' zapuskaet sluzhebnuyu programmu geom(8)

     * programma reshaet kakim klassom geom ej pridetsya upravlyat' i ischet
       biblioteku geom_CLASSNAME.so (kotoraya obychno nahoditsya v
       /lib/geom).

     * ona otkryvaet biblioteku pri pomoschi dlopen(3), izvlekaet
       vspomogatel'nye funkcii i opredeleniya parametrov komandnoj stroki.

   Vot tak proishodit sozdanie/markirovanie novogo `ekzemplyara geom:

     * geom(8) ischet komandu v argumentah komandnoj stroki (obychno `eto
       label) i vyzyvaet vspomogatel'nuyu funkciyu.

     * Vspomogatel'naya funkciya proveryaet parametry i sobiraet metadannye,
       kotorye zapisyvayutsya vo vse vovlechennye postavschiki geom.

     * `Eto <<povrezhdaet (spoil)>> suschestvuyuschie `ekzemplyary geom (esli
       oni byli) i porozhdaet novyj vitok <<testirovaniya>> postavschikov
       geom. Celevoj klass geom opoznaet metadannye i aktiviruet `ekzemplyar
       geom.

   (Privedennaya vyshe posledovatel'nost' sobytij zavisit ot konkretnoj
   realizacii, no ves' suschestvuyuschij kod rabotaet podobno opisannomu i
   podderzhivaetsya bibliotekami.)

  4.6. Struktura komand geom

   Vspomogatel'naya biblioteka geom_CLASSNAME.so `eksportiruet strukturu
   class_commands, kotoraya yavlyaetsya massivom `elementov struct g_command.
   `Eti komandy odinakovogo formata i vyglyadyat sleduyuschim obrazom:

   komanda [-opcii] imya_geom [drugie]

   Obschimi komandami yavlyayutsya:

     * label - zapisat' metadannye v ustrojstva, chtoby oni mogli byt'
       opoznany v processe testirovaniya i ispol'zovany v sootvetstvuyuschih
       `ekzemplyarah geom

     * destroy - razrushit' metadannye, za kotorym posleduet razrushenie
       `ekzemplyarov geom

   Obschie opcii:

     * -v : detal'nyj vyvod

     * -f : prinudit'

   Nekotorye operacii, k primeru markirovanie metadannymi i razrushenie
   metadannyh mogut byt' vypolneny iz prostranstva pol'zovatel'skih
   processov. Dlya `etogo, struktura g_command soderzhit pole gc_func,
   kotoroe mozhet byt' ustanovleno na funkciyu (v tom-zhe .so), kotoraya
   budet vyzvana dlya obrabotki komandy. V sluchae, kogda gc_func ravno NULL,
   komanda budet peredana modulyu yadra: funkcii .ctlreq klassa GEOM.

  4.7. `Ekzemplyary geom

   U `ekzemplyarov klassov GEOM est' vnutrennie dannye, kotorye hranyatsya v
   strukturah softc, a takzhe est' nekotorye funkcii, posredstvom kotoryh oni
   reagiruyut na vneshnie sobytiya.

   Funkcii sobytij:

     * .access : proschityvaet prava dostupa (chtenie/zapis'/isklyuchitel'nyj
       dostup)

     * .dumpconf : vozvraschaet informaciyu o `ekzemplyare geom; format XML

     * .orphan : vyzyvaetsya, kogda otsoedinyaetsya lyuboj iz nizlezhaschih
       postavschikov geom

     * .spoiled : vyzyvaetsya, kogda proizvoditsya zapis' v nizlezhaschij
       postavschik geom

     * .start : obrabatyvaet vvod/vyvod

   `Eti funkcii vyzyvayutsya iz yadernogo potoka g_down i v `etom kontekste
   ne mozhet byt' blokirovok (poischite opredelenie <<blokirovka>> v drugih
   istochnikah), chto nemnogo ogranichivaet svobodu dejstvij, no sposobstvuet
   bystrote obrabotki.

   Iz vysheupomyanutyh, naibolee vazhnoj i vypolnyayuschej poleznuyu rabotu
   funkciej yavlyaetsya .start(), kotoraya vyzyvaetsya vsyakij raz, kogda
   postavschiku geom, upravlyaemomu `ekzemplyarom klassa, prihodit zapros
   BIO.

  4.8. Potoki vypolneniya sistemy geom

   Sistemoj GEOM v yadre OS sozdayutsya i ispol'zuyutsya tri potoka
   vypolneniya (kernel threads):

     * g_down : Obrabatyvaet zaprosy, prihodyaschie ot vysokourovnevyh
       suschnostej (takih, kak zaprosy iz prostranstva pol'zovatel'skih
       processov) na puti k fizicheskim ustrojstvam

     * g_up : Obrabatyvaet otvety ot drajverov ustrojstv na zaprosy,
       vypolnennye vysokourovnevymi suschnostyami

     * g_event : Otrabatyvaet v ostal'nyh sluchayah, kak-to sozdanie
       `ekzemplyara geom, proschityvanie prav dostupa, sobytiya
       <<povrezhdeniya>> i t.p.

   Kogda pol'zovatel'skij process zaprashivaet <<prochitat' dannye X po
   smescheniyu Y fajla>>, proishodit sleduyuschee:

     * Fajlovaya sistema preobrazuet zapros v `ekzemplyar struktury bio i
       peredaet ego sisteme GEOM. Fajlovaya sistema <<znaet>>, chto
       `ekzemplyar geom dolzhen obrabotat' zapros, tak kak fajlovye sistemy
       razmeschayutsya neposredstvenno nad `ekzemplyarom geom.

     * Zapros zavershaetsya vyzovom funkcii .start() v potoke g_down i
       dostigaet verhnego `ekzemplyara geom.

     * Verhnij `ekzemplyar geom (naprimer, `eto sekcionirovschik razdelov
       (partition slicer)) opredelyaet, chto zapros dolzhen byt'
       pereadresovan nizhestoyaschemu `ekzemplyaru geom (k primeru, drajveru
       diska). Vyshestoyaschij `ekzemplyar geom sozdaet kopiyu zaprosa bio
       (zaprosy bio VSEGDA kopiruyutsya pri peredache mezhdu `ekzemplyarami
       geom pri pomoschi g_clone_bio()!), izmenyaet polya smescheniya i
       celevogo postavschika geom i zapuskaet na obrabotku kopiyu pri
       pomoschi funkcii g_io_request()

     * Drajver diska takzhe poluchaet zapros bio, kak vyzov funkcii .start()
       v potoke g_down. Drajver obraschaetsya k kontrolleru diska, poluchaet
       blok dannyh i vyzyvaet funkciyu g_io_deliver() ispol'zuya kopiyu
       zaprosa bio

     * Teper', izveschenie o zavershenii bio <<vsplyvaet>> v potoke g_up.
       Snachala v potoke g_up vyzyvaetsya funkciya .done() sekcionirovschika
       razdelov, poslednij ispol'zuet poluchennuyu informaciyu, razrushaet
       klonirovannyj `ekzemplyar struktury bio posredstvom g_destroy_bio() i
       vyzyvaet g_io_deliver() ispol'zuya pervonachal'nyj zapros

     * Fajlovaya sistema poluchaet dannye i peredaet ih pol'zovatel'skomu
       processu

   Za informaciej o tom, kak dannye peredayutsya v strukture bio mezhdu
   `ekzemplyarami geom, smotrite g_bio(9) (obratite vnimanie na ispol'zovanie
   polej bio_parent i bio_children).

   Vazhnyj moment v tom, chto NEL'ZYA DOPUSKAT' BLOKIROVOK V POTOKAH G_UP I
   G_DOWN. Vot nepolnyj perechen' togo, chto nel'zya delat' v `etih potokah:

     * Vyzyvat' funkcii msleep() ili tsleep().

     * Ispol'zovat' funkcii g_write_data() i g_read_data(), tak kak oni
       blokiruyutsya v moment obmena dannymi s potrebitelyami geom.

     * Ozhidat' vvod/vyvod.

     * Vyzyvat' malloc(9) i uma_zalloc() s ustanovlennym flagom M_WAITOK.

     * Ispol'zovat' sx(9)

   `Eto ogranichenie na kod GEOM prizvano izbezhat' ot <<zasoreniya>> puti
   zaprosa vvoda/vyvoda, tak kak blokirovki obychno ne imeyut chetkih
   vremennyh granic, i net garantij na zanimaemoe vremya (takzhe na to est' i
   drugie tehnicheskie prichiny). `Eto takzhe znachit, chto v
   vysheupomyanutyh potokah skol'-nibud' slozhnye operacii vypolnit' nel'zya,
   naprimer: lyuboe slozhnoe preobrazovanie trebuet vydeleniya pamyati. K
   schast'yu reshenie est': sozdanie dopolnitel'nyh yadernyh potokov.

  4.9. YAdernye potoki vypolneniya, prednaznachennye dlya ispol'zovaniya v kode
  geom

   YAdernye potoki vypolneniya sozdayutsya funkciej kthread_create(9), v
   svoem povedenii oni shozhi s potokami, sozdannymi v prostranstve
   pol'zovatel'skih processov, no est' odno otlichie: oni ne mogut izvestit'
   vyzvavshij ih potok o svoem zavershenii; po zaversheniyu - neobhodimo
   vyzyvat' kthread_exit(9)

   V kode GEOM obychnoe naznachenie `etih potokov - razgruzit' potok g_down
   (funkciyu .start() ) ot obrabotki zaprosov. `Eti potoki podobny
   <<obrabotchikam sobytij>> (<<event handlers>>): u nih est' ochered'
   sobytij (kotoraya napolnyaetsya sobytiyami ot raznyh funkcij iz raznyh
   potokov; ochered' neobhodimo zaschischat' m'yuteksom), sobytiya iz
   ocheredi vybirayutsya odno za drugim i obrabatyvayutsya v bol'shom bloke
   switch().

   Osnovnoe preimuschestvo ispol'zovaniya otdel'nogo potoka, kotoryj
   obrabatyvaet zaprosy vvoda/vyvoda, to, chto on mozhet blokirovat'sya po
   mere neobhodimosti. `Eto, nesomnenno, privlekatel'no, no dolzhno byt'
   horosho obdumano. Blokirovanie - horosho i udobno, no mozhet suschestvenno
   snizit' proizvoditel'nost' preobrazovanij dannyh v sisteme GEOM. Osobo
   trebovatel'nye k proizvoditel'nosti klassy mogut delat' vsyu rabotu v
   funkcii .start(), udelyaya osoboe vnimanie oshibkam pri rabote s
   pamyat'yu.

   Esche odno preimuschestvo potoka <<obrabotchika sobytij>> `eto
   serializaciya vseh zaprosov i otvetov, prihodyaschih s raznyh potokov geom
   v odin potok. `Eto takzhe udobno, no mozhet byt' medlennym. V bol'shinstve
   sluchaev, obrabotka zaprosov funkciej .done() mozhet byt' ostavlena potoku
   g_up.

   U m'yuteksov v yadre FreeBSD (mutex(9)) est' odno razlichie s ih analogami
   iz prostranstva pol'zovatel'skih processov - vo vremya uderzhaniya
   m'yuteksa v kode ne dolzhno byt' blokirovki. Esli v kode neobhodimo
   blokirovanie, to luchshe ispol'zovat' sx(9). S drugoj storony, esli vsya
   vasha rabota vypolnyaetsya v odnom potoke, vy mozhete obojtis' voobsche
   bez m'yuteksov.
