devmnt.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. /*
  16. * References are managed as follows:
  17. * The channel to the server - a network connection or pipe - has one
  18. * reference for every Chan open on the server. The server channel has
  19. * c->mux set to the Mnt used for muxing control to that server. Mnts
  20. * have no reference count; they go away when c goes away.
  21. * Each channel derived from the mount point has mchan set to c,
  22. * and increfs/decrefs mchan to manage references on the server
  23. * connection.
  24. */
  25. #define MAXRPC (IOHDRSZ+128*1024)
  26. struct Mntrpc
  27. {
  28. Chan* c; /* Channel for whom we are working */
  29. Mntrpc* list; /* Free/pending list */
  30. Fcall request; /* Outgoing file system protocol message */
  31. Fcall reply; /* Incoming reply */
  32. Mnt* m; /* Mount device during rpc */
  33. Rendez r; /* Place to hang out */
  34. uint8_t* rpc; /* I/O Data buffer */
  35. uint rpclen; /* len of buffer */
  36. Block *b; /* reply blocks */
  37. char done; /* Rpc completed */
  38. uint64_t stime; /* start time for mnt statistics */
  39. uint32_t reqlen; /* request length for mnt statistics */
  40. uint32_t replen; /* reply length for mnt statistics */
  41. Mntrpc* flushed; /* message this one flushes */
  42. };
  43. enum
  44. {
  45. TAGSHIFT = 5, /* uint32_t has to be 32 bits */
  46. TAGMASK = (1<<TAGSHIFT)-1,
  47. NMASK = (64*1024)>>TAGSHIFT,
  48. };
  49. struct Mntalloc
  50. {
  51. Lock Lock;
  52. Mnt* list; /* Mount devices in use */
  53. Mnt* mntfree; /* Free list */
  54. Mntrpc* rpcfree;
  55. int nrpcfree;
  56. int nrpcused;
  57. uint id;
  58. uint32_t tagmask[NMASK];
  59. }mntalloc;
  60. Mnt* mntchk(Chan*);
  61. void mntdirfix(uint8_t*, Chan*);
  62. Mntrpc* mntflushalloc(Mntrpc*, uint32_t);
  63. void mntflushfree(Mnt*, Mntrpc*);
  64. void mntfree(Mntrpc*);
  65. void mntgate(Mnt*);
  66. void mntpntfree(Mnt*);
  67. void mntqrm(Mnt*, Mntrpc*);
  68. Mntrpc* mntralloc(Chan*, uint32_t);
  69. int32_t mntrdwr(int, Chan*, void*, int32_t, int64_t);
  70. int mntrpcread(Mnt*, Mntrpc*);
  71. void mountio(Mnt*, Mntrpc*);
  72. void mountmux(Mnt*, Mntrpc*);
  73. void mountrpc(Mnt*, Mntrpc*);
  74. int rpcattn(void*);
  75. Chan* mntchan(void);
  76. char Esbadstat[] = "invalid directory entry received from server";
  77. char Enoversion[] = "version not established for mount channel";
  78. void (*mntstats)(int, Chan*, uint64_t, uint32_t);
  79. static void
  80. mntreset(void)
  81. {
  82. mntalloc.id = 1;
  83. mntalloc.tagmask[0] = 1; /* don't allow 0 as a tag */
  84. mntalloc.tagmask[NMASK-1] = 0x80000000UL; /* don't allow NOTAG */
  85. fmtinstall('F', fcallfmt);
  86. fmtinstall('D', dirfmt);
  87. /* We can't install %M since eipfmt does and is used in the kernel [sape] */
  88. if(mfcinit != nil)
  89. mfcinit();
  90. }
  91. /*
  92. * Version is not multiplexed: message sent only once per connection.
  93. */
  94. usize
  95. mntversion(Chan *c, uint32_t msize, char *version, usize returnlen)
  96. {
  97. Proc *up = externup();
  98. Fcall f;
  99. uint8_t *msg;
  100. Mnt *mnt;
  101. char *v;
  102. int32_t l, n;
  103. usize k;
  104. int64_t oo;
  105. char buf[128];
  106. qlock(&c->umqlock); /* make sure no one else does this until we've established ourselves */
  107. if(waserror()){
  108. qunlock(&c->umqlock);
  109. nexterror();
  110. }
  111. /* defaults */
  112. if(msize == 0)
  113. msize = MAXRPC;
  114. if(msize > c->iounit && c->iounit != 0)
  115. msize = c->iounit;
  116. v = version;
  117. if(v == nil || v[0] == '\0')
  118. v = VERSION9P;
  119. /* validity */
  120. if(strncmp(v, VERSION9P, strlen(VERSION9P)) != 0)
  121. error("bad 9P version specification");
  122. mnt = c->mux;
  123. if(mnt != nil){
  124. qunlock(&c->umqlock);
  125. poperror();
  126. strecpy(buf, buf+sizeof buf, mnt->version);
  127. k = strlen(buf);
  128. if(strncmp(buf, v, k) != 0){
  129. snprint(buf, sizeof buf, "incompatible 9P versions %s %s", mnt->version, v);
  130. error(buf);
  131. }
  132. if(returnlen != 0){
  133. if(returnlen < k)
  134. error(Eshort);
  135. memmove(version, buf, k);
  136. }
  137. return k;
  138. }
  139. f.type = Tversion;
  140. f.tag = NOTAG;
  141. f.msize = msize;
  142. f.version = v;
  143. msg = malloc(8192+IOHDRSZ);
  144. if(msg == nil)
  145. exhausted("version memory");
  146. if(waserror()){
  147. free(msg);
  148. nexterror();
  149. }
  150. k = convS2M(&f, msg, 8192+IOHDRSZ);
  151. if(k == 0)
  152. error("bad fversion conversion on send");
  153. lock(&c->r.l);
  154. oo = c->offset;
  155. c->offset += k;
  156. unlock(&c->r.l);
  157. l = c->dev->write(c, msg, k, oo);
  158. if(l < k){
  159. lock(&c->r.l);
  160. c->offset -= k - l;
  161. unlock(&c->r.l);
  162. error("short write in fversion");
  163. }
  164. /* message sent; receive and decode reply */
  165. n = c->dev->read(c, msg, 8192+IOHDRSZ, c->offset);
  166. if(n <= 0)
  167. error("EOF receiving fversion reply");
  168. lock(&c->r.l);
  169. c->offset += n;
  170. unlock(&c->r.l);
  171. l = convM2S(msg, n, &f);
  172. if(l != n)
  173. error("bad fversion conversion on reply");
  174. if(f.type != Rversion){
  175. if(f.type == Rerror)
  176. error(f.ename);
  177. error("unexpected reply type in fversion");
  178. }
  179. if(f.msize > msize)
  180. error("server tries to increase msize in fversion");
  181. if(f.msize<256 || f.msize>1024*1024)
  182. error("nonsense value of msize in fversion");
  183. k = strlen(f.version);
  184. if(strncmp(f.version, v, k) != 0)
  185. error("bad 9P version returned from server");
  186. /* now build Mnt associated with this connection */
  187. lock(&mntalloc.Lock);
  188. mnt = mntalloc.mntfree;
  189. if(mnt != nil)
  190. mntalloc.mntfree = mnt->list;
  191. else {
  192. mnt = malloc(sizeof(Mnt));
  193. if(mnt == nil) {
  194. unlock(&mntalloc.Lock);
  195. exhausted("mount devices");
  196. }
  197. }
  198. mnt->list = mntalloc.list;
  199. mntalloc.list = mnt;
  200. mnt->version = nil;
  201. kstrdup(&mnt->version, f.version);
  202. mnt->id = mntalloc.id++;
  203. mnt->q = qopen(10*MAXRPC, 0, nil, nil);
  204. mnt->msize = f.msize;
  205. unlock(&mntalloc.Lock);
  206. if(returnlen != 0){
  207. if(returnlen < k)
  208. error(Eshort);
  209. memmove(version, f.version, k);
  210. }
  211. poperror(); /* msg */
  212. free(msg);
  213. lock(&mnt->l);
  214. mnt->queue = 0;
  215. mnt->rip = 0;
  216. c->flag |= CMSG;
  217. c->mux = mnt;
  218. mnt->c = c;
  219. unlock(&mnt->l);
  220. poperror(); /* c */
  221. qunlock(&c->umqlock);
  222. return k;
  223. }
  224. Chan*
  225. mntauth(Chan *c, char *spec)
  226. {
  227. Proc *up = externup();
  228. Mnt *mnt;
  229. Mntrpc *r;
  230. mnt = c->mux;
  231. if(mnt == nil){
  232. mntversion(c, MAXRPC, VERSION9P, 0);
  233. mnt = c->mux;
  234. if(mnt == nil)
  235. error(Enoversion);
  236. }
  237. c = mntchan();
  238. if(waserror()) {
  239. /* Close must not be called since it will
  240. * call mnt recursively
  241. */
  242. chanfree(c);
  243. nexterror();
  244. }
  245. r = mntralloc(0, mnt->msize);
  246. if(waserror()) {
  247. mntfree(r);
  248. nexterror();
  249. }
  250. r->request.type = Tauth;
  251. r->request.afid = c->fid;
  252. r->request.uname = up->user;
  253. r->request.aname = spec;
  254. mountrpc(mnt, r);
  255. c->qid = r->reply.aqid;
  256. c->mchan = mnt->c;
  257. incref(&mnt->c->r);
  258. c->mqid = c->qid;
  259. c->mode = ORDWR;
  260. poperror(); /* r */
  261. mntfree(r);
  262. poperror(); /* c */
  263. return c;
  264. }
  265. static Chan*
  266. mntattach(char *muxattach)
  267. {
  268. Proc *up = externup();
  269. Mnt *mnt;
  270. Chan *c;
  271. Mntrpc *r;
  272. struct bogus{
  273. Chan *chan;
  274. Chan *authchan;
  275. char *spec;
  276. int flags;
  277. }bogus;
  278. bogus = *((struct bogus *)muxattach);
  279. c = bogus.chan;
  280. mnt = c->mux;
  281. if(mnt == nil){
  282. mntversion(c, 0, nil, 0);
  283. mnt = c->mux;
  284. if(mnt == nil)
  285. error(Enoversion);
  286. }
  287. c = mntchan();
  288. if(waserror()) {
  289. /* Close must not be called since it will
  290. * call mnt recursively
  291. */
  292. chanfree(c);
  293. nexterror();
  294. }
  295. r = mntralloc(0, mnt->msize);
  296. if(waserror()) {
  297. mntfree(r);
  298. nexterror();
  299. }
  300. r->request.type = Tattach;
  301. r->request.fid = c->fid;
  302. if(bogus.authchan == nil)
  303. r->request.afid = NOFID;
  304. else
  305. r->request.afid = bogus.authchan->fid;
  306. r->request.uname = up->user;
  307. r->request.aname = bogus.spec;
  308. mountrpc(mnt, r);
  309. c->qid = r->reply.qid;
  310. c->mchan = mnt->c;
  311. incref(&mnt->c->r);
  312. c->mqid = c->qid;
  313. poperror(); /* r */
  314. mntfree(r);
  315. poperror(); /* c */
  316. if((bogus.flags & MCACHE) && mfcinit != nil)
  317. c->flag |= CCACHE;
  318. return c;
  319. }
  320. Chan*
  321. mntchan(void)
  322. {
  323. Chan *c;
  324. c = devattach('M', 0);
  325. lock(&mntalloc.Lock);
  326. c->devno = mntalloc.id++;
  327. unlock(&mntalloc.Lock);
  328. if(c->mchan)
  329. panic("mntchan non-zero %#p", c->mchan);
  330. return c;
  331. }
  332. static Walkqid*
  333. mntwalk(Chan *c, Chan *nc, char **name, int nname)
  334. {
  335. Proc *up = externup();
  336. int i, alloc;
  337. Mnt *mnt;
  338. Mntrpc *r;
  339. Walkqid *wq;
  340. if(nc != nil)
  341. print("mntwalk: nc != nil\n");
  342. if(nname > MAXWELEM)
  343. error("devmnt: too many name elements");
  344. alloc = 0;
  345. wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
  346. if(waserror()){
  347. if(alloc && wq->clone!=nil)
  348. cclose(wq->clone);
  349. free(wq);
  350. return nil;
  351. }
  352. alloc = 0;
  353. mnt = mntchk(c);
  354. r = mntralloc(c, mnt->msize);
  355. if(nc == nil){
  356. nc = devclone(c);
  357. /*
  358. * Until the other side accepts this fid,
  359. * we can't mntclose it.
  360. * nc->dev remains nil for now.
  361. */
  362. alloc = 1;
  363. }
  364. wq->clone = nc;
  365. if(waserror()) {
  366. mntfree(r);
  367. nexterror();
  368. }
  369. r->request.type = Twalk;
  370. r->request.fid = c->fid;
  371. r->request.newfid = nc->fid;
  372. r->request.nwname = nname;
  373. memmove(r->request.wname, name, nname*sizeof(char*));
  374. mountrpc(mnt, r);
  375. if(r->reply.nwqid > nname)
  376. error("too many QIDs returned by walk");
  377. if(r->reply.nwqid < nname){
  378. if(alloc)
  379. cclose(nc);
  380. wq->clone = nil;
  381. if(r->reply.nwqid == 0){
  382. free(wq);
  383. wq = nil;
  384. goto Return;
  385. }
  386. }
  387. /* move new fid onto mnt device and update its qid */
  388. if(wq->clone != nil){
  389. if(wq->clone != c){
  390. wq->clone->dev = c->dev;
  391. //if(wq->clone->dev != nil) //XDYNX
  392. // devtabincr(wq->clone->dev);
  393. wq->clone->mchan = c->mchan;
  394. incref(&c->mchan->r);
  395. }
  396. if(r->reply.nwqid > 0)
  397. wq->clone->qid = r->reply.wqid[r->reply.nwqid-1];
  398. }
  399. wq->nqid = r->reply.nwqid;
  400. for(i=0; i<wq->nqid; i++)
  401. wq->qid[i] = r->reply.wqid[i];
  402. Return:
  403. poperror();
  404. mntfree(r);
  405. poperror();
  406. return wq;
  407. }
  408. static int32_t
  409. mntstat(Chan *c, uint8_t *dp, int32_t n)
  410. {
  411. Proc *up = externup();
  412. Mnt *mnt;
  413. Mntrpc *r;
  414. usize nstat;
  415. if(n < BIT16SZ)
  416. error(Eshortstat);
  417. mnt = mntchk(c);
  418. r = mntralloc(c, mnt->msize);
  419. if(waserror()) {
  420. mntfree(r);
  421. nexterror();
  422. }
  423. r->request.type = Tstat;
  424. r->request.fid = c->fid;
  425. mountrpc(mnt, r);
  426. if(r->reply.nstat > n){
  427. nstat = BIT16SZ;
  428. PBIT16(dp, r->reply.nstat-2);
  429. }else{
  430. nstat = r->reply.nstat;
  431. memmove(dp, r->reply.stat, nstat);
  432. validstat(dp, nstat);
  433. mntdirfix(dp, c);
  434. }
  435. poperror();
  436. mntfree(r);
  437. return nstat;
  438. }
  439. static Chan*
  440. mntopencreate(int type, Chan *c, char *name, int omode, int perm)
  441. {
  442. Proc *up = externup();
  443. Mnt *mnt;
  444. Mntrpc *r;
  445. mnt = mntchk(c);
  446. r = mntralloc(c, mnt->msize);
  447. if(waserror()) {
  448. mntfree(r);
  449. nexterror();
  450. }
  451. r->request.type = type;
  452. r->request.fid = c->fid;
  453. r->request.mode = omode;
  454. if(type == Tcreate){
  455. r->request.perm = perm;
  456. r->request.name = name;
  457. }
  458. mountrpc(mnt, r);
  459. c->qid = r->reply.qid;
  460. c->offset = 0;
  461. c->mode = openmode(omode);
  462. c->iounit = r->reply.iounit;
  463. if(c->iounit == 0 || c->iounit > mnt->msize-IOHDRSZ)
  464. c->iounit = mnt->msize-IOHDRSZ;
  465. c->flag |= COPEN;
  466. poperror();
  467. mntfree(r);
  468. if(c->flag & CCACHE)
  469. mfcopen(c);
  470. return c;
  471. }
  472. static Chan*
  473. mntopen(Chan *c, int omode)
  474. {
  475. return mntopencreate(Topen, c, nil, omode, 0);
  476. }
  477. static void
  478. mntcreate(Chan *c, char *name, int omode, int perm)
  479. {
  480. mntopencreate(Tcreate, c, name, omode, perm);
  481. }
  482. static void
  483. mntclunk(Chan *c, int t)
  484. {
  485. Proc *up = externup();
  486. Mnt *mnt;
  487. Mntrpc *r;
  488. mnt = mntchk(c);
  489. r = mntralloc(c, mnt->msize);
  490. if(waserror()){
  491. mntfree(r);
  492. nexterror();
  493. }
  494. r->request.type = t;
  495. r->request.fid = c->fid;
  496. mountrpc(mnt, r);
  497. mntfree(r);
  498. poperror();
  499. }
  500. void
  501. muxclose(Mnt *mnt)
  502. {
  503. Mntrpc *q, *r;
  504. for(q = mnt->queue; q; q = r) {
  505. r = q->list;
  506. mntfree(q);
  507. }
  508. mnt->id = 0;
  509. free(mnt->version);
  510. mnt->version = nil;
  511. mntpntfree(mnt);
  512. }
  513. void
  514. mntpntfree(Mnt *mnt)
  515. {
  516. Mnt *f, **l;
  517. Queue *q;
  518. lock(&mntalloc.Lock);
  519. l = &mntalloc.list;
  520. for(f = *l; f; f = f->list) {
  521. if(f == mnt) {
  522. *l = mnt->list;
  523. break;
  524. }
  525. l = &f->list;
  526. }
  527. mnt->list = mntalloc.mntfree;
  528. mntalloc.mntfree = mnt;
  529. q = mnt->q;
  530. unlock(&mntalloc.Lock);
  531. qfree(q);
  532. }
  533. static void
  534. mntclose(Chan *c)
  535. {
  536. mntclunk(c, Tclunk);
  537. }
  538. static void
  539. mntremove(Chan *c)
  540. {
  541. mntclunk(c, Tremove);
  542. }
  543. static int32_t
  544. mntwstat(Chan *c, uint8_t *dp, int32_t n)
  545. {
  546. Proc *up = externup();
  547. Mnt *mnt;
  548. Mntrpc *r;
  549. mnt = mntchk(c);
  550. r = mntralloc(c, mnt->msize);
  551. if(waserror()) {
  552. mntfree(r);
  553. nexterror();
  554. }
  555. r->request.type = Twstat;
  556. r->request.fid = c->fid;
  557. r->request.nstat = n;
  558. r->request.stat = dp;
  559. mountrpc(mnt, r);
  560. poperror();
  561. mntfree(r);
  562. return n;
  563. }
  564. static int32_t
  565. mntread(Chan *c, void *buf, int32_t n, int64_t off)
  566. {
  567. uint8_t *p, *e;
  568. int nc, cache, isdir;
  569. usize dirlen;
  570. isdir = 0;
  571. cache = c->flag & CCACHE;
  572. if(c->qid.type & QTDIR) {
  573. cache = 0;
  574. isdir = 1;
  575. }
  576. p = buf;
  577. if(cache) {
  578. nc = mfcread(c, buf, n, off);
  579. if(nc > 0) {
  580. n -= nc;
  581. if(n == 0)
  582. return nc;
  583. p += nc;
  584. off += nc;
  585. }
  586. n = mntrdwr(Tread, c, p, n, off);
  587. mfcupdate(c, p, n, off);
  588. return n + nc;
  589. }
  590. n = mntrdwr(Tread, c, buf, n, off);
  591. if(isdir) {
  592. for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
  593. dirlen = BIT16SZ+GBIT16(p);
  594. if(p+dirlen > e)
  595. break;
  596. validstat(p, dirlen);
  597. mntdirfix(p, c);
  598. }
  599. if(p != e)
  600. error(Esbadstat);
  601. }
  602. return n;
  603. }
  604. static int32_t
  605. mntwrite(Chan *c, void *buf, int32_t n, int64_t off)
  606. {
  607. return mntrdwr(Twrite, c, buf, n, off);
  608. }
  609. int32_t
  610. mntrdwr(int type, Chan *c, void *buf, int32_t n, int64_t off)
  611. {
  612. Proc *up = externup();
  613. Mnt *mnt;
  614. Mntrpc *r;
  615. char *uba;
  616. int cache;
  617. uint32_t cnt, nr, nreq;
  618. mnt = mntchk(c);
  619. uba = buf;
  620. cnt = 0;
  621. cache = c->flag & CCACHE;
  622. if(c->qid.type & QTDIR)
  623. cache = 0;
  624. for(;;) {
  625. r = mntralloc(c, mnt->msize);
  626. if(waserror()) {
  627. mntfree(r);
  628. nexterror();
  629. }
  630. r->request.type = type;
  631. r->request.fid = c->fid;
  632. r->request.offset = off;
  633. r->request.data = uba;
  634. nr = n;
  635. if(nr > mnt->msize-IOHDRSZ)
  636. nr = mnt->msize-IOHDRSZ;
  637. r->request.count = nr;
  638. mountrpc(mnt, r);
  639. nreq = r->request.count;
  640. nr = r->reply.count;
  641. if(nr > nreq)
  642. nr = nreq;
  643. if(type == Tread)
  644. r->b = bl2mem((uint8_t*)uba, r->b, nr);
  645. else if(cache)
  646. mfcwrite(c, (uint8_t*)uba, nr, off);
  647. poperror();
  648. mntfree(r);
  649. off += nr;
  650. uba += nr;
  651. cnt += nr;
  652. n -= nr;
  653. if(nr != nreq || n == 0 || up->nnote)
  654. break;
  655. }
  656. return cnt;
  657. }
  658. static void
  659. mntvalidreply(Mnt *mnt, Mntrpc *r)
  660. {
  661. Proc *up = externup();
  662. char *sn, *cn;
  663. int t;
  664. t = r->reply.type;
  665. switch(t) {
  666. case Rerror:
  667. error(r->reply.ename);
  668. case Rflush:
  669. error(Eintr);
  670. default:
  671. if(t == r->request.type+1) // R for T is always T+1.
  672. break;
  673. sn = "?";
  674. if(mnt->c->path != nil)
  675. sn = mnt->c->path->s;
  676. cn = "?";
  677. if(r->c != nil && r->c->path != nil)
  678. cn = r->c->path->s;
  679. print("mnt: proc %s %d: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n",
  680. up->text, up->pid, sn, cn,
  681. r, r->request.tag, r->request.fid, r->request.type,
  682. r->reply.type, r->reply.tag);
  683. error(Emountrpc);
  684. }
  685. }
  686. static void
  687. xmitrpc(Mnt *mnt, Mntrpc *r)
  688. {
  689. int n;
  690. lock(&mnt->l);
  691. r->m = mnt;
  692. r->list = mnt->queue;
  693. mnt->queue = r;
  694. unlock(&mnt->l);
  695. /* Transmit a file system rpc */
  696. if(mnt->msize == 0)
  697. panic("msize");
  698. n = convS2M(&r->request, r->rpc, mnt->msize);
  699. if(n < 0)
  700. panic("bad message type in mountio");
  701. if(mnt->c->dev->write(mnt->c, r->rpc, n, 0) != n)
  702. error(Emountrpc);
  703. r->stime = fastticks(nil);
  704. r->reqlen = n;
  705. }
  706. static void
  707. recvrpc(Mnt *mnt, Mntrpc *r)
  708. {
  709. Proc *up = externup();
  710. /* Gate readers onto the mount point one at a time */
  711. for(;;) {
  712. lock(&mnt->l);
  713. if(mnt->rip == 0)
  714. break;
  715. unlock(&mnt->l);
  716. sleep(&r->r, rpcattn, r);
  717. if(r->done)
  718. return;
  719. }
  720. mnt->rip = up;
  721. unlock(&mnt->l);
  722. while(r->done == 0) {
  723. if(mntrpcread(mnt, r) < 0)
  724. error(Emountrpc);
  725. mountmux(mnt, r);
  726. }
  727. mntgate(mnt);
  728. }
  729. /* The intent of all this is that we want to be able to batch out the T
  730. * messages and then gather up the R messages. I've done this befoer with
  731. * 9p but the corner cases for error handled are very, very trick.
  732. */
  733. void
  734. mountiostart(Mnt *mnt, Mntrpc *r)
  735. {
  736. Proc *up = externup();
  737. int gotintr;
  738. r->reply.tag = 0;
  739. r->reply.type = Tmax; /* can't ever be a valid message type */
  740. gotintr = 0;
  741. while(waserror()) {
  742. if(strcmp(up->errstr, Eintr) != 0){
  743. mntflushfree(mnt, r);
  744. nexterror();
  745. }
  746. r = mntflushalloc(r, mnt->msize);
  747. gotintr++;
  748. }
  749. xmitrpc(mnt, r);
  750. if(gotintr > 0)
  751. recvrpc(mnt, r);
  752. poperror();
  753. if(gotintr > 0){
  754. mntflushfree(mnt, r);
  755. mntvalidreply(mnt, r);
  756. }
  757. }
  758. /* this is so close to the original mount, maybe we should just have a parameter to tell
  759. * it not to wait for replies?
  760. */
  761. void
  762. mountiofinish(Mnt *mnt, Mntrpc *r)
  763. {
  764. Proc *up = externup();
  765. int gotintr;
  766. gotintr = 0;
  767. while(waserror()) {
  768. if(mnt->rip == up)
  769. mntgate(mnt);
  770. if(strcmp(up->errstr, Eintr) != 0){
  771. mntflushfree(mnt, r);
  772. nexterror();
  773. }
  774. r = mntflushalloc(r, mnt->msize);
  775. gotintr++;
  776. }
  777. if(gotintr > 0)
  778. xmitrpc(mnt, r);
  779. recvrpc(mnt, r);
  780. poperror();
  781. mntflushfree(mnt, r);
  782. mntvalidreply(mnt, r);
  783. }
  784. void
  785. mountrpc(Mnt *mnt, Mntrpc *r)
  786. {
  787. mountiostart(mnt, r);
  788. mountiofinish(mnt, r);
  789. }
  790. static int
  791. doread(Mnt *mnt, int len)
  792. {
  793. Block *b;
  794. while(qlen(mnt->q) < len){
  795. b = mnt->c->dev->bread(mnt->c, mnt->msize, 0);
  796. if(b == nil)
  797. return -1;
  798. if(blocklen(b) == 0){
  799. freeblist(b);
  800. return -1;
  801. }
  802. qaddlist(mnt->q, b);
  803. }
  804. return 0;
  805. }
  806. int
  807. mntrpcread(Mnt *mnt, Mntrpc *r)
  808. {
  809. int i, t, len, hlen;
  810. Block *b, **l, *nb;
  811. r->reply.type = 0;
  812. r->reply.tag = 0;
  813. /* read at least length, type, and tag and pullup to a single block */
  814. if(doread(mnt, BIT32SZ+BIT8SZ+BIT16SZ) < 0)
  815. return -1;
  816. nb = pullupqueue(mnt->q, BIT32SZ+BIT8SZ+BIT16SZ);
  817. /* read in the rest of the message, avoid ridiculous (for now) message sizes */
  818. len = GBIT32(nb->rp);
  819. if(len > mnt->msize){
  820. qdiscard(mnt->q, qlen(mnt->q));
  821. return -1;
  822. }
  823. if(doread(mnt, len) < 0)
  824. return -1;
  825. /* pullup the header (i.e. everything except data) */
  826. t = nb->rp[BIT32SZ];
  827. switch(t){
  828. case Rread:
  829. hlen = BIT32SZ+BIT8SZ+BIT16SZ+BIT32SZ;
  830. break;
  831. default:
  832. hlen = len;
  833. break;
  834. }
  835. nb = pullupqueue(mnt->q, hlen);
  836. if(convM2S(nb->rp, len, &r->reply) <= 0){
  837. /* bad message, dump it */
  838. print("mntrpcread: convM2S failed\n");
  839. qdiscard(mnt->q, len);
  840. return -1;
  841. }
  842. /* hang the data off of the fcall struct */
  843. l = &r->b;
  844. *l = nil;
  845. do {
  846. b = qget(mnt->q);
  847. if(hlen > 0){
  848. b->rp += hlen;
  849. len -= hlen;
  850. hlen = 0;
  851. }
  852. i = BLEN(b);
  853. if(i <= len){
  854. len -= i;
  855. *l = b;
  856. l = &(b->next);
  857. } else {
  858. /* split block and put unused bit back */
  859. nb = allocb(i-len);
  860. memmove(nb->wp, b->rp+len, i-len);
  861. b->wp = b->rp+len;
  862. nb->wp += i-len;
  863. qputback(mnt->q, nb);
  864. *l = b;
  865. return 0;
  866. }
  867. }while(len > 0);
  868. return 0;
  869. }
  870. void
  871. mntgate(Mnt *mnt)
  872. {
  873. Mntrpc *q;
  874. lock(&mnt->l);
  875. mnt->rip = 0;
  876. for(q = mnt->queue; q; q = q->list) {
  877. if(q->done == 0)
  878. if(wakeup(&q->r))
  879. break;
  880. }
  881. unlock(&mnt->l);
  882. }
  883. void
  884. mountmux(Mnt *mnt, Mntrpc *r)
  885. {
  886. Mntrpc **l, *q;
  887. lock(&mnt->l);
  888. l = &mnt->queue;
  889. for(q = *l; q; q = q->list) {
  890. /* look for a reply to a message */
  891. if(q->request.tag == r->reply.tag) {
  892. *l = q->list;
  893. if(q != r) {
  894. /*
  895. * Completed someone else.
  896. * Trade pointers to receive buffer.
  897. */
  898. q->reply = r->reply;
  899. q->b = r->b;
  900. r->b = nil;
  901. }
  902. q->done = 1;
  903. unlock(&mnt->l);
  904. if(mntstats != nil)
  905. (*mntstats)(q->request.type,
  906. mnt->c, q->stime,
  907. q->reqlen + r->replen);
  908. if(q != r)
  909. wakeup(&q->r);
  910. return;
  911. }
  912. l = &q->list;
  913. }
  914. unlock(&mnt->l);
  915. print("unexpected reply tag %u; type %d\n", r->reply.tag, r->reply.type);
  916. }
  917. /*
  918. * Create a new flush request and chain the previous
  919. * requests from it
  920. */
  921. Mntrpc*
  922. mntflushalloc(Mntrpc *r, uint32_t iounit)
  923. {
  924. Mntrpc *fr;
  925. fr = mntralloc(0, iounit);
  926. fr->request.type = Tflush;
  927. if(r->request.type == Tflush)
  928. fr->request.oldtag = r->request.oldtag;
  929. else
  930. fr->request.oldtag = r->request.tag;
  931. fr->flushed = r;
  932. return fr;
  933. }
  934. /*
  935. * Free a chain of flushes. Remove each unanswered
  936. * flush and the original message from the unanswered
  937. * request queue. Mark the original message as done
  938. * and if it hasn't been answered set the reply to to
  939. * Rflush.
  940. */
  941. void
  942. mntflushfree(Mnt *mnt, Mntrpc *r)
  943. {
  944. Mntrpc *fr;
  945. while(r){
  946. fr = r->flushed;
  947. if(!r->done){
  948. r->reply.type = Rflush;
  949. mntqrm(mnt, r);
  950. }
  951. if(fr)
  952. mntfree(r);
  953. r = fr;
  954. }
  955. }
  956. int
  957. alloctag(void)
  958. {
  959. int i, j;
  960. uint32_t v;
  961. for(i = 0; i < NMASK; i++){
  962. v = mntalloc.tagmask[i];
  963. if(v == (uint32_t)~0UL)
  964. continue;
  965. for(j = 0; j < (1<<TAGSHIFT); j++)
  966. if((v & (1<<j)) == 0){
  967. mntalloc.tagmask[i] |= 1<<j;
  968. return (i<<TAGSHIFT) + j;
  969. }
  970. }
  971. panic("no friggin tags left");
  972. return NOTAG;
  973. }
  974. void
  975. freetag(int t)
  976. {
  977. mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK));
  978. }
  979. Mntrpc*
  980. mntralloc(Chan *c, uint32_t msize)
  981. {
  982. Mntrpc *new;
  983. lock(&mntalloc.Lock);
  984. new = mntalloc.rpcfree;
  985. if(new == nil){
  986. new = malloc(sizeof(Mntrpc));
  987. if(new == nil) {
  988. unlock(&mntalloc.Lock);
  989. exhausted("mount rpc header");
  990. }
  991. /*
  992. * The header is split from the data buffer as
  993. * mountmux may swap the buffer with another header.
  994. */
  995. new->rpc = mallocz(msize, 0);
  996. if(new->rpc == nil){
  997. free(new);
  998. unlock(&mntalloc.Lock);
  999. exhausted("mount rpc buffer");
  1000. }
  1001. new->rpclen = msize;
  1002. new->request.tag = alloctag();
  1003. }
  1004. else {
  1005. mntalloc.rpcfree = new->list;
  1006. mntalloc.nrpcfree--;
  1007. if(new->rpclen < msize){
  1008. free(new->rpc);
  1009. new->rpc = mallocz(msize, 0);
  1010. if(new->rpc == nil){
  1011. free(new);
  1012. mntalloc.nrpcused--;
  1013. unlock(&mntalloc.Lock);
  1014. exhausted("mount rpc buffer");
  1015. }
  1016. new->rpclen = msize;
  1017. }
  1018. }
  1019. mntalloc.nrpcused++;
  1020. unlock(&mntalloc.Lock);
  1021. new->c = c;
  1022. new->done = 0;
  1023. new->flushed = nil;
  1024. new->b = nil;
  1025. return new;
  1026. }
  1027. void
  1028. mntfree(Mntrpc *r)
  1029. {
  1030. if(r->b != nil)
  1031. freeblist(r->b);
  1032. lock(&mntalloc.Lock);
  1033. if(mntalloc.nrpcfree >= 10){
  1034. free(r->rpc);
  1035. freetag(r->request.tag);
  1036. free(r);
  1037. }
  1038. else{
  1039. r->list = mntalloc.rpcfree;
  1040. mntalloc.rpcfree = r;
  1041. mntalloc.nrpcfree++;
  1042. }
  1043. mntalloc.nrpcused--;
  1044. unlock(&mntalloc.Lock);
  1045. }
  1046. void
  1047. mntqrm(Mnt *mnt, Mntrpc *r)
  1048. {
  1049. Mntrpc **l, *f;
  1050. lock(&mnt->l);
  1051. r->done = 1;
  1052. l = &mnt->queue;
  1053. for(f = *l; f; f = f->list) {
  1054. if(f == r) {
  1055. *l = r->list;
  1056. break;
  1057. }
  1058. l = &f->list;
  1059. }
  1060. unlock(&mnt->l);
  1061. }
  1062. Mnt*
  1063. mntchk(Chan *c)
  1064. {
  1065. Mnt *mnt;
  1066. /* This routine is mostly vestiges of prior lives; now it's just sanity checking */
  1067. if(c->mchan == nil)
  1068. panic("mntchk 1: nil mchan c %s\n", chanpath(c));
  1069. mnt = c->mchan->mux;
  1070. if(mnt == nil)
  1071. print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan));
  1072. /*
  1073. * Was it closed and reused (was error(Eshutdown); now, it cannot happen)
  1074. */
  1075. if(mnt->id == 0 || mnt->id >= c->devno)
  1076. panic("mntchk 3: can't happen");
  1077. return mnt;
  1078. }
  1079. /*
  1080. * Rewrite channel type and dev for in-flight data to
  1081. * reflect local values. These entries are known to be
  1082. * the first two in the Dir encoding after the count.
  1083. */
  1084. void
  1085. mntdirfix(uint8_t *dirbuf, Chan *c)
  1086. {
  1087. uint r;
  1088. r = c->dev->dc;
  1089. dirbuf += BIT16SZ; /* skip count */
  1090. PBIT16(dirbuf, r);
  1091. dirbuf += BIT16SZ;
  1092. PBIT32(dirbuf, c->devno);
  1093. }
  1094. int
  1095. rpcattn(void *v)
  1096. {
  1097. Mntrpc *r;
  1098. r = v;
  1099. return r->done || r->m->rip == 0;
  1100. }
  1101. Dev mntdevtab = {
  1102. .dc = 'M',
  1103. .name = "mnt",
  1104. .reset = mntreset,
  1105. .init = devinit,
  1106. .shutdown = devshutdown,
  1107. .attach = mntattach,
  1108. .walk = mntwalk,
  1109. .stat = mntstat,
  1110. .open = mntopen,
  1111. .create = mntcreate,
  1112. .close = mntclose,
  1113. .read = mntread,
  1114. .bread = devbread,
  1115. .write = mntwrite,
  1116. .bwrite = devbwrite,
  1117. .remove = mntremove,
  1118. .wstat = mntwstat,
  1119. };