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