|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Rick Macklem at The University of Guelph.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
1.1.1.4 ! root 36: * from: @(#)nfs_vnops.c 7.60 (Berkeley) 5/24/91
! 37: * nfs_vnops.c,v 1.9 1993/07/13 10:50:06 cgd Exp
1.1 root 38: */
39:
40: /*
41: * vnode op calls for sun nfs version 2
42: */
43:
44: #include "param.h"
45: #include "proc.h"
46: #include "kernel.h"
47: #include "systm.h"
48: #include "mount.h"
49: #include "buf.h"
50: #include "malloc.h"
51: #include "mbuf.h"
52: #include "conf.h"
53: #include "namei.h"
54: #include "vnode.h"
55: #include "specdev.h"
56: #include "fifo.h"
57:
58: #include "../ufs/quota.h"
59: #include "../ufs/inode.h"
60: #include "../ufs/dir.h"
61:
62: #include "nfsv2.h"
63: #include "nfs.h"
64: #include "nfsnode.h"
65: #include "nfsmount.h"
66: #include "xdr_subs.h"
67: #include "nfsm_subs.h"
68: #include "nfsiom.h"
69:
70: /* Defs */
71: #define TRUE 1
72: #define FALSE 0
73:
74: /*
75: * Global vfs data structures for nfs
76: */
77: struct vnodeops nfsv2_vnodeops = {
78: nfs_lookup, /* lookup */
79: nfs_create, /* create */
80: nfs_mknod, /* mknod */
81: nfs_open, /* open */
82: nfs_close, /* close */
83: nfs_access, /* access */
84: nfs_getattr, /* getattr */
85: nfs_setattr, /* setattr */
86: nfs_read, /* read */
87: nfs_write, /* write */
88: nfs_ioctl, /* ioctl */
89: nfs_select, /* select */
90: nfs_mmap, /* mmap */
91: nfs_fsync, /* fsync */
92: nfs_seek, /* seek */
93: nfs_remove, /* remove */
94: nfs_link, /* link */
95: nfs_rename, /* rename */
96: nfs_mkdir, /* mkdir */
97: nfs_rmdir, /* rmdir */
98: nfs_symlink, /* symlink */
99: nfs_readdir, /* readdir */
100: nfs_readlink, /* readlink */
101: nfs_abortop, /* abortop */
102: nfs_inactive, /* inactive */
103: nfs_reclaim, /* reclaim */
104: nfs_lock, /* lock */
105: nfs_unlock, /* unlock */
106: nfs_bmap, /* bmap */
107: nfs_strategy, /* strategy */
108: nfs_print, /* print */
109: nfs_islocked, /* islocked */
110: nfs_advlock, /* advlock */
111: };
112:
113: /*
114: * Special device vnode ops
115: */
116: struct vnodeops spec_nfsv2nodeops = {
117: spec_lookup, /* lookup */
118: spec_create, /* create */
119: spec_mknod, /* mknod */
120: spec_open, /* open */
121: spec_close, /* close */
122: nfs_access, /* access */
123: nfs_getattr, /* getattr */
124: nfs_setattr, /* setattr */
125: spec_read, /* read */
126: spec_write, /* write */
127: spec_ioctl, /* ioctl */
128: spec_select, /* select */
129: spec_mmap, /* mmap */
130: spec_fsync, /* fsync */
131: spec_seek, /* seek */
132: spec_remove, /* remove */
133: spec_link, /* link */
134: spec_rename, /* rename */
135: spec_mkdir, /* mkdir */
136: spec_rmdir, /* rmdir */
137: spec_symlink, /* symlink */
138: spec_readdir, /* readdir */
139: spec_readlink, /* readlink */
140: spec_abortop, /* abortop */
141: nfs_inactive, /* inactive */
142: nfs_reclaim, /* reclaim */
143: nfs_lock, /* lock */
144: nfs_unlock, /* unlock */
145: spec_bmap, /* bmap */
146: spec_strategy, /* strategy */
147: nfs_print, /* print */
148: nfs_islocked, /* islocked */
149: spec_advlock, /* advlock */
150: };
151:
152: #ifdef FIFO
153: struct vnodeops fifo_nfsv2nodeops = {
154: fifo_lookup, /* lookup */
155: fifo_create, /* create */
156: fifo_mknod, /* mknod */
157: fifo_open, /* open */
158: fifo_close, /* close */
159: nfs_access, /* access */
160: nfs_getattr, /* getattr */
161: nfs_setattr, /* setattr */
162: fifo_read, /* read */
163: fifo_write, /* write */
164: fifo_ioctl, /* ioctl */
165: fifo_select, /* select */
166: fifo_mmap, /* mmap */
167: fifo_fsync, /* fsync */
168: fifo_seek, /* seek */
169: fifo_remove, /* remove */
170: fifo_link, /* link */
171: fifo_rename, /* rename */
172: fifo_mkdir, /* mkdir */
173: fifo_rmdir, /* rmdir */
174: fifo_symlink, /* symlink */
175: fifo_readdir, /* readdir */
176: fifo_readlink, /* readlink */
177: fifo_abortop, /* abortop */
178: nfs_inactive, /* inactive */
179: nfs_reclaim, /* reclaim */
180: nfs_lock, /* lock */
181: nfs_unlock, /* unlock */
182: fifo_bmap, /* bmap */
183: fifo_badop, /* strategy */
184: nfs_print, /* print */
185: nfs_islocked, /* islocked */
186: fifo_advlock, /* advlock */
187: };
188: #endif /* FIFO */
189:
190: /*
191: * Global vars
192: */
193: extern u_long nfs_procids[NFS_NPROCS];
194: extern u_long nfs_prog, nfs_vers;
195: extern char nfsiobuf[MAXPHYS+NBPG];
196: struct buf nfs_bqueue; /* Queue head for nfsiod's */
197: struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON];
1.1.1.3 root 198: enum vtype ntov_type[7] = { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VNON };
1.1 root 199: int nfs_numasync = 0;
200:
201: /*
202: * nfs null call from vfs.
203: */
204: nfs_null(vp, cred, p)
205: struct vnode *vp;
206: struct ucred *cred;
207: struct proc *p;
208: {
209: caddr_t bpos, dpos;
210: u_long xid;
211: int error = 0;
212: struct mbuf *mreq, *mrep, *md, *mb;
213:
214: nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0);
215: nfsm_request(vp, NFSPROC_NULL, p, 0);
216: nfsm_reqdone;
217: return (error);
218: }
219:
220: /*
221: * nfs access vnode op.
222: * Essentially just get vattr and then imitate iaccess()
223: */
224: nfs_access(vp, mode, cred, p)
225: struct vnode *vp;
226: int mode;
227: register struct ucred *cred;
228: struct proc *p;
229: {
230: register struct vattr *vap;
231: register gid_t *gp;
232: struct vattr vattr;
233: register int i;
234: int error;
235:
236: /*
237: * If you're the super-user,
238: * you always get access.
239: */
240: if (cred->cr_uid == 0)
241: return (0);
242: vap = &vattr;
243: if (error = nfs_dogetattr(vp, vap, cred, 0, p))
244: return (error);
245: /*
246: * Access check is based on only one of owner, group, public.
247: * If not owner, then check group. If not a member of the
248: * group, then check public access.
249: */
250: if (cred->cr_uid != vap->va_uid) {
251: mode >>= 3;
252: gp = cred->cr_groups;
253: for (i = 0; i < cred->cr_ngroups; i++, gp++)
254: if (vap->va_gid == *gp)
255: goto found;
256: mode >>= 3;
257: found:
258: ;
259: }
1.1.1.3 root 260: if ((vap->va_mode & mode) == mode)
1.1 root 261: return (0);
262: return (EACCES);
263: }
264:
265: /*
266: * nfs open vnode op
267: * Just check to see if the type is ok
268: */
269: /* ARGSUSED */
270: nfs_open(vp, mode, cred, p)
271: struct vnode *vp;
272: int mode;
273: struct ucred *cred;
274: struct proc *p;
275: {
276: register enum vtype vtyp;
277:
278: vtyp = vp->v_type;
279: if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK)
280: return (0);
281: else
282: return (EACCES);
283: }
284:
285: /*
286: * nfs close vnode op
287: * For reg files, invalidate any buffer cache entries.
288: */
289: /* ARGSUSED */
290: nfs_close(vp, fflags, cred, p)
291: register struct vnode *vp;
292: int fflags;
293: struct ucred *cred;
294: struct proc *p;
295: {
296: register struct nfsnode *np = VTONFS(vp);
297: int error = 0;
298:
299: if (vp->v_type == VREG && (np->n_flag & NMODIFIED)) {
300: nfs_lock(vp);
301: np->n_flag &= ~NMODIFIED;
302: vinvalbuf(vp, TRUE);
303: np->n_attrstamp = 0;
304: if (np->n_flag & NWRITEERR) {
305: np->n_flag &= ~NWRITEERR;
306: error = np->n_error;
307: }
308: nfs_unlock(vp);
309: }
310: return (error);
311: }
312:
313: /*
314: * nfs getattr call from vfs.
315: */
316: nfs_getattr(vp, vap, cred, p)
317: register struct vnode *vp;
318: struct vattr *vap;
319: struct ucred *cred;
320: struct proc *p;
321: {
322: return (nfs_dogetattr(vp, vap, cred, 0, p));
323: }
324:
325: nfs_dogetattr(vp, vap, cred, tryhard, p)
326: register struct vnode *vp;
327: struct vattr *vap;
328: struct ucred *cred;
329: int tryhard;
330: struct proc *p;
331: {
332: register caddr_t cp;
333: register long t1;
334: caddr_t bpos, dpos;
335: u_long xid;
336: int error = 0;
337: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
338:
339: /* First look in the cache.. */
1.1.1.4 ! root 340: /* cred == NOCRED when we are called by mountroot */
! 341: if (cred != NOCRED && nfs_getattrcache(vp, vap) == 0)
1.1 root 342: return (0);
343: nfsstats.rpccnt[NFSPROC_GETATTR]++;
344: nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH);
345: nfsm_fhtom(vp);
346: nfsm_request(vp, NFSPROC_GETATTR, p, tryhard);
347: nfsm_loadattr(vp, vap);
348: nfsm_reqdone;
349: return (error);
350: }
351:
352: /*
353: * nfs setattr call.
354: */
355: nfs_setattr(vp, vap, cred, p)
356: register struct vnode *vp;
357: register struct vattr *vap;
358: struct ucred *cred;
359: struct proc *p;
360: {
361: register struct nfsv2_sattr *sp;
362: register caddr_t cp;
363: register long t1;
364: caddr_t bpos, dpos;
365: u_long xid;
366: int error = 0;
367: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
368: struct nfsnode *np;
369:
370: nfsstats.rpccnt[NFSPROC_SETATTR]++;
371: nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR);
372: nfsm_fhtom(vp);
373: nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
374: if (vap->va_mode == 0xffff)
375: sp->sa_mode = VNOVAL;
376: else
377: sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode);
378: if (vap->va_uid == 0xffff)
379: sp->sa_uid = VNOVAL;
380: else
381: sp->sa_uid = txdr_unsigned(vap->va_uid);
382: if (vap->va_gid == 0xffff)
383: sp->sa_gid = VNOVAL;
384: else
385: sp->sa_gid = txdr_unsigned(vap->va_gid);
386: sp->sa_size = txdr_unsigned(vap->va_size);
1.1.1.4 ! root 387: /* [email protected] 6/2/93 */
! 388: #if 0 /* bad assumption; Suns (at least) make full use of usec field */
1.1 root 389: sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec);
390: sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags);
1.1.1.4 ! root 391: #else
! 392: txdr_time(&vap->va_atime, &sp->sa_atime);
! 393: #endif
1.1 root 394: txdr_time(&vap->va_mtime, &sp->sa_mtime);
395: if (vap->va_size != VNOVAL || vap->va_mtime.tv_sec != VNOVAL ||
396: vap->va_atime.tv_sec != VNOVAL) {
397: np = VTONFS(vp);
398: if (np->n_flag & NMODIFIED) {
399: np->n_flag &= ~NMODIFIED;
400: if (vap->va_size == 0)
401: vinvalbuf(vp, FALSE);
402: else
403: vinvalbuf(vp, TRUE);
404: np->n_attrstamp = 0;
405: }
406: }
407: nfsm_request(vp, NFSPROC_SETATTR, p, 1);
408: nfsm_loadattr(vp, (struct vattr *)0);
409: /* should we fill in any vap fields ?? */
410: nfsm_reqdone;
411: return (error);
412: }
413:
414: /*
415: * nfs lookup call, one step at a time...
416: * First look in cache
417: * If not found, unlock the directory nfsnode and do the rpc
418: */
419: nfs_lookup(vp, ndp, p)
420: register struct vnode *vp;
421: register struct nameidata *ndp;
422: struct proc *p;
423: {
424: register struct vnode *vdp;
425: register u_long *tl;
426: register caddr_t cp;
427: register long t1, t2;
428: caddr_t bpos, dpos, cp2;
429: u_long xid;
430: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
431: struct vnode *newvp;
432: long len;
433: nfsv2fh_t *fhp;
434: struct nfsnode *np;
435: int lockparent, wantparent, flag, error = 0;
436:
437: ndp->ni_dvp = vp;
438: ndp->ni_vp = NULL;
439: if (vp->v_type != VDIR)
440: return (ENOTDIR);
441: lockparent = ndp->ni_nameiop & LOCKPARENT;
442: flag = ndp->ni_nameiop & OPMASK;
443: wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT);
444: if ((error = cache_lookup(ndp)) && error != ENOENT) {
445: struct vattr vattr;
446: int vpid;
447:
448: vdp = ndp->ni_vp;
449: vpid = vdp->v_id;
450: /*
451: * See the comment starting `Step through' in ufs/ufs_lookup.c
452: * for an explanation of the locking protocol
453: */
454: if (vp == vdp) {
455: VREF(vdp);
456: error = 0;
457: } else if (ndp->ni_isdotdot) {
458: nfs_unlock(vp);
459: error = vget(vdp);
460: if (!error && lockparent && *ndp->ni_next == '\0')
461: nfs_lock(vp);
462: } else {
463: error = vget(vdp);
464: if (!lockparent || error || *ndp->ni_next != '\0')
465: nfs_unlock(vp);
466: }
467: if (!error) {
468: if (vpid == vdp->v_id) {
469: if (!nfs_dogetattr(vdp, &vattr, ndp->ni_cred, 0, p)&&
470: vattr.va_ctime.tv_sec == VTONFS(vdp)->n_ctime) {
471: nfsstats.lookupcache_hits++;
472: if (flag != LOOKUP && *ndp->ni_next == 0)
473: ndp->ni_nameiop |= SAVENAME;
474: return (0);
475: }
476: cache_purge(vdp);
477: }
478: nfs_nput(vdp);
479: if (lockparent && vdp != vp && *ndp->ni_next == '\0')
480: nfs_unlock(vp);
481: }
482: ndp->ni_vp = NULLVP;
483: } else
484: nfs_unlock(vp);
485: error = 0;
486: nfsstats.lookupcache_misses++;
487: nfsstats.rpccnt[NFSPROC_LOOKUP]++;
488: len = ndp->ni_namelen;
489: nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
490: nfsm_fhtom(vp);
491: nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
492: nfsm_request(vp, NFSPROC_LOOKUP, p, 0);
493: nfsmout:
494: if (error) {
495: if (lockparent || (flag != CREATE && flag != RENAME) ||
496: *ndp->ni_next != 0)
497: nfs_lock(vp);
498: if (flag != LOOKUP && *ndp->ni_next == 0)
499: ndp->ni_nameiop |= SAVENAME;
500: return (error);
501: }
502: nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH);
503:
504: /*
505: * Handle DELETE and RENAME cases...
506: */
507: if (flag == DELETE && *ndp->ni_next == 0) {
508: if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
509: VREF(vp);
510: newvp = vp;
511: np = VTONFS(vp);
512: } else {
513: if (error = nfs_nget(vp->v_mount, fhp, &np)) {
514: nfs_lock(vp);
515: m_freem(mrep);
516: return (error);
517: }
518: newvp = NFSTOV(np);
519: }
520: if (error =
521: nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
522: nfs_lock(vp);
523: if (newvp != vp)
524: nfs_nput(newvp);
525: else
526: vrele(vp);
527: m_freem(mrep);
528: return (error);
529: }
530: ndp->ni_vp = newvp;
531: if (lockparent || vp == newvp)
532: nfs_lock(vp);
533: m_freem(mrep);
534: ndp->ni_nameiop |= SAVENAME;
535: return (0);
536: }
537:
538: if (flag == RENAME && wantparent && *ndp->ni_next == 0) {
539: if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
540: nfs_lock(vp);
541: m_freem(mrep);
542: return (EISDIR);
543: }
544: if (error = nfs_nget(vp->v_mount, fhp, &np)) {
545: nfs_lock(vp);
546: m_freem(mrep);
547: return (error);
548: }
549: newvp = NFSTOV(np);
550: if (error =
551: nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
552: nfs_lock(vp);
553: nfs_nput(newvp);
554: m_freem(mrep);
555: return (error);
556: }
557: ndp->ni_vp = newvp;
558: if (lockparent)
559: nfs_lock(vp);
560: m_freem(mrep);
561: ndp->ni_nameiop |= SAVENAME;
562: return (0);
563: }
564:
565: if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) {
566: VREF(vp);
567: newvp = vp;
568: np = VTONFS(vp);
569: } else if (ndp->ni_isdotdot) {
570: if (error = nfs_nget(vp->v_mount, fhp, &np)) {
571: nfs_lock(vp);
572: m_freem(mrep);
573: return (error);
574: }
575: newvp = NFSTOV(np);
576: } else {
577: if (error = nfs_nget(vp->v_mount, fhp, &np)) {
578: nfs_lock(vp);
579: m_freem(mrep);
580: return (error);
581: }
582: newvp = NFSTOV(np);
583: }
584: if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) {
585: nfs_lock(vp);
586: if (newvp != vp)
587: nfs_nput(newvp);
588: else
589: vrele(vp);
590: m_freem(mrep);
591: return (error);
592: }
593: m_freem(mrep);
594:
595: if (vp == newvp || (lockparent && *ndp->ni_next == '\0'))
596: nfs_lock(vp);
597: ndp->ni_vp = newvp;
598: if (flag != LOOKUP && *ndp->ni_next == 0)
599: ndp->ni_nameiop |= SAVENAME;
600: if (error == 0 && ndp->ni_makeentry) {
601: np->n_ctime = np->n_vattr.va_ctime.tv_sec;
602: cache_enter(ndp);
603: }
604: return (error);
605: }
606:
607: /*
608: * nfs read call.
609: * Just call nfs_bioread() to do the work.
610: */
611: nfs_read(vp, uiop, ioflag, cred)
612: register struct vnode *vp;
613: struct uio *uiop;
614: int ioflag;
615: struct ucred *cred;
616: {
617: if (vp->v_type != VREG)
618: return (EPERM);
619: return (nfs_bioread(vp, uiop, ioflag, cred));
620: }
621:
622: /*
623: * nfs readlink call
624: */
625: nfs_readlink(vp, uiop, cred)
626: struct vnode *vp;
627: struct uio *uiop;
628: struct ucred *cred;
629: {
630: if (vp->v_type != VLNK)
631: return (EPERM);
632: return (nfs_bioread(vp, uiop, 0, cred));
633: }
634:
635: /*
636: * Do a readlink rpc.
637: * Called by nfs_doio() from below the buffer cache.
638: */
639: nfs_readlinkrpc(vp, uiop, cred)
640: register struct vnode *vp;
641: struct uio *uiop;
642: struct ucred *cred;
643: {
644: register u_long *tl;
645: register caddr_t cp;
646: register long t1;
647: caddr_t bpos, dpos, cp2;
648: u_long xid;
649: int error = 0;
650: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
651: long len;
652:
653: nfsstats.rpccnt[NFSPROC_READLINK]++;
654: nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH);
655: nfsm_fhtom(vp);
656: nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, 0);
657: nfsm_strsiz(len, NFS_MAXPATHLEN);
658: nfsm_mtouio(uiop, len);
659: nfsm_reqdone;
660: return (error);
661: }
662:
663: /*
664: * nfs read rpc call
665: * Ditto above
666: */
667: nfs_readrpc(vp, uiop, cred)
668: register struct vnode *vp;
669: struct uio *uiop;
670: struct ucred *cred;
671: {
672: register u_long *tl;
673: register caddr_t cp;
674: register long t1;
675: caddr_t bpos, dpos, cp2;
676: u_long xid;
677: int error = 0;
678: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
679: struct nfsmount *nmp;
680: long len, retlen, tsiz;
681:
682: nmp = VFSTONFS(vp->v_mount);
683: tsiz = uiop->uio_resid;
684: while (tsiz > 0) {
685: nfsstats.rpccnt[NFSPROC_READ]++;
686: len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
687: nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3);
688: nfsm_fhtom(vp);
689: nfsm_build(tl, u_long *, NFSX_UNSIGNED*3);
690: *tl++ = txdr_unsigned(uiop->uio_offset);
691: *tl++ = txdr_unsigned(len);
692: *tl = 0;
693: nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, 1);
694: nfsm_loadattr(vp, (struct vattr *)0);
695: nfsm_strsiz(retlen, nmp->nm_rsize);
696: nfsm_mtouio(uiop, retlen);
697: m_freem(mrep);
698: if (retlen < len)
699: tsiz = 0;
700: else
701: tsiz -= len;
702: }
703: nfsmout:
704: return (error);
705: }
706:
707: /*
708: * nfs write call
709: */
710: nfs_writerpc(vp, uiop, cred)
711: register struct vnode *vp;
712: struct uio *uiop;
713: struct ucred *cred;
714: {
715: register u_long *tl;
716: register caddr_t cp;
717: register long t1;
718: caddr_t bpos, dpos;
719: u_long xid;
720: int error = 0;
721: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
722: struct nfsmount *nmp;
723: long len, tsiz;
724:
725: nmp = VFSTONFS(vp->v_mount);
726: tsiz = uiop->uio_resid;
727: while (tsiz > 0) {
728: nfsstats.rpccnt[NFSPROC_WRITE]++;
729: len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
730: nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred,
731: NFSX_FH+NFSX_UNSIGNED*4);
732: nfsm_fhtom(vp);
733: nfsm_build(tl, u_long *, NFSX_UNSIGNED*4);
734: *(tl+1) = txdr_unsigned(uiop->uio_offset);
735: *(tl+3) = txdr_unsigned(len);
736: nfsm_uiotom(uiop, len);
737: nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, 1);
738: nfsm_loadattr(vp, (struct vattr *)0);
739: m_freem(mrep);
740: tsiz -= len;
741: }
742: nfsmout:
743: return (error);
744: }
745:
746: /*
747: * nfs mknod call
748: * This is a kludge. Use a create rpc but with the IFMT bits of the mode
749: * set to specify the file type and the size field for rdev.
750: */
751: /* ARGSUSED */
752: nfs_mknod(ndp, vap, cred, p)
753: struct nameidata *ndp;
754: struct ucred *cred;
755: register struct vattr *vap;
756: struct proc *p;
757: {
758: register struct nfsv2_sattr *sp;
759: register u_long *tl;
760: register caddr_t cp;
761: register long t1, t2;
762: caddr_t bpos, dpos;
763: u_long xid;
764: int error = 0;
765: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
766: u_long rdev;
767:
768: if (vap->va_type == VCHR || vap->va_type == VBLK)
769: rdev = txdr_unsigned(vap->va_rdev);
770: #ifdef FIFO
771: else if (vap->va_type == VFIFO)
772: rdev = 0xffffffff;
773: #endif /* FIFO */
774: else {
775: VOP_ABORTOP(ndp);
776: vput(ndp->ni_dvp);
777: return (EOPNOTSUPP);
778: }
779: nfsstats.rpccnt[NFSPROC_CREATE]++;
780: nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
781: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
782: nfsm_fhtom(ndp->ni_dvp);
783: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
784: nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
785: sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
786: sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
787: sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
788: sp->sa_size = rdev;
789: /* or should these be VNOVAL ?? */
790: txdr_time(&vap->va_atime, &sp->sa_atime);
791: txdr_time(&vap->va_mtime, &sp->sa_mtime);
792: nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
793: nfsm_reqdone;
794: FREE(ndp->ni_pnbuf, M_NAMEI);
795: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
796: nfs_nput(ndp->ni_dvp);
797: return (error);
798: }
799:
800: /*
801: * nfs file create call
802: */
803: nfs_create(ndp, vap, p)
804: register struct nameidata *ndp;
805: register struct vattr *vap;
806: struct proc *p;
807: {
808: register struct nfsv2_sattr *sp;
809: register u_long *tl;
810: register caddr_t cp;
811: register long t1, t2;
812: caddr_t bpos, dpos, cp2;
813: u_long xid;
814: int error = 0;
815: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
816:
817: nfsstats.rpccnt[NFSPROC_CREATE]++;
818: nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred,
819: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_SATTR);
820: nfsm_fhtom(ndp->ni_dvp);
821: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
822: nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
823: sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode);
824: sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
825: sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
826: sp->sa_size = txdr_unsigned(0);
827: /* or should these be VNOVAL ?? */
828: txdr_time(&vap->va_atime, &sp->sa_atime);
829: txdr_time(&vap->va_mtime, &sp->sa_mtime);
830: nfsm_request(ndp->ni_dvp, NFSPROC_CREATE, p, 1);
831: nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
832: nfsm_reqdone;
833: FREE(ndp->ni_pnbuf, M_NAMEI);
834: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
835: nfs_nput(ndp->ni_dvp);
836: return (error);
837: }
838:
839: /*
840: * nfs file remove call
841: * To try and make nfs semantics closer to ufs semantics, a file that has
842: * other processes using the vnode is renamed instead of removed and then
843: * removed later on the last close.
844: * - If v_usecount > 1
845: * If a rename is not already in the works
846: * call nfs_sillyrename() to set it up
847: * else
848: * do the remove rpc
849: */
850: nfs_remove(ndp, p)
851: register struct nameidata *ndp;
852: struct proc *p;
853: {
854: register struct vnode *vp = ndp->ni_vp;
855: register struct nfsnode *np = VTONFS(ndp->ni_vp);
856: register u_long *tl;
857: register caddr_t cp;
858: register long t1, t2;
859: caddr_t bpos, dpos;
860: u_long xid;
861: int error = 0;
862: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
863:
864: if (vp->v_usecount > 1) {
865: if (!np->n_sillyrename)
866: error = nfs_sillyrename(ndp, p);
867: } else {
868: nfsstats.rpccnt[NFSPROC_REMOVE]++;
869: nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred,
870: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
871: nfsm_fhtom(ndp->ni_dvp);
872: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
873: nfsm_request(ndp->ni_dvp, NFSPROC_REMOVE, p, 1);
874: nfsm_reqdone;
875: FREE(ndp->ni_pnbuf, M_NAMEI);
876: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
877: /*
878: * Kludge City: If the first reply to the remove rpc is lost..
879: * the reply to the retransmitted request will be ENOENT
880: * since the file was in fact removed
881: * Therefore, we cheat and return success.
882: */
883: if (error == ENOENT)
884: error = 0;
885: }
886: np->n_attrstamp = 0;
887: if (ndp->ni_dvp == vp)
888: vrele(vp);
889: else
890: nfs_nput(ndp->ni_dvp);
891: nfs_nput(vp);
892: return (error);
893: }
894:
895: /*
896: * nfs file remove rpc called from nfs_inactive
897: */
898: nfs_removeit(sp, p)
899: register struct sillyrename *sp;
900: struct proc *p;
901: {
902: register u_long *tl;
903: register caddr_t cp;
904: register long t1, t2;
905: caddr_t bpos, dpos;
906: u_long xid;
907: int error = 0;
908: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
909:
910: nfsstats.rpccnt[NFSPROC_REMOVE]++;
911: nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], sp->s_cred,
912: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen));
913: nfsm_fhtom(sp->s_dvp);
914: nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
915: nfsm_request(sp->s_dvp, NFSPROC_REMOVE, p, 1);
916: nfsm_reqdone;
917: VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
918: return (error);
919: }
920:
921: /*
922: * nfs file rename call
923: */
924: nfs_rename(sndp, tndp, p)
925: register struct nameidata *sndp, *tndp;
926: struct proc *p;
927: {
928: register u_long *tl;
929: register caddr_t cp;
930: register long t1, t2;
931: caddr_t bpos, dpos;
932: u_long xid;
933: int error = 0;
934: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
935:
936: nfsstats.rpccnt[NFSPROC_RENAME]++;
937: nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred,
938: (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
939: nfsm_rndup(tndp->ni_namelen)); /* or sndp->ni_cred?*/
940: nfsm_fhtom(sndp->ni_dvp);
941: nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
942: nfsm_fhtom(tndp->ni_dvp);
943: nfsm_strtom(tndp->ni_ptr, tndp->ni_namelen, NFS_MAXNAMLEN);
944: nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
945: nfsm_reqdone;
946: VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
947: VTONFS(tndp->ni_dvp)->n_flag |= NMODIFIED;
948: if (sndp->ni_vp->v_type == VDIR) {
949: if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR)
950: cache_purge(tndp->ni_dvp);
951: cache_purge(sndp->ni_dvp);
952: }
953: if (tndp->ni_dvp == tndp->ni_vp)
954: vrele(tndp->ni_dvp);
955: else
956: vput(tndp->ni_dvp);
957: if (tndp->ni_vp)
958: vput(tndp->ni_vp);
959: vrele(sndp->ni_dvp);
960: vrele(sndp->ni_vp);
961: /*
962: * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
963: */
964: if (error == ENOENT)
965: error = 0;
966: return (error);
967: }
968:
969: /*
970: * nfs file rename rpc called from nfs_remove() above
971: */
972: nfs_renameit(sndp, sp, p)
973: register struct nameidata *sndp;
974: register struct sillyrename *sp;
975: struct proc *p;
976: {
977: register u_long *tl;
978: register caddr_t cp;
979: register long t1, t2;
980: caddr_t bpos, dpos;
981: u_long xid;
982: int error = 0;
983: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
984:
985: nfsstats.rpccnt[NFSPROC_RENAME]++;
986: nfsm_reqhead(nfs_procids[NFSPROC_RENAME], sp->s_cred,
987: (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_namelen) +
988: nfsm_rndup(sp->s_namlen)); /* or sndp->ni_cred?*/
989: nfsm_fhtom(sndp->ni_dvp);
990: nfsm_strtom(sndp->ni_ptr, sndp->ni_namelen, NFS_MAXNAMLEN);
991: nfsm_fhtom(sp->s_dvp);
992: nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN);
993: nfsm_request(sndp->ni_dvp, NFSPROC_RENAME, p, 1);
994: nfsm_reqdone;
995: FREE(sndp->ni_pnbuf, M_NAMEI);
996: VTONFS(sndp->ni_dvp)->n_flag |= NMODIFIED;
997: VTONFS(sp->s_dvp)->n_flag |= NMODIFIED;
998: return (error);
999: }
1000:
1001: /*
1002: * nfs hard link create call
1003: */
1004: nfs_link(vp, ndp, p)
1005: register struct vnode *vp;
1006: register struct nameidata *ndp;
1007: struct proc *p;
1008: {
1009: register u_long *tl;
1010: register caddr_t cp;
1011: register long t1, t2;
1012: caddr_t bpos, dpos;
1013: u_long xid;
1014: int error = 0;
1015: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1016:
1017: if (ndp->ni_dvp != vp)
1018: nfs_lock(vp);
1019: nfsstats.rpccnt[NFSPROC_LINK]++;
1020: nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred,
1021: NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
1022: nfsm_fhtom(vp);
1023: nfsm_fhtom(ndp->ni_dvp);
1024: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1025: nfsm_request(vp, NFSPROC_LINK, p, 1);
1026: nfsm_reqdone;
1027: FREE(ndp->ni_pnbuf, M_NAMEI);
1028: VTONFS(vp)->n_attrstamp = 0;
1029: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1030: if (ndp->ni_dvp != vp)
1031: nfs_unlock(vp);
1032: nfs_nput(ndp->ni_dvp);
1033: /*
1034: * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1035: */
1036: if (error == EEXIST)
1037: error = 0;
1038: return (error);
1039: }
1040:
1041: /*
1042: * nfs symbolic link create call
1043: */
1044: nfs_symlink(ndp, vap, nm, p)
1045: struct nameidata *ndp;
1046: struct vattr *vap;
1047: char *nm; /* is this the path ?? */
1048: struct proc *p;
1049: {
1050: register struct nfsv2_sattr *sp;
1051: register u_long *tl;
1052: register caddr_t cp;
1053: register long t1, t2;
1054: caddr_t bpos, dpos;
1055: u_long xid;
1056: int error = 0;
1057: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1058:
1059: nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1060: nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred,
1061: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen)+NFSX_UNSIGNED);
1062: nfsm_fhtom(ndp->ni_dvp);
1063: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1064: nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN);
1065: nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1066: sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode);
1067: sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
1068: sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
1069: sp->sa_size = txdr_unsigned(VNOVAL);
1070: txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
1071: txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
1072: nfsm_request(ndp->ni_dvp, NFSPROC_SYMLINK, p, 1);
1073: nfsm_reqdone;
1074: FREE(ndp->ni_pnbuf, M_NAMEI);
1075: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1076: nfs_nput(ndp->ni_dvp);
1077: /*
1078: * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1079: */
1080: if (error == EEXIST)
1081: error = 0;
1082: return (error);
1083: }
1084:
1085: /*
1086: * nfs make dir call
1087: */
1088: nfs_mkdir(ndp, vap, p)
1089: register struct nameidata *ndp;
1090: struct vattr *vap;
1091: struct proc *p;
1092: {
1093: register struct nfsv2_sattr *sp;
1094: register u_long *tl;
1095: register caddr_t cp;
1096: register long t1, t2;
1097: register int len;
1098: caddr_t bpos, dpos, cp2;
1099: u_long xid;
1100: int error = 0, firsttry = 1;
1101: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1102:
1103: len = ndp->ni_namelen;
1104: nfsstats.rpccnt[NFSPROC_MKDIR]++;
1105: nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred,
1106: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR);
1107: nfsm_fhtom(ndp->ni_dvp);
1108: nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
1109: nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR);
1110: sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode);
1111: sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid);
1112: sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid);
1113: sp->sa_size = txdr_unsigned(VNOVAL);
1114: txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */
1115: txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */
1116: nfsm_request(ndp->ni_dvp, NFSPROC_MKDIR, p, 1);
1117: nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
1118: nfsm_reqdone;
1119: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1120: /*
1121: * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
1122: * if we can succeed in looking up the directory.
1123: * "firsttry" is necessary since the macros may "goto nfsmout" which
1124: * is above the if on errors. (Ugh)
1125: */
1126: if (error == EEXIST && firsttry) {
1127: firsttry = 0;
1128: error = 0;
1129: nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1130: ndp->ni_vp = NULL;
1131: nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred,
1132: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1133: nfsm_fhtom(ndp->ni_dvp);
1134: nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN);
1135: nfsm_request(ndp->ni_dvp, NFSPROC_LOOKUP, p, 1);
1136: nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp);
1137: if (ndp->ni_vp->v_type != VDIR) {
1138: vput(ndp->ni_vp);
1139: error = EEXIST;
1140: }
1141: m_freem(mrep);
1142: }
1143: FREE(ndp->ni_pnbuf, M_NAMEI);
1144: nfs_nput(ndp->ni_dvp);
1145: return (error);
1146: }
1147:
1148: /*
1149: * nfs remove directory call
1150: */
1151: nfs_rmdir(ndp, p)
1152: register struct nameidata *ndp;
1153: struct proc *p;
1154: {
1155: register u_long *tl;
1156: register caddr_t cp;
1157: register long t1, t2;
1158: caddr_t bpos, dpos;
1159: u_long xid;
1160: int error = 0;
1161: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1162:
1163: if (ndp->ni_dvp == ndp->ni_vp) {
1164: vrele(ndp->ni_dvp);
1165: nfs_nput(ndp->ni_dvp);
1166: return (EINVAL);
1167: }
1168: nfsstats.rpccnt[NFSPROC_RMDIR]++;
1169: nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred,
1170: NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_namelen));
1171: nfsm_fhtom(ndp->ni_dvp);
1172: nfsm_strtom(ndp->ni_ptr, ndp->ni_namelen, NFS_MAXNAMLEN);
1173: nfsm_request(ndp->ni_dvp, NFSPROC_RMDIR, p, 1);
1174: nfsm_reqdone;
1175: FREE(ndp->ni_pnbuf, M_NAMEI);
1176: VTONFS(ndp->ni_dvp)->n_flag |= NMODIFIED;
1177: cache_purge(ndp->ni_dvp);
1178: cache_purge(ndp->ni_vp);
1179: nfs_nput(ndp->ni_vp);
1180: nfs_nput(ndp->ni_dvp);
1181: /*
1182: * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
1183: */
1184: if (error == ENOENT)
1185: error = 0;
1186: return (error);
1187: }
1188:
1189: /*
1190: * nfs readdir call
1191: * Although cookie is defined as opaque, I translate it to/from net byte
1192: * order so that it looks more sensible. This appears consistent with the
1193: * Ultrix implementation of NFS.
1194: */
1195: nfs_readdir(vp, uiop, cred, eofflagp)
1196: register struct vnode *vp;
1197: struct uio *uiop;
1198: struct ucred *cred;
1199: int *eofflagp;
1200: {
1201: register struct nfsnode *np = VTONFS(vp);
1202: int tresid, error;
1203: struct vattr vattr;
1204:
1205: if (vp->v_type != VDIR)
1206: return (EPERM);
1207: /*
1208: * First, check for hit on the EOF offset cache
1209: */
1210: if (uiop->uio_offset != 0 && uiop->uio_offset == np->n_direofoffset &&
1211: (np->n_flag & NMODIFIED) == 0 &&
1212: nfs_dogetattr(vp, &vattr, cred, 0, uiop->uio_procp) == 0 &&
1213: np->n_mtime == vattr.va_mtime.tv_sec) {
1214: *eofflagp = 1;
1215: nfsstats.direofcache_hits++;
1216: return (0);
1217: }
1218:
1219: /*
1220: * Call nfs_bioread() to do the real work.
1221: */
1222: tresid = uiop->uio_resid;
1223: error = nfs_bioread(vp, uiop, 0, cred);
1224:
1225: if (!error && uiop->uio_resid == tresid) {
1226: *eofflagp = 1;
1227: nfsstats.direofcache_misses++;
1228: } else
1229: *eofflagp = 0;
1230: return (error);
1231: }
1232:
1233: /*
1234: * Readdir rpc call.
1235: * Called from below the buffer cache by nfs_doio().
1236: */
1237: nfs_readdirrpc(vp, uiop, cred)
1238: register struct vnode *vp;
1239: struct uio *uiop;
1240: struct ucred *cred;
1241: {
1242: register long len;
1243: register struct direct *dp;
1244: register u_long *tl;
1245: register caddr_t cp;
1246: register long t1;
1247: long tlen, lastlen;
1248: caddr_t bpos, dpos, cp2;
1249: u_long xid;
1250: int error = 0;
1251: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1252: struct mbuf *md2;
1253: caddr_t dpos2;
1254: int siz;
1255: int more_dirs = 1;
1256: off_t off, savoff;
1257: struct direct *savdp;
1258: struct nfsmount *nmp;
1259: struct nfsnode *np = VTONFS(vp);
1260: long tresid;
1261:
1262: nmp = VFSTONFS(vp->v_mount);
1263: tresid = uiop->uio_resid;
1264: /*
1265: * Loop around doing readdir rpc's of size uio_resid or nm_rsize,
1266: * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ.
1267: * The stopping criteria is EOF or buffer full.
1268: */
1269: while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) {
1270: nfsstats.rpccnt[NFSPROC_READDIR]++;
1271: nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid);
1272: nfsm_fhtom(vp);
1273: nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED);
1274: *tl++ = txdr_unsigned(uiop->uio_offset);
1275: *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ?
1276: nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1));
1277: nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, 0);
1278: siz = 0;
1279: nfsm_disect(tl, u_long *, NFSX_UNSIGNED);
1280: more_dirs = fxdr_unsigned(int, *tl);
1281:
1282: /* Save the position so that we can do nfsm_mtouio() later */
1283: dpos2 = dpos;
1284: md2 = md;
1285:
1286: /* loop thru the dir entries, doctoring them to 4bsd form */
1287: off = uiop->uio_offset;
1288: #ifdef lint
1289: dp = (struct direct *)0;
1290: #endif /* lint */
1291: while (more_dirs && siz < uiop->uio_resid) {
1292: savoff = off; /* Hold onto offset and dp */
1293: savdp = dp;
1294: nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
1295: dp = (struct direct *)tl;
1296: dp->d_ino = fxdr_unsigned(u_long, *tl++);
1297: len = fxdr_unsigned(int, *tl);
1298: if (len <= 0 || len > NFS_MAXNAMLEN) {
1299: error = EBADRPC;
1300: m_freem(mrep);
1301: goto nfsmout;
1302: }
1303: dp->d_namlen = (u_short)len;
1304: nfsm_adv(len); /* Point past name */
1305: tlen = nfsm_rndup(len);
1306: /*
1307: * This should not be necessary, but some servers have
1308: * broken XDR such that these bytes are not null filled.
1309: */
1310: if (tlen != len) {
1311: *dpos = '\0'; /* Null-terminate */
1312: nfsm_adv(tlen - len);
1313: len = tlen;
1314: }
1315: nfsm_disecton(tl, u_long *, 2*NFSX_UNSIGNED);
1316: off = fxdr_unsigned(off_t, *tl);
1317: *tl++ = 0; /* Ensures null termination of name */
1318: more_dirs = fxdr_unsigned(int, *tl);
1319: dp->d_reclen = len+4*NFSX_UNSIGNED;
1320: siz += dp->d_reclen;
1321: }
1322: /*
1323: * If at end of rpc data, get the eof boolean
1324: */
1325: if (!more_dirs) {
1326: nfsm_disecton(tl, u_long *, NFSX_UNSIGNED);
1327: more_dirs = (fxdr_unsigned(int, *tl) == 0);
1328:
1329: /*
1330: * If at EOF, cache directory offset
1331: */
1332: if (!more_dirs)
1333: np->n_direofoffset = off;
1334: }
1335: /*
1336: * If there is too much to fit in the data buffer, use savoff and
1337: * savdp to trim off the last record.
1338: * --> we are not at eof
1339: */
1340: if (siz > uiop->uio_resid) {
1341: off = savoff;
1342: siz -= dp->d_reclen;
1343: dp = savdp;
1344: more_dirs = 0; /* Paranoia */
1345: }
1346: if (siz > 0) {
1347: lastlen = dp->d_reclen;
1348: md = md2;
1349: dpos = dpos2;
1350: nfsm_mtouio(uiop, siz);
1351: uiop->uio_offset = off;
1352: } else
1353: more_dirs = 0; /* Ugh, never happens, but in case.. */
1354: m_freem(mrep);
1355: }
1356: /*
1357: * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ
1358: * by increasing d_reclen for the last record.
1359: */
1360: if (uiop->uio_resid < tresid) {
1361: len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1);
1362: if (len > 0) {
1363: dp = (struct direct *)
1364: (uiop->uio_iov->iov_base - lastlen);
1365: dp->d_reclen += len;
1366: uiop->uio_iov->iov_base += len;
1367: uiop->uio_iov->iov_len -= len;
1368: uiop->uio_resid -= len;
1369: }
1370: }
1371: nfsmout:
1372: return (error);
1373: }
1374:
1375: static char hextoasc[] = "0123456789abcdef";
1376:
1377: /*
1378: * Silly rename. To make the NFS filesystem that is stateless look a little
1379: * more like the "ufs" a remove of an active vnode is translated to a rename
1380: * to a funny looking filename that is removed by nfs_inactive on the
1381: * nfsnode. There is the potential for another process on a different client
1382: * to create the same funny name between the nfs_lookitup() fails and the
1383: * nfs_rename() completes, but...
1384: */
1385: nfs_sillyrename(ndp, p)
1386: register struct nameidata *ndp;
1387: struct proc *p;
1388: {
1389: register struct nfsnode *np;
1390: register struct sillyrename *sp;
1391: int error;
1392: short pid;
1393:
1394: np = VTONFS(ndp->ni_dvp);
1395: cache_purge(ndp->ni_dvp);
1396: MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
1397: M_NFSREQ, M_WAITOK);
1398: bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH);
1399: np = VTONFS(ndp->ni_vp);
1400: sp->s_cred = crdup(ndp->ni_cred);
1401: sp->s_dvp = ndp->ni_dvp;
1402: VREF(sp->s_dvp);
1403:
1404: /* Fudge together a funny name */
1405: pid = p->p_pid;
1406: bcopy(".nfsAxxxx4.4", sp->s_name, 13);
1407: sp->s_namlen = 12;
1408: sp->s_name[8] = hextoasc[pid & 0xf];
1409: sp->s_name[7] = hextoasc[(pid >> 4) & 0xf];
1410: sp->s_name[6] = hextoasc[(pid >> 8) & 0xf];
1411: sp->s_name[5] = hextoasc[(pid >> 12) & 0xf];
1412:
1413: /* Try lookitups until we get one that isn't there */
1414: while (nfs_lookitup(sp, (nfsv2fh_t *)0, p) == 0) {
1415: sp->s_name[4]++;
1416: if (sp->s_name[4] > 'z') {
1417: error = EINVAL;
1418: goto bad;
1419: }
1420: }
1421: if (error = nfs_renameit(ndp, sp, p))
1422: goto bad;
1423: nfs_lookitup(sp, &np->n_fh, p);
1424: np->n_sillyrename = sp;
1425: return (0);
1426: bad:
1427: vrele(sp->s_dvp);
1428: crfree(sp->s_cred);
1429: free((caddr_t)sp, M_NFSREQ);
1430: return (error);
1431: }
1432:
1433: /*
1434: * Look up a file name for silly rename stuff.
1435: * Just like nfs_lookup() except that it doesn't load returned values
1436: * into the nfsnode table.
1437: * If fhp != NULL it copies the returned file handle out
1438: */
1439: nfs_lookitup(sp, fhp, p)
1440: register struct sillyrename *sp;
1441: nfsv2fh_t *fhp;
1442: struct proc *p;
1443: {
1444: register struct vnode *vp = sp->s_dvp;
1445: register u_long *tl;
1446: register caddr_t cp;
1447: register long t1, t2;
1448: caddr_t bpos, dpos, cp2;
1449: u_long xid;
1450: int error = 0;
1451: struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1452: long len;
1453:
1454: nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1455: len = sp->s_namlen;
1456: nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], sp->s_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len));
1457: nfsm_fhtom(vp);
1458: nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN);
1459: nfsm_request(vp, NFSPROC_LOOKUP, p, 1);
1460: if (fhp != NULL) {
1461: nfsm_disect(cp, caddr_t, NFSX_FH);
1462: bcopy(cp, (caddr_t)fhp, NFSX_FH);
1463: }
1464: nfsm_reqdone;
1465: return (error);
1466: }
1467:
1468: /*
1469: * Kludge City..
1470: * - make nfs_bmap() essentially a no-op that does no translation
1471: * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc
1472: * after mapping the physical addresses into Kernel Virtual space in the
1473: * nfsiobuf area.
1474: * (Maybe I could use the process's page mapping, but I was concerned that
1475: * Kernel Write might not be enabled and also figured copyout() would do
1476: * a lot more work than bcopy() and also it currently happens in the
1477: * context of the swapper process (2).
1478: */
1479: nfs_bmap(vp, bn, vpp, bnp)
1480: struct vnode *vp;
1481: daddr_t bn;
1482: struct vnode **vpp;
1483: daddr_t *bnp;
1484: {
1485: if (vpp != NULL)
1486: *vpp = vp;
1487: if (bnp != NULL)
1488: *bnp = bn * btodb(vp->v_mount->mnt_stat.f_bsize);
1489: return (0);
1490: }
1491:
1492: /*
1493: * Strategy routine for phys. i/o
1494: * If the biod's are running, queue a request
1495: * otherwise just call nfs_doio() to get it done
1496: */
1497: nfs_strategy(bp)
1498: register struct buf *bp;
1499: {
1500: register struct buf *dp;
1501: register int i;
1502: int error = 0;
1503: int fnd = 0;
1504:
1505: /*
1506: * Set b_proc. It seems a bit silly to do it here, but since bread()
1507: * doesn't set it, I will.
1508: * Set b_proc == NULL for asynchronous ops, since these may still
1509: * be hanging about after the process terminates.
1510: */
1511: if ((bp->b_flags & B_PHYS) == 0) {
1512: if (bp->b_flags & B_ASYNC)
1513: bp->b_proc = (struct proc *)0;
1514: else
1515: bp->b_proc = curproc;
1516: }
1517: /*
1518: * If the op is asynchronous and an i/o daemon is waiting
1519: * queue the request, wake it up and wait for completion
1520: * otherwise just do it ourselves.
1521: */
1522: if ((bp->b_flags & B_ASYNC) == 0 || nfs_numasync == 0)
1523: return (nfs_doio(bp));
1524: for (i = 0; i < NFS_MAXASYNCDAEMON; i++) {
1525: if (nfs_iodwant[i]) {
1526: dp = &nfs_bqueue;
1527: if (dp->b_actf == NULL) {
1528: dp->b_actl = bp;
1529: bp->b_actf = dp;
1530: } else {
1531: dp->b_actf->b_actl = bp;
1532: bp->b_actf = dp->b_actf;
1533: }
1534: dp->b_actf = bp;
1535: bp->b_actl = dp;
1536: fnd++;
1537: wakeup((caddr_t)&nfs_iodwant[i]);
1538: break;
1539: }
1540: }
1541: if (!fnd)
1542: error = nfs_doio(bp);
1543: return (error);
1544: }
1545:
1546: /*
1547: * Fun and games with i/o
1548: * Essentially play ubasetup() and disk interrupt service routine by
1549: * mapping the data buffer into kernel virtual space and doing the
1550: * nfs read or write rpc's from it.
1551: * If the nfsiod's are not running, this is just called from nfs_strategy(),
1552: * otherwise it is called by the nfsiods to do what would normally be
1553: * partially disk interrupt driven.
1554: */
1555: nfs_doio(bp)
1556: register struct buf *bp;
1557: {
1558: register struct uio *uiop;
1559: register struct vnode *vp;
1560: struct nfsnode *np;
1561: struct ucred *cr;
1562: int error;
1563: struct uio uio;
1564: struct iovec io;
1565: #if !defined(hp300) && !defined(i386)
1566: register struct pte *pte, *ppte;
1567: register caddr_t vaddr;
1568: int npf, npf2;
1569: int reg, o;
1570: caddr_t vbase;
1571: unsigned v;
1572: #endif
1573:
1574: vp = bp->b_vp;
1575: np = VTONFS(vp);
1576: uiop = &uio;
1577: uiop->uio_iov = &io;
1578: uiop->uio_iovcnt = 1;
1579: uiop->uio_segflg = UIO_SYSSPACE;
1580: uiop->uio_procp = (struct proc *)0;
1581:
1582: /*
1583: * For phys i/o, map the b_addr into kernel virtual space using
1584: * the Nfsiomap pte's
1585: * Also, add a temporary b_rcred for reading using the process's uid
1586: * and a guess at a group
1587: */
1588: if (bp->b_flags & B_PHYS) {
1589: if (bp->b_flags & B_DIRTY)
1590: uiop->uio_procp = pageproc;
1591: cr = crcopy(uiop->uio_procp->p_ucred);
1592: /* mapping was already done by vmapbuf */
1593: io.iov_base = bp->b_un.b_addr;
1594:
1595: /*
1596: * And do the i/o rpc
1597: */
1598: io.iov_len = uiop->uio_resid = bp->b_bcount;
1599: uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1600: if (bp->b_flags & B_READ) {
1601: uiop->uio_rw = UIO_READ;
1602: nfsstats.read_physios++;
1603: bp->b_error = error = nfs_readrpc(vp, uiop, cr);
1604: (void) vnode_pager_uncache(vp);
1605: } else {
1606: uiop->uio_rw = UIO_WRITE;
1607: nfsstats.write_physios++;
1608: bp->b_error = error = nfs_writerpc(vp, uiop, cr);
1609: }
1610:
1611: /*
1612: * Finally, release pte's used by physical i/o
1613: */
1614: crfree(cr);
1615: } else {
1616: if (bp->b_flags & B_READ) {
1617: io.iov_len = uiop->uio_resid = bp->b_bcount;
1618: io.iov_base = bp->b_un.b_addr;
1619: uiop->uio_rw = UIO_READ;
1620: switch (vp->v_type) {
1621: case VREG:
1622: uiop->uio_offset = bp->b_blkno * DEV_BSIZE;
1623: nfsstats.read_bios++;
1624: error = nfs_readrpc(vp, uiop, bp->b_rcred);
1625: break;
1626: case VLNK:
1627: uiop->uio_offset = 0;
1628: nfsstats.readlink_bios++;
1629: error = nfs_readlinkrpc(vp, uiop, bp->b_rcred);
1630: break;
1631: case VDIR:
1632: uiop->uio_offset = bp->b_lblkno;
1633: nfsstats.readdir_bios++;
1634: error = nfs_readdirrpc(vp, uiop, bp->b_rcred);
1635: /*
1636: * Save offset cookie in b_blkno.
1637: */
1638: bp->b_blkno = uiop->uio_offset;
1639: break;
1640: };
1641: bp->b_error = error;
1642: } else {
1643: io.iov_len = uiop->uio_resid = bp->b_dirtyend
1644: - bp->b_dirtyoff;
1645: uiop->uio_offset = (bp->b_blkno * DEV_BSIZE)
1646: + bp->b_dirtyoff;
1647: io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff;
1648: uiop->uio_rw = UIO_WRITE;
1649: nfsstats.write_bios++;
1650: bp->b_error = error = nfs_writerpc(vp, uiop,
1651: bp->b_wcred);
1652: if (error) {
1653: np->n_error = error;
1654: np->n_flag |= NWRITEERR;
1655: }
1656: bp->b_dirtyoff = bp->b_dirtyend = 0;
1657: }
1658: }
1659: if (error)
1660: bp->b_flags |= B_ERROR;
1661: bp->b_resid = uiop->uio_resid;
1662: biodone(bp);
1663: return (error);
1664: }
1665:
1666: /*
1667: * Mmap a file
1668: *
1669: * NB Currently unsupported.
1670: */
1671: /* ARGSUSED */
1672: nfs_mmap(vp, fflags, cred, p)
1673: struct vnode *vp;
1674: int fflags;
1675: struct ucred *cred;
1676: struct proc *p;
1677: {
1678:
1679: return (EINVAL);
1680: }
1681:
1682: /*
1683: * Flush all the blocks associated with a vnode.
1684: * Walk through the buffer pool and push any dirty pages
1685: * associated with the vnode.
1686: */
1687: /* ARGSUSED */
1688: nfs_fsync(vp, fflags, cred, waitfor, p)
1689: register struct vnode *vp;
1690: int fflags;
1691: struct ucred *cred;
1692: int waitfor;
1693: struct proc *p;
1694: {
1695: register struct nfsnode *np = VTONFS(vp);
1696: int error = 0;
1697:
1698: if (np->n_flag & NMODIFIED) {
1699: np->n_flag &= ~NMODIFIED;
1700: vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0);
1701: }
1702: if (!error && (np->n_flag & NWRITEERR))
1703: error = np->n_error;
1704: return (error);
1705: }
1706:
1707: /*
1708: * NFS advisory byte-level locks.
1709: * Currently unsupported.
1710: */
1711: nfs_advlock(vp, id, op, fl, flags)
1712: struct vnode *vp;
1713: caddr_t id;
1714: int op;
1715: struct flock *fl;
1716: int flags;
1717: {
1.1.1.4 ! root 1718: register struct nfsnode *np = VTONFS(vp);
1.1 root 1719:
1.1.1.4 ! root 1720: return (lf_advlock(&(np->n_lockf), np->n_size, id, op, fl, flags));
1.1 root 1721: }
1722:
1723: /*
1724: * Print out the contents of an nfsnode.
1725: */
1726: nfs_print(vp)
1727: struct vnode *vp;
1728: {
1729: register struct nfsnode *np = VTONFS(vp);
1730:
1731: printf("tag VT_NFS, fileid %d fsid 0x%x",
1732: np->n_vattr.va_fileid, np->n_vattr.va_fsid);
1733: #ifdef FIFO
1734: if (vp->v_type == VFIFO)
1735: fifo_printinfo(vp);
1736: #endif /* FIFO */
1737: printf("%s\n", (np->n_flag & NLOCKED) ? " (LOCKED)" : "");
1738: if (np->n_lockholder == 0)
1739: return;
1740: printf("\towner pid %d", np->n_lockholder);
1741: if (np->n_lockwaiter)
1742: printf(" waiting pid %d", np->n_lockwaiter);
1743: printf("\n");
1744: }
1.1.1.3 root 1745:
1746:
1747: /*
1748: * Attribute cache routines.
1749: * nfs_loadattrcache() - loads or updates the cache contents from attributes
1750: * that are on the mbuf list
1751: * nfs_getattrcache() - returns valid attributes if found in cache, returns
1752: * error otherwise
1753: */
1754:
1755: /*
1756: * Load the attribute cache (that lives in the nfsnode entry) with
1757: * the values on the mbuf list and
1758: * Iff vap not NULL
1759: * copy the attributes to *vaper
1760: */
1761: nfs_loadattrcache(vpp, mdp, dposp, vaper)
1762: struct vnode **vpp;
1763: struct mbuf **mdp;
1764: caddr_t *dposp;
1765: struct vattr *vaper;
1766: {
1767: register struct vnode *vp = *vpp;
1768: register struct vattr *vap;
1769: register struct nfsv2_fattr *fp;
1770: extern struct vnodeops spec_nfsv2nodeops;
1771: register struct nfsnode *np;
1772: register long t1;
1773: caddr_t dpos, cp2;
1774: int error = 0;
1775: struct mbuf *md;
1776: enum vtype type;
1777: u_short mode;
1778: long rdev;
1779: struct timeval mtime;
1780: struct vnode *nvp;
1781:
1782: md = *mdp;
1783: dpos = *dposp;
1784: t1 = (mtod(md, caddr_t)+md->m_len)-dpos;
1785: if (error = nfsm_disct(&md, &dpos, NFSX_FATTR, t1, TRUE, &cp2))
1786: return (error);
1787: fp = (struct nfsv2_fattr *)cp2;
1788: type = nfstov_type(fp->fa_type);
1789: mode = fxdr_unsigned(u_short, fp->fa_mode);
1790: if (type == VNON)
1791: type = IFTOVT(mode);
1792: rdev = fxdr_unsigned(long, fp->fa_rdev);
1793: fxdr_time(&fp->fa_mtime, &mtime);
1794: /*
1795: * If v_type == VNON it is a new node, so fill in the v_type,
1796: * n_mtime fields. Check to see if it represents a special
1797: * device, and if so, check for a possible alias. Once the
1798: * correct vnode has been obtained, fill in the rest of the
1799: * information.
1800: */
1801: np = VTONFS(vp);
1802: if (vp->v_type == VNON) {
1803: if (type == VCHR && rdev == 0xffffffff)
1804: vp->v_type = type = VFIFO;
1805: else
1806: vp->v_type = type;
1807: if (vp->v_type == VFIFO) {
1808: #ifdef FIFO
1809: extern struct vnodeops fifo_nfsv2nodeops;
1810: vp->v_op = &fifo_nfsv2nodeops;
1811: #else
1812: return (EOPNOTSUPP);
1813: #endif /* FIFO */
1814: }
1815: if (vp->v_type == VCHR || vp->v_type == VBLK) {
1816: vp->v_op = &spec_nfsv2nodeops;
1817: if (nvp = checkalias(vp, (dev_t)rdev, vp->v_mount)) {
1818: /*
1819: * Reinitialize aliased node.
1820: */
1821: np = VTONFS(nvp);
1822: np->n_vnode = nvp;
1823: np->n_flag = 0;
1824: nfs_lock(nvp);
1825: bcopy((caddr_t)&VTONFS(vp)->n_fh,
1826: (caddr_t)&np->n_fh, NFSX_FH);
1827: insque(np, nfs_hash(&np->n_fh));
1828: np->n_attrstamp = 0;
1829: np->n_sillyrename = (struct sillyrename *)0;
1830: /*
1831: * Discard unneeded vnode and update actual one
1832: */
1833: vput(vp);
1834: *vpp = nvp;
1835: }
1836: }
1837: np->n_mtime = mtime.tv_sec;
1838: }
1839: vap = &np->n_vattr;
1840: vap->va_type = type;
1841: vap->va_mode = (mode & 07777);
1842: vap->va_nlink = fxdr_unsigned(u_short, fp->fa_nlink);
1843: vap->va_uid = fxdr_unsigned(uid_t, fp->fa_uid);
1844: vap->va_gid = fxdr_unsigned(gid_t, fp->fa_gid);
1845: vap->va_size = fxdr_unsigned(u_long, fp->fa_size);
1846: if ((np->n_flag & NMODIFIED) == 0 || vap->va_size > np->n_size) {
1847: np->n_size = vap->va_size;
1848: vnode_pager_setsize(vp, np->n_size);
1849: }
1850: vap->va_size_rsv = 0;
1851: vap->va_blocksize = fxdr_unsigned(long, fp->fa_blocksize);
1852: vap->va_rdev = (dev_t)rdev;
1853: vap->va_bytes = fxdr_unsigned(long, fp->fa_blocks) * NFS_FABLKSIZE;
1854: vap->va_bytes_rsv = 0;
1855: vap->va_fsid = vp->v_mount->mnt_stat.f_fsid.val[0];
1856: vap->va_fileid = fxdr_unsigned(long, fp->fa_fileid);
1.1.1.4 ! root 1857: /* [email protected] 6/2/93 */
! 1858: #if 0 /* bad assumption; Suns make full (and obvious) use of .usec fields */
1.1.1.3 root 1859: vap->va_atime.tv_sec = fxdr_unsigned(long, fp->fa_atime.tv_sec);
1860: vap->va_atime.tv_usec = 0;
1861: vap->va_flags = fxdr_unsigned(u_long, fp->fa_atime.tv_usec);
1862: vap->va_mtime = mtime;
1863: vap->va_ctime.tv_sec = fxdr_unsigned(long, fp->fa_ctime.tv_sec);
1864: vap->va_ctime.tv_usec = 0;
1865: vap->va_gen = fxdr_unsigned(u_long, fp->fa_ctime.tv_usec);
1.1.1.4 ! root 1866: #else
! 1867: fxdr_time(&fp->fa_atime, &vap->va_atime);
! 1868: vap->va_mtime = mtime;
! 1869: fxdr_time(&fp->fa_ctime, &vap->va_ctime);
! 1870: vap->va_gen = 0; /* can reliably learn nothing about this via NFS. */
! 1871: vap->va_flags = 0; /* can reliably learn nothing about this via NFS. */
! 1872: #endif
1.1.1.3 root 1873: np->n_attrstamp = time.tv_sec;
1874: *dposp = dpos;
1875: *mdp = md;
1876: if (vaper != NULL) {
1877: bcopy((caddr_t)vap, (caddr_t)vaper, sizeof(*vap));
1878: if ((np->n_flag & NMODIFIED) && (np->n_size > vap->va_size))
1879: vaper->va_size = np->n_size;
1880: }
1881: return (0);
1882: }
1883:
1884: /*
1885: * Check the time stamp
1886: * If the cache is valid, copy contents to *vap and return 0
1887: * otherwise return an error
1888: */
1889: nfs_getattrcache(vp, vap)
1890: register struct vnode *vp;
1891: struct vattr *vap;
1892: {
1893: register struct nfsnode *np;
1894:
1895: np = VTONFS(vp);
1896: if ((time.tv_sec-np->n_attrstamp) < NFS_ATTRTIMEO) {
1897: nfsstats.attrcache_hits++;
1898: bcopy((caddr_t)&np->n_vattr,(caddr_t)vap,sizeof(struct vattr));
1899: if ((np->n_flag & NMODIFIED) == 0) {
1900: np->n_size = vap->va_size;
1901: vnode_pager_setsize(vp, np->n_size);
1902: } else if (np->n_size > vap->va_size)
1903: vap->va_size = np->n_size;
1904: return (0);
1905: } else {
1906: nfsstats.attrcache_misses++;
1907: return (ENOENT);
1908: }
1909: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.