|
|
1.1 root 1: #include "sys/param.h"
2: #include "sys/user.h"
3: #include "sys/netb.h"
4: #include "sys/inode.h"
5: #include "sys/buf.h"
6: #include "sys/systm.h"
7: #include "sys/stat.h"
8: #include "sys/file.h"
9: #include "sys/conf.h"
10: #include "sys/nbio.h"
11:
12: static long nbtrannum;
13: static int nbfstyp;
14: int nbdebug;
15: int nbput(), nbupdat(), nbread(), nbwrite(), nbtrunc(), nbstat();
16: int nbnami(), nbioctl(), nbmount(), nbdirread();
17: struct fstypsw nbfs =
18: fsinit(nbput, nbupdat, nbread, nbwrite, nbtrunc, nbstat,
19: nbnami, nbmount, nbioctl, nullopen, nbdirread);
20: unsigned char *getnbbuf();
21: #define NBMAXMSG (5*1024) /* probably enough */
22: int nbbsz = NBMAXMSG;
23:
24: /*
25: * flags in i_un.i_fsflags
26: * valid only in the root inode
27: */
28: #define NBUSY 01 /* already a message outstanding */
29: #define NWANT 02 /* someone waiting for BUSY */
30: #define NDEAD 04 /* communication line assumed dead */
31:
32: /*
33: * flags valid in any netb inode
34: */
35: #define NSTOK 010 /* inode data is fresh; skip next stat message */
36:
37: nbput(ip)
38: register struct inode *ip;
39: {
40: unsigned char sbuf[SNBSIZE];
41: unsigned char rbuf[RNBSIZE];
42: register unsigned char *sp;
43:
44:
45: /* don't put root, as optimization. pointless? */
46: if (ip->i_mpoint->i_mroot == ip)
47: return;
48: if(ip->i_flag & ICHG) /* this is an extra message, but not often? */
49: nbupdat(ip, &time, &time, 0);
50: sp = sbuf;
51: bzero(sp, sizeof(sbuf));
52: tonetchar(sp, SNB_VERSION, NETB);
53: tonetchar(sp, SNB_CMD, NBPUT);
54: tonetlong(sp, SNB_LEN, sizeof(sbuf));
55: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
56: nbsend(ip, sp, rbuf, sizeof(rbuf));
57: }
58:
59: nbtrunc(ip)
60: register struct inode *ip;
61: {
62: unsigned char sbuf[SNBSIZE];
63: unsigned char rbuf[RNBSIZE];
64: register unsigned char *sp;
65:
66: ip->i_un.i_fsflags &=~ NSTOK;
67: sp = sbuf;
68: bzero(sp, sizeof(sbuf));
69: tonetchar(sp, SNB_VERSION, NETB);
70: tonetchar(sp, SNB_CMD, NBTRNC);
71: tonetlong(sp, SNB_LEN, sizeof(sbuf));
72: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
73: nbsend(ip, sp, rbuf, sizeof(rbuf));
74: }
75:
76: /*
77: * the only times we're interested in are those which have waitfor == 0
78: * (or those which have ta or tb != &time)
79: */
80: nbupdat(ip, ta, tb, waitfor)
81: register time_t *ta, *tb;
82: register struct inode *ip;
83: {
84: unsigned char sbuf[SUPSIZE];
85: unsigned char rbuf[RNBSIZE];
86: register unsigned char *sp;
87:
88: ip->i_un.i_fsflags &=~ NSTOK;
89: sp = sbuf;
90: bzero(sp, sizeof(sbuf));
91: tonetchar(sp, SNB_VERSION, NETB);
92: tonetchar(sp, SNB_CMD, NBUPD);
93: tonetlong(sp, SNB_LEN, sizeof(sbuf));
94: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
95: tonetshort(sp, SUP_MODE, ip->i_mode);
96: /*
97: * in theory *ta or *tb could be incremented
98: * while we are copying them char-by-char
99: * in practice, it doesn't matter,
100: * as *t? != &time
101: */
102: if((ta != &time) && (ip->i_flag & IACC))
103: tonetlong(sp, SUP_ATIME, *ta);
104: if((tb != &time) && (ip->i_flag & IUPD))
105: tonetlong(sp, SUP_MTIME, *tb);
106: nbsend(ip, sp, rbuf, sizeof(rbuf));
107: ip->i_flag &= ~(IUPD|IACC|ICHG);
108: }
109:
110: /*
111: * if NSTOK is set,
112: * the inode is full of stat data from a recent namei
113: * for stat, NSTOK always set, because we just called namei
114: * (except for the root, for which namei isn't called)
115: * for fstat, it is probably not set
116: */
117: nbstat(ip, ub)
118: register struct inode *ip;
119: struct stat *ub;
120: {
121: unsigned char sbuf[SSTSIZE];
122: unsigned char rbuf[RSTSIZE];
123: struct stat ds;
124: register unsigned char *p;
125: long now;
126:
127: if ((ip->i_un.i_fsflags & NSTOK) == 0) {
128: p = sbuf;
129: bzero(p, sizeof(sbuf));
130: tonetchar(p, SNB_VERSION, NETB);
131: tonetchar(p, SNB_CMD, NBSTAT);
132: tonetlong(p, SNB_LEN, sizeof(sbuf));
133: tonetlong(p, SNB_TAG, ip->i_un.i_tag);
134: now = time; /* in case clock ticks */
135: tonetlong(p, SST_TIME, now);
136: nbsend(ip, p, rbuf, sizeof(rbuf));
137: if(u.u_error)
138: return;
139: p = rbuf;
140: ip->i_mode = frnetshort(p, RST_MODE);
141: ip->i_nlink = frnetshort(p, RST_NLINK);
142: ip->i_uid = frnetshort(p, RST_UID);
143: ip->i_gid = frnetshort(p, RST_GID);
144: ip->i_size = frnetlong(p, RST_SIZE);
145: ip->i_un.i_netatime = frnetlong(p, RST_ATIME);
146: ip->i_un.i_netmtime = frnetlong(p, RST_MTIME);
147: ip->i_un.i_netctime = frnetlong(p, RST_CTIME);
148: ip->i_un.i_netrdev = frnetlong(p, RST_RDEV);
149: }
150: ds.st_dev = ip->i_dev;
151: ds.st_ino = ip->i_number;
152: ds.st_mode = ip->i_mode;
153: ds.st_nlink = ip->i_nlink;
154: ds.st_uid = ip->i_uid;
155: ds.st_gid = ip->i_gid;
156: ds.st_size = ip->i_size;
157: ds.st_atime = ip->i_un.i_netatime;
158: ds.st_mtime = ip->i_un.i_netmtime;
159: ds.st_ctime = ip->i_un.i_netctime;
160: ds.st_rdev = ip->i_un.i_netrdev;
161: if(copyout((caddr_t)&ds, (caddr_t)ub, sizeof(ds)))
162: u.u_error = EFAULT;
163: ip->i_un.i_fsflags &=~ NSTOK; /* so repeated fstats check for changes */
164: }
165:
166: /*
167: * here and in nbwrite, `tonetlong(..., Ltol(u.u_offset))' is OK.
168: * it looks like four function calls, one per byte,
169: * but Ltol is a macro without side effects.
170: * maybe there should just be a temporary for clarity
171: */
172: nbread(ip)
173: register struct inode *ip;
174: {
175: unsigned char sbuf[SRDSIZE];
176: register unsigned char *rp;
177: register unsigned char *sp;
178: register int n;
179:
180: ip->i_un.i_fsflags &=~ NSTOK;
181: rp = getnbbuf();
182: sp = sbuf;
183: bzero(sp, sizeof(sbuf));
184: tonetchar(sp, SNB_VERSION, NETB);
185: tonetchar(sp, SNB_CMD, NBREAD);
186: tonetlong(sp, SNB_LEN, sizeof(sbuf));
187: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
188: do {
189: n = u.u_count;
190: if(n > nbbsz - RNBSIZE)
191: n = nbbsz - RNBSIZE;
192: tonetlong(sp, SRD_LEN, n);
193: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset));
194: nbsend(ip, sp, rp, nbbsz);
195: if (u.u_error)
196: break;
197: n = frnetlong(rp, RNB_LEN) - RNBSIZE;
198: if(n > 0 && n <= nbbsz) /* give it to user */
199: iomove(rp + RNBSIZE, n, B_READ);
200: } while (u.u_error == 0 && u.u_count > 0 && n > 0
201: && frnetchar(rp, RNB_FLAGS) != NBEND);
202: putnbbuf(rp);
203: }
204:
205: nbdirread(ip, len)
206: register struct inode *ip;
207: {
208: unsigned char sbuf[SRDSIZE];
209: register unsigned char *sp;
210: register unsigned char *rp; /* RDISIZE */
211: int n;
212: llong_t oldoff;
213: long netoff; /* just the 32-bit part */
214:
215: ip->i_un.i_fsflags &=~ NSTOK;
216: rp = getnbbuf();
217: sp = sbuf;
218: bzero(sp, sizeof(sbuf));
219: tonetchar(sp, SNB_VERSION, NETB);
220: tonetchar(sp, SNB_CMD, NBDIR);
221: tonetlong(sp, SNB_LEN, sizeof(sbuf));
222: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
223: if(len > nbbsz - RDISIZE)
224: len = nbbsz - RDISIZE;
225: tonetlong(sp, SRD_LEN, len);
226: oldoff = u.u_offset;
227: netoff = Ltol(u.u_offset);
228: tonetlong(sp, SRD_OFFSET, netoff);
229: nbsend(ip, sp, rp, nbbsz);
230: if(u.u_error)
231: goto out;
232: n = frnetlong(rp, RNB_LEN) - RDISIZE;
233: if (n > 0 && n <= nbbsz)
234: iomove(rp + RDISIZE, n, B_READ);
235: if (u.u_error)
236: goto out;
237: u.u_offset = Lladd(oldoff, frnetlong(rp, RDI_USED));
238: u.u_r.r_val1 = n;
239: out:
240: putnbbuf(rp);
241: }
242:
243: nbwrite(ip)
244: register struct inode *ip;
245: {
246: register unsigned char *sp;
247: unsigned char rbuf[RNBSIZE];
248: int n;
249:
250: ip->i_un.i_fsflags &=~ NSTOK;
251: sp = getnbbuf();
252: bzero(sp, SWRSIZE);
253: tonetchar(sp, SNB_VERSION, NETB);
254: tonetchar(sp, SNB_CMD, NBWRT);
255: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
256: do {
257: n = u.u_count;
258: if(n > nbbsz - SWRSIZE)
259: n = nbbsz - SWRSIZE;
260: tonetlong(sp, SNB_LEN, n + SWRSIZE);
261: tonetlong(sp, SWR_LEN, n);
262: tonetlong(sp, SWR_OFFSET, Ltol(u.u_offset));
263: iomove(sp + SWRSIZE, n, B_WRITE);
264: if (u.u_error)
265: break;
266: nbsend(ip, sp, rbuf, sizeof(rbuf));
267: if (u.u_error)
268: break;
269: ip->i_flag |= IUPD|ICHG;
270: } while(u.u_count > 0);
271: if(u.u_error == 0)
272: ip->i_size = frnetlong(rbuf, RNB_FSIZE);
273: putnbbuf(sp);
274: }
275:
276: nbioctl(ip, cmd, addr, flag) /* fp->f_flag */
277: register struct inode *ip;
278: caddr_t addr;
279: {
280: register unsigned char *p;
281: int size;
282:
283: switch(cmd) {
284: case NBIOCON:
285: nbdebug = 1;
286: return;
287: case NBIOCOFF:
288: nbdebug = 0;
289: return;
290: case NBIOCBSZ:
291: if (copyin(addr, (caddr_t)&size, sizeof(size))) {
292: u.u_error = EFAULT;
293: return;
294: }
295: if (size > 1024 && size <= NBMAXMSG)
296: nbbsz = size & ~1023; /* round to even 1K */
297: if (copyout(addr, (caddr_t)&nbbsz, sizeof(nbbsz)))
298: u.u_error = EFAULT;
299: return;
300: }
301: /*
302: * one buffer, used first for sbuf, then for rbuf
303: */
304: p = getnbbuf();
305: bzero(p, SIOSIZE);
306: tonetchar(p, SNB_VERSION, NETB);
307: tonetchar(p, SNB_CMD, NBIOCTL);
308: tonetlong(p, SNB_LEN, SIOSIZE + SIODATA);
309: tonetlong(p, SNB_TAG, ip->i_un.i_tag);
310: tonetlong(p, SIO_CMD, cmd);
311: tonetshort(p, SIO_FLAG, flag);
312: if(copyin(addr, p + SIOSIZE, SIODATA)) {
313: u.u_error = EFAULT;
314: goto out;
315: }
316: nbsend(ip, p, p, RNBSIZE + SIODATA);
317: if (u.u_error)
318: goto out;
319: if(frnetlong(p, RNB_LEN) != RNBSIZE + SIODATA) {
320: printf("netb: nbioc got %d, not %d\n",
321: frnetlong(p, RNB_LEN), RNBSIZE+SIODATA);
322: u.u_error = EIO;
323: goto out;
324: }
325: if(copyout(p+RNBSIZE, addr, SIODATA))
326: u.u_error = EFAULT;
327: out:
328: putnbbuf(p);
329: }
330:
331: /*
332: * namei:
333: * send the whole pathname
334: * wrong if another filesystem is mounted
335: * atop some file in this one
336: */
337: nbnami(p, flagp, follow)
338: register struct nx *p;
339: register struct argnamei *flagp;
340: {
341: register char *cp;
342: register struct inode *dp;
343: register unsigned char *pp;
344: register int nlen;
345: int used;
346: dev_t dev;
347:
348: dp = p->dp;
349: /*
350: * special case:
351: * if simple lookup of "" in the root,
352: * and the connection is dead,
353: * return OK even though dead so it's possible to unmount
354: */
355: if (dp->i_mpoint->i_mroot == dp
356: && dp->i_un.i_fsflags & NDEAD
357: && flagp->flag == NI_SEARCH && *p->cp == 0)
358: return (0); /* with the same dp and cp */
359: /*
360: * one buffer for rbuf and sbuf
361: */
362: pp = getnbbuf();
363: bzero(pp, SNMSIZE);
364: tonetchar(pp, SNB_VERSION, NETB);
365: tonetchar(pp, SNB_CMD, NBNAMI);
366: tonetlong(pp, SNB_TAG, dp->i_un.i_tag);
367: cp = p->cp;
368: while (*cp++)
369: ;
370: nlen = cp - p->cp; /* length of name, including NUL */
371: if (nlen + SNMSIZE >= nbbsz) {
372: u.u_error = ENOENT;
373: goto outnull;
374: }
375: used = nlen + SNMSIZE - 1; /* temporary to improve code */
376: tonetlong(pp, SNB_LEN, used);
377: bcopy(p->cp, pp + SNMSIZE, nlen);
378: tonetchar(pp, SNB_FLAGS, flagp->flag);
379: switch (flagp->flag) {
380:
381: case NI_CREAT:
382: case NI_NXCREAT:
383: case NI_MKDIR:
384: tonetshort(pp, SNM_MODE, flagp->un.mode);
385: break;
386:
387: case NI_LINK:
388: tonetlong(pp, SNM_INO, flagp->un.il->i_un.i_tag);
389: break;
390: }
391: nbsend(dp, pp, pp, RNMSIZE);
392: if(u.u_error)
393: goto outnull;
394: if (frnetchar(pp, RNB_FLAGS) == NBROOT) {
395: /* find my root */
396: dp = dp->i_mpoint;
397: iput(p->dp);
398: if(dp == NULL) {
399: u.u_error = EGREG;
400: goto out;
401: }
402: plock(dp);
403: dp->i_count++;
404: used = frnetlong(pp, RNM_USED);
405: if (used < 2 || used >= nlen) {
406: u.u_error = EGREG;
407: goto outnull;
408: }
409: cp = p->cp + used;
410: *--cp == '.';
411: *--cp == '.';
412: p->cp = cp;
413: goto outmore;
414: }
415: switch(flagp->flag) {
416:
417: default:
418: panic("nbnami");
419:
420: case NI_CREAT: /* only case where flagp is used later (creat()) */
421: case NI_NXCREAT: /* return an inode, like search */
422: flagp->un.mode = ~flagp->un.mode; /* obscure side-effects! */
423: case NI_SEARCH:
424: break;
425:
426: case NI_DEL: /* nothing returned */
427: case NI_LINK: /* nothing returned */
428: case NI_MKDIR: /* nothing returned */
429: case NI_RMDIR: /* nothing returned */
430: goto outnull;
431: }
432: /*
433: * release directory inode, construct a new one
434: * fill in the attributes even if inode was already in core;
435: * the new data is more correct (server gets priority)
436: */
437: prele(dp); /* in case new == old */
438: /* cheat: first character of RNM_DEV == minor */
439: dev = makedev(major(dp->i_dev), frnetchar(pp, RNM_DEV));
440: dp = iget(dp, dev, frnetlong(pp, RNM_INO));
441: /* p->dp == dp before iget was called */
442: if (dp == NULL) {
443: idec(p->dp);
444: goto out;
445: }
446: if (p->dp->i_mpoint != dp->i_mpoint) { /* something mounted here */
447: idec(p->dp);
448: p->cp += nlen - 1; /* point to NUL at the end */
449: goto outmore;
450: }
451: dp->i_un.i_cip = p->dp->i_un.i_cip;
452: idec(p->dp);
453: nbunpack(dp, pp);
454: /*
455: * no filename to save for accounting; oh well
456: */
457: if(flagp->flag == NI_SEARCH && flagp->un.buf)
458: bcopy("netb exec", flagp->un.buf, flagp->len);
459:
460: /*
461: * return the inode in dp
462: */
463: out:
464: p->dp = dp;
465: putnbbuf(pp);
466: return (0);
467:
468: /*
469: * discard dp, return NULL
470: */
471: outnull:
472: iput(dp);
473: p->dp = NULL;
474: putnbbuf(pp);
475: return (0);
476:
477: /*
478: * crossed to a different filesystem;
479: * return cp and dp
480: */
481: outmore:
482: p->dp = dp;
483: putnbbuf(pp);
484: return (1);
485: }
486:
487: nbmount(cip, dip, flag, mnt, fstyp)
488: struct inode *cip, *dip;
489: {
490:
491: nbfstyp = fstyp;
492: if (mnt)
493: nbon(cip, dip, flag, fstyp);
494: else
495: nboff(dip);
496: }
497:
498: /*
499: * data structures for keeping track of device numbers in use
500: */
501: #define NDEVS 256
502: static char nbdevs[NDEVS];
503:
504: #define D_SET(dev) nbdevs[dev] = 1
505: #define D_CLR(dev) nbdevs[dev] = 0
506: #define D_ISSET(dev) nbdevs[dev]
507:
508: /*
509: * mount the filesystem
510: * fake up a namei message to fetch the root
511: * don't call nbnami because it's too hard to get
512: * all the first-time error checks right
513: */
514:
515: nbon(cip, dip, flag, fstyp)
516: struct inode *cip;
517: struct inode *dip;
518: {
519: register struct inode *rip;
520: struct inode pi;
521: register unsigned char *pp;
522: unsigned char sbuf[SNMSIZE+1];
523: unsigned char rbuf[RNMSIZE];
524: register int dmaj;
525:
526: if(cip->i_sptr == NULL) { /* shouting into the storm */
527: u.u_error = ENXIO;
528: return;
529: }
530: for (dmaj = 0; dmaj < NDEVS; dmaj++)
531: if (D_ISSET(dmaj) == 0)
532: break;
533: if (dmaj >= NDEVS) {
534: u.u_error = EMFILE;
535: return;
536: }
537: D_SET(dmaj);
538: /*
539: * fake up an inode to represent the connection
540: * to nbsend and iget
541: */
542: pi.i_fstyp = fstyp;
543: pi.i_mpoint = π
544: pi.i_mroot = π /* pi.i_mpoint->i_mroot == &pi */
545: pi.i_un.i_cip = cip;
546: pi.i_un.i_fsflags = 0;
547: pp = sbuf;
548: bzero(pp, sizeof(sbuf));
549: tonetchar(pp, SNB_VERSION, NETB);
550: tonetchar(pp, SNB_CMD, NBNAMI);
551: tonetlong(pp, SNB_TAG, NBROOTTAG); /* lookup in the root */
552: tonetlong(pp, SNB_LEN, SNMSIZE+1); /* one char of filename */
553: /* tonetchar(pp, SNMSIZE, 0); /* "" */
554: tonetchar(pp, SNB_FLAGS, NI_SEARCH);
555: nbsend(&pi, pp, rbuf, sizeof(rbuf));
556: if (u.u_error) {
557: D_CLR(dmaj);
558: return;
559: }
560: pp = rbuf;
561: if (frnetchar(pp, RNB_FLAGS) != 0) {
562: D_CLR(dmaj);
563: u.u_error = EINVAL;
564: return;
565: }
566: if ((rip = iget(&pi, makedev(dmaj, frnetchar(pp, RNM_DEV)), frnetlong(pp, RNM_INO))) == NULL) {
567: D_CLR(dmaj);
568: return;
569: }
570: if (rip->i_count != 1) {
571: printf("nbon busy, dev %d\n", dmaj); /* shouldn't happen */
572: iput(rip);
573: D_CLR(dmaj);
574: u.u_error = EBUSY;
575: return;
576: }
577: nbunpack(rip, pp);
578: rip->i_un.i_cip = cip;
579: dip->i_mroot = rip;
580: rip->i_mpoint = dip;
581: prele(rip);
582: dip->i_count++;
583: cip->i_count++;
584: }
585:
586: /*
587: * unpack inode info from namei response
588: * a pity stat can't use this too,
589: * but the stat response isn't quite the same format
590: */
591: nbunpack(dp, pp)
592: register struct inode *dp;
593: register unsigned char *pp;
594: {
595:
596: dp->i_un.i_tag = frnetlong(pp, RNM_TAG);
597: dp->i_mode = frnetshort(pp, RNM_MODE);
598: dp->i_nlink = frnetshort(pp, RNM_NLINK);
599: dp->i_uid = frnetshort(pp, RNM_UID);
600: dp->i_gid = frnetshort(pp, RNM_GID);
601: dp->i_size = frnetlong(pp, RNM_SIZE);
602: dp->i_un.i_netatime = frnetlong(pp, RNM_ATIME);
603: dp->i_un.i_netmtime = frnetlong(pp, RNM_MTIME);
604: dp->i_un.i_netctime = frnetlong(pp, RNM_CTIME);
605: dp->i_un.i_netrdev = frnetlong(pp, RNM_RDEV);
606: if (dp->i_count == 1)
607: dp->i_un.i_fsflags = 0;
608: dp->i_un.i_fsflags |= NSTOK;
609: }
610:
611: /*
612: * unmount a netb--
613: * mip is the mount point
614: * locking needs some thought
615: */
616: nboff(mip)
617: register struct inode *mip;
618: {
619: register struct inode *rip;
620:
621: rip = mip->i_mroot;
622: plock(rip);
623: if (rip->i_mpoint != mip) { /* already unmounted */
624: prele(rip);
625: return;
626: }
627: xumount(rip);
628: iupdat(rip, &time, &time, 1);
629: ifsinacc(rip); /* turn all, including rip, to errfs */
630: plock(mip);
631: mip->i_mroot = NULL;
632: iput(mip);
633: if (rip->i_un.i_cip == NULL)
634: panic("nboff");
635: iput(rip->i_un.i_cip);
636: D_CLR(major(rip->i_dev));
637: iput(rip); /* errput, not nbput */
638: }
639:
640: nbsend(ip, sp, rp, size)
641: struct inode *ip;
642: register unsigned char *sp;
643: unsigned char *rp;
644: {
645: int bad;
646: long tn;
647: struct inode *cip;
648: register struct inode *rip;
649:
650: cip = ip->i_un.i_cip;
651: rip = ip->i_mpoint->i_mroot;
652: if (rip == NULL || rip->i_fstyp != ip->i_fstyp) {
653: u.u_error = EIO;
654: return;
655: }
656: while ((rip->i_un.i_fsflags & (NBUSY|NDEAD)) == NBUSY
657: && ip->i_fstyp == nbfstyp) {
658: rip->i_un.i_fsflags |= NWANT;
659: if (tsleep((caddr_t)cip, PZERO+1, 0) != TS_OK) {
660: u.u_error = EIO;
661: return;
662: }
663: }
664: if (ip->i_fstyp != nbfstyp /* unmounted under us */
665: || rip->i_un.i_fsflags & NDEAD) { /* or connection fell down */
666: u.u_error = EIO;
667: return;
668: }
669: rip->i_un.i_fsflags |= NBUSY;
670: tonetshort(sp, SNB_UID, u.u_uid);
671: tonetshort(sp, SNB_GID, u.u_gid);
672: tn = nbtrannum++;
673: tonetlong(sp, SNB_TRANNUM, tn);
674: if (istwrite(cip, sp, frnetlong(sp, SNB_LEN)) >= 0
675: && nbrecv(cip, rp, size, tn) >= 0)
676: bad = 0;
677: else
678: bad = 1;
679: if (ip->i_fstyp == nbfstyp) { /* in case unmounted while asleep */
680: rip->i_un.i_fsflags &=~ NBUSY;
681: if (rip->i_un.i_fsflags & NWANT) {
682: wakeup((caddr_t)cip);
683: rip->i_un.i_fsflags &=~ NWANT;
684: }
685: if (bad)
686: rip->i_un.i_fsflags |= NDEAD;
687: }
688: if (bad)
689: u.u_error = EIO;
690: else if ((bad = frnetshort(rp, RNB_ERRNO)) != 0)
691: u.u_error = bad;
692: }
693:
694: /*
695: * read an answer,
696: * and make sure it smells like one of ours
697: */
698:
699: int
700: nbrecv(cip, rp, size, tn)
701: struct inode *cip;
702: register unsigned char *rp;
703: int size;
704: long tn;
705: {
706: unsigned char *p;
707: register int n, len, netlen;
708:
709: loop:
710: p = rp;
711: len = 0;
712: /*
713: * header
714: */
715: while (len < RNBSIZE) {
716: n = istread(cip, p, size - len, 0);
717: if (n <= 0)
718: return (-1);
719: len += n;
720: p += n;
721: }
722: netlen = frnetlong(rp, RNB_LEN);
723: if (netlen > size || netlen < RNBSIZE) {
724: printf("netb: rcv len %d\n", netlen);
725: return (-1);
726: }
727: /*
728: * following data, if any
729: */
730: while (len < netlen) {
731: n = istread(cip, p, size - len, 0);
732: if (n <= 0)
733: return (-1);
734: len += n;
735: p += n;
736: }
737: if (frnetlong(rp, RNB_TRANNUM) != tn) {
738: if (frnetlong(rp, RNB_TRANNUM) < tn) /* echo from the past */
739: goto loop;
740: printf("netb: exp tran %d, got %d\n", tn, frnetlong(rp, RNB_TRANNUM));
741: return (-1);
742: }
743: return (len);
744: }
745:
746: /* oh no, it's got its own tiny buffer pool: want to avoid breakage on
747: normal (4k reads for now). we could replace this with a real
748: memory manager in the kernel */
749: #define NBUF 7 /* who knows? */
750: char nb_lock;
751: char nbflgs[NBUF];
752: unsigned char nbbuf[NBUF][NBMAXMSG];
753:
754: unsigned char *
755: getnbbuf()
756: {
757: register int i;
758:
759: loop:
760: for(i = 0; i < NBUF; i++)
761: if(!nbflgs[i]) {
762: nbflgs[i] = 1;
763: return(nbbuf[i]);
764: }
765: nb_lock = 1;
766: sleep((caddr_t)&nb_lock, PZERO);
767: goto loop;
768: }
769:
770: putnbbuf(s)
771: unsigned char *s;
772: {
773: register int i;
774:
775: for(i = 0; i < NBUF; i++)
776: if(nbbuf[i] == s) {
777: nbflgs[i] = 0;
778: if(nb_lock) {
779: nb_lock = 0;
780: wakeup((caddr_t) &nb_lock);
781: }
782: return;
783: }
784: panic("putnbbuf");
785: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.