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