devmntn.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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* mntchann(void);
  76. extern char Esbadstat[];
  77. extern char Enoversion[];
  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. static Chan*
  92. mntattach(char *muxattach)
  93. {
  94. Proc *up = externup();
  95. Mnt *mnt;
  96. Chan *c;
  97. Mntrpc *r;
  98. struct bogus{
  99. Chan *chan;
  100. Chan *authchan;
  101. char *spec;
  102. int flags;
  103. }bogus;
  104. bogus = *((struct bogus *)muxattach);
  105. c = bogus.chan;
  106. mnt = c->mux;
  107. if(mnt == nil){
  108. mntversion(c, 0, nil, 0);
  109. mnt = c->mux;
  110. if(mnt == nil)
  111. error(Enoversion);
  112. }
  113. c = mntchann();
  114. if(waserror()) {
  115. /* Close must not be called since it will
  116. * call mnt recursively
  117. */
  118. chanfree(c);
  119. nexterror();
  120. }
  121. r = mntralloc(0, mnt->msize);
  122. if(waserror()) {
  123. mntfree(r);
  124. nexterror();
  125. }
  126. r->request.type = Tattach;
  127. r->request.fid = c->fid;
  128. if(bogus.authchan == nil)
  129. r->request.afid = NOFID;
  130. else
  131. r->request.afid = bogus.authchan->fid;
  132. r->request.uname = up->user;
  133. r->request.aname = bogus.spec;
  134. mountrpc(mnt, r);
  135. c->qid = r->reply.qid;
  136. c->mchan = mnt->c;
  137. incref(&mnt->c->r);
  138. c->mqid = c->qid;
  139. poperror(); /* r */
  140. mntfree(r);
  141. poperror(); /* c */
  142. if((bogus.flags & MCACHE) && mfcinit != nil)
  143. c->flag |= CCACHE;
  144. return c;
  145. }
  146. static Walkqid*
  147. mntwalk(Chan *c, Chan *nc, char **name, int nname)
  148. {
  149. Proc *up = externup();
  150. int i, alloc;
  151. Mnt *mnt;
  152. Mntrpc *r;
  153. Walkqid *wq;
  154. if(nc != nil)
  155. print("mntwalk: nc != nil\n");
  156. if(nname > MAXWELEM)
  157. error("devmnt: too many name elements");
  158. alloc = 0;
  159. wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
  160. if(waserror()){
  161. if(alloc && wq->clone!=nil)
  162. cclose(wq->clone);
  163. free(wq);
  164. return nil;
  165. }
  166. alloc = 0;
  167. mnt = mntchk(c);
  168. r = mntralloc(c, mnt->msize);
  169. if(nc == nil){
  170. nc = devclone(c);
  171. /*
  172. * Until the other side accepts this fid,
  173. * we can't mntclose it.
  174. * nc->dev remains nil for now.
  175. */
  176. alloc = 1;
  177. }
  178. wq->clone = nc;
  179. if(waserror()) {
  180. mntfree(r);
  181. nexterror();
  182. }
  183. r->request.type = Twalk;
  184. r->request.fid = c->fid;
  185. r->request.newfid = nc->fid;
  186. r->request.nwname = nname;
  187. memmove(r->request.wname, name, nname*sizeof(char*));
  188. mountrpc(mnt, r);
  189. if(r->reply.nwqid > nname)
  190. error("too many QIDs returned by walk");
  191. if(r->reply.nwqid < nname){
  192. if(alloc)
  193. cclose(nc);
  194. wq->clone = nil;
  195. if(r->reply.nwqid == 0){
  196. free(wq);
  197. wq = nil;
  198. goto Return;
  199. }
  200. }
  201. /* move new fid onto mnt device and update its qid */
  202. if(wq->clone != nil){
  203. if(wq->clone != c){
  204. wq->clone->dev = c->dev;
  205. //if(wq->clone->dev != nil) //XDYNX
  206. // devtabincr(wq->clone->dev);
  207. wq->clone->mchan = c->mchan;
  208. incref(&c->mchan->r);
  209. }
  210. if(r->reply.nwqid > 0)
  211. wq->clone->qid = r->reply.wqid[r->reply.nwqid-1];
  212. }
  213. wq->nqid = r->reply.nwqid;
  214. for(i=0; i<wq->nqid; i++)
  215. wq->qid[i] = r->reply.wqid[i];
  216. Return:
  217. poperror();
  218. mntfree(r);
  219. poperror();
  220. return wq;
  221. }
  222. static int32_t
  223. mntstat(Chan *c, uint8_t *dp, int32_t n)
  224. {
  225. Proc *up = externup();
  226. Mnt *mnt;
  227. Mntrpc *r;
  228. usize nstat;
  229. if(n < BIT16SZ)
  230. error(Eshortstat);
  231. mnt = mntchk(c);
  232. r = mntralloc(c, mnt->msize);
  233. if(waserror()) {
  234. mntfree(r);
  235. nexterror();
  236. }
  237. r->request.type = Tstat;
  238. r->request.fid = c->fid;
  239. mountrpc(mnt, r);
  240. if(r->reply.nstat > n){
  241. nstat = BIT16SZ;
  242. PBIT16(dp, r->reply.nstat-2);
  243. }else{
  244. nstat = r->reply.nstat;
  245. memmove(dp, r->reply.stat, nstat);
  246. validstat(dp, nstat);
  247. mntdirfix(dp, c);
  248. }
  249. poperror();
  250. mntfree(r);
  251. return nstat;
  252. }
  253. static Chan*
  254. mntopencreate(int type, Chan *c, char *name, int omode, int perm)
  255. {
  256. Proc *up = externup();
  257. Mnt *mnt;
  258. Mntrpc *r;
  259. mnt = mntchk(c);
  260. r = mntralloc(c, mnt->msize);
  261. if(waserror()) {
  262. mntfree(r);
  263. nexterror();
  264. }
  265. r->request.type = type;
  266. r->request.fid = c->fid;
  267. r->request.mode = omode;
  268. if(type == Tcreate){
  269. r->request.perm = perm;
  270. r->request.name = name;
  271. }
  272. mountrpc(mnt, r);
  273. c->qid = r->reply.qid;
  274. c->offset = 0;
  275. c->mode = openmode(omode);
  276. c->iounit = r->reply.iounit;
  277. c->writeoffset = 0;
  278. c->buffend = 0;
  279. c->writebuff = nil;
  280. c->buffsize = mnt->msize;
  281. if(c->iounit == 0 || c->iounit > mnt->msize-IOHDRSZ)
  282. c->iounit = mnt->msize-IOHDRSZ;
  283. c->flag |= COPEN;
  284. poperror();
  285. mntfree(r);
  286. if(c->flag & CCACHE)
  287. mfcopen(c);
  288. return c;
  289. }
  290. static Chan*
  291. mntopen(Chan *c, int omode)
  292. {
  293. return mntopencreate(Topen, c, nil, omode, 0);
  294. }
  295. static void
  296. mntcreate(Chan *c, char *name, int omode, int perm)
  297. {
  298. mntopencreate(Tcreate, c, name, omode, perm);
  299. }
  300. static void
  301. mntclunk(Chan *c, int t)
  302. {
  303. Proc *up = externup();
  304. Mnt *mnt;
  305. Mntrpc *r;
  306. mnt = mntchk(c);
  307. r = mntralloc(c, mnt->msize);
  308. if(waserror()){
  309. mntfree(r);
  310. nexterror();
  311. }
  312. r->request.type = t;
  313. r->request.fid = c->fid;
  314. mountrpc(mnt, r);
  315. mntfree(r);
  316. poperror();
  317. }
  318. static void
  319. mntclose(Chan *c)
  320. {
  321. if (c->buffend > 0) {
  322. mntrdwr(Twrite, c, c->writebuff, c->buffend, c->writeoffset);
  323. }
  324. c->buffend = 0;
  325. free(c->writebuff);
  326. c->writebuff = nil;
  327. mntclunk(c, Tclunk);
  328. }
  329. static void
  330. mntremove(Chan *c)
  331. {
  332. mntclunk(c, Tremove);
  333. }
  334. static int32_t
  335. mntwstat(Chan *c, uint8_t *dp, int32_t n)
  336. {
  337. Proc *up = externup();
  338. Mnt *mnt;
  339. Mntrpc *r;
  340. mnt = mntchk(c);
  341. r = mntralloc(c, mnt->msize);
  342. if(waserror()) {
  343. mntfree(r);
  344. nexterror();
  345. }
  346. r->request.type = Twstat;
  347. r->request.fid = c->fid;
  348. r->request.nstat = n;
  349. r->request.stat = dp;
  350. mountrpc(mnt, r);
  351. poperror();
  352. mntfree(r);
  353. return n;
  354. }
  355. static int32_t
  356. mntread(Chan *c, void *buf, int32_t n, int64_t off)
  357. {
  358. uint8_t *p, *e;
  359. int nc, cache, isdir;
  360. usize dirlen;
  361. isdir = 0;
  362. cache = c->flag & CCACHE;
  363. if(c->qid.type & QTDIR) {
  364. cache = 0;
  365. isdir = 1;
  366. }
  367. p = buf;
  368. if(cache) {
  369. nc = mfcread(c, buf, n, off);
  370. if(nc > 0) {
  371. n -= nc;
  372. if(n == 0)
  373. return nc;
  374. p += nc;
  375. off += nc;
  376. }
  377. n = mntrdwr(Tread, c, p, n, off);
  378. mfcupdate(c, p, n, off);
  379. return n + nc;
  380. }
  381. // Flush if we're reading this file. Would be nice to see if
  382. // read could be satisfied from buffer.
  383. if (c->buffend > 0) {
  384. mntrdwr(Twrite, c, c->writebuff, c->buffend, c->writeoffset);
  385. }
  386. n = mntrdwr(Tread, c, buf, n, off);
  387. if(isdir) {
  388. for(e = &p[n]; p+BIT16SZ < e; p += dirlen){
  389. dirlen = BIT16SZ+GBIT16(p);
  390. if(p+dirlen > e)
  391. break;
  392. validstat(p, dirlen);
  393. mntdirfix(p, c);
  394. }
  395. if(p != e)
  396. error(Esbadstat);
  397. }
  398. return n;
  399. }
  400. static int32_t
  401. mntwrite(Chan *c, void *buf, int32_t n, int64_t off)
  402. {
  403. int result = n;
  404. int offset = 0;
  405. if (c->writebuff == nil){
  406. c->writebuff = (unsigned char*)malloc(c->buffsize);
  407. if(c->writebuff == nil){
  408. print("devmntn: write buffer allocation of %d bytes failed\n", c->buffsize);
  409. return mntrdwr(Twrite, c, buf, n, off);
  410. }
  411. }
  412. if(off != c->writeoffset + c->buffend){
  413. // non-continuous write - flush cached data
  414. mntrdwr(Twrite, c, c->writebuff, c->buffend, c->writeoffset);
  415. c->buffend = 0;
  416. c->writeoffset = off;
  417. }
  418. while (n + c->buffend >= c->buffsize){
  419. offset = c->mux->msize - c->buffend;
  420. n -= offset;
  421. memmove(&c->writebuff[c->buffend], buf, offset);
  422. mntrdwr(Twrite, c, c->writebuff, c->mux->msize, c->writeoffset);
  423. c->writeoffset += offset;
  424. }
  425. memmove(&c->writebuff[c->buffend], buf + offset, n);
  426. c->buffend += n;
  427. return result;
  428. }
  429. Chan*
  430. mntchann(void)
  431. {
  432. Chan *c;
  433. c = devattach('N', 0);
  434. lock(&mntalloc.Lock);
  435. c->devno = mntalloc.id++;
  436. unlock(&mntalloc.Lock);
  437. if(c->mchan)
  438. panic("mntchan non-zero %#p", c->mchan);
  439. return c;
  440. }
  441. Dev mntndevtab = {
  442. .dc = 'N',
  443. .name = "mntn",
  444. .reset = mntreset,
  445. .init = devinit,
  446. .shutdown = devshutdown,
  447. .attach = mntattach,
  448. .walk = mntwalk,
  449. .stat = mntstat,
  450. .open = mntopen,
  451. .create = mntcreate,
  452. .close = mntclose,
  453. .read = mntread,
  454. .bread = devbread,
  455. .write = mntwrite,
  456. .bwrite = devbwrite,
  457. .remove = mntremove,
  458. .wstat = mntwstat,
  459. };