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