プロセスグループ
プロセスごとに名前空間を持つと言ってきたが,正確にはプロセスグループごとに名前空間を持つと言える.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: }