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