|
|
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: nbread(ip)
167: register struct inode *ip;
168: {
169: unsigned char sbuf[SRDSIZE];
170: register unsigned char *rp;
171: register unsigned char *sp;
172: register int n;
173:
174: ip->i_un.i_fsflags &=~ NSTOK;
175: rp = getnbbuf();
176: sp = sbuf;
177: bzero(sp, sizeof(sbuf));
178: tonetchar(sp, SNB_VERSION, NETB);
179: tonetchar(sp, SNB_CMD, NBREAD);
180: tonetlong(sp, SNB_LEN, sizeof(sbuf));
181: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
182: do {
183: n = u.u_count;
184: if(n > nbbsz - RNBSIZE)
185: n = nbbsz - RNBSIZE;
186: tonetlong(sp, SRD_LEN, n);
187: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset));
188: nbsend(ip, sp, rp, nbbsz);
189: if (u.u_error)
190: break;
191: n = frnetlong(rp, RNB_LEN) - RNBSIZE;
192: if(n > 0 && n <= nbbsz) /* give it to user */
193: iomove(rp + RNBSIZE, n, B_READ);
194: } while (u.u_error == 0 && u.u_count > 0 && n > 0
195: && frnetchar(rp, RNB_FLAGS) != NBEND);
196: putnbbuf(rp);
197: }
198:
199: nbdirread(ip, len)
200: register struct inode *ip;
201: {
202: unsigned char sbuf[SRDSIZE];
203: register unsigned char *sp;
204: register unsigned char *rp; /* RDISIZE */
205: int n;
206:
207: ip->i_un.i_fsflags &=~ NSTOK;
208: rp = getnbbuf();
209: sp = sbuf;
210: bzero(sp, sizeof(sbuf));
211: tonetchar(sp, SNB_VERSION, NETB);
212: tonetchar(sp, SNB_CMD, NBDIR);
213: tonetlong(sp, SNB_LEN, sizeof(sbuf));
214: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
215: if(len > nbbsz - RDISIZE)
216: len = nbbsz - RDISIZE;
217: tonetlong(sp, SRD_LEN, len);
218: tonetlong(sp, SRD_OFFSET, Ltol(u.u_offset));
219: nbsend(ip, sp, rp, nbbsz);
220: if(u.u_error)
221: goto out;
222: n = frnetlong(rp, RNB_LEN) - RDISIZE;
223: if(n > 0) { /* why not iomove? */
224: if(u.u_segflg != SEGSYS) {
225: if(copyout(rp + RDISIZE, u.u_base, n))
226: u.u_error = EFAULT;
227: }
228: else
229: bcopy(rp + RDISIZE, u.u_base, n);
230: }
231: u.u_offset = Lladd(u.u_offset, frnetlong(rp, RDI_USED));
232: u.u_r.r_val1 = n;
233: out:
234: putnbbuf(rp);
235: }
236:
237: nbwrite(ip)
238: register struct inode *ip;
239: {
240: register unsigned char *sp;
241: unsigned char rbuf[RNBSIZE];
242: int n;
243:
244: ip->i_un.i_fsflags &=~ NSTOK;
245: sp = getnbbuf();
246: bzero(sp, SWRSIZE);
247: tonetchar(sp, SNB_VERSION, NETB);
248: tonetchar(sp, SNB_CMD, NBWRT);
249: tonetlong(sp, SNB_TAG, ip->i_un.i_tag);
250: do {
251: n = u.u_count;
252: if(n > nbbsz - SWRSIZE)
253: n = nbbsz - SWRSIZE;
254: tonetlong(sp, SNB_LEN, n + SWRSIZE);
255: tonetlong(sp, SWR_LEN, n);
256: tonetlong(sp, SWR_OFFSET, Ltol(u.u_offset));
257: iomove(sp + SWRSIZE, n, B_WRITE);
258: if (u.u_error)
259: break;
260: nbsend(ip, sp, rbuf, sizeof(rbuf));
261: if (u.u_error)
262: break;
263: ip->i_flag |= IUPD|ICHG;
264: } while(u.u_count > 0);
265: if(u.u_error == 0)
266: ip->i_size = frnetlong(rbuf, RNB_FSIZE);
267: putnbbuf(sp);
268: }
269:
270: nbioctl(ip, cmd, addr, flag) /* fp->f_flag */
271: register struct inode *ip;
272: caddr_t addr;
273: {
274: register unsigned char *p;
275: int size;
276:
277: switch(cmd) {
278: case NBIOCON:
279: nbdebug = 1;
280: return;
281: case NBIOCOFF:
282: nbdebug = 0;
283: return;
284: case NBIOCBSZ:
285: if (copyin(addr, (caddr_t)&size, sizeof(size))) {
286: u.u_error = EFAULT;
287: return;
288: }
289: if (size > 1024 && size <= NBMAXMSG)
290: nbbsz = size & ~1023; /* round to even 1K */
291: if (copyout(addr, (caddr_t)&nbbsz, sizeof(nbbsz)))
292: u.u_error = EFAULT;
293: return;
294: }
295: /*
296: * one buffer, used first for sbuf, then for rbuf
297: */
298: p = getnbbuf();
299: bzero(p, SIOSIZE);
300: tonetchar(p, SNB_VERSION, NETB);
301: tonetchar(p, SNB_CMD, NBIOCTL);
302: tonetlong(p, SNB_LEN, SIOSIZE + SIODATA);
303: tonetlong(p, SNB_TAG, ip->i_un.i_tag);
304: tonetlong(p, SIO_CMD, cmd);
305: tonetshort(p, SIO_FLAG, flag);
306: if(copyin(addr, p + SIOSIZE, SIODATA)) {
307: u.u_error = EFAULT;
308: goto out;
309: }
310: nbsend(ip, p, p, RNBSIZE + SIODATA);
311: if (u.u_error)
312: goto out;
313: if(frnetlong(p, RNB_LEN) != RNBSIZE + SIODATA) {
314: printf("netb: nbioc got %d, not %d\n",
315: frnetlong(p, RNB_LEN), RNBSIZE+SIODATA);
316: u.u_error = EIO;
317: goto out;
318: }
319: if(copyout(p+RNBSIZE, addr, SIODATA))
320: u.u_error = EFAULT;
321: out:
322: putnbbuf(p);
323: }
324:
325: /*
326: * namei:
327: * send the whole pathname
328: * wrong if another filesystem is mounted
329: * atop some file in this one
330: */
331: nbnami(p, flagp, follow)
332: register struct nx *p;
333: register struct argnamei *flagp;
334: {
335: register char *cp;
336: register struct inode *dp;
337: register unsigned char *pp;
338: register int nlen;
339: int used;
340: dev_t dev;
341:
342: dp = p->dp;
343: /*
344: * special case:
345: * if simple lookup of "" in the root,
346: * and the connection is dead,
347: * return OK even though dead so it's possible to unmount
348: */
349: if (dp->i_mpoint->i_mroot == dp
350: && dp->i_un.i_fsflags & NDEAD
351: && flagp->flag == NI_SEARCH && *p->cp == 0)
352: return (0); /* with the same dp and cp */
353: /*
354: * one buffer for rbuf and sbuf
355: */
356: pp = getnbbuf();
357: bzero(pp, SNMSIZE);
358: tonetchar(pp, SNB_VERSION, NETB);
359: tonetchar(pp, SNB_CMD, NBNAMI);
360: tonetlong(pp, SNB_TAG, dp->i_un.i_tag);
361: cp = p->cp;
362: while (*cp++)
363: ;
364: nlen = cp - p->cp; /* length of name, including NUL */
365: if (nlen + SNMSIZE >= nbbsz) {
366: u.u_error = ENOENT;
367: goto outnull;
368: }
369: used = nlen + SNMSIZE - 1; /* temporary to improve code */
370: tonetlong(pp, SNB_LEN, used);
371: bcopy(p->cp, pp + SNMSIZE, nlen);
372: tonetchar(pp, SNB_FLAGS, flagp->flag);
373: switch (flagp->flag) {
374:
375: case NI_CREAT:
376: case NI_NXCREAT:
377: case NI_MKDIR:
378: tonetshort(pp, SNM_MODE, flagp->un.mode);
379: break;
380:
381: case NI_LINK:
382: tonetlong(pp, SNM_INO, flagp->un.il->i_un.i_tag);
383: break;
384: }
385: nbsend(dp, pp, pp, RNMSIZE);
386: if(u.u_error)
387: goto outnull;
388: if (frnetchar(pp, RNB_FLAGS) == NBROOT) {
389: /* find my root */
390: dp = dp->i_mpoint;
391: iput(p->dp);
392: if(dp == NULL) {
393: u.u_error = EGREG;
394: goto out;
395: }
396: plock(dp);
397: dp->i_count++;
398: used = frnetlong(pp, RNM_USED);
399: if (used < 2 || used >= nlen) {
400: u.u_error = EGREG;
401: goto outnull;
402: }
403: cp = p->cp + used;
404: *--cp == '.';
405: *--cp == '.';
406: p->cp = cp;
407: goto outmore;
408: }
409: switch(flagp->flag) {
410:
411: default:
412: panic("nbnami");
413:
414: case NI_CREAT: /* only case where flagp is used later (creat()) */
415: case NI_NXCREAT: /* return an inode, like search */
416: flagp->un.mode = ~flagp->un.mode; /* obscure side-effects! */
417: case NI_SEARCH:
418: break;
419:
420: case NI_DEL: /* nothing returned */
421: case NI_LINK: /* nothing returned */
422: case NI_MKDIR: /* nothing returned */
423: case NI_RMDIR: /* nothing returned */
424: goto outnull;
425: }
426: /*
427: * release directory inode, construct a new one
428: * fill in the attributes even if inode was already in core;
429: * the new data is more correct (server gets priority)
430: */
431: prele(dp); /* in case new == old */
432: /* cheat: first character of RNM_DEV == minor */
433: dev = makedev(major(dp->i_dev), frnetchar(pp, RNM_DEV));
434: dp = iget(dp, dev, frnetlong(pp, RNM_INO));
435: /* p->dp == dp before iget was called */
436: if (dp == NULL) {
437: idec(p->dp);
438: goto out;
439: }
440: if (p->dp->i_mpoint != dp->i_mpoint) { /* something mounted here */
441: idec(p->dp);
442: p->cp += nlen - 1; /* point to NUL at the end */
443: goto outmore;
444: }
445: dp->i_un.i_cip = p->dp->i_un.i_cip;
446: idec(p->dp);
447: nbunpack(dp, pp);
448: /*
449: * no filename to save for accounting; oh well
450: */
451: if(flagp->flag == NI_SEARCH && flagp->un.buf)
452: bcopy("netb exec", flagp->un.buf, flagp->len);
453:
454: /*
455: * return the inode in dp
456: */
457: out:
458: p->dp = dp;
459: putnbbuf(pp);
460: return (0);
461:
462: /*
463: * discard dp, return NULL
464: */
465: outnull:
466: iput(dp);
467: p->dp = NULL;
468: putnbbuf(pp);
469: return (0);
470:
471: /*
472: * crossed to a different filesystem;
473: * return cp and dp
474: */
475: outmore:
476: p->dp = dp;
477: putnbbuf(pp);
478: return (1);
479: }
480:
481: nbmount(cip, dip, flag, mnt, fstyp)
482: struct inode *cip, *dip;
483: {
484:
485: nbfstyp = fstyp;
486: if (mnt)
487: nbon(cip, dip, flag, fstyp);
488: else
489: nboff(dip);
490: }
491:
492: /*
493: * mount the filesystem
494: * fake up a namei message to fetch the root
495: * don't call nbnami because it's too hard to get
496: * all the first-time error checks right
497: */
498:
499: nbon(cip, dip, flag, fstyp)
500: struct inode *cip;
501: struct inode *dip;
502: {
503: register struct inode *rip;
504: struct inode pi;
505: register unsigned char *pp;
506: unsigned char sbuf[SNMSIZE+1];
507: unsigned char rbuf[RNMSIZE];
508: register dev_t dev;
509:
510: if(cip->i_sptr == NULL) { /* shouting into the storm */
511: u.u_error = ENXIO;
512: return;
513: }
514: if (dip->i_fstyp == fstyp && major(dip->i_dev) == major(flag)) {
515: u.u_error = EBUSY;
516: return;
517: }
518: /*
519: * fake up an inode to represent the connection
520: * to nbsend and iget
521: */
522: pi.i_fstyp = fstyp;
523: pi.i_mpoint = π
524: pi.i_mroot = π /* pi.i_mpoint->i_mroot == &pi */
525: pi.i_un.i_cip = cip;
526: pi.i_un.i_fsflags = 0;
527: pp = sbuf;
528: bzero(pp, sizeof(sbuf));
529: tonetchar(pp, SNB_VERSION, NETB);
530: tonetchar(pp, SNB_CMD, NBNAMI);
531: tonetlong(pp, SNB_TAG, NBROOTTAG); /* lookup in the root */
532: tonetlong(pp, SNB_LEN, SNMSIZE+1); /* one char of filename */
533: /* tonetchar(pp, SNMSIZE, 0); /* "" */
534: tonetchar(pp, SNB_FLAGS, NI_SEARCH);
535: nbsend(&pi, pp, rbuf, sizeof(rbuf));
536: if (u.u_error)
537: return;
538: pp = rbuf;
539: if (frnetchar(pp, RNB_FLAGS) != 0) {
540: u.u_error = EINVAL;
541: return;
542: }
543: dev = makedev(major(flag), frnetchar(pp, RNM_DEV));
544: if ((rip = iget(&pi, dev, frnetlong(pp, RNM_INO))) == NULL)
545: return;
546: if (rip->i_count != 1) {
547: iput(rip);
548: u.u_error = EBUSY;
549: return;
550: }
551: nbunpack(rip, pp);
552: rip->i_un.i_cip = cip;
553: dip->i_mroot = rip;
554: rip->i_mpoint = dip;
555: prele(rip);
556: dip->i_count++;
557: cip->i_count++;
558: }
559:
560: /*
561: * unpack inode info from namei response
562: * a pity stat can't use this too,
563: * but the stat response isn't quite the same format
564: */
565: nbunpack(dp, pp)
566: register struct inode *dp;
567: register unsigned char *pp;
568: {
569:
570: dp->i_un.i_tag = frnetlong(pp, RNM_TAG);
571: dp->i_mode = frnetshort(pp, RNM_MODE);
572: dp->i_nlink = frnetshort(pp, RNM_NLINK);
573: dp->i_uid = frnetshort(pp, RNM_UID);
574: dp->i_gid = frnetshort(pp, RNM_GID);
575: dp->i_size = frnetlong(pp, RNM_SIZE);
576: dp->i_un.i_netatime = frnetlong(pp, RNM_ATIME);
577: dp->i_un.i_netmtime = frnetlong(pp, RNM_MTIME);
578: dp->i_un.i_netctime = frnetlong(pp, RNM_CTIME);
579: dp->i_un.i_netrdev = frnetlong(pp, RNM_RDEV);
580: if (dp->i_count == 1)
581: dp->i_un.i_fsflags = 0;
582: dp->i_un.i_fsflags |= NSTOK;
583: }
584:
585: /*
586: * unmount a netb--
587: * called from above, or from nbsend when there's an error
588: * mip is the mount point
589: * locking needs some thought
590: */
591: nboff(mip)
592: register struct inode *mip;
593: {
594: register struct inode *rip;
595:
596: rip = mip->i_mroot;
597: plock(rip);
598: if (rip->i_mpoint != mip) { /* already unmounted */
599: prele(rip);
600: return;
601: }
602: xumount(rip);
603: iupdat(rip, &time, &time, 1);
604: ifsinacc(rip); /* turn all, including rip, to errfs */
605: plock(mip);
606: mip->i_mroot = NULL;
607: iput(mip);
608: if (rip->i_un.i_cip == NULL)
609: panic("nboff");
610: iput(rip->i_un.i_cip);
611: iput(rip); /* errput, not nbput */
612: }
613:
614: nbsend(ip, sp, rp, size)
615: struct inode *ip;
616: register unsigned char *sp;
617: unsigned char *rp;
618: {
619: int bad;
620: long tn;
621: struct inode *cip;
622: register struct inode *rip;
623:
624: cip = ip->i_un.i_cip;
625: rip = ip->i_mpoint->i_mroot;
626: if (rip == NULL || rip->i_fstyp != ip->i_fstyp) {
627: u.u_error = EIO;
628: return;
629: }
630: while ((rip->i_un.i_fsflags & (NBUSY|NDEAD)) == NBUSY
631: && ip->i_fstyp == nbfstyp) {
632: rip->i_un.i_fsflags |= NWANT;
633: if (tsleep((caddr_t)cip, PZERO+1, 0) != TS_OK) {
634: u.u_error = EIO;
635: return;
636: }
637: }
638: if (ip->i_fstyp != nbfstyp /* unmounted under us */
639: || rip->i_un.i_fsflags & NDEAD) { /* or connection fell down */
640: u.u_error = EIO;
641: return;
642: }
643: rip->i_un.i_fsflags |= NBUSY;
644: tonetshort(sp, SNB_UID, u.u_uid);
645: tonetshort(sp, SNB_GID, u.u_gid);
646: tn = nbtrannum++;
647: tonetlong(sp, SNB_TRANNUM, tn);
648: if (istwrite(cip, sp, frnetlong(sp, SNB_LEN)) >= 0
649: && nbrecv(cip, rp, size, tn) >= 0)
650: bad = 0;
651: else
652: bad = 1;
653: if (ip->i_fstyp == nbfstyp) { /* in case unmounted while asleep */
654: rip->i_un.i_fsflags &=~ NBUSY;
655: if (rip->i_un.i_fsflags & NWANT) {
656: wakeup((caddr_t)cip);
657: rip->i_un.i_fsflags &=~ NWANT;
658: }
659: if (bad)
660: rip->i_un.i_fsflags |= NDEAD;
661: }
662: if (bad)
663: u.u_error = EIO;
664: else if ((bad = frnetshort(rp, RNB_ERRNO)) != 0)
665: u.u_error = bad;
666: }
667:
668: /*
669: * read an answer,
670: * and make sure it smells like one of ours
671: */
672:
673: int
674: nbrecv(cip, rp, size, tn)
675: struct inode *cip;
676: register unsigned char *rp;
677: int size;
678: long tn;
679: {
680: unsigned char *p;
681: register int n, len, netlen;
682:
683: loop:
684: p = rp;
685: len = 0;
686: /*
687: * header
688: */
689: while (len < RNBSIZE) {
690: n = istread(cip, p, size - len, 0);
691: if (n <= 0)
692: return (-1);
693: len += n;
694: p += n;
695: }
696: netlen = frnetlong(rp, RNB_LEN);
697: if (netlen > size || netlen < RNBSIZE) {
698: printf("netb: rcv len %d\n", netlen);
699: return (-1);
700: }
701: /*
702: * following data, if any
703: */
704: while (len < netlen) {
705: n = istread(cip, p, size - len, 0);
706: if (n <= 0)
707: return (-1);
708: len += n;
709: p += n;
710: }
711: if (frnetlong(rp, RNB_TRANNUM) != tn) {
712: if (frnetlong(rp, RNB_TRANNUM) < tn) /* echo from the past */
713: goto loop;
714: printf("netb: exp tran %d, got %d\n", tn, frnetlong(rp, RNB_TRANNUM));
715: return (-1);
716: }
717: return (len);
718: }
719:
720: /* oh no, it's got its own tiny buffer pool: want to avoid breakage on
721: normal (4k reads for now). we could replace this with a real
722: memory manager in the kernel */
723: #define NBUF 7 /* who knows? */
724: char nb_lock;
725: char nbflgs[NBUF];
726: unsigned char nbbuf[NBUF][NBMAXMSG];
727:
728: unsigned char *
729: getnbbuf()
730: {
731: register int i;
732:
733: loop:
734: for(i = 0; i < NBUF; i++)
735: if(!nbflgs[i]) {
736: nbflgs[i] = 1;
737: return(nbbuf[i]);
738: }
739: nb_lock = 1;
740: sleep((caddr_t)&nb_lock, PZERO);
741: goto loop;
742: }
743:
744: putnbbuf(s)
745: unsigned char *s;
746: {
747: register int i;
748:
749: for(i = 0; i < NBUF; i++)
750: if(nbbuf[i] == s) {
751: nbflgs[i] = 0;
752: if(nb_lock) {
753: nb_lock = 0;
754: wakeup((caddr_t) &nb_lock);
755: }
756: return;
757: }
758: panic("putnbbuf");
759: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.