Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / sys / vfs / nfs / nfs_vnops.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  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 8.16 (Berkeley) 5/27/95
37  * $FreeBSD: src/sys/nfs/nfs_vnops.c,v 1.150.2.5 2001/12/20 19:56:28 dillon Exp $
38  * $DragonFly: src/sys/vfs/nfs/nfs_vnops.c,v 1.40 2005/04/15 19:08:21 dillon Exp $
39  */
40
41
42 /*
43  * vnode op calls for Sun NFS version 2 and 3
44  */
45
46 #include "opt_inet.h"
47
48 #include <sys/param.h>
49 #include <sys/kernel.h>
50 #include <sys/systm.h>
51 #include <sys/resourcevar.h>
52 #include <sys/proc.h>
53 #include <sys/mount.h>
54 #include <sys/buf.h>
55 #include <sys/malloc.h>
56 #include <sys/mbuf.h>
57 #include <sys/namei.h>
58 #include <sys/nlookup.h>
59 #include <sys/socket.h>
60 #include <sys/vnode.h>
61 #include <sys/dirent.h>
62 #include <sys/fcntl.h>
63 #include <sys/lockf.h>
64 #include <sys/stat.h>
65 #include <sys/sysctl.h>
66 #include <sys/conf.h>
67
68 #include <vm/vm.h>
69 #include <vm/vm_extern.h>
70 #include <vm/vm_zone.h>
71
72 #include <sys/buf2.h>
73
74 #include <vfs/fifofs/fifo.h>
75
76 #include "rpcv2.h"
77 #include "nfsproto.h"
78 #include "nfs.h"
79 #include "nfsmount.h"
80 #include "nfsnode.h"
81 #include "xdr_subs.h"
82 #include "nfsm_subs.h"
83 #include "nqnfs.h"
84
85 #include <net/if.h>
86 #include <netinet/in.h>
87 #include <netinet/in_var.h>
88
89 /* Defs */
90 #define TRUE    1
91 #define FALSE   0
92
93 /*
94  * Ifdef for FreeBSD-current merged buffer cache. It is unfortunate that these
95  * calls are not in getblk() and brelse() so that they would not be necessary
96  * here.
97  */
98 #ifndef B_VMIO
99 #define vfs_busy_pages(bp, f)
100 #endif
101
102 static int      nfsspec_read (struct vop_read_args *);
103 static int      nfsspec_write (struct vop_write_args *);
104 static int      nfsfifo_read (struct vop_read_args *);
105 static int      nfsfifo_write (struct vop_write_args *);
106 static int      nfsspec_close (struct vop_close_args *);
107 static int      nfsfifo_close (struct vop_close_args *);
108 #define nfs_poll vop_nopoll
109 static int      nfs_setattrrpc (struct vnode *,struct vattr *,struct ucred *,struct thread *);
110 static  int     nfs_lookup (struct vop_lookup_args *);
111 static  int     nfs_create (struct vop_create_args *);
112 static  int     nfs_mknod (struct vop_mknod_args *);
113 static  int     nfs_open (struct vop_open_args *);
114 static  int     nfs_close (struct vop_close_args *);
115 static  int     nfs_access (struct vop_access_args *);
116 static  int     nfs_getattr (struct vop_getattr_args *);
117 static  int     nfs_setattr (struct vop_setattr_args *);
118 static  int     nfs_read (struct vop_read_args *);
119 static  int     nfs_mmap (struct vop_mmap_args *);
120 static  int     nfs_fsync (struct vop_fsync_args *);
121 static  int     nfs_remove (struct vop_remove_args *);
122 static  int     nfs_link (struct vop_link_args *);
123 static  int     nfs_rename (struct vop_rename_args *);
124 static  int     nfs_mkdir (struct vop_mkdir_args *);
125 static  int     nfs_rmdir (struct vop_rmdir_args *);
126 static  int     nfs_symlink (struct vop_symlink_args *);
127 static  int     nfs_readdir (struct vop_readdir_args *);
128 static  int     nfs_bmap (struct vop_bmap_args *);
129 static  int     nfs_strategy (struct vop_strategy_args *);
130 static  int     nfs_lookitup (struct vnode *, const char *, int,
131                         struct ucred *, struct thread *, struct nfsnode **);
132 static  int     nfs_sillyrename (struct vnode *,struct vnode *,struct componentname *);
133 static int      nfsspec_access (struct vop_access_args *);
134 static int      nfs_readlink (struct vop_readlink_args *);
135 static int      nfs_print (struct vop_print_args *);
136 static int      nfs_advlock (struct vop_advlock_args *);
137 static int      nfs_bwrite (struct vop_bwrite_args *);
138
139 static  int     nfs_nresolve (struct vop_nresolve_args *);
140 /*
141  * Global vfs data structures for nfs
142  */
143 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = {
144         { &vop_default_desc,            vop_defaultop },
145         { &vop_access_desc,             (vnodeopv_entry_t) nfs_access },
146         { &vop_advlock_desc,            (vnodeopv_entry_t) nfs_advlock },
147         { &vop_bmap_desc,               (vnodeopv_entry_t) nfs_bmap },
148         { &vop_bwrite_desc,             (vnodeopv_entry_t) nfs_bwrite },
149         { &vop_close_desc,              (vnodeopv_entry_t) nfs_close },
150         { &vop_create_desc,             (vnodeopv_entry_t) nfs_create },
151         { &vop_fsync_desc,              (vnodeopv_entry_t) nfs_fsync },
152         { &vop_getattr_desc,            (vnodeopv_entry_t) nfs_getattr },
153         { &vop_getpages_desc,           (vnodeopv_entry_t) nfs_getpages },
154         { &vop_putpages_desc,           (vnodeopv_entry_t) nfs_putpages },
155         { &vop_inactive_desc,           (vnodeopv_entry_t) nfs_inactive },
156         { &vop_islocked_desc,           (vnodeopv_entry_t) vop_stdislocked },
157         { &vop_lease_desc,              vop_null },
158         { &vop_link_desc,               (vnodeopv_entry_t) nfs_link },
159         { &vop_lock_desc,               (vnodeopv_entry_t) vop_stdlock },
160         { &vop_lookup_desc,             (vnodeopv_entry_t) nfs_lookup },
161         { &vop_mkdir_desc,              (vnodeopv_entry_t) nfs_mkdir },
162         { &vop_mknod_desc,              (vnodeopv_entry_t) nfs_mknod },
163         { &vop_mmap_desc,               (vnodeopv_entry_t) nfs_mmap },
164         { &vop_open_desc,               (vnodeopv_entry_t) nfs_open },
165         { &vop_poll_desc,               (vnodeopv_entry_t) nfs_poll },
166         { &vop_print_desc,              (vnodeopv_entry_t) nfs_print },
167         { &vop_read_desc,               (vnodeopv_entry_t) nfs_read },
168         { &vop_readdir_desc,            (vnodeopv_entry_t) nfs_readdir },
169         { &vop_readlink_desc,           (vnodeopv_entry_t) nfs_readlink },
170         { &vop_reclaim_desc,            (vnodeopv_entry_t) nfs_reclaim },
171         { &vop_remove_desc,             (vnodeopv_entry_t) nfs_remove },
172         { &vop_rename_desc,             (vnodeopv_entry_t) nfs_rename },
173         { &vop_rmdir_desc,              (vnodeopv_entry_t) nfs_rmdir },
174         { &vop_setattr_desc,            (vnodeopv_entry_t) nfs_setattr },
175         { &vop_strategy_desc,           (vnodeopv_entry_t) nfs_strategy },
176         { &vop_symlink_desc,            (vnodeopv_entry_t) nfs_symlink },
177         { &vop_unlock_desc,             (vnodeopv_entry_t) vop_stdunlock },
178         { &vop_write_desc,              (vnodeopv_entry_t) nfs_write },
179
180         { &vop_nresolve_desc,           (vnodeopv_entry_t) nfs_nresolve },
181         { NULL, NULL }
182 };
183
184 /*
185  * Special device vnode ops
186  */
187 struct vnodeopv_entry_desc nfsv2_specop_entries[] = {
188         { &vop_default_desc,            (vnodeopv_entry_t) spec_vnoperate },
189         { &vop_access_desc,             (vnodeopv_entry_t) nfsspec_access },
190         { &vop_close_desc,              (vnodeopv_entry_t) nfsspec_close },
191         { &vop_fsync_desc,              (vnodeopv_entry_t) nfs_fsync },
192         { &vop_getattr_desc,            (vnodeopv_entry_t) nfs_getattr },
193         { &vop_inactive_desc,           (vnodeopv_entry_t) nfs_inactive },
194         { &vop_islocked_desc,           (vnodeopv_entry_t) vop_stdislocked },
195         { &vop_lock_desc,               (vnodeopv_entry_t) vop_stdlock },
196         { &vop_print_desc,              (vnodeopv_entry_t) nfs_print },
197         { &vop_read_desc,               (vnodeopv_entry_t) nfsspec_read },
198         { &vop_reclaim_desc,            (vnodeopv_entry_t) nfs_reclaim },
199         { &vop_setattr_desc,            (vnodeopv_entry_t) nfs_setattr },
200         { &vop_unlock_desc,             (vnodeopv_entry_t) vop_stdunlock },
201         { &vop_write_desc,              (vnodeopv_entry_t) nfsspec_write },
202         { NULL, NULL }
203 };
204
205 struct vnodeopv_entry_desc nfsv2_fifoop_entries[] = {
206         { &vop_default_desc,            (vnodeopv_entry_t) fifo_vnoperate },
207         { &vop_access_desc,             (vnodeopv_entry_t) nfsspec_access },
208         { &vop_close_desc,              (vnodeopv_entry_t) nfsfifo_close },
209         { &vop_fsync_desc,              (vnodeopv_entry_t) nfs_fsync },
210         { &vop_getattr_desc,            (vnodeopv_entry_t) nfs_getattr },
211         { &vop_inactive_desc,           (vnodeopv_entry_t) nfs_inactive },
212         { &vop_islocked_desc,           (vnodeopv_entry_t) vop_stdislocked },
213         { &vop_lock_desc,               (vnodeopv_entry_t) vop_stdlock },
214         { &vop_print_desc,              (vnodeopv_entry_t) nfs_print },
215         { &vop_read_desc,               (vnodeopv_entry_t) nfsfifo_read },
216         { &vop_reclaim_desc,            (vnodeopv_entry_t) nfs_reclaim },
217         { &vop_setattr_desc,            (vnodeopv_entry_t) nfs_setattr },
218         { &vop_unlock_desc,             (vnodeopv_entry_t) vop_stdunlock },
219         { &vop_write_desc,              (vnodeopv_entry_t) nfsfifo_write },
220         { NULL, NULL }
221 };
222
223 static int      nfs_mknodrpc (struct vnode *dvp, struct vnode **vpp,
224                                   struct componentname *cnp,
225                                   struct vattr *vap);
226 static int      nfs_removerpc (struct vnode *dvp, const char *name,
227                                    int namelen,
228                                    struct ucred *cred, struct thread *td);
229 static int      nfs_renamerpc (struct vnode *fdvp, const char *fnameptr,
230                                    int fnamelen, struct vnode *tdvp,
231                                    const char *tnameptr, int tnamelen,
232                                    struct ucred *cred, struct thread *td);
233 static int      nfs_renameit (struct vnode *sdvp,
234                                   struct componentname *scnp,
235                                   struct sillyrename *sp);
236
237 /*
238  * Global variables
239  */
240 extern u_int32_t nfs_true, nfs_false;
241 extern u_int32_t nfs_xdrneg1;
242 extern struct nfsstats nfsstats;
243 extern nfstype nfsv3_type[9];
244 struct thread *nfs_iodwant[NFS_MAXASYNCDAEMON];
245 struct nfsmount *nfs_iodmount[NFS_MAXASYNCDAEMON];
246 int nfs_numasync = 0;
247 #define DIRHDSIZ        (sizeof (struct dirent) - (MAXNAMLEN + 1))
248
249 SYSCTL_DECL(_vfs_nfs);
250
251 static int      nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
252 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW, 
253            &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
254
255 static int      nfsneg_cache_timeout = NFS_MINATTRTIMO;
256 SYSCTL_INT(_vfs_nfs, OID_AUTO, neg_cache_timeout, CTLFLAG_RW, 
257            &nfsneg_cache_timeout, 0, "NFS NEGATIVE ACCESS cache timeout");
258
259 static int      nfsv3_commit_on_close = 0;
260 SYSCTL_INT(_vfs_nfs, OID_AUTO, nfsv3_commit_on_close, CTLFLAG_RW, 
261            &nfsv3_commit_on_close, 0, "write+commit on close, else only write");
262 #if 0
263 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_hits, CTLFLAG_RD, 
264            &nfsstats.accesscache_hits, 0, "NFS ACCESS cache hit count");
265
266 SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_misses, CTLFLAG_RD, 
267            &nfsstats.accesscache_misses, 0, "NFS ACCESS cache miss count");
268 #endif
269
270 #define NFSV3ACCESS_ALL (NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY          \
271                          | NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE     \
272                          | NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP)
273 static int
274 nfs3_access_otw(struct vnode *vp, int wmode,
275                 struct thread *td, struct ucred *cred)
276 {
277         const int v3 = 1;
278         u_int32_t *tl;
279         int error = 0, attrflag;
280         
281         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
282         caddr_t bpos, dpos, cp2;
283         int32_t t1, t2;
284         caddr_t cp;
285         u_int32_t rmode;
286         struct nfsnode *np = VTONFS(vp);
287
288         nfsstats.rpccnt[NFSPROC_ACCESS]++;
289         nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED);
290         nfsm_fhtom(vp, v3);
291         nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
292         *tl = txdr_unsigned(wmode); 
293         nfsm_request(vp, NFSPROC_ACCESS, td, cred);
294         nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
295         if (!error) {
296                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
297                 rmode = fxdr_unsigned(u_int32_t, *tl);
298                 np->n_mode = rmode;
299                 np->n_modeuid = cred->cr_uid;
300                 np->n_modestamp = mycpu->gd_time_seconds;
301         }
302         m_freem(mrep);
303 nfsmout:
304         return error;
305 }
306
307 /*
308  * nfs access vnode op.
309  * For nfs version 2, just return ok. File accesses may fail later.
310  * For nfs version 3, use the access rpc to check accessibility. If file modes
311  * are changed on the server, accesses might still fail later.
312  *
313  * nfs_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
314  *            struct thread *a_td)
315  */
316 static int
317 nfs_access(struct vop_access_args *ap)
318 {
319         struct vnode *vp = ap->a_vp;
320         int error = 0;
321         u_int32_t mode, wmode;
322         int v3 = NFS_ISV3(vp);
323         struct nfsnode *np = VTONFS(vp);
324
325         /*
326          * Disallow write attempts on filesystems mounted read-only;
327          * unless the file is a socket, fifo, or a block or character
328          * device resident on the filesystem.
329          */
330         if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
331                 switch (vp->v_type) {
332                 case VREG:
333                 case VDIR:
334                 case VLNK:
335                         return (EROFS);
336                 default:
337                         break;
338                 }
339         }
340         /*
341          * For nfs v3, check to see if we have done this recently, and if
342          * so return our cached result instead of making an ACCESS call.
343          * If not, do an access rpc, otherwise you are stuck emulating
344          * ufs_access() locally using the vattr. This may not be correct,
345          * since the server may apply other access criteria such as
346          * client uid-->server uid mapping that we do not know about.
347          */
348         if (v3) {
349                 if (ap->a_mode & VREAD)
350                         mode = NFSV3ACCESS_READ;
351                 else
352                         mode = 0;
353                 if (vp->v_type != VDIR) {
354                         if (ap->a_mode & VWRITE)
355                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
356                         if (ap->a_mode & VEXEC)
357                                 mode |= NFSV3ACCESS_EXECUTE;
358                 } else {
359                         if (ap->a_mode & VWRITE)
360                                 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
361                                          NFSV3ACCESS_DELETE);
362                         if (ap->a_mode & VEXEC)
363                                 mode |= NFSV3ACCESS_LOOKUP;
364                 }
365                 /* XXX safety belt, only make blanket request if caching */
366                 if (nfsaccess_cache_timeout > 0) {
367                         wmode = NFSV3ACCESS_READ | NFSV3ACCESS_MODIFY | 
368                                 NFSV3ACCESS_EXTEND | NFSV3ACCESS_EXECUTE | 
369                                 NFSV3ACCESS_DELETE | NFSV3ACCESS_LOOKUP;
370                 } else {
371                         wmode = mode;
372                 }
373
374                 /*
375                  * Does our cached result allow us to give a definite yes to
376                  * this request?
377                  */
378                 if (np->n_modestamp && 
379                    (mycpu->gd_time_seconds < (np->n_modestamp + nfsaccess_cache_timeout)) &&
380                    (ap->a_cred->cr_uid == np->n_modeuid) &&
381                    ((np->n_mode & mode) == mode)) {
382                         nfsstats.accesscache_hits++;
383                 } else {
384                         /*
385                          * Either a no, or a don't know.  Go to the wire.
386                          */
387                         nfsstats.accesscache_misses++;
388                         error = nfs3_access_otw(vp, wmode, ap->a_td,ap->a_cred);
389                         if (!error) {
390                                 if ((np->n_mode & mode) != mode) {
391                                         error = EACCES;
392                                 }
393                         }
394                 }
395         } else {
396                 if ((error = nfsspec_access(ap)) != 0)
397                         return (error);
398
399                 /*
400                  * Attempt to prevent a mapped root from accessing a file
401                  * which it shouldn't.  We try to read a byte from the file
402                  * if the user is root and the file is not zero length.
403                  * After calling nfsspec_access, we should have the correct
404                  * file size cached.
405                  */
406                 if (ap->a_cred->cr_uid == 0 && (ap->a_mode & VREAD)
407                     && VTONFS(vp)->n_size > 0) {
408                         struct iovec aiov;
409                         struct uio auio;
410                         char buf[1];
411
412                         aiov.iov_base = buf;
413                         aiov.iov_len = 1;
414                         auio.uio_iov = &aiov;
415                         auio.uio_iovcnt = 1;
416                         auio.uio_offset = 0;
417                         auio.uio_resid = 1;
418                         auio.uio_segflg = UIO_SYSSPACE;
419                         auio.uio_rw = UIO_READ;
420                         auio.uio_td = ap->a_td;
421
422                         if (vp->v_type == VREG) {
423                                 error = nfs_readrpc(vp, &auio);
424                         } else if (vp->v_type == VDIR) {
425                                 char* bp;
426                                 bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
427                                 aiov.iov_base = bp;
428                                 aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
429                                 error = nfs_readdirrpc(vp, &auio);
430                                 free(bp, M_TEMP);
431                         } else if (vp->v_type == VLNK) {
432                                 error = nfs_readlinkrpc(vp, &auio);
433                         } else {
434                                 error = EACCES;
435                         }
436                 }
437         }
438         /*
439          * [re]record creds for reading and/or writing if access
440          * was granted.  Assume the NFS server will grant read access
441          * for execute requests.
442          */
443         if (error == 0) {
444                 if ((ap->a_mode & (VREAD|VEXEC)) && ap->a_cred != np->n_rucred) {
445                         crhold(ap->a_cred);
446                         if (np->n_rucred)
447                                 crfree(np->n_rucred);
448                         np->n_rucred = ap->a_cred;
449                 }
450                 if ((ap->a_mode & VWRITE) && ap->a_cred != np->n_wucred) {
451                         crhold(ap->a_cred);
452                         if (np->n_wucred)
453                                 crfree(np->n_wucred);
454                         np->n_wucred = ap->a_cred;
455                 }
456         }
457         return(error);
458 }
459
460 /*
461  * nfs open vnode op
462  * Check to see if the type is ok
463  * and that deletion is not in progress.
464  * For paged in text files, you will need to flush the page cache
465  * if consistency is lost.
466  *
467  * nfs_open(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
468  *          struct thread *a_td)
469  */
470 /* ARGSUSED */
471 static int
472 nfs_open(struct vop_open_args *ap)
473 {
474         struct vnode *vp = ap->a_vp;
475         struct nfsnode *np = VTONFS(vp);
476         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
477         struct vattr vattr;
478         int error;
479
480         if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) {
481 #ifdef DIAGNOSTIC
482                 printf("open eacces vtyp=%d\n",vp->v_type);
483 #endif
484                 return (EOPNOTSUPP);
485         }
486
487         /*
488          * Clear the attribute cache only if opening with write access.  It
489          * is unclear if we should do this at all here, but we certainly
490          * should not clear the cache unconditionally simply because a file
491          * is being opened.
492          */
493         if (ap->a_mode & FWRITE)
494                 np->n_attrstamp = 0;
495
496         if (nmp->nm_flag & NFSMNT_NQNFS) {
497                 /*
498                  * If NQNFS is active, get a valid lease
499                  */
500                 if (NQNFS_CKINVALID(vp, np, ND_READ)) {
501                     do {
502                         error = nqnfs_getlease(vp, ND_READ, ap->a_td);
503                     } while (error == NQNFS_EXPIRED);
504                     if (error)
505                         return (error);
506                     if (np->n_lrev != np->n_brev ||
507                         (np->n_flag & NQNFSNONCACHE)) {
508                         if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1))
509                             == EINTR) {
510                                 return (error);
511                         }
512                         np->n_brev = np->n_lrev;
513                     }
514                 }
515         } else {
516                 /*
517                  * For normal NFS, reconcile changes made locally verses 
518                  * changes made remotely.  Note that VOP_GETATTR only goes
519                  * to the wire if the cached attribute has timed out or been
520                  * cleared.
521                  *
522                  * If local modifications have been made clear the attribute
523                  * cache to force an attribute and modified time check.  If
524                  * GETATTR detects that the file has been changed by someone
525                  * other then us it will set NRMODIFIED.
526                  *
527                  * If we are opening a directory and local changes have been
528                  * made we have to invalidate the cache in order to ensure
529                  * that we get the most up-to-date information from the
530                  * server.  XXX
531                  */
532                 if (np->n_flag & NLMODIFIED) {
533                         np->n_attrstamp = 0;
534                         if (vp->v_type == VDIR) {
535                                 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
536                                 if (error == EINTR)
537                                         return (error);
538                                 nfs_invaldir(vp);
539                         }
540                 }
541                 error = VOP_GETATTR(vp, &vattr, ap->a_td);
542                 if (error)
543                         return (error);
544                 if (np->n_flag & NRMODIFIED) {
545                         if (vp->v_type == VDIR)
546                                 nfs_invaldir(vp);
547                         error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
548                         if (error == EINTR)
549                                 return (error);
550                         np->n_flag &= ~NRMODIFIED;
551                 }
552         }
553
554         return (0);
555 }
556
557 /*
558  * nfs close vnode op
559  * What an NFS client should do upon close after writing is a debatable issue.
560  * Most NFS clients push delayed writes to the server upon close, basically for
561  * two reasons:
562  * 1 - So that any write errors may be reported back to the client process
563  *     doing the close system call. By far the two most likely errors are
564  *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
565  * 2 - To put a worst case upper bound on cache inconsistency between
566  *     multiple clients for the file.
567  * There is also a consistency problem for Version 2 of the protocol w.r.t.
568  * not being able to tell if other clients are writing a file concurrently,
569  * since there is no way of knowing if the changed modify time in the reply
570  * is only due to the write for this client.
571  * (NFS Version 3 provides weak cache consistency data in the reply that
572  *  should be sufficient to detect and handle this case.)
573  *
574  * The current code does the following:
575  * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
576  * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
577  *                     or commit them (this satisfies 1 and 2 except for the
578  *                     case where the server crashes after this close but
579  *                     before the commit RPC, which is felt to be "good
580  *                     enough". Changing the last argument to nfs_flush() to
581  *                     a 1 would force a commit operation, if it is felt a
582  *                     commit is necessary now.
583  * for NQNFS         - do nothing now, since 2 is dealt with via leases and
584  *                     1 should be dealt with via an fsync() system call for
585  *                     cases where write errors are important.
586  *
587  * nfs_close(struct vnodeop_desc *a_desc, struct vnode *a_vp, int a_fflag,
588  *           struct ucred *a_cred, struct thread *a_td)
589  */
590 /* ARGSUSED */
591 static int
592 nfs_close(struct vop_close_args *ap)
593 {
594         struct vnode *vp = ap->a_vp;
595         struct nfsnode *np = VTONFS(vp);
596         int error = 0;
597
598         if (vp->v_type == VREG) {
599             if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 &&
600                 (np->n_flag & NLMODIFIED)) {
601                 if (NFS_ISV3(vp)) {
602                     /*
603                      * Under NFSv3 we have dirty buffers to dispose of.  We
604                      * must flush them to the NFS server.  We have the option
605                      * of waiting all the way through the commit rpc or just
606                      * waiting for the initial write.  The default is to only
607                      * wait through the initial write so the data is in the
608                      * server's cache, which is roughly similar to the state
609                      * a standard disk subsystem leaves the file in on close().
610                      *
611                      * We cannot clear the NLMODIFIED bit in np->n_flag due to
612                      * potential races with other processes, and certainly
613                      * cannot clear it if we don't commit.
614                      */
615                     int cm = nfsv3_commit_on_close ? 1 : 0;
616                     error = nfs_flush(vp, MNT_WAIT, ap->a_td, cm);
617                     /* np->n_flag &= ~NLMODIFIED; */
618                 } else {
619                     error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
620                 }
621                 np->n_attrstamp = 0;
622             }
623             if (np->n_flag & NWRITEERR) {
624                 np->n_flag &= ~NWRITEERR;
625                 error = np->n_error;
626             }
627         }
628         return (error);
629 }
630
631 /*
632  * nfs getattr call from vfs.
633  *
634  * nfs_getattr(struct vnode *a_vp, struct vattr *a_vap, struct ucred *a_cred,
635  *              struct thread *a_td)
636  */
637 static int
638 nfs_getattr(struct vop_getattr_args *ap)
639 {
640         struct vnode *vp = ap->a_vp;
641         struct nfsnode *np = VTONFS(vp);
642         caddr_t cp;
643         u_int32_t *tl;
644         int32_t t1, t2;
645         caddr_t bpos, dpos;
646         int error = 0;
647         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
648         int v3 = NFS_ISV3(vp);
649         
650         /*
651          * Update local times for special files.
652          */
653         if (np->n_flag & (NACC | NUPD))
654                 np->n_flag |= NCHG;
655         /*
656          * First look in the cache.
657          */
658         if (nfs_getattrcache(vp, ap->a_vap) == 0)
659                 return (0);
660
661         if (v3 && nfsaccess_cache_timeout > 0) {
662                 nfsstats.accesscache_misses++;
663                 nfs3_access_otw(vp, NFSV3ACCESS_ALL, ap->a_td, nfs_vpcred(vp, ND_CHECK));
664                 if (nfs_getattrcache(vp, ap->a_vap) == 0)
665                         return (0);
666         }
667
668         nfsstats.rpccnt[NFSPROC_GETATTR]++;
669         nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3));
670         nfsm_fhtom(vp, v3);
671         nfsm_request(vp, NFSPROC_GETATTR, ap->a_td, nfs_vpcred(vp, ND_CHECK));
672         if (!error) {
673                 nfsm_loadattr(vp, ap->a_vap);
674         }
675         m_freem(mrep);
676 nfsmout:
677         return (error);
678 }
679
680 /*
681  * nfs setattr call.
682  *
683  * nfs_setattr(struct vnodeop_desc *a_desc, struct vnode *a_vp,
684  *              struct vattr *a_vap, struct ucred *a_cred,
685  *              struct thread *a_td)
686  */
687 static int
688 nfs_setattr(struct vop_setattr_args *ap)
689 {
690         struct vnode *vp = ap->a_vp;
691         struct nfsnode *np = VTONFS(vp);
692         struct vattr *vap = ap->a_vap;
693         int error = 0;
694         u_quad_t tsize;
695
696 #ifndef nolint
697         tsize = (u_quad_t)0;
698 #endif
699
700         /*
701          * Setting of flags is not supported.
702          */
703         if (vap->va_flags != VNOVAL)
704                 return (EOPNOTSUPP);
705
706         /*
707          * Disallow write attempts if the filesystem is mounted read-only.
708          */
709         if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
710             vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
711             vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
712             (vp->v_mount->mnt_flag & MNT_RDONLY))
713                 return (EROFS);
714         if (vap->va_size != VNOVAL) {
715                 switch (vp->v_type) {
716                 case VDIR:
717                         return (EISDIR);
718                 case VCHR:
719                 case VBLK:
720                 case VSOCK:
721                 case VFIFO:
722                         if (vap->va_mtime.tv_sec == VNOVAL &&
723                             vap->va_atime.tv_sec == VNOVAL &&
724                             vap->va_mode == (mode_t)VNOVAL &&
725                             vap->va_uid == (uid_t)VNOVAL &&
726                             vap->va_gid == (gid_t)VNOVAL)
727                                 return (0);
728                         vap->va_size = VNOVAL;
729                         break;
730                 default:
731                         /*
732                          * Disallow write attempts if the filesystem is
733                          * mounted read-only.
734                          */
735                         if (vp->v_mount->mnt_flag & MNT_RDONLY)
736                                 return (EROFS);
737
738                         /*
739                          * This is nasty.  The RPCs we send to flush pending
740                          * data often return attribute information which is
741                          * cached via a callback to nfs_loadattrcache(), which
742                          * has the effect of changing our notion of the file
743                          * size.  Due to flushed appends and other operations
744                          * the file size can be set to virtually anything, 
745                          * including values that do not match either the old
746                          * or intended file size.
747                          *
748                          * When this condition is detected we must loop to
749                          * try the operation again.  Hopefully no more
750                          * flushing is required on the loop so it works the
751                          * second time around.  THIS CASE ALMOST ALWAYS
752                          * HAPPENS!
753                          */
754                         tsize = np->n_size;
755 again:
756                         error = nfs_meta_setsize(vp, ap->a_td, vap->va_size);
757
758                         if (np->n_flag & NLMODIFIED) {
759                             if (vap->va_size == 0)
760                                 error = nfs_vinvalbuf(vp, 0, ap->a_td, 1);
761                             else
762                                 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
763                         }
764                         /*
765                          * note: this loop case almost always happens at 
766                          * least once per truncation.
767                          */
768                         if (error == 0 && np->n_size != vap->va_size)
769                                 goto again;
770                         np->n_vattr.va_size = vap->va_size;
771                         break;
772                 }
773         } else if ((vap->va_mtime.tv_sec != VNOVAL ||
774                 vap->va_atime.tv_sec != VNOVAL) && (np->n_flag & NLMODIFIED) &&
775                 vp->v_type == VREG &&
776                 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_td, 1)) == EINTR
777         ) {
778                 return (error);
779         }
780         error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_td);
781
782         /*
783          * Sanity check if a truncation was issued.  This should only occur
784          * if multiple processes are racing on the same file.
785          */
786         if (error == 0 && vap->va_size != VNOVAL && 
787             np->n_size != vap->va_size) {
788                 printf("NFS ftruncate: server disagrees on the file size: %lld/%lld/%lld\n", tsize, vap->va_size, np->n_size);
789                 goto again;
790         }
791         if (error && vap->va_size != VNOVAL) {
792                 np->n_size = np->n_vattr.va_size = tsize;
793                 vnode_pager_setsize(vp, np->n_size);
794         }
795         return (error);
796 }
797
798 /*
799  * Do an nfs setattr rpc.
800  */
801 static int
802 nfs_setattrrpc(struct vnode *vp, struct vattr *vap,
803                struct ucred *cred, struct thread *td)
804 {
805         struct nfsv2_sattr *sp;
806         struct nfsnode *np = VTONFS(vp);
807         caddr_t cp;
808         int32_t t1, t2;
809         caddr_t bpos, dpos, cp2;
810         u_int32_t *tl;
811         int error = 0, wccflag = NFSV3_WCCRATTR;
812         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
813         int v3 = NFS_ISV3(vp);
814
815         nfsstats.rpccnt[NFSPROC_SETATTR]++;
816         nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3));
817         nfsm_fhtom(vp, v3);
818         if (v3) {
819                 nfsm_v3attrbuild(vap, TRUE);
820                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
821                 *tl = nfs_false;
822         } else {
823                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
824                 if (vap->va_mode == (mode_t)VNOVAL)
825                         sp->sa_mode = nfs_xdrneg1;
826                 else
827                         sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode);
828                 if (vap->va_uid == (uid_t)VNOVAL)
829                         sp->sa_uid = nfs_xdrneg1;
830                 else
831                         sp->sa_uid = txdr_unsigned(vap->va_uid);
832                 if (vap->va_gid == (gid_t)VNOVAL)
833                         sp->sa_gid = nfs_xdrneg1;
834                 else
835                         sp->sa_gid = txdr_unsigned(vap->va_gid);
836                 sp->sa_size = txdr_unsigned(vap->va_size);
837                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
838                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
839         }
840         nfsm_request(vp, NFSPROC_SETATTR, td, cred);
841         if (v3) {
842                 np->n_modestamp = 0;
843                 nfsm_wcc_data(vp, wccflag);
844         } else
845                 nfsm_loadattr(vp, (struct vattr *)0);
846         m_freem(mrep);
847 nfsmout:
848         return (error);
849 }
850
851 /*
852  * NEW API CALL - replaces nfs_lookup().  However, we cannot remove 
853  * nfs_lookup() until all remaining new api calls are implemented.
854  *
855  * Resolve a namecache entry.  This function is passed a locked ncp and
856  * must call cache_setvp() on it as appropriate to resolve the entry.
857  */
858 static int
859 nfs_nresolve(struct vop_nresolve_args *ap)
860 {
861         struct thread *td = curthread;
862         struct namecache *ncp;
863         struct ucred *cred;
864         struct nfsnode *np;
865         struct vnode *dvp;
866         struct vnode *nvp;
867         nfsfh_t *fhp;
868         int attrflag;
869         int fhsize;
870         int error;
871         int len;
872         int v3;
873         /******NFSM MACROS********/
874         struct mbuf *mb, *mrep, *mreq, *mb2, *md;
875         caddr_t bpos, dpos, cp, cp2;
876         u_int32_t *tl;
877         int32_t t1, t2;
878
879         cred = ap->a_cred;
880         ncp = ap->a_ncp;
881
882         KKASSERT(ncp->nc_parent && ncp->nc_parent->nc_vp);
883         dvp = ncp->nc_parent->nc_vp;
884         if ((error = vget(dvp, LK_SHARED, td)) != 0)
885                 return (error);
886
887         nvp = NULL;
888         v3 = NFS_ISV3(dvp);
889         nfsstats.lookupcache_misses++;
890         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
891         len = ncp->nc_nlen;
892         nfsm_reqhead(dvp, NFSPROC_LOOKUP,
893                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
894         nfsm_fhtom(dvp, v3);
895         nfsm_strtom(ncp->nc_name, len, NFS_MAXNAMLEN);
896         nfsm_request(dvp, NFSPROC_LOOKUP, td, ap->a_cred);
897         if (error) {
898                 /*
899                  * Cache negatve lookups to reduce NFS traffic, but use
900                  * a fast timeout.  Otherwise use a timeout of 1 tick.
901                  * XXX we should add a namecache flag for no-caching
902                  * to uncache the negative hit as soon as possible, but
903                  * we cannot simply destroy the entry because it is used
904                  * as a placeholder by the caller.
905                  */
906                 if (error == ENOENT) {
907                         int nticks;
908
909                         if (nfsneg_cache_timeout)
910                                 nticks = nfsneg_cache_timeout * hz;
911                         else
912                                 nticks = 1;
913                         cache_setvp(ncp, NULL);
914                         cache_settimeout(ncp, nticks);
915                 }
916                 nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
917                 m_freem(mrep);
918                 goto nfsmout;
919         }
920
921         /*
922          * Success, get the file handle, do various checks, and load 
923          * post-operation data from the reply packet.  Theoretically
924          * we should never be looking up "." so, theoretically, we
925          * should never get the same file handle as our directory.  But
926          * we check anyway. XXX
927          *
928          * Note that no timeout is set for the positive cache hit.  We
929          * assume, theoretically, that ESTALE returns will be dealt with
930          * properly to handle NFS races and in anycase we cannot depend
931          * on a timeout to deal with NFS open/create/excl issues so instead
932          * of a bad hack here the rest of the NFS client code needs to do
933          * the right thing.
934          */
935         nfsm_getfh(fhp, fhsize, v3);
936
937         np = VTONFS(dvp);
938         if (NFS_CMPFH(np, fhp, fhsize)) {
939                 vref(dvp);
940                 nvp = dvp;
941         } else {
942                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
943                 if (error) {
944                         m_freem(mrep);
945                         vput(dvp);
946                         return (error);
947                 }
948                 nvp = NFSTOV(np);
949         }
950         if (v3) {
951                 nfsm_postop_attr(nvp, attrflag, NFS_LATTR_NOSHRINK);
952                 nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
953         } else {
954                 nfsm_loadattr(nvp, NULL);
955         }
956         cache_setvp(ncp, nvp);
957         m_freem(mrep);
958 nfsmout:
959         vput(dvp);
960         if (nvp) {
961                 if (nvp == dvp)
962                         vrele(nvp);
963                 else
964                         vput(nvp);
965         }
966         return (error);
967 }
968
969 /*
970  * 'cached' nfs directory lookup
971  *
972  * NOTE: cannot be removed until NFS implements all the new n*() API calls.
973  *
974  * nfs_lookup(struct vnodeop_desc *a_desc, struct vnode *a_dvp,
975  *            struct vnode **a_vpp, struct componentname *a_cnp)
976  */
977 static int
978 nfs_lookup(struct vop_lookup_args *ap)
979 {
980         struct componentname *cnp = ap->a_cnp;
981         struct vnode *dvp = ap->a_dvp;
982         struct vnode **vpp = ap->a_vpp;
983         int flags = cnp->cn_flags;
984         struct vnode *newvp;
985         u_int32_t *tl;
986         caddr_t cp;
987         int32_t t1, t2;
988         struct nfsmount *nmp;
989         caddr_t bpos, dpos, cp2;
990         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
991         long len;
992         nfsfh_t *fhp;
993         struct nfsnode *np;
994         int lockparent, wantparent, error = 0, attrflag, fhsize;
995         int v3 = NFS_ISV3(dvp);
996         struct thread *td = cnp->cn_td;
997
998         /*
999          * Read-only mount check and directory check.
1000          */
1001         *vpp = NULLVP;
1002         if ((dvp->v_mount->mnt_flag & MNT_RDONLY) &&
1003             (cnp->cn_nameiop == NAMEI_DELETE || cnp->cn_nameiop == NAMEI_RENAME))
1004                 return (EROFS);
1005
1006         if (dvp->v_type != VDIR)
1007                 return (ENOTDIR);
1008
1009         /*
1010          * Look it up in the cache.  Note that ENOENT is only returned if we
1011          * previously entered a negative hit (see later on).  The additional
1012          * nfsneg_cache_timeout check causes previously cached results to
1013          * be instantly ignored if the negative caching is turned off.
1014          */
1015         lockparent = flags & CNP_LOCKPARENT;
1016         wantparent = flags & (CNP_LOCKPARENT|CNP_WANTPARENT);
1017         nmp = VFSTONFS(dvp->v_mount);
1018         np = VTONFS(dvp);
1019
1020         /*
1021          * Go to the wire.
1022          */
1023         error = 0;
1024         newvp = NULLVP;
1025         nfsstats.lookupcache_misses++;
1026         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
1027         len = cnp->cn_namelen;
1028         nfsm_reqhead(dvp, NFSPROC_LOOKUP,
1029                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
1030         nfsm_fhtom(dvp, v3);
1031         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
1032         nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_td, cnp->cn_cred);
1033         if (error) {
1034                 nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
1035                 m_freem(mrep);
1036                 goto nfsmout;
1037         }
1038         nfsm_getfh(fhp, fhsize, v3);
1039
1040         /*
1041          * Handle RENAME case...
1042          */
1043         if (cnp->cn_nameiop == NAMEI_RENAME && wantparent) {
1044                 if (NFS_CMPFH(np, fhp, fhsize)) {
1045                         m_freem(mrep);
1046                         return (EISDIR);
1047                 }
1048                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1049                 if (error) {
1050                         m_freem(mrep);
1051                         return (error);
1052                 }
1053                 newvp = NFSTOV(np);
1054                 if (v3) {
1055                         nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
1056                         nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
1057                 } else
1058                         nfsm_loadattr(newvp, (struct vattr *)0);
1059                 *vpp = newvp;
1060                 m_freem(mrep);
1061                 if (!lockparent) {
1062                         VOP_UNLOCK(dvp, 0, td);
1063                         cnp->cn_flags |= CNP_PDIRUNLOCK;
1064                 }
1065                 return (0);
1066         }
1067
1068         if (flags & CNP_ISDOTDOT) {
1069                 VOP_UNLOCK(dvp, 0, td);
1070                 cnp->cn_flags |= CNP_PDIRUNLOCK;
1071                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1072                 if (error) {
1073                         vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td);
1074                         cnp->cn_flags &= ~CNP_PDIRUNLOCK;
1075                         return (error); /* NOTE: return error from nget */
1076                 }
1077                 newvp = NFSTOV(np);
1078                 if (lockparent) {
1079                         error = vn_lock(dvp, LK_EXCLUSIVE, td);
1080                         if (error) {
1081                                 vput(newvp);
1082                                 return (error);
1083                         }
1084                         cnp->cn_flags |= CNP_PDIRUNLOCK;
1085                 }
1086         } else if (NFS_CMPFH(np, fhp, fhsize)) {
1087                 vref(dvp);
1088                 newvp = dvp;
1089         } else {
1090                 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np);
1091                 if (error) {
1092                         m_freem(mrep);
1093                         return (error);
1094                 }
1095                 if (!lockparent) {
1096                         VOP_UNLOCK(dvp, 0, td);
1097                         cnp->cn_flags |= CNP_PDIRUNLOCK;
1098                 }
1099                 newvp = NFSTOV(np);
1100         }
1101         if (v3) {
1102                 nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
1103                 nfsm_postop_attr(dvp, attrflag, NFS_LATTR_NOSHRINK);
1104         } else
1105                 nfsm_loadattr(newvp, (struct vattr *)0);
1106 #if 0
1107         /* XXX MOVE TO nfs_nremove() */
1108         if ((cnp->cn_flags & CNP_MAKEENTRY) &&
1109             cnp->cn_nameiop != NAMEI_DELETE) {
1110                 np->n_ctime = np->n_vattr.va_ctime.tv_sec; /* XXX */
1111         }
1112 #endif
1113         *vpp = newvp;
1114         m_freem(mrep);
1115 nfsmout:
1116         if (error) {
1117                 if (newvp != NULLVP) {
1118                         vrele(newvp);
1119                         *vpp = NULLVP;
1120                 }
1121                 if ((cnp->cn_nameiop == NAMEI_CREATE || 
1122                      cnp->cn_nameiop == NAMEI_RENAME) &&
1123                     error == ENOENT) {
1124                         if (!lockparent) {
1125                                 VOP_UNLOCK(dvp, 0, td);
1126                                 cnp->cn_flags |= CNP_PDIRUNLOCK;
1127                         }
1128                         if (dvp->v_mount->mnt_flag & MNT_RDONLY)
1129                                 error = EROFS;
1130                         else
1131                                 error = EJUSTRETURN;
1132                 }
1133         }
1134         return (error);
1135 }
1136
1137 /*
1138  * nfs read call.
1139  * Just call nfs_bioread() to do the work.
1140  *
1141  * nfs_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
1142  *          struct ucred *a_cred)
1143  */
1144 static int
1145 nfs_read(struct vop_read_args *ap)
1146 {
1147         struct vnode *vp = ap->a_vp;
1148
1149         return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag));
1150         switch (vp->v_type) {
1151         case VREG:
1152                 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag));
1153         case VDIR:
1154                 return (EISDIR);
1155         default:
1156                 return EOPNOTSUPP;
1157         }
1158 }
1159
1160 /*
1161  * nfs readlink call
1162  *
1163  * nfs_readlink(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
1164  */
1165 static int
1166 nfs_readlink(struct vop_readlink_args *ap)
1167 {
1168         struct vnode *vp = ap->a_vp;
1169
1170         if (vp->v_type != VLNK)
1171                 return (EINVAL);
1172         return (nfs_bioread(vp, ap->a_uio, 0));
1173 }
1174
1175 /*
1176  * Do a readlink rpc.
1177  * Called by nfs_doio() from below the buffer cache.
1178  */
1179 int
1180 nfs_readlinkrpc(struct vnode *vp, struct uio *uiop)
1181 {
1182         u_int32_t *tl;
1183         caddr_t cp;
1184         int32_t t1, t2;
1185         caddr_t bpos, dpos, cp2;
1186         int error = 0, len, attrflag;
1187         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1188         int v3 = NFS_ISV3(vp);
1189
1190         nfsstats.rpccnt[NFSPROC_READLINK]++;
1191         nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3));
1192         nfsm_fhtom(vp, v3);
1193         nfsm_request(vp, NFSPROC_READLINK, uiop->uio_td, nfs_vpcred(vp, ND_CHECK));
1194         if (v3)
1195                 nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
1196         if (!error) {
1197                 nfsm_strsiz(len, NFS_MAXPATHLEN);
1198                 if (len == NFS_MAXPATHLEN) {
1199                         struct nfsnode *np = VTONFS(vp);
1200                         if (np->n_size && np->n_size < NFS_MAXPATHLEN)
1201                                 len = np->n_size;
1202                 }
1203                 nfsm_mtouio(uiop, len);
1204         }
1205         m_freem(mrep);
1206 nfsmout:
1207         return (error);
1208 }
1209
1210 /*
1211  * nfs read rpc call
1212  * Ditto above
1213  */
1214 int
1215 nfs_readrpc(struct vnode *vp, struct uio *uiop)
1216 {
1217         u_int32_t *tl;
1218         caddr_t cp;
1219         int32_t t1, t2;
1220         caddr_t bpos, dpos, cp2;
1221         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1222         struct nfsmount *nmp;
1223         int error = 0, len, retlen, tsiz, eof, attrflag;
1224         int v3 = NFS_ISV3(vp);
1225
1226 #ifndef nolint
1227         eof = 0;
1228 #endif
1229         nmp = VFSTONFS(vp->v_mount);
1230         tsiz = uiop->uio_resid;
1231         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1232                 return (EFBIG);
1233         while (tsiz > 0) {
1234                 nfsstats.rpccnt[NFSPROC_READ]++;
1235                 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz;
1236                 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3);
1237                 nfsm_fhtom(vp, v3);
1238                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3);
1239                 if (v3) {
1240                         txdr_hyper(uiop->uio_offset, tl);
1241                         *(tl + 2) = txdr_unsigned(len);
1242                 } else {
1243                         *tl++ = txdr_unsigned(uiop->uio_offset);
1244                         *tl++ = txdr_unsigned(len);
1245                         *tl = 0;
1246                 }
1247                 nfsm_request(vp, NFSPROC_READ, uiop->uio_td, nfs_vpcred(vp, ND_READ));
1248                 if (v3) {
1249                         nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
1250                         if (error) {
1251                                 m_freem(mrep);
1252                                 goto nfsmout;
1253                         }
1254                         nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1255                         eof = fxdr_unsigned(int, *(tl + 1));
1256                 } else
1257                         nfsm_loadattr(vp, (struct vattr *)0);
1258                 nfsm_strsiz(retlen, nmp->nm_rsize);
1259                 nfsm_mtouio(uiop, retlen);
1260                 m_freem(mrep);
1261                 tsiz -= retlen;
1262                 if (v3) {
1263                         if (eof || retlen == 0) {
1264                                 tsiz = 0;
1265                         }
1266                 } else if (retlen < len) {
1267                         tsiz = 0;
1268                 }
1269         }
1270 nfsmout:
1271         return (error);
1272 }
1273
1274 /*
1275  * nfs write call
1276  */
1277 int
1278 nfs_writerpc(struct vnode *vp, struct uio *uiop, int *iomode, int *must_commit)
1279 {
1280         u_int32_t *tl;
1281         caddr_t cp;
1282         int32_t t1, t2, backup;
1283         caddr_t bpos, dpos, cp2;
1284         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1285         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
1286         int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit;
1287         int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC;
1288
1289 #ifndef DIAGNOSTIC
1290         if (uiop->uio_iovcnt != 1)
1291                 panic("nfs: writerpc iovcnt > 1");
1292 #endif
1293         *must_commit = 0;
1294         tsiz = uiop->uio_resid;
1295         if (uiop->uio_offset + tsiz > nmp->nm_maxfilesize)
1296                 return (EFBIG);
1297         while (tsiz > 0) {
1298                 nfsstats.rpccnt[NFSPROC_WRITE]++;
1299                 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz;
1300                 nfsm_reqhead(vp, NFSPROC_WRITE,
1301                         NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len));
1302                 nfsm_fhtom(vp, v3);
1303                 if (v3) {
1304                         nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1305                         txdr_hyper(uiop->uio_offset, tl);
1306                         tl += 2;
1307                         *tl++ = txdr_unsigned(len);
1308                         *tl++ = txdr_unsigned(*iomode);
1309                         *tl = txdr_unsigned(len);
1310                 } else {
1311                         u_int32_t x;
1312
1313                         nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1314                         /* Set both "begin" and "current" to non-garbage. */
1315                         x = txdr_unsigned((u_int32_t)uiop->uio_offset);
1316                         *tl++ = x;      /* "begin offset" */
1317                         *tl++ = x;      /* "current offset" */
1318                         x = txdr_unsigned(len);
1319                         *tl++ = x;      /* total to this offset */
1320                         *tl = x;        /* size of this write */
1321                 }
1322                 nfsm_uiotom(uiop, len);
1323                 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_td, nfs_vpcred(vp, ND_WRITE));
1324                 if (v3) {
1325                         /*
1326                          * The write RPC returns a before and after mtime.  The
1327                          * nfsm_wcc_data() macro checks the before n_mtime
1328                          * against the before time and stores the after time
1329                          * in the nfsnode's cached vattr and n_mtime field.
1330                          * The NRMODIFIED bit will be set if the before
1331                          * time did not match the original mtime.
1332                          */
1333                         wccflag = NFSV3_WCCCHK;
1334                         nfsm_wcc_data(vp, wccflag);
1335                         if (!error) {
1336                                 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED
1337                                         + NFSX_V3WRITEVERF);
1338                                 rlen = fxdr_unsigned(int, *tl++);
1339                                 if (rlen == 0) {
1340                                         error = NFSERR_IO;
1341                                         m_freem(mrep);
1342                                         break;
1343                                 } else if (rlen < len) {
1344                                         backup = len - rlen;
1345                                         uiop->uio_iov->iov_base -= backup;
1346                                         uiop->uio_iov->iov_len += backup;
1347                                         uiop->uio_offset -= backup;
1348                                         uiop->uio_resid += backup;
1349                                         len = rlen;
1350                                 }
1351                                 commit = fxdr_unsigned(int, *tl++);
1352
1353                                 /*
1354                                  * Return the lowest committment level
1355                                  * obtained by any of the RPCs.
1356                                  */
1357                                 if (committed == NFSV3WRITE_FILESYNC)
1358                                         committed = commit;
1359                                 else if (committed == NFSV3WRITE_DATASYNC &&
1360                                         commit == NFSV3WRITE_UNSTABLE)
1361                                         committed = commit;
1362                                 if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0){
1363                                     bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1364                                         NFSX_V3WRITEVERF);
1365                                     nmp->nm_state |= NFSSTA_HASWRITEVERF;
1366                                 } else if (bcmp((caddr_t)tl,
1367                                     (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) {
1368                                     *must_commit = 1;
1369                                     bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
1370                                         NFSX_V3WRITEVERF);
1371                                 }
1372                         }
1373                 } else {
1374                         nfsm_loadattr(vp, (struct vattr *)0);
1375                 }
1376                 m_freem(mrep);
1377                 if (error)
1378                         break;
1379                 tsiz -= len;
1380         }
1381 nfsmout:
1382         if (vp->v_mount->mnt_flag & MNT_ASYNC)
1383                 committed = NFSV3WRITE_FILESYNC;
1384         *iomode = committed;
1385         if (error)
1386                 uiop->uio_resid = tsiz;
1387         return (error);
1388 }
1389
1390 /*
1391  * nfs mknod rpc
1392  * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1393  * mode set to specify the file type and the size field for rdev.
1394  */
1395 static int
1396 nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
1397              struct vattr *vap)
1398 {
1399         struct nfsv2_sattr *sp;
1400         u_int32_t *tl;
1401         caddr_t cp;
1402         int32_t t1, t2;
1403         struct vnode *newvp = (struct vnode *)0;
1404         struct nfsnode *np = (struct nfsnode *)0;
1405         struct vattr vattr;
1406         char *cp2;
1407         caddr_t bpos, dpos;
1408         int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0;
1409         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1410         u_int32_t rdev;
1411         int v3 = NFS_ISV3(dvp);
1412
1413         if (vap->va_type == VCHR || vap->va_type == VBLK)
1414                 rdev = txdr_unsigned(vap->va_rdev);
1415         else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1416                 rdev = nfs_xdrneg1;
1417         else {
1418                 return (EOPNOTSUPP);
1419         }
1420         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_td)) != 0) {
1421                 return (error);
1422         }
1423         nfsstats.rpccnt[NFSPROC_MKNOD]++;
1424         nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED +
1425                 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1426         nfsm_fhtom(dvp, v3);
1427         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1428         if (v3) {
1429                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1430                 *tl++ = vtonfsv3_type(vap->va_type);
1431                 nfsm_v3attrbuild(vap, FALSE);
1432                 if (vap->va_type == VCHR || vap->va_type == VBLK) {
1433                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1434                         *tl++ = txdr_unsigned(umajor(vap->va_rdev));
1435                         *tl = txdr_unsigned(uminor(vap->va_rdev));
1436                 }
1437         } else {
1438                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1439                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1440                 sp->sa_uid = nfs_xdrneg1;
1441                 sp->sa_gid = nfs_xdrneg1;
1442                 sp->sa_size = rdev;
1443                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1444                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1445         }
1446         nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_td, cnp->cn_cred);
1447         if (!error) {
1448                 nfsm_mtofh(dvp, newvp, v3, gotvp);
1449                 if (!gotvp) {
1450                         if (newvp) {
1451                                 vput(newvp);
1452                                 newvp = (struct vnode *)0;
1453                         }
1454                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
1455                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_td, &np);
1456                         if (!error)
1457                                 newvp = NFSTOV(np);
1458                 }
1459         }
1460         if (v3)
1461                 nfsm_wcc_data(dvp, wccflag);
1462         m_freem(mrep);
1463 nfsmout:
1464         if (error) {
1465                 if (newvp)
1466                         vput(newvp);
1467         } else {
1468                 *vpp = newvp;
1469         }
1470         VTONFS(dvp)->n_flag |= NLMODIFIED;
1471         if (!wccflag)
1472                 VTONFS(dvp)->n_attrstamp = 0;
1473         return (error);
1474 }
1475
1476 /*
1477  * nfs mknod vop
1478  * just call nfs_mknodrpc() to do the work.
1479  *
1480  * nfs_mknod(struct vnode *a_dvp, struct vnode **a_vpp,
1481  *           struct componentname *a_cnp, struct vattr *a_vap)
1482  */
1483 /* ARGSUSED */
1484 static int
1485 nfs_mknod(struct vop_mknod_args *ap)
1486 {
1487         return nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap);
1488 }
1489
1490 static u_long create_verf;
1491 /*
1492  * nfs file create call
1493  *
1494  * nfs_create(struct vnode *a_dvp, struct vnode **a_vpp,
1495  *            struct componentname *a_cnp, struct vattr *a_vap)
1496  */
1497 static int
1498 nfs_create(struct vop_create_args *ap)
1499 {
1500         struct vnode *dvp = ap->a_dvp;
1501         struct vattr *vap = ap->a_vap;
1502         struct componentname *cnp = ap->a_cnp;
1503         struct nfsv2_sattr *sp;
1504         u_int32_t *tl;
1505         caddr_t cp;
1506         int32_t t1, t2;
1507         struct nfsnode *np = (struct nfsnode *)0;
1508         struct vnode *newvp = (struct vnode *)0;
1509         caddr_t bpos, dpos, cp2;
1510         int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0;
1511         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1512         struct vattr vattr;
1513         int v3 = NFS_ISV3(dvp);
1514
1515         /*
1516          * Oops, not for me..
1517          */
1518         if (vap->va_type == VSOCK)
1519                 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1520
1521         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_td)) != 0) {
1522                 return (error);
1523         }
1524         if (vap->va_vaflags & VA_EXCLUSIVE)
1525                 fmode |= O_EXCL;
1526 again:
1527         nfsstats.rpccnt[NFSPROC_CREATE]++;
1528         nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED +
1529                 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3));
1530         nfsm_fhtom(dvp, v3);
1531         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1532         if (v3) {
1533                 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
1534                 if (fmode & O_EXCL) {
1535                         *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE);
1536                         nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF);
1537 #ifdef INET
1538                         if (!TAILQ_EMPTY(&in_ifaddrhead))
1539                                 *tl++ = IA_SIN(TAILQ_FIRST(&in_ifaddrhead))->sin_addr.s_addr;
1540                         else
1541 #endif
1542                                 *tl++ = create_verf;
1543                         *tl = ++create_verf;
1544                 } else {
1545                         *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED);
1546                         nfsm_v3attrbuild(vap, FALSE);
1547                 }
1548         } else {
1549                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1550                 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode);
1551                 sp->sa_uid = nfs_xdrneg1;
1552                 sp->sa_gid = nfs_xdrneg1;
1553                 sp->sa_size = 0;
1554                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1555                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1556         }
1557         nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_td, cnp->cn_cred);
1558         if (!error) {
1559                 nfsm_mtofh(dvp, newvp, v3, gotvp);
1560                 if (!gotvp) {
1561                         if (newvp) {
1562                                 vput(newvp);
1563                                 newvp = (struct vnode *)0;
1564                         }
1565                         error = nfs_lookitup(dvp, cnp->cn_nameptr,
1566                             cnp->cn_namelen, cnp->cn_cred, cnp->cn_td, &np);
1567                         if (!error)
1568                                 newvp = NFSTOV(np);
1569                 }
1570         }
1571         if (v3)
1572                 nfsm_wcc_data(dvp, wccflag);
1573         m_freem(mrep);
1574 nfsmout:
1575         if (error) {
1576                 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) {
1577                         fmode &= ~O_EXCL;
1578                         goto again;
1579                 }
1580                 if (newvp)
1581                         vput(newvp);
1582         } else if (v3 && (fmode & O_EXCL)) {
1583                 /*
1584                  * We are normally called with only a partially initialized
1585                  * VAP.  Since the NFSv3 spec says that server may use the
1586                  * file attributes to store the verifier, the spec requires
1587                  * us to do a SETATTR RPC. FreeBSD servers store the verifier
1588                  * in atime, but we can't really assume that all servers will
1589                  * so we ensure that our SETATTR sets both atime and mtime.
1590                  */
1591                 if (vap->va_mtime.tv_sec == VNOVAL)
1592                         vfs_timestamp(&vap->va_mtime);
1593                 if (vap->va_atime.tv_sec == VNOVAL)
1594                         vap->va_atime = vap->va_mtime;
1595                 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_td);
1596         }
1597         if (!error) {
1598                 /*
1599                  * The new np may have enough info for access
1600                  * checks, make sure rucred and wucred are
1601                  * initialized for read and write rpc's.
1602                  */
1603                 np = VTONFS(newvp);
1604                 if (np->n_rucred == NULL)
1605                         np->n_rucred = crhold(cnp->cn_cred);
1606                 if (np->n_wucred == NULL)
1607                         np->n_wucred = crhold(cnp->cn_cred);
1608                 *ap->a_vpp = newvp;
1609         }
1610         VTONFS(dvp)->n_flag |= NLMODIFIED;
1611         if (!wccflag)
1612                 VTONFS(dvp)->n_attrstamp = 0;
1613         return (error);
1614 }
1615
1616 /*
1617  * nfs file remove call
1618  * To try and make nfs semantics closer to ufs semantics, a file that has
1619  * other processes using the vnode is renamed instead of removed and then
1620  * removed later on the last close.
1621  * - If v_usecount > 1
1622  *        If a rename is not already in the works
1623  *           call nfs_sillyrename() to set it up
1624  *     else
1625  *        do the remove rpc
1626  *
1627  * nfs_remove(struct vnodeop_desc *a_desc, struct vnode *a_dvp,
1628  *            struct vnode *a_vp, struct componentname *a_cnp)
1629  */
1630 static int
1631 nfs_remove(struct vop_remove_args *ap)
1632 {
1633         struct vnode *vp = ap->a_vp;
1634         struct vnode *dvp = ap->a_dvp;
1635         struct componentname *cnp = ap->a_cnp;
1636         struct nfsnode *np = VTONFS(vp);
1637         int error = 0;
1638         struct vattr vattr;
1639
1640 #ifndef DIAGNOSTIC
1641         if (vp->v_usecount < 1)
1642                 panic("nfs_remove: bad v_usecount");
1643 #endif
1644         if (vp->v_type == VDIR)
1645                 error = EPERM;
1646         else if (vp->v_usecount == 1 || (np->n_sillyrename &&
1647             VOP_GETATTR(vp, &vattr, cnp->cn_td) == 0 &&
1648             vattr.va_nlink > 1)) {
1649                 /*
1650                  * throw away biocache buffers, mainly to avoid
1651                  * unnecessary delayed writes later.
1652                  */
1653                 error = nfs_vinvalbuf(vp, 0, cnp->cn_td, 1);
1654                 /* Do the rpc */
1655                 if (error != EINTR)
1656                         error = nfs_removerpc(dvp, cnp->cn_nameptr,
1657                                 cnp->cn_namelen, cnp->cn_cred, cnp->cn_td);
1658                 /*
1659                  * Kludge City: If the first reply to the remove rpc is lost..
1660                  *   the reply to the retransmitted request will be ENOENT
1661                  *   since the file was in fact removed
1662                  *   Therefore, we cheat and return success.
1663                  */
1664                 if (error == ENOENT)
1665                         error = 0;
1666         } else if (!np->n_sillyrename) {
1667                 error = nfs_sillyrename(dvp, vp, cnp);
1668         }
1669         np->n_attrstamp = 0;
1670         return (error);
1671 }
1672
1673 /*
1674  * nfs file remove rpc called from nfs_inactive
1675  */
1676 int
1677 nfs_removeit(struct sillyrename *sp)
1678 {
1679         return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen,
1680                 sp->s_cred, NULL));
1681 }
1682
1683 /*
1684  * Nfs remove rpc, called from nfs_remove() and nfs_removeit().
1685  */
1686 static int
1687 nfs_removerpc(struct vnode *dvp, const char *name, int namelen,
1688               struct ucred *cred, struct thread *td)
1689 {
1690         u_int32_t *tl;
1691         caddr_t cp;
1692         int32_t t1, t2;
1693         caddr_t bpos, dpos, cp2;
1694         int error = 0, wccflag = NFSV3_WCCRATTR;
1695         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1696         int v3 = NFS_ISV3(dvp);
1697
1698         nfsstats.rpccnt[NFSPROC_REMOVE]++;
1699         nfsm_reqhead(dvp, NFSPROC_REMOVE,
1700                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen));
1701         nfsm_fhtom(dvp, v3);
1702         nfsm_strtom(name, namelen, NFS_MAXNAMLEN);
1703         nfsm_request(dvp, NFSPROC_REMOVE, td, cred);
1704         if (v3)
1705                 nfsm_wcc_data(dvp, wccflag);
1706         m_freem(mrep);
1707 nfsmout:
1708         VTONFS(dvp)->n_flag |= NLMODIFIED;
1709         if (!wccflag)
1710                 VTONFS(dvp)->n_attrstamp = 0;
1711         return (error);
1712 }
1713
1714 /*
1715  * nfs file rename call
1716  *
1717  * nfs_rename(struct vnode *a_fdvp, struct vnode *a_fvp,
1718  *            struct componentname *a_fcnp, struct vnode *a_tdvp,
1719  *            struct vnode *a_tvp, struct componentname *a_tcnp)
1720  */
1721 static int
1722 nfs_rename(struct vop_rename_args *ap)
1723 {
1724         struct vnode *fvp = ap->a_fvp;
1725         struct vnode *tvp = ap->a_tvp;
1726         struct vnode *fdvp = ap->a_fdvp;
1727         struct vnode *tdvp = ap->a_tdvp;
1728         struct componentname *tcnp = ap->a_tcnp;
1729         struct componentname *fcnp = ap->a_fcnp;
1730         int error;
1731
1732         /* Check for cross-device rename */
1733         if ((fvp->v_mount != tdvp->v_mount) ||
1734             (tvp && (fvp->v_mount != tvp->v_mount))) {
1735                 error = EXDEV;
1736                 goto out;
1737         }
1738
1739         /*
1740          * We have to flush B_DELWRI data prior to renaming
1741          * the file.  If we don't, the delayed-write buffers
1742          * can be flushed out later after the file has gone stale
1743          * under NFSV3.  NFSV2 does not have this problem because
1744          * ( as far as I can tell ) it flushes dirty buffers more
1745          * often.
1746          */
1747
1748         VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_td);
1749         if (tvp)
1750             VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_td);
1751
1752         /*
1753          * If the tvp exists and is in use, sillyrename it before doing the
1754          * rename of the new file over it.
1755          *
1756          * XXX Can't sillyrename a directory.
1757          *
1758          * We do not attempt to do any namecache purges in this old API
1759          * routine.  The new API compat functions have access to the actual
1760          * namecache structures and will do it for us.
1761          */
1762         if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename &&
1763                 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1764                 vput(tvp);
1765                 tvp = NULL;
1766         } else if (tvp) {
1767                 ;
1768         }
1769
1770         error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1771                 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1772                 tcnp->cn_td);
1773
1774 out:
1775         if (tdvp == tvp)
1776                 vrele(tdvp);
1777         else
1778                 vput(tdvp);
1779         if (tvp)
1780                 vput(tvp);
1781         vrele(fdvp);
1782         vrele(fvp);
1783         /*
1784          * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1785          */
1786         if (error == ENOENT)
1787                 error = 0;
1788         return (error);
1789 }
1790
1791 /*
1792  * nfs file rename rpc called from nfs_remove() above
1793  */
1794 static int
1795 nfs_renameit(struct vnode *sdvp, struct componentname *scnp,
1796              struct sillyrename *sp)
1797 {
1798         return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen,
1799                 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_td));
1800 }
1801
1802 /*
1803  * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
1804  */
1805 static int
1806 nfs_renamerpc(struct vnode *fdvp, const char *fnameptr, int fnamelen,
1807               struct vnode *tdvp, const char *tnameptr, int tnamelen,
1808               struct ucred *cred, struct thread *td)
1809 {
1810         u_int32_t *tl;
1811         caddr_t cp;
1812         int32_t t1, t2;
1813         caddr_t bpos, dpos, cp2;
1814         int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR;
1815         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1816         int v3 = NFS_ISV3(fdvp);
1817
1818         nfsstats.rpccnt[NFSPROC_RENAME]++;
1819         nfsm_reqhead(fdvp, NFSPROC_RENAME,
1820                 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) +
1821                 nfsm_rndup(tnamelen));
1822         nfsm_fhtom(fdvp, v3);
1823         nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN);
1824         nfsm_fhtom(tdvp, v3);
1825         nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN);
1826         nfsm_request(fdvp, NFSPROC_RENAME, td, cred);
1827         if (v3) {
1828                 nfsm_wcc_data(fdvp, fwccflag);
1829                 nfsm_wcc_data(tdvp, twccflag);
1830         }
1831         m_freem(mrep);
1832 nfsmout:
1833         VTONFS(fdvp)->n_flag |= NLMODIFIED;
1834         VTONFS(tdvp)->n_flag |= NLMODIFIED;
1835         if (!fwccflag)
1836                 VTONFS(fdvp)->n_attrstamp = 0;
1837         if (!twccflag)
1838                 VTONFS(tdvp)->n_attrstamp = 0;
1839         return (error);
1840 }
1841
1842 /*
1843  * nfs hard link create call
1844  *
1845  * nfs_link(struct vnode *a_tdvp, struct vnode *a_vp,
1846  *          struct componentname *a_cnp)
1847  */
1848 static int
1849 nfs_link(struct vop_link_args *ap)
1850 {
1851         struct vnode *vp = ap->a_vp;
1852         struct vnode *tdvp = ap->a_tdvp;
1853         struct componentname *cnp = ap->a_cnp;
1854         u_int32_t *tl;
1855         caddr_t cp;
1856         int32_t t1, t2;
1857         caddr_t bpos, dpos, cp2;
1858         int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0;
1859         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1860         int v3;
1861
1862         if (vp->v_mount != tdvp->v_mount) {
1863                 return (EXDEV);
1864         }
1865
1866         /*
1867          * Push all writes to the server, so that the attribute cache
1868          * doesn't get "out of sync" with the server.
1869          * XXX There should be a better way!
1870          */
1871         VOP_FSYNC(vp, MNT_WAIT, cnp->cn_td);
1872
1873         v3 = NFS_ISV3(vp);
1874         nfsstats.rpccnt[NFSPROC_LINK]++;
1875         nfsm_reqhead(vp, NFSPROC_LINK,
1876                 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
1877         nfsm_fhtom(vp, v3);
1878         nfsm_fhtom(tdvp, v3);
1879         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1880         nfsm_request(vp, NFSPROC_LINK, cnp->cn_td, cnp->cn_cred);
1881         if (v3) {
1882                 nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
1883                 nfsm_wcc_data(tdvp, wccflag);
1884         }
1885         m_freem(mrep);
1886 nfsmout:
1887         VTONFS(tdvp)->n_flag |= NLMODIFIED;
1888         if (!attrflag)
1889                 VTONFS(vp)->n_attrstamp = 0;
1890         if (!wccflag)
1891                 VTONFS(tdvp)->n_attrstamp = 0;
1892         /*
1893          * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry.
1894          */
1895         if (error == EEXIST)
1896                 error = 0;
1897         return (error);
1898 }
1899
1900 /*
1901  * nfs symbolic link create call
1902  *
1903  * nfs_symlink(struct vnode *a_dvp, struct vnode **a_vpp,
1904  *              struct componentname *a_cnp, struct vattr *a_vap,
1905  *              char *a_target)
1906  */
1907 static int
1908 nfs_symlink(struct vop_symlink_args *ap)
1909 {
1910         struct vnode *dvp = ap->a_dvp;
1911         struct vattr *vap = ap->a_vap;
1912         struct componentname *cnp = ap->a_cnp;
1913         struct nfsv2_sattr *sp;
1914         u_int32_t *tl;
1915         caddr_t cp;
1916         int32_t t1, t2;
1917         caddr_t bpos, dpos, cp2;
1918         int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp;
1919         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
1920         struct vnode *newvp = (struct vnode *)0;
1921         int v3 = NFS_ISV3(dvp);
1922
1923         nfsstats.rpccnt[NFSPROC_SYMLINK]++;
1924         slen = strlen(ap->a_target);
1925         nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED +
1926             nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3));
1927         nfsm_fhtom(dvp, v3);
1928         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
1929         if (v3) {
1930                 nfsm_v3attrbuild(vap, FALSE);
1931         }
1932         nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN);
1933         if (!v3) {
1934                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1935                 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode);
1936                 sp->sa_uid = nfs_xdrneg1;
1937                 sp->sa_gid = nfs_xdrneg1;
1938                 sp->sa_size = nfs_xdrneg1;
1939                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
1940                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
1941         }
1942
1943         /*
1944          * Issue the NFS request and get the rpc response.
1945          *
1946          * Only NFSv3 responses returning an error of 0 actually return
1947          * a file handle that can be converted into newvp without having
1948          * to do an extra lookup rpc.
1949          */
1950         nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_td, cnp->cn_cred);
1951         if (v3) {
1952                 if (error == 0)
1953                         nfsm_mtofh(dvp, newvp, v3, gotvp);
1954                 nfsm_wcc_data(dvp, wccflag);
1955         }
1956
1957         /*
1958          * out code jumps -> here, mrep is also freed.
1959          */
1960
1961         m_freem(mrep);
1962 nfsmout:
1963
1964         /*
1965          * If we get an EEXIST error, silently convert it to no-error
1966          * in case of an NFS retry.
1967          */
1968         if (error == EEXIST)
1969                 error = 0;
1970
1971         /*
1972          * If we do not have (or no longer have) an error, and we could
1973          * not extract the newvp from the response due to the request being
1974          * NFSv2 or the error being EEXIST.  We have to do a lookup in order
1975          * to obtain a newvp to return.  
1976          */
1977         if (error == 0 && newvp == NULL) {
1978                 struct nfsnode *np = NULL;
1979
1980                 error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
1981                     cnp->cn_cred, cnp->cn_td, &np);
1982                 if (!error)
1983                         newvp = NFSTOV(np);
1984         }
1985         if (error) {
1986                 if (newvp)
1987                         vput(newvp);
1988         } else {
1989                 *ap->a_vpp = newvp;
1990         }
1991         VTONFS(dvp)->n_flag |= NLMODIFIED;
1992         if (!wccflag)
1993                 VTONFS(dvp)->n_attrstamp = 0;
1994         return (error);
1995 }
1996
1997 /*
1998  * nfs make dir call
1999  *
2000  * nfs_mkdir(struct vnode *a_dvp, struct vnode **a_vpp,
2001  *           struct componentname *a_cnp, struct vattr *a_vap)
2002  */
2003 static int
2004 nfs_mkdir(struct vop_mkdir_args *ap)
2005 {
2006         struct vnode *dvp = ap->a_dvp;
2007         struct vattr *vap = ap->a_vap;
2008         struct componentname *cnp = ap->a_cnp;
2009         struct nfsv2_sattr *sp;
2010         u_int32_t *tl;
2011         caddr_t cp;
2012         int32_t t1, t2;
2013         int len;
2014         struct nfsnode *np = (struct nfsnode *)0;
2015         struct vnode *newvp = (struct vnode *)0;
2016         caddr_t bpos, dpos, cp2;
2017         int error = 0, wccflag = NFSV3_WCCRATTR;
2018         int gotvp = 0;
2019         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2020         struct vattr vattr;
2021         int v3 = NFS_ISV3(dvp);
2022
2023         if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_td)) != 0) {
2024                 return (error);
2025         }
2026         len = cnp->cn_namelen;
2027         nfsstats.rpccnt[NFSPROC_MKDIR]++;
2028         nfsm_reqhead(dvp, NFSPROC_MKDIR,
2029           NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3));
2030         nfsm_fhtom(dvp, v3);
2031         nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN);
2032         if (v3) {
2033                 nfsm_v3attrbuild(vap, FALSE);
2034         } else {
2035                 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2036                 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode);
2037                 sp->sa_uid = nfs_xdrneg1;
2038                 sp->sa_gid = nfs_xdrneg1;
2039                 sp->sa_size = nfs_xdrneg1;
2040                 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime);
2041                 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime);
2042         }
2043         nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_td, cnp->cn_cred);
2044         if (!error)
2045                 nfsm_mtofh(dvp, newvp, v3, gotvp);
2046         if (v3)
2047                 nfsm_wcc_data(dvp, wccflag);
2048         m_freem(mrep);
2049 nfsmout:
2050         VTONFS(dvp)->n_flag |= NLMODIFIED;
2051         if (!wccflag)
2052                 VTONFS(dvp)->n_attrstamp = 0;
2053         /*
2054          * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry
2055          * if we can succeed in looking up the directory.
2056          */
2057         if (error == EEXIST || (!error && !gotvp)) {
2058                 if (newvp) {
2059                         vrele(newvp);
2060                         newvp = (struct vnode *)0;
2061                 }
2062                 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred,
2063                         cnp->cn_td, &np);
2064                 if (!error) {
2065                         newvp = NFSTOV(np);
2066                         if (newvp->v_type != VDIR)
2067                                 error = EEXIST;
2068                 }
2069         }
2070         if (error) {
2071                 if (newvp)
2072                         vrele(newvp);
2073         } else
2074                 *ap->a_vpp = newvp;
2075         return (error);
2076 }
2077
2078 /*
2079  * nfs remove directory call
2080  *
2081  * nfs_rmdir(struct vnode *a_dvp, struct vnode *a_vp,
2082  *           struct componentname *a_cnp)
2083  */
2084 static int
2085 nfs_rmdir(struct vop_rmdir_args *ap)
2086 {
2087         struct vnode *vp = ap->a_vp;
2088         struct vnode *dvp = ap->a_dvp;
2089         struct componentname *cnp = ap->a_cnp;
2090         u_int32_t *tl;
2091         caddr_t cp;
2092         int32_t t1, t2;
2093         caddr_t bpos, dpos, cp2;
2094         int error = 0, wccflag = NFSV3_WCCRATTR;
2095         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2096         int v3 = NFS_ISV3(dvp);
2097
2098         if (dvp == vp)
2099                 return (EINVAL);
2100         nfsstats.rpccnt[NFSPROC_RMDIR]++;
2101         nfsm_reqhead(dvp, NFSPROC_RMDIR,
2102                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen));
2103         nfsm_fhtom(dvp, v3);
2104         nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN);
2105         nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_td, cnp->cn_cred);
2106         if (v3)
2107                 nfsm_wcc_data(dvp, wccflag);
2108         m_freem(mrep);
2109 nfsmout:
2110         VTONFS(dvp)->n_flag |= NLMODIFIED;
2111         if (!wccflag)
2112                 VTONFS(dvp)->n_attrstamp = 0;
2113         /*
2114          * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2115          */
2116         if (error == ENOENT)
2117                 error = 0;
2118         return (error);
2119 }
2120
2121 /*
2122  * nfs readdir call
2123  *
2124  * nfs_readdir(struct vnode *a_vp, struct uio *a_uio, struct ucred *a_cred)
2125  */
2126 static int
2127 nfs_readdir(struct vop_readdir_args *ap)
2128 {
2129         struct vnode *vp = ap->a_vp;
2130         struct nfsnode *np = VTONFS(vp);
2131         struct uio *uio = ap->a_uio;
2132         int tresid, error;
2133         struct vattr vattr;
2134
2135         if (vp->v_type != VDIR)
2136                 return (EPERM);
2137
2138         /*
2139          * If we have a valid EOF offset cache we must call VOP_GETATTR()
2140          * and then check that is still valid, or if this is an NQNFS mount
2141          * we call NQNFS_CKCACHEABLE() instead of VOP_GETATTR().  Note that
2142          * VOP_GETATTR() does not necessarily go to the wire.
2143          */
2144         if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
2145             (np->n_flag & (NLMODIFIED|NRMODIFIED)) == 0) {
2146                 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) {
2147                         if (NQNFS_CKCACHABLE(vp, ND_READ)) {
2148                                 nfsstats.direofcache_hits++;
2149                                 return (0);
2150                         }
2151                 } else if (VOP_GETATTR(vp, &vattr, uio->uio_td) == 0 &&
2152                         (np->n_flag & (NLMODIFIED|NRMODIFIED)) == 0
2153                 ) {
2154                         nfsstats.direofcache_hits++;
2155                         return (0);
2156                 }
2157         }
2158
2159         /*
2160          * Call nfs_bioread() to do the real work.  nfs_bioread() does its
2161          * own cache coherency checks so we do not have to.
2162          */
2163         tresid = uio->uio_resid;
2164         error = nfs_bioread(vp, uio, 0);
2165
2166         if (!error && uio->uio_resid == tresid)
2167                 nfsstats.direofcache_misses++;
2168         return (error);
2169 }
2170
2171 /*
2172  * Readdir rpc call.
2173  * Called from below the buffer cache by nfs_doio().
2174  */
2175 int
2176 nfs_readdirrpc(struct vnode *vp, struct uio *uiop)
2177 {
2178         int len, left;
2179         struct dirent *dp = NULL;
2180         u_int32_t *tl;
2181         caddr_t cp;
2182         int32_t t1, t2;
2183         nfsuint64 *cookiep;
2184         caddr_t bpos, dpos, cp2;
2185         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2186         nfsuint64 cookie;
2187         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2188         struct nfsnode *dnp = VTONFS(vp);
2189         u_quad_t fileno;
2190         int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1;
2191         int attrflag;
2192         int v3 = NFS_ISV3(vp);
2193
2194 #ifndef DIAGNOSTIC
2195         if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2196                 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2197                 panic("nfs readdirrpc bad uio");
2198 #endif
2199
2200         /*
2201          * If there is no cookie, assume directory was stale.
2202          */
2203         cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2204         if (cookiep)
2205                 cookie = *cookiep;
2206         else
2207                 return (NFSERR_BAD_COOKIE);
2208         /*
2209          * Loop around doing readdir rpc's of size nm_readdirsize
2210          * truncated to a multiple of DIRBLKSIZ.
2211          * The stopping criteria is EOF or buffer full.
2212          */
2213         while (more_dirs && bigenough) {
2214                 nfsstats.rpccnt[NFSPROC_READDIR]++;
2215                 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) +
2216                         NFSX_READDIR(v3));
2217                 nfsm_fhtom(vp, v3);
2218                 if (v3) {
2219                         nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2220                         *tl++ = cookie.nfsuquad[0];
2221                         *tl++ = cookie.nfsuquad[1];
2222                         *tl++ = dnp->n_cookieverf.nfsuquad[0];
2223                         *tl++ = dnp->n_cookieverf.nfsuquad[1];
2224                 } else {
2225                         nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2226                         *tl++ = cookie.nfsuquad[0];
2227                 }
2228                 *tl = txdr_unsigned(nmp->nm_readdirsize);
2229                 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_td, nfs_vpcred(vp, ND_READ));
2230                 if (v3) {
2231                         nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
2232                         if (!error) {
2233                                 nfsm_dissect(tl, u_int32_t *,
2234                                     2 * NFSX_UNSIGNED);
2235                                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2236                                 dnp->n_cookieverf.nfsuquad[1] = *tl;
2237                         } else {
2238                                 m_freem(mrep);
2239                                 goto nfsmout;
2240                         }
2241                 }
2242                 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2243                 more_dirs = fxdr_unsigned(int, *tl);
2244         
2245                 /* loop thru the dir entries, doctoring them to 4bsd form */
2246                 while (more_dirs && bigenough) {
2247                         if (v3) {
2248                                 nfsm_dissect(tl, u_int32_t *,
2249                                     3 * NFSX_UNSIGNED);
2250                                 fileno = fxdr_hyper(tl);
2251                                 len = fxdr_unsigned(int, *(tl + 2));
2252                         } else {
2253                                 nfsm_dissect(tl, u_int32_t *,
2254                                     2 * NFSX_UNSIGNED);
2255                                 fileno = fxdr_unsigned(u_quad_t, *tl++);
2256                                 len = fxdr_unsigned(int, *tl);
2257                         }
2258                         if (len <= 0 || len > NFS_MAXNAMLEN) {
2259                                 error = EBADRPC;
2260                                 m_freem(mrep);
2261                                 goto nfsmout;
2262                         }
2263                         tlen = nfsm_rndup(len);
2264                         if (tlen == len)
2265                                 tlen += 4;      /* To ensure null termination */
2266                         left = DIRBLKSIZ - blksiz;
2267                         if ((tlen + DIRHDSIZ) > left) {
2268                                 dp->d_reclen += left;
2269                                 uiop->uio_iov->iov_base += left;
2270                                 uiop->uio_iov->iov_len -= left;
2271                                 uiop->uio_offset += left;
2272                                 uiop->uio_resid -= left;
2273                                 blksiz = 0;
2274                         }
2275                         if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2276                                 bigenough = 0;
2277                         if (bigenough) {
2278                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
2279                                 dp->d_fileno = (int)fileno;
2280                                 dp->d_namlen = len;
2281                                 dp->d_reclen = tlen + DIRHDSIZ;
2282                                 dp->d_type = DT_UNKNOWN;
2283                                 blksiz += dp->d_reclen;
2284                                 if (blksiz == DIRBLKSIZ)
2285                                         blksiz = 0;
2286                                 uiop->uio_offset += DIRHDSIZ;
2287                                 uiop->uio_resid -= DIRHDSIZ;
2288                                 uiop->uio_iov->iov_base += DIRHDSIZ;
2289                                 uiop->uio_iov->iov_len -= DIRHDSIZ;
2290                                 nfsm_mtouio(uiop, len);
2291                                 cp = uiop->uio_iov->iov_base;
2292                                 tlen -= len;
2293                                 *cp = '\0';     /* null terminate */
2294                                 uiop->uio_iov->iov_base += tlen;
2295                                 uiop->uio_iov->iov_len -= tlen;
2296                                 uiop->uio_offset += tlen;
2297                                 uiop->uio_resid -= tlen;
2298                         } else
2299                                 nfsm_adv(nfsm_rndup(len));
2300                         if (v3) {
2301                                 nfsm_dissect(tl, u_int32_t *,
2302                                     3 * NFSX_UNSIGNED);
2303                         } else {
2304                                 nfsm_dissect(tl, u_int32_t *,
2305                                     2 * NFSX_UNSIGNED);
2306                         }
2307                         if (bigenough) {
2308                                 cookie.nfsuquad[0] = *tl++;
2309                                 if (v3)
2310                                         cookie.nfsuquad[1] = *tl++;
2311                         } else if (v3)
2312                                 tl += 2;
2313                         else
2314                                 tl++;
2315                         more_dirs = fxdr_unsigned(int, *tl);
2316                 }
2317                 /*
2318                  * If at end of rpc data, get the eof boolean
2319                  */
2320                 if (!more_dirs) {
2321                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2322                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
2323                 }
2324                 m_freem(mrep);
2325         }
2326         /*
2327          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2328          * by increasing d_reclen for the last record.
2329          */
2330         if (blksiz > 0) {
2331                 left = DIRBLKSIZ - blksiz;
2332                 dp->d_reclen += left;
2333                 uiop->uio_iov->iov_base += left;
2334                 uiop->uio_iov->iov_len -= left;
2335                 uiop->uio_offset += left;
2336                 uiop->uio_resid -= left;
2337         }
2338
2339         /*
2340          * We are now either at the end of the directory or have filled the
2341          * block.
2342          */
2343         if (bigenough)
2344                 dnp->n_direofoffset = uiop->uio_offset;
2345         else {
2346                 if (uiop->uio_resid > 0)
2347                         printf("EEK! readdirrpc resid > 0\n");
2348                 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2349                 *cookiep = cookie;
2350         }
2351 nfsmout:
2352         return (error);
2353 }
2354
2355 /*
2356  * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc().
2357  */
2358 int
2359 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop)
2360 {
2361         int len, left;
2362         struct dirent *dp;
2363         u_int32_t *tl;
2364         caddr_t cp;
2365         int32_t t1, t2;
2366         struct vnode *newvp;
2367         nfsuint64 *cookiep;
2368         caddr_t bpos, dpos, cp2, dpossav1, dpossav2;
2369         struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2;
2370         nfsuint64 cookie;
2371         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2372         struct nfsnode *dnp = VTONFS(vp), *np;
2373         nfsfh_t *fhp;
2374         u_quad_t fileno;
2375         int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i;
2376         int attrflag, fhsize;
2377         struct namecache *ncp;
2378         struct namecache *dncp;
2379         struct nlcomponent nlc;
2380
2381 #ifndef nolint
2382         dp = (struct dirent *)0;
2383 #endif
2384 #ifndef DIAGNOSTIC
2385         if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) ||
2386                 (uiop->uio_resid & (DIRBLKSIZ - 1)))
2387                 panic("nfs readdirplusrpc bad uio");
2388 #endif
2389         /*
2390          * Obtain the namecache record for the directory so we have something
2391          * to use as a basis for creating the entries.  This function will
2392          * return a held (but not locked) ncp.  The ncp may be disconnected
2393          * from the tree and cannot be used for upward traversals, and the
2394          * ncp may be unnamed.  Note that other unrelated operations may 
2395          * cause the ncp to be named at any time.
2396          */
2397         dncp = cache_fromdvp(vp, NULL, 0);
2398         bzero(&nlc, sizeof(nlc));
2399         newvp = NULLVP;
2400
2401         /*
2402          * If there is no cookie, assume directory was stale.
2403          */
2404         cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0);
2405         if (cookiep)
2406                 cookie = *cookiep;
2407         else
2408                 return (NFSERR_BAD_COOKIE);
2409         /*
2410          * Loop around doing readdir rpc's of size nm_readdirsize
2411          * truncated to a multiple of DIRBLKSIZ.
2412          * The stopping criteria is EOF or buffer full.
2413          */
2414         while (more_dirs && bigenough) {
2415                 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++;
2416                 nfsm_reqhead(vp, NFSPROC_READDIRPLUS,
2417                         NFSX_FH(1) + 6 * NFSX_UNSIGNED);
2418                 nfsm_fhtom(vp, 1);
2419                 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2420                 *tl++ = cookie.nfsuquad[0];
2421                 *tl++ = cookie.nfsuquad[1];
2422                 *tl++ = dnp->n_cookieverf.nfsuquad[0];
2423                 *tl++ = dnp->n_cookieverf.nfsuquad[1];
2424                 *tl++ = txdr_unsigned(nmp->nm_readdirsize);
2425                 *tl = txdr_unsigned(nmp->nm_rsize);
2426                 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_td, nfs_vpcred(vp, ND_READ));
2427                 nfsm_postop_attr(vp, attrflag, NFS_LATTR_NOSHRINK);
2428                 if (error) {
2429                         m_freem(mrep);
2430                         goto nfsmout;
2431                 }
2432                 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2433                 dnp->n_cookieverf.nfsuquad[0] = *tl++;
2434                 dnp->n_cookieverf.nfsuquad[1] = *tl++;
2435                 more_dirs = fxdr_unsigned(int, *tl);
2436
2437                 /* loop thru the dir entries, doctoring them to 4bsd form */
2438                 while (more_dirs && bigenough) {
2439                         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2440                         fileno = fxdr_hyper(tl);
2441                         len = fxdr_unsigned(int, *(tl + 2));
2442                         if (len <= 0 || len > NFS_MAXNAMLEN) {
2443                                 error = EBADRPC;
2444                                 m_freem(mrep);
2445                                 goto nfsmout;
2446                         }
2447                         tlen = nfsm_rndup(len);
2448                         if (tlen == len)
2449                                 tlen += 4;      /* To ensure null termination*/
2450                         left = DIRBLKSIZ - blksiz;
2451                         if ((tlen + DIRHDSIZ) > left) {
2452                                 dp->d_reclen += left;
2453                                 uiop->uio_iov->iov_base += left;
2454                                 uiop->uio_iov->iov_len -= left;
2455                                 uiop->uio_offset += left;
2456                                 uiop->uio_resid -= left;
2457                                 blksiz = 0;
2458                         }
2459                         if ((tlen + DIRHDSIZ) > uiop->uio_resid)
2460                                 bigenough = 0;
2461                         if (bigenough) {
2462                                 dp = (struct dirent *)uiop->uio_iov->iov_base;
2463                                 dp->d_fileno = (int)fileno;
2464                                 dp->d_namlen = len;
2465                                 dp->d_reclen = tlen + DIRHDSIZ;
2466                                 dp->d_type = DT_UNKNOWN;
2467                                 blksiz += dp->d_reclen;
2468                                 if (blksiz == DIRBLKSIZ)
2469                                         blksiz = 0;
2470                                 uiop->uio_offset += DIRHDSIZ;
2471                                 uiop->uio_resid -= DIRHDSIZ;
2472                                 uiop->uio_iov->iov_base += DIRHDSIZ;
2473                                 uiop->uio_iov->iov_len -= DIRHDSIZ;
2474                                 nlc.nlc_nameptr = uiop->uio_iov->iov_base;
2475                                 nlc.nlc_namelen = len;
2476                                 nfsm_mtouio(uiop, len);
2477                                 cp = uiop->uio_iov->iov_base;
2478                                 tlen -= len;
2479                                 *cp = '\0';
2480                                 uiop->uio_iov->iov_base += tlen;
2481                                 uiop->uio_iov->iov_len -= tlen;
2482                                 uiop->uio_offset += tlen;
2483                                 uiop->uio_resid -= tlen;
2484                         } else
2485                                 nfsm_adv(nfsm_rndup(len));
2486                         nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2487                         if (bigenough) {
2488                                 cookie.nfsuquad[0] = *tl++;
2489                                 cookie.nfsuquad[1] = *tl++;
2490                         } else
2491                                 tl += 2;
2492
2493                         /*
2494                          * Since the attributes are before the file handle
2495                          * (sigh), we must skip over the attributes and then
2496                          * come back and get them.
2497                          */
2498                         attrflag = fxdr_unsigned(int, *tl);
2499                         if (attrflag) {
2500                             dpossav1 = dpos;
2501                             mdsav1 = md;
2502                             nfsm_adv(NFSX_V3FATTR);
2503                             nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2504                             doit = fxdr_unsigned(int, *tl);
2505                             if (doit) {
2506                                 nfsm_getfh(fhp, fhsize, 1);
2507                                 if (NFS_CMPFH(dnp, fhp, fhsize)) {
2508                                     vref(vp);
2509                                     newvp = vp;
2510                                     np = dnp;
2511                                 } else {
2512                                     error = nfs_nget(vp->v_mount, fhp,
2513                                         fhsize, &np);
2514                                     if (error)
2515                                         doit = 0;
2516                                     else
2517                                         newvp = NFSTOV(np);
2518                                 }
2519                             }
2520                             if (doit && bigenough) {
2521                                 dpossav2 = dpos;
2522                                 dpos = dpossav1;
2523                                 mdsav2 = md;
2524                                 md = mdsav1;
2525                                 nfsm_loadattr(newvp, (struct vattr *)0);
2526                                 dpos = dpossav2;
2527                                 md = mdsav2;
2528                                 dp->d_type =
2529                                     IFTODT(VTTOIF(np->n_vattr.va_type));
2530                                 if (dncp) {
2531                                     printf("NFS/READDIRPLUS, ENTER %*.*s\n",
2532                                         nlc.nlc_namelen, nlc.nlc_namelen,
2533                                         nlc.nlc_nameptr);
2534                                     ncp = cache_nlookup(dncp, &nlc);
2535                                     cache_setunresolved(ncp);
2536                                     cache_setvp(ncp, newvp);
2537                                     cache_put(ncp);
2538                                 } else {
2539                                     printf("NFS/READDIRPLUS, UNABLE TO ENTER"
2540                                         " %*.*s\n",
2541                                         nlc.nlc_namelen, nlc.nlc_namelen,
2542                                         nlc.nlc_nameptr);
2543                                 }
2544                             }
2545                         } else {
2546                             /* Just skip over the file handle */
2547                             nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2548                             i = fxdr_unsigned(int, *tl);
2549                             nfsm_adv(nfsm_rndup(i));
2550                         }
2551                         if (newvp != NULLVP) {
2552                             if (newvp == vp)
2553                                 vrele(newvp);
2554                             else
2555                                 vput(newvp);
2556                             newvp = NULLVP;
2557                         }
2558                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2559                         more_dirs = fxdr_unsigned(int, *tl);
2560                 }
2561                 /*
2562                  * If at end of rpc data, get the eof boolean
2563                  */
2564                 if (!more_dirs) {
2565                         nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2566                         more_dirs = (fxdr_unsigned(int, *tl) == 0);
2567                 }
2568                 m_freem(mrep);
2569         }
2570         /*
2571          * Fill last record, iff any, out to a multiple of DIRBLKSIZ
2572          * by increasing d_reclen for the last record.
2573          */
2574         if (blksiz > 0) {
2575                 left = DIRBLKSIZ - blksiz;
2576                 dp->d_reclen += left;
2577                 uiop->uio_iov->iov_base += left;
2578                 uiop->uio_iov->iov_len -= left;
2579                 uiop->uio_offset += left;
2580                 uiop->uio_resid -= left;
2581         }
2582
2583         /*
2584          * We are now either at the end of the directory or have filled the
2585          * block.
2586          */
2587         if (bigenough)
2588                 dnp->n_direofoffset = uiop->uio_offset;
2589         else {
2590                 if (uiop->uio_resid > 0)
2591                         printf("EEK! readdirplusrpc resid > 0\n");
2592                 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1);
2593                 *cookiep = cookie;
2594         }
2595 nfsmout:
2596         if (newvp != NULLVP) {
2597                 if (newvp == vp)
2598                         vrele(newvp);
2599                 else
2600                         vput(newvp);
2601                 newvp = NULLVP;
2602         }
2603         if (dncp)
2604                 cache_drop(dncp);
2605         return (error);
2606 }
2607
2608 /*
2609  * Silly rename. To make the NFS filesystem that is stateless look a little
2610  * more like the "ufs" a remove of an active vnode is translated to a rename
2611  * to a funny looking filename that is removed by nfs_inactive on the
2612  * nfsnode. There is the potential for another process on a different client
2613  * to create the same funny name between the nfs_lookitup() fails and the
2614  * nfs_rename() completes, but...
2615  */
2616 static int
2617 nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
2618 {
2619         struct sillyrename *sp;
2620         struct nfsnode *np;
2621         int error;
2622
2623         /*
2624          * We previously purged dvp instead of vp.  I don't know why, it
2625          * completely destroys performance.  We can't do it anyway with the
2626          * new VFS API since we would be breaking the namecache topology.
2627          */
2628         cache_purge(vp);        /* XXX */
2629         np = VTONFS(vp);
2630 #ifndef DIAGNOSTIC
2631         if (vp->v_type == VDIR)
2632                 panic("nfs: sillyrename dir");
2633 #endif
2634         MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename),
2635                 M_NFSREQ, M_WAITOK);
2636         sp->s_cred = crdup(cnp->cn_cred);
2637         sp->s_dvp = dvp;
2638         vref(dvp);
2639
2640         /* Fudge together a funny name */
2641         sp->s_namlen = sprintf(sp->s_name, ".nfsA%08x4.4", (int)cnp->cn_td);
2642
2643         /* Try lookitups until we get one that isn't there */
2644         while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2645                 cnp->cn_td, (struct nfsnode **)0) == 0) {
2646                 sp->s_name[4]++;
2647                 if (sp->s_name[4] > 'z') {
2648                         error = EINVAL;
2649                         goto bad;
2650                 }
2651         }
2652         error = nfs_renameit(dvp, cnp, sp);
2653         if (error)
2654                 goto bad;
2655         error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2656                 cnp->cn_td, &np);
2657         np->n_sillyrename = sp;
2658         return (0);
2659 bad:
2660         vrele(sp->s_dvp);
2661         crfree(sp->s_cred);
2662         free((caddr_t)sp, M_NFSREQ);
2663         return (error);
2664 }
2665
2666 /*
2667  * Look up a file name and optionally either update the file handle or
2668  * allocate an nfsnode, depending on the value of npp.
2669  * npp == NULL  --> just do the lookup
2670  * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2671  *                      handled too
2672  * *npp != NULL --> update the file handle in the vnode
2673  */
2674 static int
2675 nfs_lookitup(struct vnode *dvp, const char *name, int len, struct ucred *cred,
2676              struct thread *td, struct nfsnode **npp)
2677 {
2678         u_int32_t *tl;
2679         caddr_t cp;
2680         int32_t t1, t2;
2681         struct vnode *newvp = (struct vnode *)0;
2682         struct nfsnode *np, *dnp = VTONFS(dvp);
2683         caddr_t bpos, dpos, cp2;
2684         int error = 0, fhlen, attrflag;
2685         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2686         nfsfh_t *nfhp;
2687         int v3 = NFS_ISV3(dvp);
2688
2689         nfsstats.rpccnt[NFSPROC_LOOKUP]++;
2690         nfsm_reqhead(dvp, NFSPROC_LOOKUP,
2691                 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len));
2692         nfsm_fhtom(dvp, v3);
2693         nfsm_strtom(name, len, NFS_MAXNAMLEN);
2694         nfsm_request(dvp, NFSPROC_LOOKUP, td, cred);
2695         if (npp && !error) {
2696                 nfsm_getfh(nfhp, fhlen, v3);
2697                 if (*npp) {
2698                     np = *npp;
2699                     if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) {
2700                         free((caddr_t)np->n_fhp, M_NFSBIGFH);
2701                         np->n_fhp = &np->n_fh;
2702                     } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH)
2703                         np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK);
2704                     bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen);
2705                     np->n_fhsize = fhlen;
2706                     newvp = NFSTOV(np);
2707                 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) {
2708                     vref(dvp);
2709                     newvp = dvp;
2710                 } else {
2711                     error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np);
2712                     if (error) {
2713                         m_freem(mrep);
2714                         return (error);
2715                     }
2716                     newvp = NFSTOV(np);
2717                 }
2718                 if (v3) {
2719                         nfsm_postop_attr(newvp, attrflag, NFS_LATTR_NOSHRINK);
2720                         if (!attrflag && *npp == NULL) {
2721                                 m_freem(mrep);
2722                                 if (newvp == dvp)
2723                                         vrele(newvp);
2724                                 else
2725                                         vput(newvp);
2726                                 return (ENOENT);
2727                         }
2728                 } else
2729                         nfsm_loadattr(newvp, (struct vattr *)0);
2730         }
2731         m_freem(mrep);
2732 nfsmout:
2733         if (npp && *npp == NULL) {
2734                 if (error) {
2735                         if (newvp) {
2736                                 if (newvp == dvp)
2737                                         vrele(newvp);
2738                                 else
2739                                         vput(newvp);
2740                         }
2741                 } else
2742                         *npp = np;
2743         }
2744         return (error);
2745 }
2746
2747 /*
2748  * Nfs Version 3 commit rpc
2749  */
2750 int
2751 nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct thread *td)
2752 {
2753         caddr_t cp;
2754         u_int32_t *tl;
2755         int32_t t1, t2;
2756         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2757         caddr_t bpos, dpos, cp2;
2758         int error = 0, wccflag = NFSV3_WCCRATTR;
2759         struct mbuf *mreq, *mrep, *md, *mb, *mb2;
2760         
2761         if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0)
2762                 return (0);
2763         nfsstats.rpccnt[NFSPROC_COMMIT]++;
2764         nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1));
2765         nfsm_fhtom(vp, 1);
2766         nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
2767         txdr_hyper(offset, tl);
2768         tl += 2;
2769         *tl = txdr_unsigned(cnt);
2770         nfsm_request(vp, NFSPROC_COMMIT, td, nfs_vpcred(vp, ND_WRITE));
2771         nfsm_wcc_data(vp, wccflag);
2772         if (!error) {
2773                 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF);
2774                 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl,
2775                         NFSX_V3WRITEVERF)) {
2776                         bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf,
2777                                 NFSX_V3WRITEVERF);
2778                         error = NFSERR_STALEWRITEVERF;
2779                 }
2780         }
2781         m_freem(mrep);
2782 nfsmout:
2783         return (error);
2784 }
2785
2786 /*
2787  * Kludge City..
2788  * - make nfs_bmap() essentially a no-op that does no translation
2789  * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc
2790  *   (Maybe I could use the process's page mapping, but I was concerned that
2791  *    Kernel Write might not be enabled and also figured copyout() would do
2792  *    a lot more work than bcopy() and also it currently happens in the
2793  *    context of the swapper process (2).
2794  *
2795  * nfs_bmap(struct vnode *a_vp, daddr_t a_bn, struct vnode **a_vpp,
2796  *          daddr_t *a_bnp, int *a_runp, int *a_runb)
2797  */
2798 static int
2799 nfs_bmap(struct vop_bmap_args *ap)
2800 {
2801         struct vnode *vp = ap->a_vp;
2802
2803         if (ap->a_vpp != NULL)
2804                 *ap->a_vpp = vp;
2805         if (ap->a_bnp != NULL)
2806                 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize);
2807         if (ap->a_runp != NULL)
2808                 *ap->a_runp = 0;
2809         if (ap->a_runb != NULL)
2810                 *ap->a_runb = 0;
2811         return (0);
2812 }
2813
2814 /*
2815  * Strategy routine.
2816  * For async requests when nfsiod(s) are running, queue the request by
2817  * calling nfs_asyncio(), otherwise just all nfs_doio() to do the
2818  * request.
2819  */
2820 static int
2821 nfs_strategy(struct vop_strategy_args *ap)
2822 {
2823         struct buf *bp = ap->a_bp;
2824         struct thread *td;
2825         int error = 0;
2826
2827         KASSERT(!(bp->b_flags & B_DONE), ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp));
2828         KASSERT(BUF_REFCNT(bp) > 0, ("nfs_strategy: buffer %p not locked", bp));
2829
2830         if (bp->b_flags & B_PHYS)
2831                 panic("nfs physio");
2832
2833         if (bp->b_flags & B_ASYNC)
2834                 td = NULL;
2835         else
2836                 td = curthread; /* XXX */
2837
2838         /*
2839          * If the op is asynchronous and an i/o daemon is waiting
2840          * queue the request, wake it up and wait for completion
2841          * otherwise just do it ourselves.
2842          */
2843         if ((bp->b_flags & B_ASYNC) == 0 ||
2844                 nfs_asyncio(bp, td))
2845                 error = nfs_doio(bp, td);
2846         return (error);
2847 }
2848
2849 /*
2850  * Mmap a file
2851  *
2852  * NB Currently unsupported.
2853  *
2854  * nfs_mmap(struct vnode *a_vp, int a_fflags, struct ucred *a_cred,
2855  *          struct thread *a_td)
2856  */
2857 /* ARGSUSED */
2858 static int
2859 nfs_mmap(struct vop_mmap_args *ap)
2860 {
2861         return (EINVAL);
2862 }
2863
2864 /*
2865  * fsync vnode op. Just call nfs_flush() with commit == 1.
2866  *
2867  * nfs_fsync(struct vnodeop_desc *a_desc, struct vnode *a_vp,
2868  *           struct ucred * a_cred, int a_waitfor, struct thread *a_td)
2869  */
2870 /* ARGSUSED */
2871 static int
2872 nfs_fsync(struct vop_fsync_args *ap)
2873 {
2874         return (nfs_flush(ap->a_vp, ap->a_waitfor, ap->a_td, 1));
2875 }
2876
2877 /*
2878  * Flush all the blocks associated with a vnode.   Dirty NFS buffers may be
2879  * in one of two states:  If B_NEEDCOMMIT is clear then the buffer contains
2880  * new NFS data which needs to be written to the server.  If B_NEEDCOMMIT is
2881  * set the buffer contains data that has already been written to the server
2882  * and which now needs a commit RPC.
2883  *
2884  * If commit is 0 we only take one pass and only flush buffers containing new
2885  * dirty data.
2886  *
2887  * If commit is 1 we take two passes, issuing a commit RPC in the second
2888  * pass.
2889  *
2890  * If waitfor is MNT_WAIT and commit is 1, we loop as many times as required
2891  * to completely flush all pending data.
2892  *
2893  * Note that the RB_SCAN code properly handles the case where the
2894  * callback might block and directly or indirectly (another thread) cause
2895  * the RB tree to change.
2896  */
2897
2898 #ifndef NFS_COMMITBVECSIZ
2899 #define NFS_COMMITBVECSIZ       16
2900 #endif
2901
2902 struct nfs_flush_info {
2903         enum { NFI_FLUSHNEW, NFI_COMMIT } mode;
2904         struct thread *td;
2905         struct vnode *vp;
2906         int waitfor;
2907         int slpflag;
2908         int slptimeo;
2909         int loops;
2910         struct buf *bvary[NFS_COMMITBVECSIZ];
2911         int bvsize;
2912         off_t beg_off;
2913         off_t end_off;
2914 };
2915
2916 static int nfs_flush_bp(struct buf *bp, void *data);
2917 static int nfs_flush_docommit(struct nfs_flush_info *info, int error);
2918
2919 int
2920 nfs_flush(struct vnode *vp, int waitfor, struct thread *td, int commit)
2921 {
2922         struct nfsnode *np = VTONFS(vp);
2923         struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2924         struct nfs_flush_info info;
2925         int error;
2926
2927         bzero(&info, sizeof(info));
2928         info.td = td;
2929         info.vp = vp;
2930         info.waitfor = waitfor;
2931         info.slpflag = (nmp->nm_flag & NFSMNT_INT) ? PCATCH : 0;
2932         info.loops = 0;
2933
2934         do {
2935                 /*
2936                  * Flush mode
2937                  */
2938                 info.mode = NFI_FLUSHNEW;
2939                 error = RB_SCAN(buf_rb_tree, &vp->v_rbdirty_tree, NULL, 
2940                                 nfs_flush_bp, &info);
2941
2942                 /*
2943                  * Take a second pass if committing and no error occured.  
2944                  * Clean up any left over collection (whether an error 
2945                  * occurs or not).
2946                  */
2947                 if (commit && error == 0) {
2948                         info.mode = NFI_COMMIT;
2949                         error = RB_SCAN(buf_rb_tree, &vp->v_rbdirty_tree, NULL, 
2950                                         nfs_flush_bp, &info);
2951                         if (info.bvsize)
2952                                 error = nfs_flush_docommit(&info, error);
2953                 }
2954
2955                 /*
2956                  * Wait for pending I/O to complete before checking whether
2957                  * any further dirty buffers exist.
2958                  */
2959                 while (waitfor == MNT_WAIT && vp->v_numoutput) {
2960                         vp->v_flag |= VBWAIT;
2961                         error = tsleep((caddr_t)&vp->v_numoutput,
2962                                 info.slpflag, "nfsfsync", info.slptimeo);
2963                         if (error) {
2964                                 /*
2965                                  * We have to be able to break out if this 
2966                                  * is an 'intr' mount.
2967                                  */
2968                                 if (nfs_sigintr(nmp, (struct nfsreq *)0, td)) {
2969                                         error = -EINTR;
2970                                         break;
2971                                 }
2972
2973                                 /*
2974                                  * Since we do not process pending signals,
2975                                  * once we get a PCATCH our tsleep() will no
2976                                  * longer sleep, switch to a fixed timeout
2977                                  * instead.
2978                                  */
2979                                 if (info.slpflag == PCATCH) {
2980                                         info.slpflag = 0;
2981                                         info.slptimeo = 2 * hz;
2982                                 }
2983                                 error = 0;
2984                         }
2985                 }
2986                 ++info.loops;
2987                 /*
2988                  * Loop if we are flushing synchronous as well as committing,
2989                  * and dirty buffers are still present.  Otherwise we might livelock.
2990                  */
2991         } while (waitfor == MNT_WAIT && commit && 
2992                  error == 0 && !RB_EMPTY(&vp->v_rbdirty_tree));
2993
2994         /*
2995          * The callbacks have to return a negative error to terminate the
2996          * RB scan.
2997          */
2998         if (error < 0)
2999                 error = -error;
3000
3001         /*
3002          * Deal with any error collection
3003          */
3004         if (np->n_flag & NWRITEERR) {
3005                 error = np->n_error;
3006                 np->n_flag &= ~NWRITEERR;
3007         }
3008         return (error);
3009 }
3010
3011
3012 static
3013 int
3014 nfs_flush_bp(struct buf *bp, void *data)
3015 {
3016         struct nfs_flush_info *info = data;
3017         off_t toff;
3018         int error;
3019         int s;
3020
3021         error = 0;
3022         switch(info->mode) {
3023         case NFI_FLUSHNEW:
3024                 s = splbio();
3025                 if (info->loops && info->waitfor == MNT_WAIT) {
3026                         error = BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT);
3027                         if (error) {
3028                                 error = BUF_TIMELOCK(bp,
3029                                                 LK_EXCLUSIVE | LK_SLEEPFAIL,
3030                                                 "nfsfsync",
3031                                                 info->slpflag, info->slptimeo);
3032                         }
3033                 } else {
3034                         error = BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT);
3035                 }
3036                 if (error == 0) {
3037                         if ((bp->b_flags & B_DELWRI) == 0)
3038                                 panic("nfs_fsync: not dirty");
3039                         if (bp->b_flags & B_NEEDCOMMIT) {
3040                                 BUF_UNLOCK(bp);
3041                                 splx(s);
3042                                 break;
3043                         }
3044                         bremfree(bp);
3045
3046                         bp->b_flags |= B_ASYNC;
3047                         splx(s);
3048                         VOP_BWRITE(bp->b_vp, bp);
3049                 } else {
3050                         splx(s);
3051                         error = 0;
3052                 }
3053                 break;
3054         case NFI_COMMIT:
3055                 /*
3056                  * Only process buffers in need of a commit which we can
3057                  * immediately lock.  This may prevent a buffer from being
3058                  * committed, but the normal flush loop will block on the
3059                  * same buffer so we shouldn't get into an endless loop.
3060                  */
3061                 s = splbio();
3062                 if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) != 
3063                     (B_DELWRI | B_NEEDCOMMIT) ||
3064                     BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT) != 0) {
3065                         splx(s);
3066                         break;
3067                 }
3068
3069                 bremfree(bp);
3070
3071                 /*
3072                  * NOTE: we are not clearing B_DONE here, so we have
3073                  * to do it later on in this routine if we intend to 
3074                  * initiate I/O on the bp.
3075                  *
3076                  * Note: to avoid loopback deadlocks, we do not
3077                  * assign b_runningbufspace.
3078                  */
3079                 vfs_busy_pages(bp, 1);
3080
3081                 info->bvary[info->bvsize] = bp;
3082                 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
3083                         bp->b_dirtyoff;
3084                 if (info->bvsize == 0 || toff < info->beg_off)
3085                         info->beg_off = toff;
3086                 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
3087                 if (info->bvsize == 0 || toff > info->end_off)
3088                         info->end_off = toff;
3089                 ++info->bvsize;
3090                 if (info->bvsize == NFS_COMMITBVECSIZ) {
3091                         error = nfs_flush_docommit(info, 0);
3092                         KKASSERT(info->bvsize == 0);
3093                 }
3094                 splx(s);
3095         }
3096         return (error);
3097 }
3098
3099 static
3100 int
3101 nfs_flush_docommit(struct nfs_flush_info *info, int error)
3102 {
3103         struct vnode *vp;
3104         struct buf *bp;
3105         off_t bytes;
3106         int retv;
3107         int i;
3108         int s;
3109
3110         vp = info->vp;
3111
3112         if (info->bvsize > 0) {
3113                 /*
3114                  * Commit data on the server, as required.  Note that
3115                  * nfs_commit will use the vnode's cred for the commit.
3116                  * The NFSv3 commit RPC is limited to a 32 bit byte count.
3117                  */
3118                 bytes = info->end_off - info->beg_off;
3119                 if (bytes > 0x40000000)
3120                         bytes = 0x40000000;
3121                 if (error) {
3122                         retv = -error;
3123                 } else {
3124                         retv = nfs_commit(vp, info->beg_off, 
3125                                             (int)bytes, info->td);
3126                         if (retv == NFSERR_STALEWRITEVERF)
3127                                 nfs_clearcommit(vp->v_mount);
3128                 }
3129
3130                 /*
3131                  * Now, either mark the blocks I/O done or mark the
3132                  * blocks dirty, depending on whether the commit
3133                  * succeeded.
3134                  */
3135                 for (i = 0; i < info->bvsize; ++i) {
3136                         bp = info->bvary[i];
3137                         bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
3138                         if (retv) {
3139                                 /*
3140                                  * Error, leave B_DELWRI intact
3141                                  */
3142                                 vfs_unbusy_pages(bp);
3143                                 brelse(bp);
3144                         } else {
3145                                 /*
3146                                  * Success, remove B_DELWRI ( bundirty() ).
3147                                  *
3148                                  * b_dirtyoff/b_dirtyend seem to be NFS 
3149                                  * specific.  We should probably move that
3150                                  * into bundirty(). XXX
3151                                  */
3152                                 s = splbio();
3153                                 vp->v_numoutput++;
3154                                 bp->b_flags |= B_ASYNC;
3155                                 bundirty(bp);
3156                                 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
3157                                 bp->b_dirtyoff = bp->b_dirtyend = 0;
3158                                 splx(s);
3159                                 biodone(bp);
3160                         }
3161                 }
3162                 info->bvsize = 0;
3163         }
3164         return (error);
3165 }
3166
3167 /*
3168  * NFS advisory byte-level locks.
3169  * Currently unsupported.
3170  *
3171  * nfs_advlock(struct vnode *a_vp, caddr_t a_id, int a_op, struct flock *a_fl,
3172  *              int a_flags)
3173  */
3174 static int
3175 nfs_advlock(struct vop_advlock_args *ap)
3176 {
3177         struct nfsnode *np = VTONFS(ap->a_vp);
3178
3179         /*
3180          * The following kludge is to allow diskless support to work
3181          * until a real NFS lockd is implemented. Basically, just pretend
3182          * that this is a local lock.
3183          */
3184         return (lf_advlock(ap, &(np->n_lockf), np->n_size));
3185 }
3186
3187 /*
3188  * Print out the contents of an nfsnode.
3189  *
3190  * nfs_print(struct vnode *a_vp)
3191  */
3192 static int
3193 nfs_print(struct vop_print_args *ap)
3194 {
3195         struct vnode *vp = ap->a_vp;
3196         struct nfsnode *np = VTONFS(vp);
3197
3198         printf("tag VT_NFS, fileid %ld fsid 0x%x",
3199                 np->n_vattr.va_fileid, np->n_vattr.va_fsid);
3200         if (vp->v_type == VFIFO)
3201                 fifo_printinfo(vp);
3202         printf("\n");
3203         return (0);
3204 }
3205
3206 /*
3207  * Just call nfs_writebp() with the force argument set to 1.
3208  *
3209  * NOTE: B_DONE may or may not be set in a_bp on call.
3210  *
3211  * nfs_bwrite(struct vnode *a_bp)
3212  */
3213 static int
3214 nfs_bwrite(struct vop_bwrite_args *ap)
3215 {
3216         return (nfs_writebp(ap->a_bp, 1, curthread));
3217 }
3218
3219 /*
3220  * This is a clone of vn_bwrite(), except that it also handles the
3221  * B_NEEDCOMMIT flag.  We set B_CACHE if this is a VMIO buffer.
3222  */
3223 int
3224 nfs_writebp(struct buf *bp, int force, struct thread *td)
3225 {
3226         int s;
3227         int oldflags = bp->b_flags;
3228 #if 0
3229         int retv = 1;
3230         off_t off;
3231 #endif
3232
3233         if (BUF_REFCNT(bp) == 0)
3234                 panic("bwrite: buffer is not locked???");
3235
3236         if (bp->b_flags & B_INVAL) {
3237                 brelse(bp);
3238                 return(0);
3239         }
3240
3241         bp->b_flags |= B_CACHE;
3242
3243         /*
3244          * Undirty the bp.  We will redirty it later if the I/O fails.
3245          */
3246
3247         s = splbio();
3248         bundirty(bp);
3249         bp->b_flags &= ~(B_READ|B_DONE|B_ERROR);
3250
3251         bp->b_vp->v_numoutput++;
3252         splx(s);
3253
3254         /*
3255          * Note: to avoid loopback deadlocks, we do not
3256          * assign b_runningbufspace.
3257          */
3258         vfs_busy_pages(bp, 1);
3259
3260         BUF_KERNPROC(bp);
3261         VOP_STRATEGY(bp->b_vp, bp);
3262
3263         if( (oldflags & B_ASYNC) == 0) {
3264                 int rtval = biowait(bp);
3265
3266                 if (oldflags & B_DELWRI) {
3267                         s = splbio();
3268                         reassignbuf(bp, bp->b_vp);
3269                         splx(s);
3270                 }
3271
3272                 brelse(bp);
3273                 return (rtval);
3274         } 
3275
3276         return (0);
3277 }
3278
3279 /*
3280  * nfs special file access vnode op.
3281  * Essentially just get vattr and then imitate iaccess() since the device is
3282  * local to the client.
3283  *
3284  * nfsspec_access(struct vnode *a_vp, int a_mode, struct ucred *a_cred,
3285  *                struct thread *a_td)
3286  */
3287 static int
3288 nfsspec_access(struct vop_access_args *ap)
3289 {
3290         struct vattr *vap;
3291         gid_t *gp;
3292         struct ucred *cred = ap->a_cred;
3293         struct vnode *vp = ap->a_vp;
3294         mode_t mode = ap->a_mode;
3295         struct vattr vattr;
3296         int i;
3297         int error;
3298
3299         /*
3300          * Disallow write attempts on filesystems mounted read-only;
3301          * unless the file is a socket, fifo, or a block or character
3302          * device resident on the filesystem.
3303          */
3304         if ((mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3305                 switch (vp->v_type) {
3306                 case VREG:
3307                 case VDIR:
3308                 case VLNK:
3309                         return (EROFS);
3310                 default:
3311                         break;
3312                 }
3313         }
3314         /*
3315          * If you're the super-user,
3316          * you always get access.
3317          */
3318         if (cred->cr_uid == 0)
3319                 return (0);
3320         vap = &vattr;
3321         error = VOP_GETATTR(vp, vap, ap->a_td);
3322         if (error)
3323                 return (error);
3324         /*
3325          * Access check is based on only one of owner, group, public.
3326          * If not owner, then check group. If not a member of the
3327          * group, then check public access.
3328          */
3329         if (cred->cr_uid != vap->va_uid) {
3330                 mode >>= 3;
3331                 gp = cred->cr_groups;
3332                 for (i = 0; i < cred->cr_ngroups; i++, gp++)
3333                         if (vap->va_gid == *gp)
3334                                 goto found;
3335                 mode >>= 3;
3336 found:
3337                 ;
3338         }
3339         error = (vap->va_mode & mode) == mode ? 0 : EACCES;
3340         return (error);
3341 }
3342
3343 /*
3344  * Read wrapper for special devices.
3345  *
3346  * nfsspec_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
3347  *              struct ucred *a_cred)
3348  */
3349 static int
3350 nfsspec_read(struct vop_read_args *ap)
3351 {
3352         struct nfsnode *np = VTONFS(ap->a_vp);
3353
3354         /*
3355          * Set access flag.
3356          */
3357         np->n_flag |= NACC;
3358         getnanotime(&np->n_atim);
3359         return (VOCALL(spec_vnode_vops, &ap->a_head));
3360 }
3361
3362 /*
3363  * Write wrapper for special devices.
3364  *
3365  * nfsspec_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
3366  *               struct ucred *a_cred)
3367  */
3368 static int
3369 nfsspec_write(struct vop_write_args *ap)
3370 {
3371         struct nfsnode *np = VTONFS(ap->a_vp);
3372
3373         /*
3374          * Set update flag.
3375          */
3376         np->n_flag |= NUPD;
3377         getnanotime(&np->n_mtim);
3378         return (VOCALL(spec_vnode_vops, &ap->a_head));
3379 }
3380
3381 /*
3382  * Close wrapper for special devices.
3383  *
3384  * Update the times on the nfsnode then do device close.
3385  *
3386  * nfsspec_close(struct vnode *a_vp, int a_fflag, struct ucred *a_cred,
3387  *               struct thread *a_td)
3388  */
3389 static int
3390 nfsspec_close(struct vop_close_args *ap)
3391 {
3392         struct vnode *vp = ap->a_vp;
3393         struct nfsnode *np = VTONFS(vp);
3394         struct vattr vattr;
3395
3396         if (np->n_flag & (NACC | NUPD)) {
3397                 np->n_flag |= NCHG;
3398                 if (vp->v_usecount == 1 &&
3399                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3400                         VATTR_NULL(&vattr);
3401                         if (np->n_flag & NACC)
3402                                 vattr.va_atime = np->n_atim;
3403                         if (np->n_flag & NUPD)
3404                                 vattr.va_mtime = np->n_mtim;
3405                         (void)VOP_SETATTR(vp, &vattr, nfs_vpcred(vp, ND_WRITE), ap->a_td);
3406                 }
3407         }
3408         return (VOCALL(spec_vnode_vops, &ap->a_head));
3409 }
3410
3411 /*
3412  * Read wrapper for fifos.
3413  *
3414  * nfsfifo_read(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
3415  *              struct ucred *a_cred)
3416  */
3417 static int
3418 nfsfifo_read(struct vop_read_args *ap)
3419 {
3420         struct nfsnode *np = VTONFS(ap->a_vp);
3421
3422         /*
3423          * Set access flag.
3424          */
3425         np->n_flag |= NACC;
3426         getnanotime(&np->n_atim);
3427         return (VOCALL(fifo_vnode_vops, &ap->a_head));
3428 }
3429
3430 /*
3431  * Write wrapper for fifos.
3432  *
3433  * nfsfifo_write(struct vnode *a_vp, struct uio *a_uio, int a_ioflag,
3434  *               struct ucred *a_cred)
3435  */
3436 static int
3437 nfsfifo_write(struct vop_write_args *ap)
3438 {
3439         struct nfsnode *np = VTONFS(ap->a_vp);
3440
3441         /*
3442          * Set update flag.
3443          */
3444         np->n_flag |= NUPD;
3445         getnanotime(&np->n_mtim);
3446         return (VOCALL(fifo_vnode_vops, &ap->a_head));
3447 }
3448
3449 /*
3450  * Close wrapper for fifos.
3451  *
3452  * Update the times on the nfsnode then do fifo close.
3453  *
3454  * nfsfifo_close(struct vnode *a_vp, int a_fflag, struct thread *a_td)
3455  */
3456 static int
3457 nfsfifo_close(struct vop_close_args *ap)
3458 {
3459         struct vnode *vp = ap->a_vp;
3460         struct nfsnode *np = VTONFS(vp);
3461         struct vattr vattr;
3462         struct timespec ts;
3463
3464         if (np->n_flag & (NACC | NUPD)) {
3465                 getnanotime(&ts);
3466                 if (np->n_flag & NACC)
3467                         np->n_atim = ts;
3468                 if (np->n_flag & NUPD)
3469                         np->n_mtim = ts;
3470                 np->n_flag |= NCHG;
3471                 if (vp->v_usecount == 1 &&
3472                     (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3473                         VATTR_NULL(&vattr);
3474                         if (np->n_flag & NACC)
3475                                 vattr.va_atime = np->n_atim;
3476                         if (np->n_flag & NUPD)
3477                                 vattr.va_mtime = np->n_mtim;
3478                         (void)VOP_SETATTR(vp, &vattr, nfs_vpcred(vp, ND_WRITE), ap->a_td);
3479                 }
3480         }
3481         return (VOCALL(fifo_vnode_vops, &ap->a_head));
3482 }
3483