devmnt.c 21 KB

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