プロセスグループ

プロセスごとに名前空間を持つと言ってきたが,正確にはプロセスグループごとに名前空間を持つと言える.Proc構造体はプロセスグループを示すPgrpへのポインタを持っている.UNIXの場合は,名前空間はシステムで一つだったのでマウントテーブルはシステムで一つでよかった.一方,Plan9の場合は,プロセス(グループ)ごとにマウントテーブルを持つ必要がある.この辺が名前空間のキモっぽいなぁ.

この辺からぽつぽつ出てくるQidはファイルサーバローカルなファイルの識別子である.

port/lib.h
  163: struct Qid
  164: {
  165:         uvlong path;
  166:         ulong  vers;
  167:         uchar  type;
  168: };

port/portdat.h
 424: #define MOUNTH(p,qid)   ((p)->mnthash[(qid).path&((1<<MNTLOG)-1)])

Pgrp構造体はこんな感じ.マウントテーブルはmnthashというハッシュテーブルとして実装されている.ハッシュ関数はMOUNTHマクロで,Qid.pathからMheadへのポインタを求める.マウントできるファイルサーバの上限は2^5だから,32個かぁ.

port/portdat.h
  417:         MNTLOG =       5,
  418:         MNTHASH =      1<<MNTLOG,   /* Hash to walk mount table */

  426: struct Pgrp
  427: {
  428:         Ref;                           /* also used as a lock when mounting */
  429:         int    noattach;
  430:         ulong  pgrpid;
  431:         QLock  debug;                   /* single access via devproc.c */
  432:         RWlock ns;                     /* Namespace n read/one write lock */
  433:         Mhead  *mnthash[MNTHASH];
  434: };

まず,oldがカレントプロセスグループでmountされているかチェックして,mountされていなかったmountする.そして,newをmnthashに追加する.名前空間の設定は引数flagごとに異なる.MREPLの場合は,oldをnewで置きかえる.oldとnewが共にディレクトリの場合は,MBEFOREとMAFTERを指定できる.これらはユニオンディレクトリの指定で,newが先に見えるのがMBEFOREで,後に見えるのがMAFTERを指定した場合になる.なお,MREPL,MBEFORE,MAFTERは,bind(1)およびmount(1)コマンドのオプションなし,-b,-aオプションに対応する.

port/chan.c
  628: int
  629: cmount(Chan **newp, Chan *old, int flag, char *spec)
  630: {
  631:         int order, flg;
  632:         Chan *new;
  633:         Mhead *m, **l, *mh;
  634:         Mount *nm, *f, *um, **h;
  635:         Pgrp *pg;

  643:         order = flag&MORDER;

  648:         new = *newp;
  649:         mh = new->umh;

  673:         pg = up->pgrp;

  676:         l = &MOUNTH(pg, old->qid);
  677:         for(m = *l; m; m = m->hash){
  678:                 if(eqchan(m->from, old, 1))
  679:                         break;
  680:                 l = &m->hash;
  681:         }
  682: 
  683:         if(m == nil){
  684:                 /*
  685:                  *  nothing mounted here yet.  create a mount
  686:                  *  head and add to the hash table.
  687:                  */
  688:                 m = newmhead(old);
  689:                 *l = m;
  690: 
  691:                 /*
  692:                  *  if this is a union mount, add the old
  693:                  *  node to the mount chain.
  694:                  */
  695:                 if(order != MREPL)
  696:                         m->mount = newmount(m, old, 0, 0);
  697:         }
  704: 
  705:         nm = newmount(m, new, flag, spec);
  706:         if(mh != nil && mh->mount != nil){
  707:                 /*
  708:                  *  copy a union when binding it onto a directory
  709:                  */
  710:                 flg = order;
  711:                 if(order == MREPL)
  712:                         flg = MAFTER;
  713:                 h = &nm->next;
  714:                 um = mh->mount;
  715:                 for(um = um->next; um; um = um->next){
  716:                         f = newmount(m, um->to, flg, um->spec);
  717:                         *h = f;
  718:                         h = &f->next;
  719:                 }
  720:         }
  721: 
  722:         if(m->mount && order == MREPL){
  723:                 mountfree(m->mount);
  724:                 m->mount = 0;
  725:         }
  726: 
  727:         if(flag & MCREATE)
  728:                 nm->mflag |= MCREATE;
  729: 
  730:         if(m->mount && order == MAFTER){
  731:                 for(f = m->mount; f->next; f = f->next)
  732:                         ;
  733:                 f->next = nm;
  734:         }else{
  735:                 for(f = nm; f->next; f = f->next)
  736:                         ;
  737:                 f->next = m->mount;
  738:                 m->mount = nm;
  739:         }

  743:         return nm->mountid;
  744: }

最後にnewmount関数を示す.

port/pgrp.c
  261: Mount*
  262: newmount(Mhead *mh, Chan *to, int flag, char *spec)
  263: {
  264:         Mount *m;
  265: 
  266:         m = smalloc(sizeof(Mount));
  267:         m->to = to;
  268:         m->head = mh;
  269:         incref(to);
  270:         m->mountid = incref(&mountid);
  271:         m->mflag = flag;
  272:         if(spec != 0)
  273:                 kstrdup(&m->spec, spec);
  274: 
  275:         return m;
  276: }