[Kos-dev] Progressions du WE

d2 kos-dev@enix.org
28 Apr 2003 11:23:36 +0200


Hello,

Ca a ete productif a ce que je vois : plus que moi en tous cas (en
vacances de mercredi a hier). J'ai rapidement lu les 53 mails que
j'avais en retard sur ces 5 jours, mais pas le code qui va
avec. Desole de ne pas avoir participe au developpement ni au
brainstorming.

Pour l'idee de la "serialisation" (qui, je confirme, veut dire en
info: "mise a plat" de structure de donnees, et meme de code, pour
(entre autre) faire disparaitre tout pointeur, dans le but de
transmettre donnees ou taches en cours a travers un reseau ou tout
autre "tuyau" de ce style), d'apres ce que je comprends, ca correspond
a un mecanisme d'empilement d'interfaces ("stackable resources" on
pourrait dire, ce qui ferait toujours "sres" en abrege). Julien, je
resume dans ce qui suit ce que je comprends a ta proposition.

La difference avec un open "canonique" est que pour un open canonique
on doit seulement connaitre le nom de la ressource avant de recuperer
une kres (+ l'interface pour creer une ures).  Ici on a besoin du nom
canonique juste pour la premiere interface ("block" dans son exemple)
du open de la sres. Pour les 2 autres (ie "libblockcache:bs=512" et
"part"), on n'utilise plus le nommage du FS, mais on part directement
de l'ures construite a partir de la 1ere interface, pour construire
d'autres kres : c'est necessaire de construire d'autres kres puisque a
priori quand un driver definit sa notion de kres, il ne prevoit pas
les structures de donnees utiles aux couches qui pourraient venir
s'empiler au dessus. En effet un driver de disque a interet a proposer
le necessaire dans la kres pour permettre l'interface "block", mais ne
peut pas prevoir a priori qu'il faudra des donnees supplementaires (et
quelles donnees supplementaires) pour l'interface libblockcache et
part. D'ou le besoin de pouvoir creer une kres a partir d'un nom, mais
egalement a partir d'une kres ouverte suivant une interface donnee (ie
une ures "interne" au noyau).

Bref, tout ca pour dire que cette idee me parait interessante. En
somme, avec l'exemple de Julien, on ferait :
 - lookup de la kres /dev/hda
 - creation d'une ures intermediaire (interne au noyau) avec
   l'interface "block". On est oblige de passer par une ures parce
   qu'il faut associer l'interface block a la kres
 - utilisation de cette ures interne pour la creation d'une kres par
   libblockcache. On suppose que ca cree de facto une ures associee
   avec une interface unique implicite (definie par
   libblockcache). Encore une fois c'est une ures interne au noyau
 - utilisation de cette ures interne pour la creation d'une kres par
   part. On suppose que ca cree de facto une ures associee avec une
   interface unique implicite (definie par part). C'est cette ures
   que l'utilisateur pourra manipuler.

On voit apparaitre 2 types de ures (ie une kres ouverte avec une
interface donnee) : ures "interne au noyau", et ures au sens habituel
(ie figurant dans la liste des ures ouvertes par le processus). De
meme 2 scenarios d'ouverture de kres (et d'ures) : a partir d'un nom,
ou a partir d'une ures "interne". Je vois une difficulte importante a
prendre en compte : si 3 processus font l'open de l'exemple a Julien,
il faut que les 2 ures internes (celles apres ouverture suivant block
et celle apres ouverture suivant libblockcache) correspondent a 2 kres
seulement, et non pas a 3x2 = 6 ures (sinon le cache risque de pas
s'en sortir s'il a pas moyen de faire simplement un lookup pour voir
si un block demande n'a pas deja ete charge) ! Ce qui est difficile
puisque le cache de kres jusqu'a maintenant utilisait un lookup a
partir du nom de la kres. Desormais, le nom ne suffit pas, il faut
prendre en compte l'empilement d'interfaces.

Bon, est-ce que j'ai pige comme il faut ?

Sinon, concernant la proposition de Thomas, je pense l'avoir comprise,
elle me semble plus directe. Si j'en reste aux mails que t'as envoyes
(et pas au code, que je n'ai pas regarde), l'idee est de laisser au
developpeur la responsabilite de superposer les couches directement
dans le code du driver, plutot que de demander a l'utilisateur de s'en
charger (en precisant l'empilement de ressources). Ca me semble etre
en accord avec un principe de base, qui est que toute la cuisine pour
le dialogue cpl3/cpl0 (aka interfaces) soit independante de la cuisine
interne au noyau concernant la gestion de ressources (faudra qu'on me
traduise "KARM" : KOS A*** Resource Manager ???).

Entre les 2 methodes, je dirais que celle de Julien est plus
seduisante, mais me semble poser d'importants problemes. Le premier
est celui de la verification de compatibilite entre couches. Je ne
vois pas d'exemple a ca, la maintenant tout de suite. Je pense qu'en
regle generale on prend plus de risques en laissant l'utilisateur
definir son empilement. Un autre probleme : cette methode me semble
empiler "dans un sens" ie : on suppose qu'une couche (haute) B repose
sur une autre couche (basse) A, ie qu'on a naturellement le lien B->A,
et qu'on n'a pas besoin de s'embeter avec le lien A->B. En regle
generale ca suffit : A n'a pas a avoir conscience de la couche B qui
est au dessus, ie le lien A->B n'a pas besoin d'exister. Mais si on
imagine un systeme de fichiers en reseau (autre que NFS) dans lequel
chaque machine possede une couche A qui s'occupe de l'acces reseau, et
une couche B (au-dessus) qui s'occupe de la gestion d'un cache : on a
un probleme si A ne peut pas invalider le cache B, ie si le lien A->B
n'existe pas. Bref, dans ce cas le mecanisme d'empilement se
complexifie terriblement, puisqu'il faut prevoir des mecanismes de
rappel d'une couche basse vers la couche haute, ce qui brise la notion
d'interface a A (pour le lien B->A) qui aurait du etre *suffisante* :
en effet, il faut alors prevoir une interface rudimentaire pour le
lien A->B. On retrouve le meme probleme avec le hotplug : si on a un
USB de type mass storage qu'on debranche, il faut invalider le cache
associe (si l'*utilisateur* a choisi d'en utiliser un). Bref, c'est
vrai que gerer ces parties sensibles directement au niveau du noyau
evite 1/ les ouvertures en cascades, les verifs et les indirections en
chaines quand on veut un service d'une interface (pb d'efficacite), 2/
les problemes des fonctions de rappel A->B.

Voila mes premieres reflexions sur le sujet. Bien que vraiment seduit
par l'idee de Julien, j'aimerais rappeler quand meme que "simple is
beautiful", du moins dans un premier temps...

Bonne journee,

-- 
d2