source: rtems-libbsd/freebsd/sys/fs/nfsclient/nfs_clvnops.c @ 6e4709b

6-freebsd-12
Last change on this file since 6e4709b was 6e4709b, checked in by Sebastian Huber <sebastian.huber@…>, on 01/05/23 at 16:42:48

vfs/nfs: Revert white space changes

  • Property mode set to 100644
File size: 96.1 KB
RevLine 
[882425f]1#include <machine/rtems-bsd-kernel-space.h>
2
[6138f24]3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 1989, 1993
7 *      The Regents of the University of California.  All rights reserved.
8 *
9 * This code is derived from software contributed to Berkeley by
10 * Rick Macklem at The University of Guelph.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. 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 *      from nfs_vnops.c        8.16 (Berkeley) 5/27/95
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD$");
41
42/*
43 * vnode op calls for Sun NFS version 2, 3 and 4
44 */
45
[882425f]46#include <rtems/bsd/local/opt_inet.h>
[6138f24]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/bio.h>
55#include <sys/buf.h>
56#include <sys/jail.h>
57#include <sys/malloc.h>
58#include <sys/mbuf.h>
59#include <sys/namei.h>
60#include <sys/socket.h>
61#include <sys/vnode.h>
62#include <sys/dirent.h>
63#include <sys/fcntl.h>
[882425f]64#ifndef __rtems__
[6138f24]65#include <sys/lockf.h>
[882425f]66#endif /* __rtems__ */
[6138f24]67#include <sys/stat.h>
68#include <sys/sysctl.h>
69#include <sys/signalvar.h>
70
71#include <vm/vm.h>
72#include <vm/vm_extern.h>
73#include <vm/vm_object.h>
74
75#include <fs/nfs/nfsport.h>
76#include <fs/nfsclient/nfsnode.h>
77#include <fs/nfsclient/nfsmount.h>
78#include <fs/nfsclient/nfs.h>
79#include <fs/nfsclient/nfs_kdtrace.h>
80
81#include <net/if.h>
82#include <netinet/in.h>
83#include <netinet/in_var.h>
84
85#include <nfs/nfs_lock.h>
86
87#ifdef KDTRACE_HOOKS
88#include <sys/dtrace_bsd.h>
89
90dtrace_nfsclient_accesscache_flush_probe_func_t
91                dtrace_nfscl_accesscache_flush_done_probe;
92uint32_t        nfscl_accesscache_flush_done_id;
93
94dtrace_nfsclient_accesscache_get_probe_func_t
95                dtrace_nfscl_accesscache_get_hit_probe,
96                dtrace_nfscl_accesscache_get_miss_probe;
97uint32_t        nfscl_accesscache_get_hit_id;
98uint32_t        nfscl_accesscache_get_miss_id;
99
100dtrace_nfsclient_accesscache_load_probe_func_t
101                dtrace_nfscl_accesscache_load_done_probe;
102uint32_t        nfscl_accesscache_load_done_id;
103#endif /* !KDTRACE_HOOKS */
104
105/* Defs */
106#define TRUE    1
107#define FALSE   0
108
109extern struct nfsstatsv1 nfsstatsv1;
110extern int nfsrv_useacl;
111extern int nfscl_debuglevel;
112MALLOC_DECLARE(M_NEWNFSREQ);
113
114static vop_read_t       nfsfifo_read;
115static vop_write_t      nfsfifo_write;
116static vop_close_t      nfsfifo_close;
117static int      nfs_setattrrpc(struct vnode *, struct vattr *, struct ucred *,
118                    struct thread *);
119static vop_lookup_t     nfs_lookup;
120static vop_create_t     nfs_create;
121static vop_mknod_t      nfs_mknod;
122static vop_open_t       nfs_open;
123static vop_pathconf_t   nfs_pathconf;
124static vop_close_t      nfs_close;
125static vop_access_t     nfs_access;
126static vop_getattr_t    nfs_getattr;
127static vop_setattr_t    nfs_setattr;
128static vop_read_t       nfs_read;
129static vop_fsync_t      nfs_fsync;
130static vop_remove_t     nfs_remove;
131static vop_link_t       nfs_link;
132static vop_rename_t     nfs_rename;
133static vop_mkdir_t      nfs_mkdir;
134static vop_rmdir_t      nfs_rmdir;
135static vop_symlink_t    nfs_symlink;
136static vop_readdir_t    nfs_readdir;
137static vop_strategy_t   nfs_strategy;
138static  int     nfs_lookitup(struct vnode *, char *, int,
139                    struct ucred *, struct thread *, struct nfsnode **);
140static  int     nfs_sillyrename(struct vnode *, struct vnode *,
141                    struct componentname *);
142static vop_access_t     nfsspec_access;
143static vop_readlink_t   nfs_readlink;
144static vop_print_t      nfs_print;
145static vop_advlock_t    nfs_advlock;
146static vop_advlockasync_t nfs_advlockasync;
147static vop_getacl_t nfs_getacl;
148static vop_setacl_t nfs_setacl;
149static vop_lock1_t      nfs_lock;
150
151/*
152 * Global vfs data structures for nfs
153 */
154struct vop_vector newnfs_vnodeops = {
155        .vop_default =          &default_vnodeops,
156        .vop_access =           nfs_access,
157        .vop_advlock =          nfs_advlock,
158        .vop_advlockasync =     nfs_advlockasync,
159        .vop_close =            nfs_close,
160        .vop_create =           nfs_create,
161        .vop_fsync =            nfs_fsync,
162        .vop_getattr =          nfs_getattr,
163        .vop_getpages =         ncl_getpages,
164        .vop_putpages =         ncl_putpages,
165        .vop_inactive =         ncl_inactive,
166        .vop_link =             nfs_link,
167        .vop_lock1 =            nfs_lock,
168        .vop_lookup =           nfs_lookup,
169        .vop_mkdir =            nfs_mkdir,
170        .vop_mknod =            nfs_mknod,
171        .vop_open =             nfs_open,
172        .vop_pathconf =         nfs_pathconf,
173        .vop_print =            nfs_print,
174        .vop_read =             nfs_read,
175        .vop_readdir =          nfs_readdir,
176        .vop_readlink =         nfs_readlink,
177        .vop_reclaim =          ncl_reclaim,
178        .vop_remove =           nfs_remove,
179        .vop_rename =           nfs_rename,
180        .vop_rmdir =            nfs_rmdir,
181        .vop_setattr =          nfs_setattr,
182        .vop_strategy =         nfs_strategy,
183        .vop_symlink =          nfs_symlink,
184        .vop_write =            ncl_write,
185        .vop_getacl =           nfs_getacl,
186        .vop_setacl =           nfs_setacl,
187};
188
189struct vop_vector newnfs_fifoops = {
190        .vop_default =          &fifo_specops,
191        .vop_access =           nfsspec_access,
192        .vop_close =            nfsfifo_close,
193        .vop_fsync =            nfs_fsync,
194        .vop_getattr =          nfs_getattr,
195        .vop_inactive =         ncl_inactive,
196        .vop_pathconf =         nfs_pathconf,
197        .vop_print =            nfs_print,
198        .vop_read =             nfsfifo_read,
199        .vop_reclaim =          ncl_reclaim,
200        .vop_setattr =          nfs_setattr,
201        .vop_write =            nfsfifo_write,
202};
203
204static int nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp,
205    struct componentname *cnp, struct vattr *vap);
206static int nfs_removerpc(struct vnode *dvp, struct vnode *vp, char *name,
207    int namelen, struct ucred *cred, struct thread *td);
208static int nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp,
209    char *fnameptr, int fnamelen, struct vnode *tdvp, struct vnode *tvp,
210    char *tnameptr, int tnamelen, struct ucred *cred, struct thread *td);
211static int nfs_renameit(struct vnode *sdvp, struct vnode *svp,
212    struct componentname *scnp, struct sillyrename *sp);
213
214/*
215 * Global variables
216 */
217SYSCTL_DECL(_vfs_nfs);
218
219static int      nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
220SYSCTL_INT(_vfs_nfs, OID_AUTO, access_cache_timeout, CTLFLAG_RW,
221           &nfsaccess_cache_timeout, 0, "NFS ACCESS cache timeout");
222
223static int      nfs_prime_access_cache = 0;
224SYSCTL_INT(_vfs_nfs, OID_AUTO, prime_access_cache, CTLFLAG_RW,
225           &nfs_prime_access_cache, 0,
226           "Prime NFS ACCESS cache when fetching attributes");
227
228static int      newnfs_commit_on_close = 0;
229SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_on_close, CTLFLAG_RW,
230    &newnfs_commit_on_close, 0, "write+commit on close, else only write");
231
232static int      nfs_clean_pages_on_close = 1;
233SYSCTL_INT(_vfs_nfs, OID_AUTO, clean_pages_on_close, CTLFLAG_RW,
234           &nfs_clean_pages_on_close, 0, "NFS clean dirty pages on close");
235
236int newnfs_directio_enable = 0;
237SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_enable, CTLFLAG_RW,
238           &newnfs_directio_enable, 0, "Enable NFS directio");
239
240int nfs_keep_dirty_on_error;
241SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_keep_dirty_on_error, CTLFLAG_RW,
242    &nfs_keep_dirty_on_error, 0, "Retry pageout if error returned");
243
244/*
245 * This sysctl allows other processes to mmap a file that has been opened
246 * O_DIRECT by a process.  In general, having processes mmap the file while
247 * Direct IO is in progress can lead to Data Inconsistencies.  But, we allow
248 * this by default to prevent DoS attacks - to prevent a malicious user from
249 * opening up files O_DIRECT preventing other users from mmap'ing these
250 * files.  "Protected" environments where stricter consistency guarantees are
251 * required can disable this knob.  The process that opened the file O_DIRECT
252 * cannot mmap() the file, because mmap'ed IO on an O_DIRECT open() is not
253 * meaningful.
254 */
255int newnfs_directio_allow_mmap = 1;
256SYSCTL_INT(_vfs_nfs, OID_AUTO, nfs_directio_allow_mmap, CTLFLAG_RW,
257           &newnfs_directio_allow_mmap, 0, "Enable mmaped IO on file with O_DIRECT opens");
258
259#define NFSACCESS_ALL (NFSACCESS_READ | NFSACCESS_MODIFY                \
260                         | NFSACCESS_EXTEND | NFSACCESS_EXECUTE \
261                         | NFSACCESS_DELETE | NFSACCESS_LOOKUP)
262
263/*
264 * SMP Locking Note :
265 * The list of locks after the description of the lock is the ordering
266 * of other locks acquired with the lock held.
267 * np->n_mtx : Protects the fields in the nfsnode.
268       VM Object Lock
269       VI_MTX (acquired indirectly)
270 * nmp->nm_mtx : Protects the fields in the nfsmount.
271       rep->r_mtx
272 * ncl_iod_mutex : Global lock, protects shared nfsiod state.
273 * nfs_reqq_mtx : Global lock, protects the nfs_reqq list.
274       nmp->nm_mtx
275       rep->r_mtx
276 * rep->r_mtx : Protects the fields in an nfsreq.
277 */
278
279static int
280nfs_lock(struct vop_lock1_args *ap)
281{
282        struct vnode *vp;
283        struct nfsnode *np;
284        u_quad_t nsize;
285        int error, lktype;
286        bool onfault;
287
288        vp = ap->a_vp;
289        lktype = ap->a_flags & LK_TYPE_MASK;
290        error = VOP_LOCK1_APV(&default_vnodeops, ap);
291        if (error != 0 || vp->v_op != &newnfs_vnodeops)
292                return (error);
293        np = VTONFS(vp);
294        if (np == NULL)
295                return (0);
296        NFSLOCKNODE(np);
297        if ((np->n_flag & NVNSETSZSKIP) == 0 || (lktype != LK_SHARED &&
298            lktype != LK_EXCLUSIVE && lktype != LK_UPGRADE &&
299            lktype != LK_TRYUPGRADE)) {
300                NFSUNLOCKNODE(np);
301                return (0);
302        }
303        onfault = (ap->a_flags & LK_EATTR_MASK) == LK_NOWAIT &&
304            (ap->a_flags & LK_INIT_MASK) == LK_CANRECURSE &&
305            (lktype == LK_SHARED || lktype == LK_EXCLUSIVE);
306        if (onfault && vp->v_vnlock->lk_recurse == 0) {
307                /*
308                 * Force retry in vm_fault(), to make the lock request
309                 * sleepable, which allows us to piggy-back the
310                 * sleepable call to vnode_pager_setsize().
311                 */
312                NFSUNLOCKNODE(np);
313                VOP_UNLOCK(vp, 0);
314                return (EBUSY);
315        }
316        if ((ap->a_flags & LK_NOWAIT) != 0 ||
317            (lktype == LK_SHARED && vp->v_vnlock->lk_recurse > 0)) {
318                NFSUNLOCKNODE(np);
319                return (0);
320        }
321        if (lktype == LK_SHARED) {
322                NFSUNLOCKNODE(np);
323                VOP_UNLOCK(vp, 0);
324                ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
325                ap->a_flags |= LK_EXCLUSIVE;
326                error = VOP_LOCK1_APV(&default_vnodeops, ap);
327                if (error != 0 || vp->v_op != &newnfs_vnodeops)
328                        return (error);
329                if (vp->v_data == NULL)
330                        goto downgrade;
331                MPASS(vp->v_data == np);
332                NFSLOCKNODE(np);
333                if ((np->n_flag & NVNSETSZSKIP) == 0) {
334                        NFSUNLOCKNODE(np);
335                        goto downgrade;
336                }
337        }
338        np->n_flag &= ~NVNSETSZSKIP;
339        nsize = np->n_size;
340        NFSUNLOCKNODE(np);
[882425f]341#ifndef __rtems__
[6138f24]342        vnode_pager_setsize(vp, nsize);
[882425f]343#endif /* __rtems__ */
[6138f24]344downgrade:
345        if (lktype == LK_SHARED) {
346                ap->a_flags &= ~(LK_TYPE_MASK | LK_INTERLOCK);
347                ap->a_flags |= LK_DOWNGRADE;
348                (void)VOP_LOCK1_APV(&default_vnodeops, ap);
349        }
350        return (0);
351}
352
353static int
354nfs34_access_otw(struct vnode *vp, int wmode, struct thread *td,
355    struct ucred *cred, u_int32_t *retmode)
356{
357        int error = 0, attrflag, i, lrupos;
358        u_int32_t rmode;
359        struct nfsnode *np = VTONFS(vp);
360        struct nfsvattr nfsva;
361
362        error = nfsrpc_accessrpc(vp, wmode, cred, td, &nfsva, &attrflag,
363            &rmode, NULL);
364        if (attrflag)
365                (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
366        if (!error) {
367                lrupos = 0;
368                NFSLOCKNODE(np);
369                for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
370                        if (np->n_accesscache[i].uid == cred->cr_uid) {
371                                np->n_accesscache[i].mode = rmode;
372                                np->n_accesscache[i].stamp = time_second;
373                                break;
374                        }
375                        if (i > 0 && np->n_accesscache[i].stamp <
376                            np->n_accesscache[lrupos].stamp)
377                                lrupos = i;
378                }
379                if (i == NFS_ACCESSCACHESIZE) {
380                        np->n_accesscache[lrupos].uid = cred->cr_uid;
381                        np->n_accesscache[lrupos].mode = rmode;
382                        np->n_accesscache[lrupos].stamp = time_second;
383                }
384                NFSUNLOCKNODE(np);
385                if (retmode != NULL)
386                        *retmode = rmode;
387                KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, rmode, 0);
388        } else if (NFS_ISV4(vp)) {
389                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
390        }
391#ifdef KDTRACE_HOOKS
392        if (error != 0)
393                KDTRACE_NFS_ACCESSCACHE_LOAD_DONE(vp, cred->cr_uid, 0,
394                    error);
395#endif
396        return (error);
397}
398
399/*
400 * nfs access vnode op.
401 * For nfs version 2, just return ok. File accesses may fail later.
402 * For nfs version 3, use the access rpc to check accessibility. If file modes
403 * are changed on the server, accesses might still fail later.
404 */
405static int
406nfs_access(struct vop_access_args *ap)
407{
408        struct vnode *vp = ap->a_vp;
409        int error = 0, i, gotahit;
410        u_int32_t mode, wmode, rmode;
411        int v34 = NFS_ISV34(vp);
412        struct nfsnode *np = VTONFS(vp);
413
414        /*
415         * Disallow write attempts on filesystems mounted read-only;
416         * unless the file is a socket, fifo, or a block or character
417         * device resident on the filesystem.
418         */
419        if ((ap->a_accmode & (VWRITE | VAPPEND | VWRITE_NAMED_ATTRS |
420            VDELETE_CHILD | VWRITE_ATTRIBUTES | VDELETE | VWRITE_ACL |
421            VWRITE_OWNER)) != 0 && (vp->v_mount->mnt_flag & MNT_RDONLY) != 0) {
422                switch (vp->v_type) {
423                case VREG:
424                case VDIR:
425                case VLNK:
426                        return (EROFS);
427                default:
428                        break;
429                }
430        }
431        /*
432         * For nfs v3 or v4, check to see if we have done this recently, and if
433         * so return our cached result instead of making an ACCESS call.
434         * If not, do an access rpc, otherwise you are stuck emulating
435         * ufs_access() locally using the vattr. This may not be correct,
436         * since the server may apply other access criteria such as
437         * client uid-->server uid mapping that we do not know about.
438         */
439        if (v34) {
440                if (ap->a_accmode & VREAD)
441                        mode = NFSACCESS_READ;
442                else
443                        mode = 0;
444                if (vp->v_type != VDIR) {
445                        if (ap->a_accmode & VWRITE)
446                                mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND);
447                        if (ap->a_accmode & VAPPEND)
448                                mode |= NFSACCESS_EXTEND;
449                        if (ap->a_accmode & VEXEC)
450                                mode |= NFSACCESS_EXECUTE;
451                        if (ap->a_accmode & VDELETE)
452                                mode |= NFSACCESS_DELETE;
453                } else {
454                        if (ap->a_accmode & VWRITE)
455                                mode |= (NFSACCESS_MODIFY | NFSACCESS_EXTEND);
456                        if (ap->a_accmode & VAPPEND)
457                                mode |= NFSACCESS_EXTEND;
458                        if (ap->a_accmode & VEXEC)
459                                mode |= NFSACCESS_LOOKUP;
460                        if (ap->a_accmode & VDELETE)
461                                mode |= NFSACCESS_DELETE;
462                        if (ap->a_accmode & VDELETE_CHILD)
463                                mode |= NFSACCESS_MODIFY;
464                }
465                /* XXX safety belt, only make blanket request if caching */
466                if (nfsaccess_cache_timeout > 0) {
467                        wmode = NFSACCESS_READ | NFSACCESS_MODIFY |
468                                NFSACCESS_EXTEND | NFSACCESS_EXECUTE |
469                                NFSACCESS_DELETE | NFSACCESS_LOOKUP;
470                } else {
471                        wmode = mode;
472                }
473
474                /*
475                 * Does our cached result allow us to give a definite yes to
476                 * this request?
477                 */
478                gotahit = 0;
479                NFSLOCKNODE(np);
480                for (i = 0; i < NFS_ACCESSCACHESIZE; i++) {
481                        if (ap->a_cred->cr_uid == np->n_accesscache[i].uid) {
482                            if (time_second < (np->n_accesscache[i].stamp
483                                + nfsaccess_cache_timeout) &&
484                                (np->n_accesscache[i].mode & mode) == mode) {
485                                NFSINCRGLOBAL(nfsstatsv1.accesscache_hits);
486                                gotahit = 1;
487                            }
488                            break;
489                        }
490                }
491                NFSUNLOCKNODE(np);
492#ifdef KDTRACE_HOOKS
493                if (gotahit != 0)
494                        KDTRACE_NFS_ACCESSCACHE_GET_HIT(vp,
495                            ap->a_cred->cr_uid, mode);
496                else
497                        KDTRACE_NFS_ACCESSCACHE_GET_MISS(vp,
498                            ap->a_cred->cr_uid, mode);
499#endif
500                if (gotahit == 0) {
501                        /*
502                         * Either a no, or a don't know.  Go to the wire.
503                         */
504                        NFSINCRGLOBAL(nfsstatsv1.accesscache_misses);
505                        error = nfs34_access_otw(vp, wmode, ap->a_td,
506                            ap->a_cred, &rmode);
507                        if (!error &&
508                            (rmode & mode) != mode)
509                                error = EACCES;
510                }
511                return (error);
512        } else {
513                if ((error = nfsspec_access(ap)) != 0) {
514                        return (error);
515                }
516                /*
517                 * Attempt to prevent a mapped root from accessing a file
518                 * which it shouldn't.  We try to read a byte from the file
519                 * if the user is root and the file is not zero length.
520                 * After calling nfsspec_access, we should have the correct
521                 * file size cached.
522                 */
523                NFSLOCKNODE(np);
524                if (ap->a_cred->cr_uid == 0 && (ap->a_accmode & VREAD)
525                    && VTONFS(vp)->n_size > 0) {
526                        struct iovec aiov;
527                        struct uio auio;
528                        char buf[1];
529
530                        NFSUNLOCKNODE(np);
531                        aiov.iov_base = buf;
532                        aiov.iov_len = 1;
533                        auio.uio_iov = &aiov;
534                        auio.uio_iovcnt = 1;
535                        auio.uio_offset = 0;
536                        auio.uio_resid = 1;
537                        auio.uio_segflg = UIO_SYSSPACE;
538                        auio.uio_rw = UIO_READ;
539                        auio.uio_td = ap->a_td;
540
541                        if (vp->v_type == VREG)
542                                error = ncl_readrpc(vp, &auio, ap->a_cred);
543                        else if (vp->v_type == VDIR) {
544                                char* bp;
545                                bp = malloc(NFS_DIRBLKSIZ, M_TEMP, M_WAITOK);
546                                aiov.iov_base = bp;
547                                aiov.iov_len = auio.uio_resid = NFS_DIRBLKSIZ;
548                                error = ncl_readdirrpc(vp, &auio, ap->a_cred,
549                                    ap->a_td);
550                                free(bp, M_TEMP);
551                        } else if (vp->v_type == VLNK)
552                                error = ncl_readlinkrpc(vp, &auio, ap->a_cred);
553                        else
554                                error = EACCES;
555                } else
556                        NFSUNLOCKNODE(np);
557                return (error);
558        }
559}
560
561
562/*
563 * nfs open vnode op
564 * Check to see if the type is ok
565 * and that deletion is not in progress.
566 * For paged in text files, you will need to flush the page cache
567 * if consistency is lost.
568 */
569/* ARGSUSED */
570static int
571nfs_open(struct vop_open_args *ap)
572{
573        struct vnode *vp = ap->a_vp;
574        struct nfsnode *np = VTONFS(vp);
575        struct vattr vattr;
576        int error;
577        int fmode = ap->a_mode;
578        struct ucred *cred;
579        vm_object_t obj;
580
581        if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
582                return (EOPNOTSUPP);
583
584        /*
585         * For NFSv4, we need to do the Open Op before cache validation,
586         * so that we conform to RFC3530 Sec. 9.3.1.
587         */
588        if (NFS_ISV4(vp)) {
589                error = nfsrpc_open(vp, fmode, ap->a_cred, ap->a_td);
590                if (error) {
591                        error = nfscl_maperr(ap->a_td, error, (uid_t)0,
592                            (gid_t)0);
593                        return (error);
594                }
595        }
596
597        /*
598         * Now, if this Open will be doing reading, re-validate/flush the
599         * cache, so that Close/Open coherency is maintained.
600         */
601        NFSLOCKNODE(np);
602        if (np->n_flag & NMODIFIED) {
603                NFSUNLOCKNODE(np);
604                error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
605                if (error == EINTR || error == EIO) {
606                        if (NFS_ISV4(vp))
607                                (void) nfsrpc_close(vp, 0, ap->a_td);
608                        return (error);
609                }
610                NFSLOCKNODE(np);
611                np->n_attrstamp = 0;
612                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
613                if (vp->v_type == VDIR)
614                        np->n_direofoffset = 0;
615                NFSUNLOCKNODE(np);
616                error = VOP_GETATTR(vp, &vattr, ap->a_cred);
617                if (error) {
618                        if (NFS_ISV4(vp))
619                                (void) nfsrpc_close(vp, 0, ap->a_td);
620                        return (error);
621                }
622                NFSLOCKNODE(np);
623                np->n_mtime = vattr.va_mtime;
624                if (NFS_ISV4(vp))
625                        np->n_change = vattr.va_filerev;
626        } else {
627                NFSUNLOCKNODE(np);
628                error = VOP_GETATTR(vp, &vattr, ap->a_cred);
629                if (error) {
630                        if (NFS_ISV4(vp))
631                                (void) nfsrpc_close(vp, 0, ap->a_td);
632                        return (error);
633                }
634                NFSLOCKNODE(np);
635                if ((NFS_ISV4(vp) && np->n_change != vattr.va_filerev) ||
636                    NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
637                        if (vp->v_type == VDIR)
638                                np->n_direofoffset = 0;
639                        NFSUNLOCKNODE(np);
640                        error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
641                        if (error == EINTR || error == EIO) {
642                                if (NFS_ISV4(vp))
643                                        (void) nfsrpc_close(vp, 0, ap->a_td);
644                                return (error);
645                        }
646                        NFSLOCKNODE(np);
647                        np->n_mtime = vattr.va_mtime;
648                        if (NFS_ISV4(vp))
649                                np->n_change = vattr.va_filerev;
650                }
651        }
652
653        /*
654         * If the object has >= 1 O_DIRECT active opens, we disable caching.
655         */
656        if (newnfs_directio_enable && (fmode & O_DIRECT) &&
657            (vp->v_type == VREG)) {
658                if (np->n_directio_opens == 0) {
659                        NFSUNLOCKNODE(np);
660                        error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
661                        if (error) {
662                                if (NFS_ISV4(vp))
663                                        (void) nfsrpc_close(vp, 0, ap->a_td);
664                                return (error);
665                        }
666                        NFSLOCKNODE(np);
667                        np->n_flag |= NNONCACHE;
668                }
669                np->n_directio_opens++;
670        }
671
672        /* If opened for writing via NFSv4.1 or later, mark that for pNFS. */
673        if (NFSHASPNFS(VFSTONFS(vp->v_mount)) && (fmode & FWRITE) != 0)
674                np->n_flag |= NWRITEOPENED;
675
676        /*
677         * If this is an open for writing, capture a reference to the
678         * credentials, so they can be used by ncl_putpages(). Using
679         * these write credentials is preferable to the credentials of
680         * whatever thread happens to be doing the VOP_PUTPAGES() since
681         * the write RPCs are less likely to fail with EACCES.
682         */
683        if ((fmode & FWRITE) != 0) {
684                cred = np->n_writecred;
685                np->n_writecred = crhold(ap->a_cred);
686        } else
687                cred = NULL;
688        NFSUNLOCKNODE(np);
689
690        if (cred != NULL)
691                crfree(cred);
[882425f]692#ifndef __rtems__
[6138f24]693        vnode_create_vobject(vp, vattr.va_size, ap->a_td);
[882425f]694#endif /* __rtems__ */
[6138f24]695
696        /*
697         * If the text file has been mmap'd, flush any dirty pages to the
698         * buffer cache and then...
699         * Make sure all writes are pushed to the NFS server.  If this is not
700         * done, the modify time of the file can change while the text
701         * file is being executed.  This will cause the process that is
702         * executing the text file to be terminated.
703         */
704        if (vp->v_writecount <= -1) {
[882425f]705#ifndef __rtems__
[6138f24]706                if ((obj = vp->v_object) != NULL &&
707                    (obj->flags & OBJ_MIGHTBEDIRTY) != 0) {
708                        VM_OBJECT_WLOCK(obj);
709                        vm_object_page_clean(obj, 0, 0, OBJPC_SYNC);
710                        VM_OBJECT_WUNLOCK(obj);
711                }
[882425f]712#endif /* __rtems__ */
[6138f24]713
714                /* Now, flush the buffer cache. */
715                ncl_flush(vp, MNT_WAIT, curthread, 0, 0);
716
717                /* And, finally, make sure that n_mtime is up to date. */
718                np = VTONFS(vp);
719                NFSLOCKNODE(np);
720                np->n_mtime = np->n_vattr.na_mtime;
721                NFSUNLOCKNODE(np);
722        }
723        return (0);
724}
725
726/*
727 * nfs close vnode op
728 * What an NFS client should do upon close after writing is a debatable issue.
729 * Most NFS clients push delayed writes to the server upon close, basically for
730 * two reasons:
731 * 1 - So that any write errors may be reported back to the client process
732 *     doing the close system call. By far the two most likely errors are
733 *     NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure.
734 * 2 - To put a worst case upper bound on cache inconsistency between
735 *     multiple clients for the file.
736 * There is also a consistency problem for Version 2 of the protocol w.r.t.
737 * not being able to tell if other clients are writing a file concurrently,
738 * since there is no way of knowing if the changed modify time in the reply
739 * is only due to the write for this client.
740 * (NFS Version 3 provides weak cache consistency data in the reply that
741 *  should be sufficient to detect and handle this case.)
742 *
743 * The current code does the following:
744 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers
745 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate
746 *                     or commit them (this satisfies 1 and 2 except for the
747 *                     case where the server crashes after this close but
748 *                     before the commit RPC, which is felt to be "good
749 *                     enough". Changing the last argument to ncl_flush() to
750 *                     a 1 would force a commit operation, if it is felt a
751 *                     commit is necessary now.
752 * for NFS Version 4 - flush the dirty buffers and commit them, if
753 *                     nfscl_mustflush() says this is necessary.
754 *                     It is necessary if there is no write delegation held,
755 *                     in order to satisfy open/close coherency.
756 *                     If the file isn't cached on local stable storage,
757 *                     it may be necessary in order to detect "out of space"
758 *                     errors from the server, if the write delegation
759 *                     issued by the server doesn't allow the file to grow.
760 */
761/* ARGSUSED */
762static int
763nfs_close(struct vop_close_args *ap)
764{
765        struct vnode *vp = ap->a_vp;
766        struct nfsnode *np = VTONFS(vp);
767        struct nfsvattr nfsva;
768        struct ucred *cred;
769        int error = 0, ret, localcred = 0;
770        int fmode = ap->a_fflag;
771
772        if (NFSCL_FORCEDISM(vp->v_mount))
773                return (0);
774        /*
775         * During shutdown, a_cred isn't valid, so just use root.
776         */
777        if (ap->a_cred == NOCRED) {
778                cred = newnfs_getcred();
779                localcred = 1;
780        } else {
781                cred = ap->a_cred;
782        }
783        if (vp->v_type == VREG) {
784            /*
785             * Examine and clean dirty pages, regardless of NMODIFIED.
786             * This closes a major hole in close-to-open consistency.
787             * We want to push out all dirty pages (and buffers) on
788             * close, regardless of whether they were dirtied by
789             * mmap'ed writes or via write().
790             */
[882425f]791#ifndef __rtems__
[6138f24]792            if (nfs_clean_pages_on_close && vp->v_object) {
793                VM_OBJECT_WLOCK(vp->v_object);
794                vm_object_page_clean(vp->v_object, 0, 0, 0);
795                VM_OBJECT_WUNLOCK(vp->v_object);
796            }
[882425f]797#endif /* __rtems__ */
[6138f24]798            NFSLOCKNODE(np);
799            if (np->n_flag & NMODIFIED) {
800                NFSUNLOCKNODE(np);
801                if (NFS_ISV3(vp)) {
802                    /*
803                     * Under NFSv3 we have dirty buffers to dispose of.  We
804                     * must flush them to the NFS server.  We have the option
805                     * of waiting all the way through the commit rpc or just
806                     * waiting for the initial write.  The default is to only
807                     * wait through the initial write so the data is in the
808                     * server's cache, which is roughly similar to the state
809                     * a standard disk subsystem leaves the file in on close().
810                     *
811                     * We cannot clear the NMODIFIED bit in np->n_flag due to
812                     * potential races with other processes, and certainly
813                     * cannot clear it if we don't commit.
814                     * These races occur when there is no longer the old
815                     * traditional vnode locking implemented for Vnode Ops.
816                     */
817                    int cm = newnfs_commit_on_close ? 1 : 0;
818                    error = ncl_flush(vp, MNT_WAIT, ap->a_td, cm, 0);
819                    /* np->n_flag &= ~NMODIFIED; */
[6e4709b]820                } else if (NFS_ISV4(vp)) {
[6138f24]821                        if (nfscl_mustflush(vp) != 0) {
822                                int cm = newnfs_commit_on_close ? 1 : 0;
823                                error = ncl_flush(vp, MNT_WAIT, ap->a_td,
824                                    cm, 0);
825                                /*
826                                 * as above w.r.t races when clearing
827                                 * NMODIFIED.
828                                 * np->n_flag &= ~NMODIFIED;
829                                 */
830                        }
831                } else {
832                        error = ncl_vinvalbuf(vp, V_SAVE, ap->a_td, 1);
833                }
834                NFSLOCKNODE(np);
835            }
[6e4709b]836            /*
[6138f24]837             * Invalidate the attribute cache in all cases.
838             * An open is going to fetch fresh attrs any way, other procs
[6e4709b]839             * on this node that have file open will be forced to do an
[6138f24]840             * otw attr fetch, but this is safe.
841             * --> A user found that their RPC count dropped by 20% when
842             *     this was commented out and I can't see any requirement
843             *     for it, so I've disabled it when negative lookups are
844             *     enabled. (What does this have to do with negative lookup
845             *     caching? Well nothing, except it was reported by the
846             *     same user that needed negative lookup caching and I wanted
847             *     there to be a way to disable it to see if it
848             *     is the cause of some caching/coherency issue that might
849             *     crop up.)
850             */
851            if (VFSTONFS(vp->v_mount)->nm_negnametimeo == 0) {
852                    np->n_attrstamp = 0;
853                    KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
854            }
855            if (np->n_flag & NWRITEERR) {
856                np->n_flag &= ~NWRITEERR;
857                error = np->n_error;
858            }
859            NFSUNLOCKNODE(np);
860        }
861
862        if (NFS_ISV4(vp)) {
863                /*
864                 * Get attributes so "change" is up to date.
865                 */
866                if (error == 0 && nfscl_mustflush(vp) != 0 &&
867                    vp->v_type == VREG &&
868                    (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOCTO) == 0) {
869                        ret = nfsrpc_getattr(vp, cred, ap->a_td, &nfsva,
870                            NULL);
871                        if (!ret) {
872                                np->n_change = nfsva.na_filerev;
873                                (void) nfscl_loadattrcache(&vp, &nfsva, NULL,
874                                    NULL, 0, 0);
875                        }
876                }
877
878                /*
879                 * and do the close.
880                 */
881                ret = nfsrpc_close(vp, 0, ap->a_td);
882                if (!error && ret)
883                        error = ret;
884                if (error)
885                        error = nfscl_maperr(ap->a_td, error, (uid_t)0,
886                            (gid_t)0);
887        }
888        if (newnfs_directio_enable)
889                KASSERT((np->n_directio_asyncwr == 0),
890                        ("nfs_close: dirty unflushed (%d) directio buffers\n",
891                         np->n_directio_asyncwr));
892        if (newnfs_directio_enable && (fmode & O_DIRECT) && (vp->v_type == VREG)) {
893                NFSLOCKNODE(np);
[6e4709b]894                KASSERT((np->n_directio_opens > 0),
[6138f24]895                        ("nfs_close: unexpectedly value (0) of n_directio_opens\n"));
896                np->n_directio_opens--;
897                if (np->n_directio_opens == 0)
898                        np->n_flag &= ~NNONCACHE;
899                NFSUNLOCKNODE(np);
900        }
901        if (localcred)
902                NFSFREECRED(cred);
903        return (error);
904}
905
906/*
907 * nfs getattr call from vfs.
908 */
909static int
910nfs_getattr(struct vop_getattr_args *ap)
911{
912        struct vnode *vp = ap->a_vp;
913        struct thread *td = curthread;  /* XXX */
914        struct nfsnode *np = VTONFS(vp);
915        int error = 0;
916        struct nfsvattr nfsva;
917        struct vattr *vap = ap->a_vap;
918        struct vattr vattr;
919
920        /*
921         * Update local times for special files.
922         */
923        NFSLOCKNODE(np);
924        if (np->n_flag & (NACC | NUPD))
925                np->n_flag |= NCHG;
926        NFSUNLOCKNODE(np);
927        /*
928         * First look in the cache.
929         */
930        if (ncl_getattrcache(vp, &vattr) == 0) {
931                vap->va_type = vattr.va_type;
932                vap->va_mode = vattr.va_mode;
933                vap->va_nlink = vattr.va_nlink;
934                vap->va_uid = vattr.va_uid;
935                vap->va_gid = vattr.va_gid;
936                vap->va_fsid = vattr.va_fsid;
937                vap->va_fileid = vattr.va_fileid;
938                vap->va_size = vattr.va_size;
939                vap->va_blocksize = vattr.va_blocksize;
940                vap->va_atime = vattr.va_atime;
941                vap->va_mtime = vattr.va_mtime;
942                vap->va_ctime = vattr.va_ctime;
943                vap->va_gen = vattr.va_gen;
944                vap->va_flags = vattr.va_flags;
945                vap->va_rdev = vattr.va_rdev;
946                vap->va_bytes = vattr.va_bytes;
947                vap->va_filerev = vattr.va_filerev;
948                /*
949                 * Get the local modify time for the case of a write
950                 * delegation.
951                 */
952                nfscl_deleggetmodtime(vp, &vap->va_mtime);
953                return (0);
954        }
955
956        if (NFS_ISV34(vp) && nfs_prime_access_cache &&
957            nfsaccess_cache_timeout > 0) {
958                NFSINCRGLOBAL(nfsstatsv1.accesscache_misses);
959                nfs34_access_otw(vp, NFSACCESS_ALL, td, ap->a_cred, NULL);
960                if (ncl_getattrcache(vp, ap->a_vap) == 0) {
961                        nfscl_deleggetmodtime(vp, &ap->a_vap->va_mtime);
962                        return (0);
963                }
964        }
965        error = nfsrpc_getattr(vp, ap->a_cred, td, &nfsva, NULL);
966        if (!error)
967                error = nfscl_loadattrcache(&vp, &nfsva, vap, NULL, 0, 0);
968        if (!error) {
969                /*
970                 * Get the local modify time for the case of a write
971                 * delegation.
972                 */
973                nfscl_deleggetmodtime(vp, &vap->va_mtime);
974        } else if (NFS_ISV4(vp)) {
975                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
976        }
977        return (error);
978}
979
980/*
981 * nfs setattr call.
982 */
983static int
984nfs_setattr(struct vop_setattr_args *ap)
985{
986        struct vnode *vp = ap->a_vp;
987        struct nfsnode *np = VTONFS(vp);
988        struct thread *td = curthread;  /* XXX */
989        struct vattr *vap = ap->a_vap;
990        int error = 0;
991        u_quad_t tsize;
992
993#ifndef nolint
994        tsize = (u_quad_t)0;
995#endif
996
997        /*
998         * Setting of flags and marking of atimes are not supported.
999         */
1000        if (vap->va_flags != VNOVAL)
1001                return (EOPNOTSUPP);
1002
1003        /*
1004         * Disallow write attempts if the filesystem is mounted read-only.
1005         */
1006        if ((vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL ||
1007            vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL ||
1008            vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) &&
1009            (vp->v_mount->mnt_flag & MNT_RDONLY))
1010                return (EROFS);
1011        if (vap->va_size != VNOVAL) {
1012                switch (vp->v_type) {
1013                case VDIR:
1014                        return (EISDIR);
1015                case VCHR:
1016                case VBLK:
1017                case VSOCK:
1018                case VFIFO:
1019                        if (vap->va_mtime.tv_sec == VNOVAL &&
1020                            vap->va_atime.tv_sec == VNOVAL &&
1021                            vap->va_mode == (mode_t)VNOVAL &&
1022                            vap->va_uid == (uid_t)VNOVAL &&
1023                            vap->va_gid == (gid_t)VNOVAL)
[6e4709b]1024                                return (0);             
[6138f24]1025                        vap->va_size = VNOVAL;
1026                        break;
1027                default:
1028                        /*
1029                         * Disallow write attempts if the filesystem is
1030                         * mounted read-only.
1031                         */
1032                        if (vp->v_mount->mnt_flag & MNT_RDONLY)
1033                                return (EROFS);
1034                        /*
1035                         *  We run vnode_pager_setsize() early (why?),
1036                         * we must set np->n_size now to avoid vinvalbuf
1037                         * V_SAVE races that might setsize a lower
1038                         * value.
1039                         */
1040                        NFSLOCKNODE(np);
1041                        tsize = np->n_size;
1042                        NFSUNLOCKNODE(np);
1043                        error = ncl_meta_setsize(vp, td, vap->va_size);
1044                        NFSLOCKNODE(np);
1045                        if (np->n_flag & NMODIFIED) {
1046                            tsize = np->n_size;
1047                            NFSUNLOCKNODE(np);
1048                            error = ncl_vinvalbuf(vp, vap->va_size == 0 ?
1049                                0 : V_SAVE, td, 1);
1050                            if (error != 0) {
[882425f]1051#ifndef __rtems__
[6138f24]1052                                    vnode_pager_setsize(vp, tsize);
[882425f]1053#endif /* __rtems__ */
[6138f24]1054                                    return (error);
1055                            }
1056                            /*
1057                             * Call nfscl_delegmodtime() to set the modify time
1058                             * locally, as required.
1059                             */
1060                            nfscl_delegmodtime(vp);
1061                        } else
1062                            NFSUNLOCKNODE(np);
1063                        /*
1064                         * np->n_size has already been set to vap->va_size
1065                         * in ncl_meta_setsize(). We must set it again since
1066                         * nfs_loadattrcache() could be called through
1067                         * ncl_meta_setsize() and could modify np->n_size.
1068                         */
1069                        NFSLOCKNODE(np);
1070                        np->n_vattr.na_size = np->n_size = vap->va_size;
1071                        NFSUNLOCKNODE(np);
1072                }
1073        } else {
1074                NFSLOCKNODE(np);
[6e4709b]1075                if ((vap->va_mtime.tv_sec != VNOVAL || vap->va_atime.tv_sec != VNOVAL) &&
[6138f24]1076                    (np->n_flag & NMODIFIED) && vp->v_type == VREG) {
1077                        NFSUNLOCKNODE(np);
1078                        error = ncl_vinvalbuf(vp, V_SAVE, td, 1);
1079                        if (error == EINTR || error == EIO)
1080                                return (error);
1081                } else
1082                        NFSUNLOCKNODE(np);
1083        }
1084        error = nfs_setattrrpc(vp, vap, ap->a_cred, td);
1085        if (error && vap->va_size != VNOVAL) {
1086                NFSLOCKNODE(np);
1087                np->n_size = np->n_vattr.na_size = tsize;
[882425f]1088#ifndef __rtems__
[6138f24]1089                vnode_pager_setsize(vp, tsize);
[882425f]1090#endif /* __rtems__ */
[6138f24]1091                NFSUNLOCKNODE(np);
1092        }
1093        return (error);
1094}
1095
1096/*
1097 * Do an nfs setattr rpc.
1098 */
1099static int
1100nfs_setattrrpc(struct vnode *vp, struct vattr *vap, struct ucred *cred,
1101    struct thread *td)
1102{
1103        struct nfsnode *np = VTONFS(vp);
1104        int error, ret, attrflag, i;
1105        struct nfsvattr nfsva;
1106
1107        if (NFS_ISV34(vp)) {
1108                NFSLOCKNODE(np);
1109                for (i = 0; i < NFS_ACCESSCACHESIZE; i++)
1110                        np->n_accesscache[i].stamp = 0;
1111                np->n_flag |= NDELEGMOD;
1112                NFSUNLOCKNODE(np);
1113                KDTRACE_NFS_ACCESSCACHE_FLUSH_DONE(vp);
1114        }
1115        error = nfsrpc_setattr(vp, vap, NULL, cred, td, &nfsva, &attrflag,
1116            NULL);
1117        if (attrflag) {
1118                ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
1119                if (ret && !error)
1120                        error = ret;
1121        }
1122        if (error && NFS_ISV4(vp))
1123                error = nfscl_maperr(td, error, vap->va_uid, vap->va_gid);
1124        return (error);
1125}
1126
1127/*
1128 * nfs lookup call, one step at a time...
1129 * First look in cache
1130 * If not found, unlock the directory nfsnode and do the rpc
1131 */
1132static int
1133nfs_lookup(struct vop_lookup_args *ap)
1134{
1135        struct componentname *cnp = ap->a_cnp;
1136        struct vnode *dvp = ap->a_dvp;
1137        struct vnode **vpp = ap->a_vpp;
1138        struct mount *mp = dvp->v_mount;
1139        int flags = cnp->cn_flags;
1140        struct vnode *newvp;
1141        struct nfsmount *nmp;
1142        struct nfsnode *np, *newnp;
1143        int error = 0, attrflag, dattrflag, ltype, ncticks;
1144        struct thread *td = cnp->cn_thread;
1145        struct nfsfh *nfhp;
1146        struct nfsvattr dnfsva, nfsva;
1147        struct vattr vattr;
1148        struct timespec nctime;
[6e4709b]1149       
[6138f24]1150        *vpp = NULLVP;
1151        if ((flags & ISLASTCN) && (mp->mnt_flag & MNT_RDONLY) &&
1152            (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
1153                return (EROFS);
1154        if (dvp->v_type != VDIR)
1155                return (ENOTDIR);
1156        nmp = VFSTONFS(mp);
1157        np = VTONFS(dvp);
1158
1159        /* For NFSv4, wait until any remove is done. */
1160        NFSLOCKNODE(np);
1161        while (NFSHASNFSV4(nmp) && (np->n_flag & NREMOVEINPROG)) {
1162                np->n_flag |= NREMOVEWANT;
1163                (void) msleep((caddr_t)np, &np->n_mtx, PZERO, "nfslkup", 0);
1164        }
1165        NFSUNLOCKNODE(np);
1166
1167        error = vn_dir_check_exec(dvp, cnp);
1168        if (error != 0)
1169                return (error);
1170        error = cache_lookup(dvp, vpp, cnp, &nctime, &ncticks);
1171        if (error > 0 && error != ENOENT)
1172                return (error);
1173        if (error == -1) {
1174                /*
1175                 * Lookups of "." are special and always return the
1176                 * current directory.  cache_lookup() already handles
1177                 * associated locking bookkeeping, etc.
1178                 */
1179                if (cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
1180                        /* XXX: Is this really correct? */
1181                        if (cnp->cn_nameiop != LOOKUP &&
1182                            (flags & ISLASTCN))
1183                                cnp->cn_flags |= SAVENAME;
1184                        return (0);
1185                }
1186
1187                /*
1188                 * We only accept a positive hit in the cache if the
1189                 * change time of the file matches our cached copy.
1190                 * Otherwise, we discard the cache entry and fallback
1191                 * to doing a lookup RPC.  We also only trust cache
1192                 * entries for less than nm_nametimeo seconds.
1193                 *
1194                 * To better handle stale file handles and attributes,
1195                 * clear the attribute cache of this node if it is a
1196                 * leaf component, part of an open() call, and not
1197                 * locally modified before fetching the attributes.
1198                 * This should allow stale file handles to be detected
1199                 * here where we can fall back to a LOOKUP RPC to
1200                 * recover rather than having nfs_open() detect the
1201                 * stale file handle and failing open(2) with ESTALE.
1202                 */
1203                newvp = *vpp;
1204                newnp = VTONFS(newvp);
1205                if (!(nmp->nm_flag & NFSMNT_NOCTO) &&
1206                    (flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
1207                    !(newnp->n_flag & NMODIFIED)) {
1208                        NFSLOCKNODE(newnp);
1209                        newnp->n_attrstamp = 0;
1210                        KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1211                        NFSUNLOCKNODE(newnp);
1212                }
1213                if (nfscl_nodeleg(newvp, 0) == 0 ||
1214                    ((u_int)(ticks - ncticks) < (nmp->nm_nametimeo * hz) &&
1215                    VOP_GETATTR(newvp, &vattr, cnp->cn_cred) == 0 &&
1216                    timespeccmp(&vattr.va_ctime, &nctime, ==))) {
1217                        NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits);
1218                        if (cnp->cn_nameiop != LOOKUP &&
1219                            (flags & ISLASTCN))
1220                                cnp->cn_flags |= SAVENAME;
1221                        return (0);
1222                }
1223                cache_purge(newvp);
1224                if (dvp != newvp)
1225                        vput(newvp);
[6e4709b]1226                else
[6138f24]1227                        vrele(newvp);
1228                *vpp = NULLVP;
1229        } else if (error == ENOENT) {
1230                if (dvp->v_iflag & VI_DOOMED)
1231                        return (ENOENT);
1232                /*
1233                 * We only accept a negative hit in the cache if the
1234                 * modification time of the parent directory matches
1235                 * the cached copy in the name cache entry.
1236                 * Otherwise, we discard all of the negative cache
1237                 * entries for this directory.  We also only trust
1238                 * negative cache entries for up to nm_negnametimeo
1239                 * seconds.
1240                 */
1241                if ((u_int)(ticks - ncticks) < (nmp->nm_negnametimeo * hz) &&
1242                    VOP_GETATTR(dvp, &vattr, cnp->cn_cred) == 0 &&
1243                    timespeccmp(&vattr.va_mtime, &nctime, ==)) {
1244                        NFSINCRGLOBAL(nfsstatsv1.lookupcache_hits);
1245                        return (ENOENT);
1246                }
1247                cache_purge_negative(dvp);
1248        }
1249
1250        error = 0;
1251        newvp = NULLVP;
1252        NFSINCRGLOBAL(nfsstatsv1.lookupcache_misses);
1253        error = nfsrpc_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
1254            cnp->cn_cred, td, &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
1255            NULL);
1256        if (dattrflag)
1257                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
1258        if (error) {
1259                if (newvp != NULLVP) {
1260                        vput(newvp);
1261                        *vpp = NULLVP;
1262                }
1263
1264                if (error != ENOENT) {
1265                        if (NFS_ISV4(dvp))
1266                                error = nfscl_maperr(td, error, (uid_t)0,
1267                                    (gid_t)0);
1268                        return (error);
1269                }
1270
1271                /* The requested file was not found. */
1272                if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) &&
1273                    (flags & ISLASTCN)) {
1274                        /*
1275                         * XXX: UFS does a full VOP_ACCESS(dvp,
1276                         * VWRITE) here instead of just checking
1277                         * MNT_RDONLY.
1278                         */
1279                        if (mp->mnt_flag & MNT_RDONLY)
1280                                return (EROFS);
1281                        cnp->cn_flags |= SAVENAME;
1282                        return (EJUSTRETURN);
1283                }
1284
1285                if ((cnp->cn_flags & MAKEENTRY) != 0 && dattrflag) {
1286                        /*
1287                         * Cache the modification time of the parent
1288                         * directory from the post-op attributes in
1289                         * the name cache entry.  The negative cache
1290                         * entry will be ignored once the directory
1291                         * has changed.  Don't bother adding the entry
1292                         * if the directory has already changed.
1293                         */
1294                        NFSLOCKNODE(np);
1295                        if (timespeccmp(&np->n_vattr.na_mtime,
1296                            &dnfsva.na_mtime, ==)) {
1297                                NFSUNLOCKNODE(np);
1298                                cache_enter_time(dvp, NULL, cnp,
1299                                    &dnfsva.na_mtime, NULL);
1300                        } else
1301                                NFSUNLOCKNODE(np);
1302                }
1303                return (ENOENT);
1304        }
1305
1306        /*
1307         * Handle RENAME case...
1308         */
1309        if (cnp->cn_nameiop == RENAME && (flags & ISLASTCN)) {
1310                if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) {
1311                        free(nfhp, M_NFSFH);
1312                        return (EISDIR);
1313                }
1314                error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL,
1315                    LK_EXCLUSIVE);
1316                if (error)
1317                        return (error);
1318                newvp = NFSTOV(np);
1319                if (attrflag)
1320                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1321                            0, 1);
1322                *vpp = newvp;
1323                cnp->cn_flags |= SAVENAME;
1324                return (0);
1325        }
1326
1327        if (flags & ISDOTDOT) {
1328                ltype = NFSVOPISLOCKED(dvp);
1329                error = vfs_busy(mp, MBF_NOWAIT);
1330                if (error != 0) {
1331                        vfs_ref(mp);
1332                        NFSVOPUNLOCK(dvp, 0);
1333                        error = vfs_busy(mp, 0);
1334                        NFSVOPLOCK(dvp, ltype | LK_RETRY);
1335                        vfs_rel(mp);
1336                        if (error == 0 && (dvp->v_iflag & VI_DOOMED)) {
1337                                vfs_unbusy(mp);
1338                                error = ENOENT;
1339                        }
1340                        if (error != 0)
1341                                return (error);
1342                }
1343                NFSVOPUNLOCK(dvp, 0);
1344                error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL,
1345                    cnp->cn_lkflags);
1346                if (error == 0)
1347                        newvp = NFSTOV(np);
1348                vfs_unbusy(mp);
1349                if (newvp != dvp)
1350                        NFSVOPLOCK(dvp, ltype | LK_RETRY);
1351                if (dvp->v_iflag & VI_DOOMED) {
1352                        if (error == 0) {
1353                                if (newvp == dvp)
1354                                        vrele(newvp);
1355                                else
1356                                        vput(newvp);
1357                        }
1358                        error = ENOENT;
1359                }
1360                if (error != 0)
1361                        return (error);
1362                if (attrflag)
1363                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1364                            0, 1);
1365        } else if (NFS_CMPFH(np, nfhp->nfh_fh, nfhp->nfh_len)) {
1366                free(nfhp, M_NFSFH);
1367                VREF(dvp);
1368                newvp = dvp;
1369                if (attrflag)
1370                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1371                            0, 1);
1372        } else {
1373                error = nfscl_nget(mp, dvp, nfhp, cnp, td, &np, NULL,
1374                    cnp->cn_lkflags);
1375                if (error)
1376                        return (error);
1377                newvp = NFSTOV(np);
1378                if (attrflag)
1379                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1380                            0, 1);
1381                else if ((flags & (ISLASTCN | ISOPEN)) == (ISLASTCN | ISOPEN) &&
[6e4709b]1382                    !(np->n_flag & NMODIFIED)) {                       
[6138f24]1383                        /*
1384                         * Flush the attribute cache when opening a
1385                         * leaf node to ensure that fresh attributes
1386                         * are fetched in nfs_open() since we did not
1387                         * fetch attributes from the LOOKUP reply.
1388                         */
1389                        NFSLOCKNODE(np);
1390                        np->n_attrstamp = 0;
1391                        KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(newvp);
1392                        NFSUNLOCKNODE(np);
1393                }
1394        }
1395        if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN))
1396                cnp->cn_flags |= SAVENAME;
1397        if ((cnp->cn_flags & MAKEENTRY) &&
1398            (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)) &&
1399            attrflag != 0 && (newvp->v_type != VDIR || dattrflag != 0))
1400                cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
1401                    newvp->v_type != VDIR ? NULL : &dnfsva.na_ctime);
1402        *vpp = newvp;
1403        return (0);
1404}
1405
1406/*
1407 * nfs read call.
1408 * Just call ncl_bioread() to do the work.
1409 */
1410static int
1411nfs_read(struct vop_read_args *ap)
1412{
1413        struct vnode *vp = ap->a_vp;
1414
1415        switch (vp->v_type) {
1416        case VREG:
1417                return (ncl_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred));
1418        case VDIR:
1419                return (EISDIR);
1420        default:
1421                return (EOPNOTSUPP);
1422        }
1423}
1424
1425/*
1426 * nfs readlink call
1427 */
1428static int
1429nfs_readlink(struct vop_readlink_args *ap)
1430{
1431        struct vnode *vp = ap->a_vp;
1432
1433        if (vp->v_type != VLNK)
1434                return (EINVAL);
1435        return (ncl_bioread(vp, ap->a_uio, 0, ap->a_cred));
1436}
1437
1438/*
1439 * Do a readlink rpc.
1440 * Called by ncl_doio() from below the buffer cache.
1441 */
1442int
1443ncl_readlinkrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
1444{
1445        int error, ret, attrflag;
1446        struct nfsvattr nfsva;
1447
1448        error = nfsrpc_readlink(vp, uiop, cred, uiop->uio_td, &nfsva,
1449            &attrflag, NULL);
1450        if (attrflag) {
1451                ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
1452                if (ret && !error)
1453                        error = ret;
1454        }
1455        if (error && NFS_ISV4(vp))
1456                error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0);
1457        return (error);
1458}
1459
1460/*
1461 * nfs read rpc call
1462 * Ditto above
1463 */
1464int
1465ncl_readrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred)
1466{
1467        int error, ret, attrflag;
1468        struct nfsvattr nfsva;
1469        struct nfsmount *nmp;
1470
1471        nmp = VFSTONFS(vnode_mount(vp));
1472        error = EIO;
1473        attrflag = 0;
1474        if (NFSHASPNFS(nmp))
1475                error = nfscl_doiods(vp, uiop, NULL, NULL,
1476                    NFSV4OPEN_ACCESSREAD, 0, cred, uiop->uio_td);
1477        NFSCL_DEBUG(4, "readrpc: aft doiods=%d\n", error);
1478        if (error != 0)
1479                error = nfsrpc_read(vp, uiop, cred, uiop->uio_td, &nfsva,
1480                    &attrflag, NULL);
1481        if (attrflag) {
1482                ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
1483                if (ret && !error)
1484                        error = ret;
1485        }
1486        if (error && NFS_ISV4(vp))
1487                error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0);
1488        return (error);
1489}
1490
1491/*
1492 * nfs write call
1493 */
1494int
1495ncl_writerpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
1496    int *iomode, int *must_commit, int called_from_strategy)
1497{
1498        struct nfsvattr nfsva;
1499        int error, attrflag, ret;
1500        struct nfsmount *nmp;
1501
1502        nmp = VFSTONFS(vnode_mount(vp));
1503        error = EIO;
1504        attrflag = 0;
1505        if (NFSHASPNFS(nmp))
1506                error = nfscl_doiods(vp, uiop, iomode, must_commit,
1507                    NFSV4OPEN_ACCESSWRITE, 0, cred, uiop->uio_td);
1508        NFSCL_DEBUG(4, "writerpc: aft doiods=%d\n", error);
1509        if (error != 0)
1510                error = nfsrpc_write(vp, uiop, iomode, must_commit, cred,
1511                    uiop->uio_td, &nfsva, &attrflag, NULL,
1512                    called_from_strategy);
1513        if (attrflag) {
1514                if (VTONFS(vp)->n_flag & ND_NFSV4)
1515                        ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 1,
1516                            1);
1517                else
1518                        ret = nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
1519                            1);
1520                if (ret && !error)
1521                        error = ret;
1522        }
1523        if (DOINGASYNC(vp))
1524                *iomode = NFSWRITE_FILESYNC;
1525        if (error && NFS_ISV4(vp))
1526                error = nfscl_maperr(uiop->uio_td, error, (uid_t)0, (gid_t)0);
1527        return (error);
1528}
1529
1530/*
1531 * nfs mknod rpc
1532 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the
1533 * mode set to specify the file type and the size field for rdev.
1534 */
1535static int
1536nfs_mknodrpc(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp,
1537    struct vattr *vap)
1538{
1539        struct nfsvattr nfsva, dnfsva;
1540        struct vnode *newvp = NULL;
1541        struct nfsnode *np = NULL, *dnp;
1542        struct nfsfh *nfhp;
1543        struct vattr vattr;
1544        int error = 0, attrflag, dattrflag;
1545        u_int32_t rdev;
1546
1547        if (vap->va_type == VCHR || vap->va_type == VBLK)
1548                rdev = vap->va_rdev;
1549        else if (vap->va_type == VFIFO || vap->va_type == VSOCK)
1550                rdev = 0xffffffff;
1551        else
1552                return (EOPNOTSUPP);
1553        if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)))
1554                return (error);
1555        error = nfsrpc_mknod(dvp, cnp->cn_nameptr, cnp->cn_namelen, vap,
1556            rdev, vap->va_type, cnp->cn_cred, cnp->cn_thread, &dnfsva,
1557            &nfsva, &nfhp, &attrflag, &dattrflag, NULL);
1558        if (!error) {
1559                if (!nfhp)
1560                        (void) nfsrpc_lookup(dvp, cnp->cn_nameptr,
1561                            cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread,
1562                            &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
1563                            NULL);
1564                if (nfhp)
1565                        error = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp,
1566                            cnp->cn_thread, &np, NULL, LK_EXCLUSIVE);
1567        }
1568        if (dattrflag)
1569                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
1570        if (!error) {
1571                newvp = NFSTOV(np);
1572                if (attrflag != 0) {
1573                        error = nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1574                            0, 1);
1575                        if (error != 0)
1576                                vput(newvp);
1577                }
1578        }
1579        if (!error) {
1580                *vpp = newvp;
1581        } else if (NFS_ISV4(dvp)) {
1582                error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid,
1583                    vap->va_gid);
1584        }
1585        dnp = VTONFS(dvp);
1586        NFSLOCKNODE(dnp);
1587        dnp->n_flag |= NMODIFIED;
1588        if (!dattrflag) {
1589                dnp->n_attrstamp = 0;
1590                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
1591        }
1592        NFSUNLOCKNODE(dnp);
1593        return (error);
1594}
1595
1596/*
1597 * nfs mknod vop
1598 * just call nfs_mknodrpc() to do the work.
1599 */
1600/* ARGSUSED */
1601static int
1602nfs_mknod(struct vop_mknod_args *ap)
1603{
1604        return (nfs_mknodrpc(ap->a_dvp, ap->a_vpp, ap->a_cnp, ap->a_vap));
1605}
1606
1607static struct mtx nfs_cverf_mtx;
1608MTX_SYSINIT(nfs_cverf_mtx, &nfs_cverf_mtx, "NFS create verifier mutex",
1609    MTX_DEF);
1610
1611static nfsquad_t
1612nfs_get_cverf(void)
1613{
1614        static nfsquad_t cverf;
1615        nfsquad_t ret;
1616        static int cverf_initialized = 0;
1617
1618        mtx_lock(&nfs_cverf_mtx);
1619        if (cverf_initialized == 0) {
1620                cverf.lval[0] = arc4random();
1621                cverf.lval[1] = arc4random();
1622                cverf_initialized = 1;
1623        } else
1624                cverf.qval++;
1625        ret = cverf;
1626        mtx_unlock(&nfs_cverf_mtx);
1627
1628        return (ret);
1629}
1630
1631/*
1632 * nfs file create call
1633 */
1634static int
1635nfs_create(struct vop_create_args *ap)
1636{
1637        struct vnode *dvp = ap->a_dvp;
1638        struct vattr *vap = ap->a_vap;
1639        struct componentname *cnp = ap->a_cnp;
1640        struct nfsnode *np = NULL, *dnp;
1641        struct vnode *newvp = NULL;
1642        struct nfsmount *nmp;
1643        struct nfsvattr dnfsva, nfsva;
1644        struct nfsfh *nfhp;
1645        nfsquad_t cverf;
1646        int error = 0, attrflag, dattrflag, fmode = 0;
1647        struct vattr vattr;
1648
1649        /*
1650         * Oops, not for me..
1651         */
1652        if (vap->va_type == VSOCK)
1653                return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap));
1654
1655        if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)))
1656                return (error);
1657        if (vap->va_vaflags & VA_EXCLUSIVE)
1658                fmode |= O_EXCL;
1659        dnp = VTONFS(dvp);
1660        nmp = VFSTONFS(vnode_mount(dvp));
1661again:
1662        /* For NFSv4, wait until any remove is done. */
1663        NFSLOCKNODE(dnp);
1664        while (NFSHASNFSV4(nmp) && (dnp->n_flag & NREMOVEINPROG)) {
1665                dnp->n_flag |= NREMOVEWANT;
1666                (void) msleep((caddr_t)dnp, &dnp->n_mtx, PZERO, "nfscrt", 0);
1667        }
1668        NFSUNLOCKNODE(dnp);
1669
1670        cverf = nfs_get_cverf();
1671        error = nfsrpc_create(dvp, cnp->cn_nameptr, cnp->cn_namelen,
1672            vap, cverf, fmode, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva,
1673            &nfhp, &attrflag, &dattrflag, NULL);
1674        if (!error) {
1675                if (nfhp == NULL)
1676                        (void) nfsrpc_lookup(dvp, cnp->cn_nameptr,
1677                            cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread,
1678                            &dnfsva, &nfsva, &nfhp, &attrflag, &dattrflag,
1679                            NULL);
1680                if (nfhp != NULL)
1681                        error = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp,
1682                            cnp->cn_thread, &np, NULL, LK_EXCLUSIVE);
1683        }
1684        if (dattrflag)
1685                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
1686        if (!error) {
1687                newvp = NFSTOV(np);
1688                if (attrflag == 0)
1689                        error = nfsrpc_getattr(newvp, cnp->cn_cred,
1690                            cnp->cn_thread, &nfsva, NULL);
1691                if (error == 0)
1692                        error = nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
1693                            0, 1);
1694        }
1695        if (error) {
1696                if (newvp != NULL) {
1697                        vput(newvp);
1698                        newvp = NULL;
1699                }
1700                if (NFS_ISV34(dvp) && (fmode & O_EXCL) &&
1701                    error == NFSERR_NOTSUPP) {
1702                        fmode &= ~O_EXCL;
1703                        goto again;
1704                }
1705        } else if (NFS_ISV34(dvp) && (fmode & O_EXCL)) {
1706                if (nfscl_checksattr(vap, &nfsva)) {
1707                        error = nfsrpc_setattr(newvp, vap, NULL, cnp->cn_cred,
1708                            cnp->cn_thread, &nfsva, &attrflag, NULL);
1709                        if (error && (vap->va_uid != (uid_t)VNOVAL ||
1710                            vap->va_gid != (gid_t)VNOVAL)) {
1711                                /* try again without setting uid/gid */
1712                                vap->va_uid = (uid_t)VNOVAL;
1713                                vap->va_gid = (uid_t)VNOVAL;
[6e4709b]1714                                error = nfsrpc_setattr(newvp, vap, NULL,
[6138f24]1715                                    cnp->cn_cred, cnp->cn_thread, &nfsva,
1716                                    &attrflag, NULL);
1717                        }
1718                        if (attrflag)
1719                                (void) nfscl_loadattrcache(&newvp, &nfsva, NULL,
1720                                    NULL, 0, 1);
1721                        if (error != 0)
1722                                vput(newvp);
1723                }
1724        }
1725        if (!error) {
1726                if ((cnp->cn_flags & MAKEENTRY) && attrflag)
1727                        cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
1728                            NULL);
1729                *ap->a_vpp = newvp;
1730        } else if (NFS_ISV4(dvp)) {
1731                error = nfscl_maperr(cnp->cn_thread, error, vap->va_uid,
1732                    vap->va_gid);
1733        }
1734        NFSLOCKNODE(dnp);
1735        dnp->n_flag |= NMODIFIED;
1736        if (!dattrflag) {
1737                dnp->n_attrstamp = 0;
1738                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
1739        }
1740        NFSUNLOCKNODE(dnp);
1741        return (error);
1742}
1743
1744/*
1745 * nfs file remove call
1746 * To try and make nfs semantics closer to ufs semantics, a file that has
1747 * other processes using the vnode is renamed instead of removed and then
1748 * removed later on the last close.
1749 * - If v_usecount > 1
1750 *        If a rename is not already in the works
1751 *           call nfs_sillyrename() to set it up
1752 *     else
1753 *        do the remove rpc
1754 */
1755static int
1756nfs_remove(struct vop_remove_args *ap)
1757{
1758        struct vnode *vp = ap->a_vp;
1759        struct vnode *dvp = ap->a_dvp;
1760        struct componentname *cnp = ap->a_cnp;
1761        struct nfsnode *np = VTONFS(vp);
1762        int error = 0;
1763        struct vattr vattr;
1764
1765        KASSERT((cnp->cn_flags & HASBUF) != 0, ("nfs_remove: no name"));
1766        KASSERT(vrefcnt(vp) > 0, ("nfs_remove: bad v_usecount"));
1767        if (vp->v_type == VDIR)
1768                error = EPERM;
1769        else if (vrefcnt(vp) == 1 || (np->n_sillyrename &&
1770            VOP_GETATTR(vp, &vattr, cnp->cn_cred) == 0 &&
1771            vattr.va_nlink > 1)) {
1772                /*
1773                 * Purge the name cache so that the chance of a lookup for
1774                 * the name succeeding while the remove is in progress is
1775                 * minimized. Without node locking it can still happen, such
1776                 * that an I/O op returns ESTALE, but since you get this if
1777                 * another host removes the file..
1778                 */
1779                cache_purge(vp);
1780                /*
1781                 * throw away biocache buffers, mainly to avoid
1782                 * unnecessary delayed writes later.
1783                 */
1784                error = ncl_vinvalbuf(vp, 0, cnp->cn_thread, 1);
1785                if (error != EINTR && error != EIO)
1786                        /* Do the rpc */
1787                        error = nfs_removerpc(dvp, vp, cnp->cn_nameptr,
1788                            cnp->cn_namelen, cnp->cn_cred, cnp->cn_thread);
1789                /*
1790                 * Kludge City: If the first reply to the remove rpc is lost..
1791                 *   the reply to the retransmitted request will be ENOENT
1792                 *   since the file was in fact removed
1793                 *   Therefore, we cheat and return success.
1794                 */
1795                if (error == ENOENT)
1796                        error = 0;
1797        } else if (!np->n_sillyrename)
1798                error = nfs_sillyrename(dvp, vp, cnp);
1799        NFSLOCKNODE(np);
1800        np->n_attrstamp = 0;
1801        NFSUNLOCKNODE(np);
1802        KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
1803        return (error);
1804}
1805
1806/*
1807 * nfs file remove rpc called from nfs_inactive
1808 */
1809int
1810ncl_removeit(struct sillyrename *sp, struct vnode *vp)
1811{
1812        /*
1813         * Make sure that the directory vnode is still valid.
1814         * XXX we should lock sp->s_dvp here.
1815         */
1816        if (sp->s_dvp->v_type == VBAD)
1817                return (0);
1818        return (nfs_removerpc(sp->s_dvp, vp, sp->s_name, sp->s_namlen,
1819            sp->s_cred, NULL));
1820}
1821
1822/*
1823 * Nfs remove rpc, called from nfs_remove() and ncl_removeit().
1824 */
1825static int
1826nfs_removerpc(struct vnode *dvp, struct vnode *vp, char *name,
1827    int namelen, struct ucred *cred, struct thread *td)
1828{
1829        struct nfsvattr dnfsva;
1830        struct nfsnode *dnp = VTONFS(dvp);
1831        int error = 0, dattrflag;
1832
1833        NFSLOCKNODE(dnp);
1834        dnp->n_flag |= NREMOVEINPROG;
1835        NFSUNLOCKNODE(dnp);
1836        error = nfsrpc_remove(dvp, name, namelen, vp, cred, td, &dnfsva,
1837            &dattrflag, NULL);
1838        NFSLOCKNODE(dnp);
1839        if ((dnp->n_flag & NREMOVEWANT)) {
1840                dnp->n_flag &= ~(NREMOVEWANT | NREMOVEINPROG);
1841                NFSUNLOCKNODE(dnp);
1842                wakeup((caddr_t)dnp);
1843        } else {
1844                dnp->n_flag &= ~NREMOVEINPROG;
1845                NFSUNLOCKNODE(dnp);
1846        }
1847        if (dattrflag)
1848                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
1849        NFSLOCKNODE(dnp);
1850        dnp->n_flag |= NMODIFIED;
1851        if (!dattrflag) {
1852                dnp->n_attrstamp = 0;
1853                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
1854        }
1855        NFSUNLOCKNODE(dnp);
1856        if (error && NFS_ISV4(dvp))
1857                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
1858        return (error);
1859}
1860
1861/*
1862 * nfs file rename call
1863 */
1864static int
1865nfs_rename(struct vop_rename_args *ap)
1866{
1867        struct vnode *fvp = ap->a_fvp;
1868        struct vnode *tvp = ap->a_tvp;
1869        struct vnode *fdvp = ap->a_fdvp;
1870        struct vnode *tdvp = ap->a_tdvp;
1871        struct componentname *tcnp = ap->a_tcnp;
1872        struct componentname *fcnp = ap->a_fcnp;
1873        struct nfsnode *fnp = VTONFS(ap->a_fvp);
1874        struct nfsnode *tdnp = VTONFS(ap->a_tdvp);
1875        struct nfsv4node *newv4 = NULL;
1876        int error;
1877
1878        KASSERT((tcnp->cn_flags & HASBUF) != 0 &&
1879            (fcnp->cn_flags & HASBUF) != 0, ("nfs_rename: no name"));
1880        /* Check for cross-device rename */
1881        if ((fvp->v_mount != tdvp->v_mount) ||
1882            (tvp && (fvp->v_mount != tvp->v_mount))) {
1883                error = EXDEV;
1884                goto out;
1885        }
1886
1887        if (fvp == tvp) {
1888                printf("nfs_rename: fvp == tvp (can't happen)\n");
1889                error = 0;
1890                goto out;
1891        }
1892        if ((error = NFSVOPLOCK(fvp, LK_EXCLUSIVE)) != 0)
1893                goto out;
1894
1895        /*
1896         * We have to flush B_DELWRI data prior to renaming
1897         * the file.  If we don't, the delayed-write buffers
1898         * can be flushed out later after the file has gone stale
1899         * under NFSV3.  NFSV2 does not have this problem because
1900         * ( as far as I can tell ) it flushes dirty buffers more
1901         * often.
[6e4709b]1902         *
[6138f24]1903         * Skip the rename operation if the fsync fails, this can happen
1904         * due to the server's volume being full, when we pushed out data
1905         * that was written back to our cache earlier. Not checking for
1906         * this condition can result in potential (silent) data loss.
1907         */
1908        error = VOP_FSYNC(fvp, MNT_WAIT, fcnp->cn_thread);
1909        NFSVOPUNLOCK(fvp, 0);
1910        if (!error && tvp)
1911                error = VOP_FSYNC(tvp, MNT_WAIT, tcnp->cn_thread);
1912        if (error)
1913                goto out;
1914
1915        /*
1916         * If the tvp exists and is in use, sillyrename it before doing the
1917         * rename of the new file over it.
1918         * XXX Can't sillyrename a directory.
1919         */
1920        if (tvp && vrefcnt(tvp) > 1 && !VTONFS(tvp)->n_sillyrename &&
1921                tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) {
1922                vput(tvp);
1923                tvp = NULL;
1924        }
1925
1926        error = nfs_renamerpc(fdvp, fvp, fcnp->cn_nameptr, fcnp->cn_namelen,
1927            tdvp, tvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred,
1928            tcnp->cn_thread);
1929
1930        if (error == 0 && NFS_ISV4(tdvp)) {
1931                /*
1932                 * For NFSv4, check to see if it is the same name and
1933                 * replace the name, if it is different.
1934                 */
1935                newv4 = malloc(
1936                    sizeof (struct nfsv4node) +
1937                    tdnp->n_fhp->nfh_len + tcnp->cn_namelen - 1,
1938                    M_NFSV4NODE, M_WAITOK);
1939                NFSLOCKNODE(tdnp);
1940                NFSLOCKNODE(fnp);
1941                if (fnp->n_v4 != NULL && fvp->v_type == VREG &&
1942                    (fnp->n_v4->n4_namelen != tcnp->cn_namelen ||
1943                      NFSBCMP(tcnp->cn_nameptr, NFS4NODENAME(fnp->n_v4),
1944                      tcnp->cn_namelen) ||
1945                      tdnp->n_fhp->nfh_len != fnp->n_v4->n4_fhlen ||
1946                      NFSBCMP(tdnp->n_fhp->nfh_fh, fnp->n_v4->n4_data,
1947                        tdnp->n_fhp->nfh_len))) {
1948#ifdef notdef
1949{ char nnn[100]; int nnnl;
1950nnnl = (tcnp->cn_namelen < 100) ? tcnp->cn_namelen : 99;
1951bcopy(tcnp->cn_nameptr, nnn, nnnl);
1952nnn[nnnl] = '\0';
1953printf("ren replace=%s\n",nnn);
1954}
1955#endif
1956                        free(fnp->n_v4, M_NFSV4NODE);
1957                        fnp->n_v4 = newv4;
1958                        newv4 = NULL;
1959                        fnp->n_v4->n4_fhlen = tdnp->n_fhp->nfh_len;
1960                        fnp->n_v4->n4_namelen = tcnp->cn_namelen;
1961                        NFSBCOPY(tdnp->n_fhp->nfh_fh, fnp->n_v4->n4_data,
1962                            tdnp->n_fhp->nfh_len);
1963                        NFSBCOPY(tcnp->cn_nameptr,
1964                            NFS4NODENAME(fnp->n_v4), tcnp->cn_namelen);
1965                }
1966                NFSUNLOCKNODE(tdnp);
1967                NFSUNLOCKNODE(fnp);
1968                if (newv4 != NULL)
1969                        free(newv4, M_NFSV4NODE);
1970        }
1971
1972        if (fvp->v_type == VDIR) {
1973                if (tvp != NULL && tvp->v_type == VDIR)
1974                        cache_purge(tdvp);
1975                cache_purge(fdvp);
1976        }
1977
1978out:
1979        if (tdvp == tvp)
1980                vrele(tdvp);
1981        else
1982                vput(tdvp);
1983        if (tvp)
1984                vput(tvp);
1985        vrele(fdvp);
1986        vrele(fvp);
1987        /*
1988         * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry.
1989         */
1990        if (error == ENOENT)
1991                error = 0;
1992        return (error);
1993}
1994
1995/*
1996 * nfs file rename rpc called from nfs_remove() above
1997 */
1998static int
1999nfs_renameit(struct vnode *sdvp, struct vnode *svp, struct componentname *scnp,
2000    struct sillyrename *sp)
2001{
2002
2003        return (nfs_renamerpc(sdvp, svp, scnp->cn_nameptr, scnp->cn_namelen,
2004            sdvp, NULL, sp->s_name, sp->s_namlen, scnp->cn_cred,
2005            scnp->cn_thread));
2006}
2007
2008/*
2009 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit().
2010 */
2011static int
2012nfs_renamerpc(struct vnode *fdvp, struct vnode *fvp, char *fnameptr,
2013    int fnamelen, struct vnode *tdvp, struct vnode *tvp, char *tnameptr,
2014    int tnamelen, struct ucred *cred, struct thread *td)
2015{
2016        struct nfsvattr fnfsva, tnfsva;
2017        struct nfsnode *fdnp = VTONFS(fdvp);
2018        struct nfsnode *tdnp = VTONFS(tdvp);
2019        int error = 0, fattrflag, tattrflag;
2020
2021        error = nfsrpc_rename(fdvp, fvp, fnameptr, fnamelen, tdvp, tvp,
2022            tnameptr, tnamelen, cred, td, &fnfsva, &tnfsva, &fattrflag,
2023            &tattrflag, NULL, NULL);
2024        NFSLOCKNODE(fdnp);
2025        fdnp->n_flag |= NMODIFIED;
2026        if (fattrflag != 0) {
2027                NFSUNLOCKNODE(fdnp);
2028                (void) nfscl_loadattrcache(&fdvp, &fnfsva, NULL, NULL, 0, 1);
2029        } else {
2030                fdnp->n_attrstamp = 0;
2031                NFSUNLOCKNODE(fdnp);
2032                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(fdvp);
2033        }
2034        NFSLOCKNODE(tdnp);
2035        tdnp->n_flag |= NMODIFIED;
2036        if (tattrflag != 0) {
2037                NFSUNLOCKNODE(tdnp);
2038                (void) nfscl_loadattrcache(&tdvp, &tnfsva, NULL, NULL, 0, 1);
2039        } else {
2040                tdnp->n_attrstamp = 0;
2041                NFSUNLOCKNODE(tdnp);
2042                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
2043        }
2044        if (error && NFS_ISV4(fdvp))
2045                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
2046        return (error);
2047}
2048
2049/*
2050 * nfs hard link create call
2051 */
2052static int
2053nfs_link(struct vop_link_args *ap)
2054{
2055        struct vnode *vp = ap->a_vp;
2056        struct vnode *tdvp = ap->a_tdvp;
2057        struct componentname *cnp = ap->a_cnp;
2058        struct nfsnode *np, *tdnp;
2059        struct nfsvattr nfsva, dnfsva;
2060        int error = 0, attrflag, dattrflag;
2061
2062        /*
2063         * Push all writes to the server, so that the attribute cache
2064         * doesn't get "out of sync" with the server.
2065         * XXX There should be a better way!
2066         */
2067        VOP_FSYNC(vp, MNT_WAIT, cnp->cn_thread);
2068
2069        error = nfsrpc_link(tdvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
2070            cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, &attrflag,
2071            &dattrflag, NULL);
2072        tdnp = VTONFS(tdvp);
2073        NFSLOCKNODE(tdnp);
2074        tdnp->n_flag |= NMODIFIED;
2075        if (dattrflag != 0) {
2076                NFSUNLOCKNODE(tdnp);
2077                (void) nfscl_loadattrcache(&tdvp, &dnfsva, NULL, NULL, 0, 1);
2078        } else {
2079                tdnp->n_attrstamp = 0;
2080                NFSUNLOCKNODE(tdnp);
2081                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(tdvp);
2082        }
2083        if (attrflag)
2084                (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
2085        else {
2086                np = VTONFS(vp);
2087                NFSLOCKNODE(np);
2088                np->n_attrstamp = 0;
2089                NFSUNLOCKNODE(np);
2090                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
2091        }
2092        /*
2093         * If negative lookup caching is enabled, I might as well
2094         * add an entry for this node. Not necessary for correctness,
2095         * but if negative caching is enabled, then the system
2096         * must care about lookup caching hit rate, so...
2097         */
2098        if (VFSTONFS(vp->v_mount)->nm_negnametimeo != 0 &&
2099            (cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
2100                cache_enter_time(tdvp, vp, cnp, &nfsva.na_ctime, NULL);
2101        }
2102        if (error && NFS_ISV4(vp))
2103                error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0,
2104                    (gid_t)0);
2105        return (error);
2106}
2107
2108/*
2109 * nfs symbolic link create call
2110 */
2111static int
2112nfs_symlink(struct vop_symlink_args *ap)
2113{
2114        struct vnode *dvp = ap->a_dvp;
2115        struct vattr *vap = ap->a_vap;
2116        struct componentname *cnp = ap->a_cnp;
2117        struct nfsvattr nfsva, dnfsva;
2118        struct nfsfh *nfhp;
2119        struct nfsnode *np = NULL, *dnp;
2120        struct vnode *newvp = NULL;
2121        int error = 0, attrflag, dattrflag, ret;
2122
2123        vap->va_type = VLNK;
2124        error = nfsrpc_symlink(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2125            ap->a_target, vap, cnp->cn_cred, cnp->cn_thread, &dnfsva,
2126            &nfsva, &nfhp, &attrflag, &dattrflag, NULL);
2127        if (nfhp) {
2128                ret = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, cnp->cn_thread,
2129                    &np, NULL, LK_EXCLUSIVE);
2130                if (!ret)
2131                        newvp = NFSTOV(np);
2132                else if (!error)
2133                        error = ret;
2134        }
2135        if (newvp != NULL) {
2136                if (attrflag)
2137                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
2138                            0, 1);
2139        } else if (!error) {
2140                /*
2141                 * If we do not have an error and we could not extract the
2142                 * newvp from the response due to the request being NFSv2, we
2143                 * have to do a lookup in order to obtain a newvp to return.
2144                 */
2145                error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2146                    cnp->cn_cred, cnp->cn_thread, &np);
2147                if (!error)
2148                        newvp = NFSTOV(np);
2149        }
2150        if (error) {
2151                if (newvp)
2152                        vput(newvp);
2153                if (NFS_ISV4(dvp))
2154                        error = nfscl_maperr(cnp->cn_thread, error,
2155                            vap->va_uid, vap->va_gid);
2156        } else {
2157                *ap->a_vpp = newvp;
2158        }
2159
2160        dnp = VTONFS(dvp);
2161        NFSLOCKNODE(dnp);
2162        dnp->n_flag |= NMODIFIED;
2163        if (dattrflag != 0) {
2164                NFSUNLOCKNODE(dnp);
2165                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
2166        } else {
2167                dnp->n_attrstamp = 0;
2168                NFSUNLOCKNODE(dnp);
2169                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
2170        }
2171        /*
2172         * If negative lookup caching is enabled, I might as well
2173         * add an entry for this node. Not necessary for correctness,
2174         * but if negative caching is enabled, then the system
2175         * must care about lookup caching hit rate, so...
2176         */
2177        if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
2178            (cnp->cn_flags & MAKEENTRY) && attrflag != 0 && error == 0) {
2179                cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime, NULL);
2180        }
2181        return (error);
2182}
2183
2184/*
2185 * nfs make dir call
2186 */
2187static int
2188nfs_mkdir(struct vop_mkdir_args *ap)
2189{
2190        struct vnode *dvp = ap->a_dvp;
2191        struct vattr *vap = ap->a_vap;
2192        struct componentname *cnp = ap->a_cnp;
2193        struct nfsnode *np = NULL, *dnp;
2194        struct vnode *newvp = NULL;
2195        struct vattr vattr;
2196        struct nfsfh *nfhp;
2197        struct nfsvattr nfsva, dnfsva;
2198        int error = 0, attrflag, dattrflag, ret;
2199
2200        if ((error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred)) != 0)
2201                return (error);
2202        vap->va_type = VDIR;
2203        error = nfsrpc_mkdir(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2204            vap, cnp->cn_cred, cnp->cn_thread, &dnfsva, &nfsva, &nfhp,
2205            &attrflag, &dattrflag, NULL);
2206        dnp = VTONFS(dvp);
2207        NFSLOCKNODE(dnp);
2208        dnp->n_flag |= NMODIFIED;
2209        if (dattrflag != 0) {
2210                NFSUNLOCKNODE(dnp);
2211                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
2212        } else {
2213                dnp->n_attrstamp = 0;
2214                NFSUNLOCKNODE(dnp);
2215                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
2216        }
2217        if (nfhp) {
2218                ret = nfscl_nget(dvp->v_mount, dvp, nfhp, cnp, cnp->cn_thread,
2219                    &np, NULL, LK_EXCLUSIVE);
2220                if (!ret) {
2221                        newvp = NFSTOV(np);
2222                        if (attrflag)
2223                           (void) nfscl_loadattrcache(&newvp, &nfsva, NULL,
2224                                NULL, 0, 1);
2225                } else if (!error)
2226                        error = ret;
2227        }
2228        if (!error && newvp == NULL) {
2229                error = nfs_lookitup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2230                    cnp->cn_cred, cnp->cn_thread, &np);
2231                if (!error) {
2232                        newvp = NFSTOV(np);
2233                        if (newvp->v_type != VDIR)
2234                                error = EEXIST;
2235                }
2236        }
2237        if (error) {
2238                if (newvp)
2239                        vput(newvp);
2240                if (NFS_ISV4(dvp))
2241                        error = nfscl_maperr(cnp->cn_thread, error,
2242                            vap->va_uid, vap->va_gid);
2243        } else {
2244                /*
2245                 * If negative lookup caching is enabled, I might as well
2246                 * add an entry for this node. Not necessary for correctness,
2247                 * but if negative caching is enabled, then the system
2248                 * must care about lookup caching hit rate, so...
2249                 */
2250                if (VFSTONFS(dvp->v_mount)->nm_negnametimeo != 0 &&
2251                    (cnp->cn_flags & MAKEENTRY) &&
2252                    attrflag != 0 && dattrflag != 0)
2253                        cache_enter_time(dvp, newvp, cnp, &nfsva.na_ctime,
2254                            &dnfsva.na_ctime);
2255                *ap->a_vpp = newvp;
2256        }
2257        return (error);
2258}
2259
2260/*
2261 * nfs remove directory call
2262 */
2263static int
2264nfs_rmdir(struct vop_rmdir_args *ap)
2265{
2266        struct vnode *vp = ap->a_vp;
2267        struct vnode *dvp = ap->a_dvp;
2268        struct componentname *cnp = ap->a_cnp;
2269        struct nfsnode *dnp;
2270        struct nfsvattr dnfsva;
2271        int error, dattrflag;
2272
2273        if (dvp == vp)
2274                return (EINVAL);
2275        error = nfsrpc_rmdir(dvp, cnp->cn_nameptr, cnp->cn_namelen,
2276            cnp->cn_cred, cnp->cn_thread, &dnfsva, &dattrflag, NULL);
2277        dnp = VTONFS(dvp);
2278        NFSLOCKNODE(dnp);
2279        dnp->n_flag |= NMODIFIED;
2280        if (dattrflag != 0) {
2281                NFSUNLOCKNODE(dnp);
2282                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
2283        } else {
2284                dnp->n_attrstamp = 0;
2285                NFSUNLOCKNODE(dnp);
2286                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(dvp);
2287        }
2288
2289        cache_purge(dvp);
2290        cache_purge(vp);
2291        if (error && NFS_ISV4(dvp))
2292                error = nfscl_maperr(cnp->cn_thread, error, (uid_t)0,
2293                    (gid_t)0);
2294        /*
2295         * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry.
2296         */
2297        if (error == ENOENT)
2298                error = 0;
2299        return (error);
2300}
2301
2302/*
2303 * nfs readdir call
2304 */
2305static int
2306nfs_readdir(struct vop_readdir_args *ap)
2307{
2308        struct vnode *vp = ap->a_vp;
2309        struct nfsnode *np = VTONFS(vp);
2310        struct uio *uio = ap->a_uio;
2311        ssize_t tresid, left;
2312        int error = 0;
2313        struct vattr vattr;
[6e4709b]2314       
[6138f24]2315        if (ap->a_eofflag != NULL)
2316                *ap->a_eofflag = 0;
[6e4709b]2317        if (vp->v_type != VDIR)
[6138f24]2318                return(EPERM);
2319
2320        /*
2321         * First, check for hit on the EOF offset cache
2322         */
2323        if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset &&
2324            (np->n_flag & NMODIFIED) == 0) {
2325                if (VOP_GETATTR(vp, &vattr, ap->a_cred) == 0) {
2326                        NFSLOCKNODE(np);
2327                        if ((NFS_ISV4(vp) && np->n_change == vattr.va_filerev) ||
2328                            !NFS_TIMESPEC_COMPARE(&np->n_mtime, &vattr.va_mtime)) {
2329                                NFSUNLOCKNODE(np);
2330                                NFSINCRGLOBAL(nfsstatsv1.direofcache_hits);
2331                                if (ap->a_eofflag != NULL)
2332                                        *ap->a_eofflag = 1;
2333                                return (0);
2334                        } else
2335                                NFSUNLOCKNODE(np);
2336                }
2337        }
2338
2339        /*
2340         * NFS always guarantees that directory entries don't straddle
2341         * DIRBLKSIZ boundaries.  As such, we need to limit the size
2342         * to an exact multiple of DIRBLKSIZ, to avoid copying a partial
2343         * directory entry.
2344         */
2345        left = uio->uio_resid % DIRBLKSIZ;
2346        if (left == uio->uio_resid)
2347                return (EINVAL);
2348        uio->uio_resid -= left;
2349
2350        /*
2351         * Call ncl_bioread() to do the real work.
2352         */
2353        tresid = uio->uio_resid;
2354        error = ncl_bioread(vp, uio, 0, ap->a_cred);
2355
2356        if (!error && uio->uio_resid == tresid) {
2357                NFSINCRGLOBAL(nfsstatsv1.direofcache_misses);
2358                if (ap->a_eofflag != NULL)
2359                        *ap->a_eofflag = 1;
2360        }
[6e4709b]2361       
[6138f24]2362        /* Add the partial DIRBLKSIZ (left) back in. */
2363        uio->uio_resid += left;
2364        return (error);
2365}
2366
2367/*
2368 * Readdir rpc call.
2369 * Called from below the buffer cache by ncl_doio().
2370 */
2371int
2372ncl_readdirrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2373    struct thread *td)
2374{
2375        struct nfsvattr nfsva;
2376        nfsuint64 *cookiep, cookie;
2377        struct nfsnode *dnp = VTONFS(vp);
2378        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2379        int error = 0, eof, attrflag;
2380
2381        KASSERT(uiop->uio_iovcnt == 1 &&
2382            (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 &&
2383            (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
2384            ("nfs readdirrpc bad uio"));
2385
2386        /*
2387         * If there is no cookie, assume directory was stale.
2388         */
2389        ncl_dircookie_lock(dnp);
2390        cookiep = ncl_getcookie(dnp, uiop->uio_offset, 0);
2391        if (cookiep) {
2392                cookie = *cookiep;
2393                ncl_dircookie_unlock(dnp);
2394        } else {
[6e4709b]2395                ncl_dircookie_unlock(dnp);             
[6138f24]2396                return (NFSERR_BAD_COOKIE);
2397        }
2398
2399        if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp))
2400                (void)ncl_fsinfo(nmp, vp, cred, td);
2401
2402        error = nfsrpc_readdir(vp, uiop, &cookie, cred, td, &nfsva,
2403            &attrflag, &eof, NULL);
2404        if (attrflag)
2405                (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
2406
2407        if (!error) {
2408                /*
2409                 * We are now either at the end of the directory or have filled
2410                 * the block.
2411                 */
2412                if (eof)
2413                        dnp->n_direofoffset = uiop->uio_offset;
2414                else {
2415                        if (uiop->uio_resid > 0)
2416                                printf("EEK! readdirrpc resid > 0\n");
2417                        ncl_dircookie_lock(dnp);
2418                        cookiep = ncl_getcookie(dnp, uiop->uio_offset, 1);
2419                        *cookiep = cookie;
2420                        ncl_dircookie_unlock(dnp);
2421                }
2422        } else if (NFS_ISV4(vp)) {
2423                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
2424        }
2425        return (error);
2426}
2427
2428/*
2429 * NFS V3 readdir plus RPC. Used in place of ncl_readdirrpc().
2430 */
2431int
2432ncl_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred,
2433    struct thread *td)
2434{
2435        struct nfsvattr nfsva;
2436        nfsuint64 *cookiep, cookie;
2437        struct nfsnode *dnp = VTONFS(vp);
2438        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2439        int error = 0, attrflag, eof;
2440
2441        KASSERT(uiop->uio_iovcnt == 1 &&
2442            (uiop->uio_offset & (DIRBLKSIZ - 1)) == 0 &&
2443            (uiop->uio_resid & (DIRBLKSIZ - 1)) == 0,
2444            ("nfs readdirplusrpc bad uio"));
2445
2446        /*
2447         * If there is no cookie, assume directory was stale.
2448         */
2449        ncl_dircookie_lock(dnp);
2450        cookiep = ncl_getcookie(dnp, uiop->uio_offset, 0);
2451        if (cookiep) {
2452                cookie = *cookiep;
2453                ncl_dircookie_unlock(dnp);
2454        } else {
2455                ncl_dircookie_unlock(dnp);
2456                return (NFSERR_BAD_COOKIE);
2457        }
2458
2459        if (NFSHASNFSV3(nmp) && !NFSHASGOTFSINFO(nmp))
2460                (void)ncl_fsinfo(nmp, vp, cred, td);
2461        error = nfsrpc_readdirplus(vp, uiop, &cookie, cred, td, &nfsva,
2462            &attrflag, &eof, NULL);
2463        if (attrflag)
2464                (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0, 1);
2465
2466        if (!error) {
2467                /*
2468                 * We are now either at end of the directory or have filled the
2469                 * the block.
2470                 */
2471                if (eof)
2472                        dnp->n_direofoffset = uiop->uio_offset;
2473                else {
2474                        if (uiop->uio_resid > 0)
2475                                printf("EEK! readdirplusrpc resid > 0\n");
2476                        ncl_dircookie_lock(dnp);
2477                        cookiep = ncl_getcookie(dnp, uiop->uio_offset, 1);
2478                        *cookiep = cookie;
2479                        ncl_dircookie_unlock(dnp);
2480                }
2481        } else if (NFS_ISV4(vp)) {
2482                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
2483        }
2484        return (error);
2485}
2486
2487/*
2488 * Silly rename. To make the NFS filesystem that is stateless look a little
2489 * more like the "ufs" a remove of an active vnode is translated to a rename
2490 * to a funny looking filename that is removed by nfs_inactive on the
2491 * nfsnode. There is the potential for another process on a different client
2492 * to create the same funny name between the nfs_lookitup() fails and the
2493 * nfs_rename() completes, but...
2494 */
2495static int
2496nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
2497{
2498        struct sillyrename *sp;
2499        struct nfsnode *np;
2500        int error;
2501        short pid;
2502        unsigned int lticks;
2503
2504        cache_purge(dvp);
2505        np = VTONFS(vp);
2506        KASSERT(vp->v_type != VDIR, ("nfs: sillyrename dir"));
2507        sp = malloc(sizeof (struct sillyrename),
2508            M_NEWNFSREQ, M_WAITOK);
2509        sp->s_cred = crhold(cnp->cn_cred);
2510        sp->s_dvp = dvp;
2511        VREF(dvp);
2512
[6e4709b]2513        /*
[6138f24]2514         * Fudge together a funny name.
[6e4709b]2515         * Changing the format of the funny name to accommodate more
[6138f24]2516         * sillynames per directory.
[6e4709b]2517         * The name is now changed to .nfs.<ticks>.<pid>.4, where ticks is
[6138f24]2518         * CPU ticks since boot.
2519         */
[882425f]2520#ifndef __rtems__
[6138f24]2521        pid = cnp->cn_thread->td_proc->p_pid;
[882425f]2522#else /* __rtems__ */
2523        pid = 1;
2524#endif /* __rtems__ */
[6138f24]2525        lticks = (unsigned int)ticks;
2526        for ( ; ; ) {
[6e4709b]2527                sp->s_namlen = sprintf(sp->s_name,
2528                                       ".nfs.%08x.%04x4.4", lticks,
[6138f24]2529                                       pid);
2530                if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2531                                 cnp->cn_thread, NULL))
2532                        break;
2533                lticks++;
2534        }
2535        error = nfs_renameit(dvp, vp, cnp, sp);
2536        if (error)
2537                goto bad;
2538        error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred,
2539                cnp->cn_thread, &np);
2540        np->n_sillyrename = sp;
2541        return (0);
2542bad:
2543        vrele(sp->s_dvp);
2544        crfree(sp->s_cred);
2545        free(sp, M_NEWNFSREQ);
2546        return (error);
2547}
2548
2549/*
2550 * Look up a file name and optionally either update the file handle or
2551 * allocate an nfsnode, depending on the value of npp.
2552 * npp == NULL  --> just do the lookup
2553 * *npp == NULL --> allocate a new nfsnode and make sure attributes are
2554 *                      handled too
2555 * *npp != NULL --> update the file handle in the vnode
2556 */
2557static int
2558nfs_lookitup(struct vnode *dvp, char *name, int len, struct ucred *cred,
2559    struct thread *td, struct nfsnode **npp)
2560{
2561        struct vnode *newvp = NULL, *vp;
2562        struct nfsnode *np, *dnp = VTONFS(dvp);
2563        struct nfsfh *nfhp, *onfhp;
2564        struct nfsvattr nfsva, dnfsva;
2565        struct componentname cn;
2566        int error = 0, attrflag, dattrflag;
2567        u_int hash;
2568
2569        error = nfsrpc_lookup(dvp, name, len, cred, td, &dnfsva, &nfsva,
2570            &nfhp, &attrflag, &dattrflag, NULL);
2571        if (dattrflag)
2572                (void) nfscl_loadattrcache(&dvp, &dnfsva, NULL, NULL, 0, 1);
2573        if (npp && !error) {
2574                if (*npp != NULL) {
2575                    np = *npp;
2576                    vp = NFSTOV(np);
2577                    /*
2578                     * For NFSv4, check to see if it is the same name and
2579                     * replace the name, if it is different.
2580                     */
2581                    if (np->n_v4 != NULL && nfsva.na_type == VREG &&
2582                        (np->n_v4->n4_namelen != len ||
2583                         NFSBCMP(name, NFS4NODENAME(np->n_v4), len) ||
2584                         dnp->n_fhp->nfh_len != np->n_v4->n4_fhlen ||
2585                         NFSBCMP(dnp->n_fhp->nfh_fh, np->n_v4->n4_data,
2586                         dnp->n_fhp->nfh_len))) {
2587#ifdef notdef
2588{ char nnn[100]; int nnnl;
2589nnnl = (len < 100) ? len : 99;
2590bcopy(name, nnn, nnnl);
2591nnn[nnnl] = '\0';
2592printf("replace=%s\n",nnn);
2593}
2594#endif
2595                            free(np->n_v4, M_NFSV4NODE);
2596                            np->n_v4 = malloc(
2597                                sizeof (struct nfsv4node) +
2598                                dnp->n_fhp->nfh_len + len - 1,
2599                                M_NFSV4NODE, M_WAITOK);
2600                            np->n_v4->n4_fhlen = dnp->n_fhp->nfh_len;
2601                            np->n_v4->n4_namelen = len;
2602                            NFSBCOPY(dnp->n_fhp->nfh_fh, np->n_v4->n4_data,
2603                                dnp->n_fhp->nfh_len);
2604                            NFSBCOPY(name, NFS4NODENAME(np->n_v4), len);
2605                    }
2606                    hash = fnv_32_buf(nfhp->nfh_fh, nfhp->nfh_len,
2607                        FNV1_32_INIT);
2608                    onfhp = np->n_fhp;
2609                    /*
2610                     * Rehash node for new file handle.
2611                     */
2612                    vfs_hash_rehash(vp, hash);
2613                    np->n_fhp = nfhp;
2614                    if (onfhp != NULL)
2615                        free(onfhp, M_NFSFH);
2616                    newvp = NFSTOV(np);
2617                } else if (NFS_CMPFH(dnp, nfhp->nfh_fh, nfhp->nfh_len)) {
2618                    free(nfhp, M_NFSFH);
2619                    VREF(dvp);
2620                    newvp = dvp;
2621                } else {
2622                    cn.cn_nameptr = name;
2623                    cn.cn_namelen = len;
2624                    error = nfscl_nget(dvp->v_mount, dvp, nfhp, &cn, td,
2625                        &np, NULL, LK_EXCLUSIVE);
2626                    if (error)
2627                        return (error);
2628                    newvp = NFSTOV(np);
2629                }
2630                if (!attrflag && *npp == NULL) {
2631                        if (newvp == dvp)
2632                                vrele(newvp);
2633                        else
2634                                vput(newvp);
2635                        return (ENOENT);
2636                }
2637                if (attrflag)
2638                        (void) nfscl_loadattrcache(&newvp, &nfsva, NULL, NULL,
2639                            0, 1);
2640        }
2641        if (npp && *npp == NULL) {
2642                if (error) {
2643                        if (newvp) {
2644                                if (newvp == dvp)
2645                                        vrele(newvp);
2646                                else
2647                                        vput(newvp);
2648                        }
2649                } else
2650                        *npp = np;
2651        }
2652        if (error && NFS_ISV4(dvp))
2653                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
2654        return (error);
2655}
2656
2657/*
2658 * Nfs Version 3 and 4 commit rpc
2659 */
2660int
2661ncl_commit(struct vnode *vp, u_quad_t offset, int cnt, struct ucred *cred,
2662   struct thread *td)
2663{
2664        struct nfsvattr nfsva;
2665        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2666        struct nfsnode *np;
2667        struct uio uio;
2668        int error, attrflag;
2669
2670        np = VTONFS(vp);
2671        error = EIO;
2672        attrflag = 0;
2673        if (NFSHASPNFS(nmp) && (np->n_flag & NDSCOMMIT) != 0) {
2674                uio.uio_offset = offset;
2675                uio.uio_resid = cnt;
2676                error = nfscl_doiods(vp, &uio, NULL, NULL,
2677                    NFSV4OPEN_ACCESSWRITE, 1, cred, td);
2678                if (error != 0) {
2679                        NFSLOCKNODE(np);
2680                        np->n_flag &= ~NDSCOMMIT;
2681                        NFSUNLOCKNODE(np);
2682                }
2683        }
2684        if (error != 0) {
2685                mtx_lock(&nmp->nm_mtx);
2686                if ((nmp->nm_state & NFSSTA_HASWRITEVERF) == 0) {
2687                        mtx_unlock(&nmp->nm_mtx);
2688                        return (0);
2689                }
2690                mtx_unlock(&nmp->nm_mtx);
2691                error = nfsrpc_commit(vp, offset, cnt, cred, td, &nfsva,
2692                    &attrflag, NULL);
2693        }
2694        if (attrflag != 0)
2695                (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL,
2696                    0, 1);
2697        if (error != 0 && NFS_ISV4(vp))
2698                error = nfscl_maperr(td, error, (uid_t)0, (gid_t)0);
2699        return (error);
2700}
2701
2702/*
2703 * Strategy routine.
2704 * For async requests when nfsiod(s) are running, queue the request by
2705 * calling ncl_asyncio(), otherwise just all ncl_doio() to do the
2706 * request.
2707 */
2708static int
2709nfs_strategy(struct vop_strategy_args *ap)
2710{
2711        struct buf *bp;
2712        struct vnode *vp;
2713        struct ucred *cr;
2714
2715        bp = ap->a_bp;
2716        vp = ap->a_vp;
2717        KASSERT(bp->b_vp == vp, ("missing b_getvp"));
2718        KASSERT(!(bp->b_flags & B_DONE),
2719            ("nfs_strategy: buffer %p unexpectedly marked B_DONE", bp));
2720        BUF_ASSERT_HELD(bp);
2721
2722        if (vp->v_type == VREG && bp->b_blkno == bp->b_lblkno)
2723                bp->b_blkno = bp->b_lblkno * (vp->v_bufobj.bo_bsize /
2724                    DEV_BSIZE);
2725        if (bp->b_iocmd == BIO_READ)
2726                cr = bp->b_rcred;
2727        else
2728                cr = bp->b_wcred;
2729
2730        /*
2731         * If the op is asynchronous and an i/o daemon is waiting
2732         * queue the request, wake it up and wait for completion
2733         * otherwise just do it ourselves.
2734         */
2735        if ((bp->b_flags & B_ASYNC) == 0 ||
2736            ncl_asyncio(VFSTONFS(vp->v_mount), bp, NOCRED, curthread))
2737                (void) ncl_doio(vp, bp, cr, curthread, 1);
2738        return (0);
2739}
2740
2741/*
2742 * fsync vnode op. Just call ncl_flush() with commit == 1.
2743 */
2744/* ARGSUSED */
2745static int
2746nfs_fsync(struct vop_fsync_args *ap)
2747{
2748
2749        if (ap->a_vp->v_type != VREG) {
2750                /*
2751                 * For NFS, metadata is changed synchronously on the server,
2752                 * so there is nothing to flush. Also, ncl_flush() clears
2753                 * the NMODIFIED flag and that shouldn't be done here for
2754                 * directories.
2755                 */
2756                return (0);
2757        }
2758        return (ncl_flush(ap->a_vp, ap->a_waitfor, ap->a_td, 1, 0));
2759}
2760
2761/*
2762 * Flush all the blocks associated with a vnode.
2763 *      Walk through the buffer pool and push any dirty pages
2764 *      associated with the vnode.
2765 * If the called_from_renewthread argument is TRUE, it has been called
2766 * from the NFSv4 renew thread and, as such, cannot block indefinitely
2767 * waiting for a buffer write to complete.
2768 */
2769int
2770ncl_flush(struct vnode *vp, int waitfor, struct thread *td,
2771    int commit, int called_from_renewthread)
2772{
2773        struct nfsnode *np = VTONFS(vp);
2774        struct buf *bp;
2775        int i;
2776        struct buf *nbp;
2777        struct nfsmount *nmp = VFSTONFS(vp->v_mount);
2778        int error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos;
2779        int passone = 1, trycnt = 0;
2780        u_quad_t off, endoff, toff;
2781        struct ucred* wcred = NULL;
2782        struct buf **bvec = NULL;
2783        struct bufobj *bo;
2784#ifndef NFS_COMMITBVECSIZ
2785#define NFS_COMMITBVECSIZ       20
2786#endif
2787        struct buf *bvec_on_stack[NFS_COMMITBVECSIZ];
2788        u_int bvecsize = 0, bveccount;
2789
2790        if (called_from_renewthread != 0)
2791                slptimeo = hz;
2792        if (nmp->nm_flag & NFSMNT_INT)
2793                slpflag = PCATCH;
2794        if (!commit)
2795                passone = 0;
2796        bo = &vp->v_bufobj;
2797        /*
2798         * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the
2799         * server, but has not been committed to stable storage on the server
2800         * yet. On the first pass, the byte range is worked out and the commit
2801         * rpc is done. On the second pass, ncl_writebp() is called to do the
2802         * job.
2803         */
2804again:
2805        off = (u_quad_t)-1;
2806        endoff = 0;
2807        bvecpos = 0;
2808        if (NFS_ISV34(vp) && commit) {
2809                if (bvec != NULL && bvec != bvec_on_stack)
2810                        free(bvec, M_TEMP);
2811                /*
2812                 * Count up how many buffers waiting for a commit.
2813                 */
2814                bveccount = 0;
2815                BO_LOCK(bo);
2816                TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
2817                        if (!BUF_ISLOCKED(bp) &&
2818                            (bp->b_flags & (B_DELWRI | B_NEEDCOMMIT))
2819                                == (B_DELWRI | B_NEEDCOMMIT))
2820                                bveccount++;
2821                }
2822                /*
2823                 * Allocate space to remember the list of bufs to commit.  It is
2824                 * important to use M_NOWAIT here to avoid a race with nfs_write.
2825                 * If we can't get memory (for whatever reason), we will end up
2826                 * committing the buffers one-by-one in the loop below.
2827                 */
2828                if (bveccount > NFS_COMMITBVECSIZ) {
2829                        /*
2830                         * Release the vnode interlock to avoid a lock
2831                         * order reversal.
2832                         */
2833                        BO_UNLOCK(bo);
2834                        bvec = (struct buf **)
2835                                malloc(bveccount * sizeof(struct buf *),
2836                                       M_TEMP, M_NOWAIT);
2837                        BO_LOCK(bo);
2838                        if (bvec == NULL) {
2839                                bvec = bvec_on_stack;
2840                                bvecsize = NFS_COMMITBVECSIZ;
2841                        } else
2842                                bvecsize = bveccount;
2843                } else {
2844                        bvec = bvec_on_stack;
2845                        bvecsize = NFS_COMMITBVECSIZ;
2846                }
2847                TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
2848                        if (bvecpos >= bvecsize)
2849                                break;
2850                        if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
2851                                nbp = TAILQ_NEXT(bp, b_bobufs);
2852                                continue;
2853                        }
2854                        if ((bp->b_flags & (B_DELWRI | B_NEEDCOMMIT)) !=
2855                            (B_DELWRI | B_NEEDCOMMIT)) {
2856                                BUF_UNLOCK(bp);
2857                                nbp = TAILQ_NEXT(bp, b_bobufs);
2858                                continue;
2859                        }
2860                        BO_UNLOCK(bo);
2861                        bremfree(bp);
2862                        /*
2863                         * Work out if all buffers are using the same cred
2864                         * so we can deal with them all with one commit.
2865                         *
2866                         * NOTE: we are not clearing B_DONE here, so we have
2867                         * to do it later on in this routine if we intend to
2868                         * initiate I/O on the bp.
2869                         *
2870                         * Note: to avoid loopback deadlocks, we do not
2871                         * assign b_runningbufspace.
2872                         */
2873                        if (wcred == NULL)
2874                                wcred = bp->b_wcred;
2875                        else if (wcred != bp->b_wcred)
2876                                wcred = NOCRED;
2877                        vfs_busy_pages(bp, 1);
2878
2879                        BO_LOCK(bo);
2880                        /*
2881                         * bp is protected by being locked, but nbp is not
2882                         * and vfs_busy_pages() may sleep.  We have to
2883                         * recalculate nbp.
2884                         */
2885                        nbp = TAILQ_NEXT(bp, b_bobufs);
2886
2887                        /*
2888                         * A list of these buffers is kept so that the
2889                         * second loop knows which buffers have actually
2890                         * been committed. This is necessary, since there
2891                         * may be a race between the commit rpc and new
2892                         * uncommitted writes on the file.
2893                         */
2894                        bvec[bvecpos++] = bp;
2895                        toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2896                                bp->b_dirtyoff;
2897                        if (toff < off)
2898                                off = toff;
2899                        toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff);
2900                        if (toff > endoff)
2901                                endoff = toff;
2902                }
2903                BO_UNLOCK(bo);
2904        }
2905        if (bvecpos > 0) {
2906                /*
2907                 * Commit data on the server, as required.
2908                 * If all bufs are using the same wcred, then use that with
2909                 * one call for all of them, otherwise commit each one
2910                 * separately.
2911                 */
2912                if (wcred != NOCRED)
2913                        retv = ncl_commit(vp, off, (int)(endoff - off),
2914                                          wcred, td);
2915                else {
2916                        retv = 0;
2917                        for (i = 0; i < bvecpos; i++) {
2918                                off_t off, size;
2919                                bp = bvec[i];
2920                                off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE +
2921                                        bp->b_dirtyoff;
2922                                size = (u_quad_t)(bp->b_dirtyend
2923                                                  - bp->b_dirtyoff);
2924                                retv = ncl_commit(vp, off, (int)size,
2925                                                  bp->b_wcred, td);
2926                                if (retv) break;
2927                        }
2928                }
2929
2930                if (retv == NFSERR_STALEWRITEVERF)
2931                        ncl_clearcommit(vp->v_mount);
2932
2933                /*
2934                 * Now, either mark the blocks I/O done or mark the
2935                 * blocks dirty, depending on whether the commit
2936                 * succeeded.
2937                 */
2938                for (i = 0; i < bvecpos; i++) {
2939                        bp = bvec[i];
2940                        bp->b_flags &= ~(B_NEEDCOMMIT | B_CLUSTEROK);
2941                        if (retv) {
2942                                /*
2943                                 * Error, leave B_DELWRI intact
2944                                 */
2945                                vfs_unbusy_pages(bp);
2946                                brelse(bp);
2947                        } else {
2948                                /*
2949                                 * Success, remove B_DELWRI ( bundirty() ).
2950                                 *
2951                                 * b_dirtyoff/b_dirtyend seem to be NFS
2952                                 * specific.  We should probably move that
2953                                 * into bundirty(). XXX
2954                                 */
2955                                bufobj_wref(bo);
2956                                bp->b_flags |= B_ASYNC;
2957                                bundirty(bp);
2958                                bp->b_flags &= ~B_DONE;
2959                                bp->b_ioflags &= ~BIO_ERROR;
2960                                bp->b_dirtyoff = bp->b_dirtyend = 0;
2961                                bufdone(bp);
2962                        }
2963                }
2964        }
2965
2966        /*
2967         * Start/do any write(s) that are required.
2968         */
2969loop:
2970        BO_LOCK(bo);
2971        TAILQ_FOREACH_SAFE(bp, &bo->bo_dirty.bv_hd, b_bobufs, nbp) {
2972                if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT, NULL)) {
2973                        if (waitfor != MNT_WAIT || passone)
2974                                continue;
2975
2976                        error = BUF_TIMELOCK(bp,
2977                            LK_EXCLUSIVE | LK_SLEEPFAIL | LK_INTERLOCK,
2978                            BO_LOCKPTR(bo), "nfsfsync", slpflag, slptimeo);
2979                        if (error == 0) {
2980                                BUF_UNLOCK(bp);
2981                                goto loop;
2982                        }
2983                        if (error == ENOLCK) {
2984                                error = 0;
2985                                goto loop;
2986                        }
2987                        if (called_from_renewthread != 0) {
2988                                /*
2989                                 * Return EIO so the flush will be retried
2990                                 * later.
2991                                 */
2992                                error = EIO;
2993                                goto done;
2994                        }
2995                        if (newnfs_sigintr(nmp, td)) {
2996                                error = EINTR;
2997                                goto done;
2998                        }
2999                        if (slpflag == PCATCH) {
3000                                slpflag = 0;
3001                                slptimeo = 2 * hz;
3002                        }
3003                        goto loop;
3004                }
3005                if ((bp->b_flags & B_DELWRI) == 0)
3006                        panic("nfs_fsync: not dirty");
3007                if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) {
3008                        BUF_UNLOCK(bp);
3009                        continue;
3010                }
3011                BO_UNLOCK(bo);
3012                bremfree(bp);
3013                if (passone || !commit)
3014                    bp->b_flags |= B_ASYNC;
3015                else
3016                    bp->b_flags |= B_ASYNC;
3017                bwrite(bp);
3018                if (newnfs_sigintr(nmp, td)) {
3019                        error = EINTR;
3020                        goto done;
3021                }
3022                goto loop;
3023        }
3024        if (passone) {
3025                passone = 0;
3026                BO_UNLOCK(bo);
3027                goto again;
3028        }
3029        if (waitfor == MNT_WAIT) {
3030                while (bo->bo_numoutput) {
3031                        error = bufobj_wwait(bo, slpflag, slptimeo);
3032                        if (error) {
3033                            BO_UNLOCK(bo);
3034                            if (called_from_renewthread != 0) {
3035                                /*
3036                                 * Return EIO so that the flush will be
3037                                 * retried later.
3038                                 */
3039                                error = EIO;
3040                                goto done;
3041                            }
3042                            error = newnfs_sigintr(nmp, td);
3043                            if (error)
3044                                goto done;
3045                            if (slpflag == PCATCH) {
3046                                slpflag = 0;
3047                                slptimeo = 2 * hz;
3048                            }
3049                            BO_LOCK(bo);
3050                        }
3051                }
3052                if (bo->bo_dirty.bv_cnt != 0 && commit) {
3053                        BO_UNLOCK(bo);
3054                        goto loop;
3055                }
3056                /*
3057                 * Wait for all the async IO requests to drain
3058                 */
3059                BO_UNLOCK(bo);
3060                NFSLOCKNODE(np);
3061                while (np->n_directio_asyncwr > 0) {
3062                        np->n_flag |= NFSYNCWAIT;
3063                        error = newnfs_msleep(td, &np->n_directio_asyncwr,
[6e4709b]3064                            &np->n_mtx, slpflag | (PRIBIO + 1),
[6138f24]3065                            "nfsfsync", 0);
3066                        if (error) {
3067                                if (newnfs_sigintr(nmp, td)) {
3068                                        NFSUNLOCKNODE(np);
[6e4709b]3069                                        error = EINTR; 
[6138f24]3070                                        goto done;
3071                                }
3072                        }
3073                }
3074                NFSUNLOCKNODE(np);
3075        } else
3076                BO_UNLOCK(bo);
3077        if (NFSHASPNFS(nmp)) {
3078                nfscl_layoutcommit(vp, td);
3079                /*
3080                 * Invalidate the attribute cache, since writes to a DS
3081                 * won't update the size attribute.
3082                 */
3083                NFSLOCKNODE(np);
3084                np->n_attrstamp = 0;
3085        } else
3086                NFSLOCKNODE(np);
3087        if (np->n_flag & NWRITEERR) {
3088                error = np->n_error;
3089                np->n_flag &= ~NWRITEERR;
3090        }
3091        if (commit && bo->bo_dirty.bv_cnt == 0 &&
3092            bo->bo_numoutput == 0 && np->n_directio_asyncwr == 0)
3093                np->n_flag &= ~NMODIFIED;
3094        NFSUNLOCKNODE(np);
3095done:
3096        if (bvec != NULL && bvec != bvec_on_stack)
3097                free(bvec, M_TEMP);
3098        if (error == 0 && commit != 0 && waitfor == MNT_WAIT &&
3099            (bo->bo_dirty.bv_cnt != 0 || bo->bo_numoutput != 0 ||
3100            np->n_directio_asyncwr != 0)) {
3101                if (trycnt++ < 5) {
3102                        /* try, try again... */
3103                        passone = 1;
3104                        wcred = NULL;
3105                        bvec = NULL;
3106                        bvecsize = 0;
3107                        goto again;
3108                }
3109                vn_printf(vp, "ncl_flush failed");
3110                error = called_from_renewthread != 0 ? EIO : EBUSY;
3111        }
3112        return (error);
3113}
3114
3115/*
3116 * NFS advisory byte-level locks.
3117 */
3118static int
3119nfs_advlock(struct vop_advlock_args *ap)
3120{
3121        struct vnode *vp = ap->a_vp;
3122        struct ucred *cred;
3123        struct nfsnode *np = VTONFS(ap->a_vp);
3124        struct proc *p = (struct proc *)ap->a_id;
3125        struct thread *td = curthread;  /* XXX */
3126        struct vattr va;
3127        int ret, error = EOPNOTSUPP;
3128        u_quad_t size;
[6e4709b]3129       
[6138f24]3130        ret = NFSVOPLOCK(vp, LK_SHARED);
3131        if (ret != 0)
3132                return (EBADF);
3133        if (NFS_ISV4(vp) && (ap->a_flags & (F_POSIX | F_FLOCK)) != 0) {
3134                if (vp->v_type != VREG) {
3135                        NFSVOPUNLOCK(vp, 0);
3136                        return (EINVAL);
3137                }
[882425f]3138#ifndef __rtems__
[6138f24]3139                if ((ap->a_flags & F_POSIX) != 0)
3140                        cred = p->p_ucred;
3141                else
[882425f]3142#endif /* __rtems__ */
[6138f24]3143                        cred = td->td_ucred;
3144                NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY);
3145                if (vp->v_iflag & VI_DOOMED) {
3146                        NFSVOPUNLOCK(vp, 0);
3147                        return (EBADF);
3148                }
3149
3150                /*
3151                 * If this is unlocking a write locked region, flush and
3152                 * commit them before unlocking. This is required by
3153                 * RFC3530 Sec. 9.3.2.
3154                 */
3155                if (ap->a_op == F_UNLCK &&
3156                    nfscl_checkwritelocked(vp, ap->a_fl, cred, td, ap->a_id,
3157                    ap->a_flags))
3158                        (void) ncl_flush(vp, MNT_WAIT, td, 1, 0);
3159
3160                /*
3161                 * Loop around doing the lock op, while a blocking lock
3162                 * must wait for the lock op to succeed.
3163                 */
3164                do {
3165                        ret = nfsrpc_advlock(vp, np->n_size, ap->a_op,
3166                            ap->a_fl, 0, cred, td, ap->a_id, ap->a_flags);
3167                        if (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) &&
3168                            ap->a_op == F_SETLK) {
3169                                NFSVOPUNLOCK(vp, 0);
3170                                error = nfs_catnap(PZERO | PCATCH, ret,
3171                                    "ncladvl");
3172                                if (error)
3173                                        return (EINTR);
3174                                NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY);
3175                                if (vp->v_iflag & VI_DOOMED) {
3176                                        NFSVOPUNLOCK(vp, 0);
3177                                        return (EBADF);
3178                                }
3179                        }
3180                } while (ret == NFSERR_DENIED && (ap->a_flags & F_WAIT) &&
3181                     ap->a_op == F_SETLK);
3182                if (ret == NFSERR_DENIED) {
3183                        NFSVOPUNLOCK(vp, 0);
3184                        return (EAGAIN);
3185                } else if (ret == EINVAL || ret == EBADF || ret == EINTR) {
3186                        NFSVOPUNLOCK(vp, 0);
3187                        return (ret);
3188                } else if (ret != 0) {
3189                        NFSVOPUNLOCK(vp, 0);
3190                        return (EACCES);
3191                }
3192
3193                /*
3194                 * Now, if we just got a lock, invalidate data in the buffer
3195                 * cache, as required, so that the coherency conforms with
3196                 * RFC3530 Sec. 9.3.2.
3197                 */
3198                if (ap->a_op == F_SETLK) {
3199                        if ((np->n_flag & NMODIFIED) == 0) {
3200                                np->n_attrstamp = 0;
3201                                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
3202                                ret = VOP_GETATTR(vp, &va, cred);
3203                        }
3204                        if ((np->n_flag & NMODIFIED) || ret ||
3205                            np->n_change != va.va_filerev) {
3206                                (void) ncl_vinvalbuf(vp, V_SAVE, td, 1);
3207                                np->n_attrstamp = 0;
3208                                KDTRACE_NFS_ATTRCACHE_FLUSH_DONE(vp);
3209                                ret = VOP_GETATTR(vp, &va, cred);
3210                                if (!ret) {
3211                                        np->n_mtime = va.va_mtime;
3212                                        np->n_change = va.va_filerev;
3213                                }
3214                        }
3215                        /* Mark that a file lock has been acquired. */
3216                        NFSLOCKNODE(np);
3217                        np->n_flag |= NHASBEENLOCKED;
3218                        NFSUNLOCKNODE(np);
3219                }
3220                NFSVOPUNLOCK(vp, 0);
3221                return (0);
3222        } else if (!NFS_ISV4(vp)) {
[882425f]3223#ifndef __rtems__
[6138f24]3224                if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
3225                        size = VTONFS(vp)->n_size;
3226                        NFSVOPUNLOCK(vp, 0);
3227                        error = lf_advlock(ap, &(vp->v_lockf), size);
3228                } else {
3229                        if (nfs_advlock_p != NULL)
3230                                error = nfs_advlock_p(ap);
3231                        else {
3232                                NFSVOPUNLOCK(vp, 0);
3233                                error = ENOLCK;
3234                        }
3235                }
3236                if (error == 0 && ap->a_op == F_SETLK) {
3237                        error = NFSVOPLOCK(vp, LK_SHARED);
3238                        if (error == 0) {
3239                                /* Mark that a file lock has been acquired. */
3240                                NFSLOCKNODE(np);
3241                                np->n_flag |= NHASBEENLOCKED;
3242                                NFSUNLOCKNODE(np);
3243                                NFSVOPUNLOCK(vp, 0);
3244                        }
3245                }
[882425f]3246#else /* __rtems__ */
3247                NFSVOPUNLOCK(vp, 0);
3248                return (0);
3249#endif /* __rtems__ */
[6138f24]3250        } else
3251                NFSVOPUNLOCK(vp, 0);
3252        return (error);
3253}
3254
3255/*
3256 * NFS advisory byte-level locks.
3257 */
3258static int
3259nfs_advlockasync(struct vop_advlockasync_args *ap)
3260{
3261        struct vnode *vp = ap->a_vp;
3262        u_quad_t size;
3263        int error;
[6e4709b]3264       
[6138f24]3265        if (NFS_ISV4(vp))
3266                return (EOPNOTSUPP);
3267        error = NFSVOPLOCK(vp, LK_SHARED);
3268        if (error)
3269                return (error);
3270        if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) {
3271                size = VTONFS(vp)->n_size;
3272                NFSVOPUNLOCK(vp, 0);
[882425f]3273#ifndef __rtems__
[6138f24]3274                error = lf_advlockasync(ap, &(vp->v_lockf), size);
[882425f]3275#endif /* __rtems__ */
[6138f24]3276        } else {
3277                NFSVOPUNLOCK(vp, 0);
3278                error = EOPNOTSUPP;
3279        }
3280        return (error);
3281}
3282
3283/*
3284 * Print out the contents of an nfsnode.
3285 */
3286static int
3287nfs_print(struct vop_print_args *ap)
3288{
3289        struct vnode *vp = ap->a_vp;
3290        struct nfsnode *np = VTONFS(vp);
3291
3292        printf("\tfileid %jd fsid 0x%jx", (uintmax_t)np->n_vattr.na_fileid,
3293            (uintmax_t)np->n_vattr.na_fsid);
[882425f]3294#ifndef __rtems__
[6138f24]3295        if (vp->v_type == VFIFO)
3296                fifo_printinfo(vp);
[882425f]3297#endif /* __rtems__ */
[6138f24]3298        printf("\n");
3299        return (0);
3300}
3301
3302/*
3303 * This is the "real" nfs::bwrite(struct buf*).
3304 * We set B_CACHE if this is a VMIO buffer.
3305 */
3306int
3307ncl_writebp(struct buf *bp, int force __unused, struct thread *td)
3308{
3309        int oldflags, rtval;
3310
3311        BUF_ASSERT_HELD(bp);
3312
3313        if (bp->b_flags & B_INVAL) {
3314                brelse(bp);
3315                return (0);
3316        }
3317
3318        oldflags = bp->b_flags;
3319        bp->b_flags |= B_CACHE;
3320
3321        /*
3322         * Undirty the bp.  We will redirty it later if the I/O fails.
3323         */
3324        bundirty(bp);
3325        bp->b_flags &= ~B_DONE;
3326        bp->b_ioflags &= ~BIO_ERROR;
3327        bp->b_iocmd = BIO_WRITE;
3328
3329        bufobj_wref(bp->b_bufobj);
[882425f]3330#ifndef __rtems__
[6138f24]3331        curthread->td_ru.ru_oublock++;
[882425f]3332#endif /* __rtems__ */
[6138f24]3333
3334        /*
3335         * Note: to avoid loopback deadlocks, we do not
3336         * assign b_runningbufspace.
3337         */
3338        vfs_busy_pages(bp, 1);
3339
3340        BUF_KERNPROC(bp);
3341        bp->b_iooffset = dbtob(bp->b_blkno);
3342        bstrategy(bp);
3343
3344        if ((oldflags & B_ASYNC) != 0)
3345                return (0);
3346
3347        rtval = bufwait(bp);
3348        if (oldflags & B_DELWRI)
3349                reassignbuf(bp);
3350        brelse(bp);
3351        return (rtval);
3352}
3353
3354/*
3355 * nfs special file access vnode op.
3356 * Essentially just get vattr and then imitate iaccess() since the device is
3357 * local to the client.
3358 */
3359static int
3360nfsspec_access(struct vop_access_args *ap)
3361{
3362        struct vattr *vap;
3363        struct ucred *cred = ap->a_cred;
3364        struct vnode *vp = ap->a_vp;
3365        accmode_t accmode = ap->a_accmode;
3366        struct vattr vattr;
3367        int error;
3368
3369        /*
3370         * Disallow write attempts on filesystems mounted read-only;
3371         * unless the file is a socket, fifo, or a block or character
3372         * device resident on the filesystem.
3373         */
3374        if ((accmode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3375                switch (vp->v_type) {
3376                case VREG:
3377                case VDIR:
3378                case VLNK:
3379                        return (EROFS);
3380                default:
3381                        break;
3382                }
3383        }
3384        vap = &vattr;
3385        error = VOP_GETATTR(vp, vap, cred);
3386        if (error)
3387                goto out;
3388        error  = vaccess(vp->v_type, vap->va_mode, vap->va_uid, vap->va_gid,
3389            accmode, cred, NULL);
3390out:
3391        return error;
3392}
3393
3394/*
3395 * Read wrapper for fifos.
3396 */
3397static int
3398nfsfifo_read(struct vop_read_args *ap)
3399{
[882425f]3400#ifndef __rtems__
[6138f24]3401        struct nfsnode *np = VTONFS(ap->a_vp);
3402        int error;
3403
3404        /*
3405         * Set access flag.
3406         */
3407        NFSLOCKNODE(np);
3408        np->n_flag |= NACC;
3409        vfs_timestamp(&np->n_atim);
3410        NFSUNLOCKNODE(np);
3411        error = fifo_specops.vop_read(ap);
[6e4709b]3412        return error;   
[882425f]3413#else /* __rtems__ */
3414        return (EINVAL);
3415#endif /* __rtems__ */
[6138f24]3416}
3417
3418/*
3419 * Write wrapper for fifos.
3420 */
3421static int
3422nfsfifo_write(struct vop_write_args *ap)
3423{
[882425f]3424#ifndef __rtems__
[6138f24]3425        struct nfsnode *np = VTONFS(ap->a_vp);
3426
3427        /*
3428         * Set update flag.
3429         */
3430        NFSLOCKNODE(np);
3431        np->n_flag |= NUPD;
3432        vfs_timestamp(&np->n_mtim);
3433        NFSUNLOCKNODE(np);
3434        return(fifo_specops.vop_write(ap));
[882425f]3435#else /* __rtems__ */
3436        return (EINVAL);
3437#endif /* __rtems__ */
[6138f24]3438}
3439
3440/*
3441 * Close wrapper for fifos.
3442 *
3443 * Update the times on the nfsnode then do fifo close.
3444 */
3445static int
3446nfsfifo_close(struct vop_close_args *ap)
3447{
[882425f]3448#ifndef __rtems__
[6138f24]3449        struct vnode *vp = ap->a_vp;
3450        struct nfsnode *np = VTONFS(vp);
3451        struct vattr vattr;
3452        struct timespec ts;
3453
3454        NFSLOCKNODE(np);
3455        if (np->n_flag & (NACC | NUPD)) {
3456                vfs_timestamp(&ts);
3457                if (np->n_flag & NACC)
3458                        np->n_atim = ts;
3459                if (np->n_flag & NUPD)
3460                        np->n_mtim = ts;
3461                np->n_flag |= NCHG;
3462                if (vrefcnt(vp) == 1 &&
3463                    (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) {
3464                        VATTR_NULL(&vattr);
3465                        if (np->n_flag & NACC)
3466                                vattr.va_atime = np->n_atim;
3467                        if (np->n_flag & NUPD)
3468                                vattr.va_mtime = np->n_mtim;
3469                        NFSUNLOCKNODE(np);
3470                        (void)VOP_SETATTR(vp, &vattr, ap->a_cred);
3471                        goto out;
3472                }
3473        }
3474        NFSUNLOCKNODE(np);
3475out:
3476        return (fifo_specops.vop_close(ap));
[882425f]3477#else /* __rtems__ */
3478        return (EINVAL);
3479#endif /* __rtems__ */
[6138f24]3480}
3481
3482/*
3483 * Just call ncl_writebp() with the force argument set to 1.
3484 *
3485 * NOTE: B_DONE may or may not be set in a_bp on call.
3486 */
3487static int
3488nfs_bwrite(struct buf *bp)
3489{
3490
3491        return (ncl_writebp(bp, 1, curthread));
3492}
3493
3494struct buf_ops buf_ops_newnfs = {
3495        .bop_name       =       "buf_ops_nfs",
3496        .bop_write      =       nfs_bwrite,
3497        .bop_strategy   =       bufstrategy,
3498        .bop_sync       =       bufsync,
3499        .bop_bdflush    =       bufbdflush,
3500};
3501
3502static int
3503nfs_getacl(struct vop_getacl_args *ap)
3504{
3505        int error;
3506
3507        if (ap->a_type != ACL_TYPE_NFS4)
3508                return (EOPNOTSUPP);
3509        error = nfsrpc_getacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp,
3510            NULL);
3511        if (error > NFSERR_STALE) {
3512                (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0);
3513                error = EPERM;
3514        }
3515        return (error);
3516}
3517
3518static int
3519nfs_setacl(struct vop_setacl_args *ap)
3520{
3521        int error;
3522
3523        if (ap->a_type != ACL_TYPE_NFS4)
3524                return (EOPNOTSUPP);
3525        error = nfsrpc_setacl(ap->a_vp, ap->a_cred, ap->a_td, ap->a_aclp,
3526            NULL);
3527        if (error > NFSERR_STALE) {
3528                (void) nfscl_maperr(ap->a_td, error, (uid_t)0, (gid_t)0);
3529                error = EPERM;
3530        }
3531        return (error);
3532}
3533
3534/*
3535 * Return POSIX pathconf information applicable to nfs filesystems.
3536 */
3537static int
3538nfs_pathconf(struct vop_pathconf_args *ap)
3539{
3540        struct nfsv3_pathconf pc;
3541        struct nfsvattr nfsva;
3542        struct vnode *vp = ap->a_vp;
3543        struct thread *td = curthread;
3544        int attrflag, error;
3545
3546        if ((NFS_ISV34(vp) && (ap->a_name == _PC_LINK_MAX ||
3547            ap->a_name == _PC_NAME_MAX || ap->a_name == _PC_CHOWN_RESTRICTED ||
3548            ap->a_name == _PC_NO_TRUNC)) ||
3549            (NFS_ISV4(vp) && ap->a_name == _PC_ACL_NFS4)) {
3550                /*
3551                 * Since only the above 4 a_names are returned by the NFSv3
3552                 * Pathconf RPC, there is no point in doing it for others.
3553                 * For NFSv4, the Pathconf RPC (actually a Getattr Op.) can
3554                 * be used for _PC_NFS4_ACL as well.
3555                 */
3556                error = nfsrpc_pathconf(vp, &pc, td->td_ucred, td, &nfsva,
3557                    &attrflag, NULL);
3558                if (attrflag != 0)
3559                        (void) nfscl_loadattrcache(&vp, &nfsva, NULL, NULL, 0,
3560                            1);
3561                if (error != 0)
3562                        return (error);
3563        } else {
3564                /*
3565                 * For NFSv2 (or NFSv3 when not one of the above 4 a_names),
3566                 * just fake them.
3567                 */
3568                pc.pc_linkmax = NFS_LINK_MAX;
3569                pc.pc_namemax = NFS_MAXNAMLEN;
3570                pc.pc_notrunc = 1;
3571                pc.pc_chownrestricted = 1;
3572                pc.pc_caseinsensitive = 0;
3573                pc.pc_casepreserving = 1;
3574                error = 0;
3575        }
3576        switch (ap->a_name) {
3577        case _PC_LINK_MAX:
3578#ifdef _LP64
3579                *ap->a_retval = pc.pc_linkmax;
3580#else
3581                *ap->a_retval = MIN(LONG_MAX, pc.pc_linkmax);
3582#endif
3583                break;
3584        case _PC_NAME_MAX:
3585                *ap->a_retval = pc.pc_namemax;
3586                break;
3587        case _PC_PIPE_BUF:
3588                if (ap->a_vp->v_type == VDIR || ap->a_vp->v_type == VFIFO)
3589                        *ap->a_retval = PIPE_BUF;
3590                else
3591                        error = EINVAL;
3592                break;
3593        case _PC_CHOWN_RESTRICTED:
3594                *ap->a_retval = pc.pc_chownrestricted;
3595                break;
3596        case _PC_NO_TRUNC:
3597                *ap->a_retval = pc.pc_notrunc;
3598                break;
3599        case _PC_ACL_NFS4:
3600                if (NFS_ISV4(vp) && nfsrv_useacl != 0 && attrflag != 0 &&
3601                    NFSISSET_ATTRBIT(&nfsva.na_suppattr, NFSATTRBIT_ACL))
3602                        *ap->a_retval = 1;
3603                else
3604                        *ap->a_retval = 0;
3605                break;
3606        case _PC_ACL_PATH_MAX:
3607                if (NFS_ISV4(vp))
3608                        *ap->a_retval = ACL_MAX_ENTRIES;
3609                else
3610                        *ap->a_retval = 3;
3611                break;
3612        case _PC_PRIO_IO:
3613                *ap->a_retval = 0;
3614                break;
3615        case _PC_SYNC_IO:
3616                *ap->a_retval = 0;
3617                break;
3618        case _PC_ALLOC_SIZE_MIN:
3619                *ap->a_retval = vp->v_mount->mnt_stat.f_bsize;
3620                break;
3621        case _PC_FILESIZEBITS:
3622                if (NFS_ISV34(vp))
3623                        *ap->a_retval = 64;
3624                else
3625                        *ap->a_retval = 32;
3626                break;
3627        case _PC_REC_INCR_XFER_SIZE:
3628                *ap->a_retval = vp->v_mount->mnt_stat.f_iosize;
3629                break;
3630        case _PC_REC_MAX_XFER_SIZE:
3631                *ap->a_retval = -1; /* means ``unlimited'' */
3632                break;
3633        case _PC_REC_MIN_XFER_SIZE:
3634                *ap->a_retval = vp->v_mount->mnt_stat.f_iosize;
3635                break;
3636        case _PC_REC_XFER_ALIGN:
3637                *ap->a_retval = PAGE_SIZE;
3638                break;
3639        case _PC_SYMLINK_MAX:
3640                *ap->a_retval = NFS_MAXPATHLEN;
3641                break;
3642
3643        default:
3644                error = vop_stdpathconf(ap);
3645                break;
3646        }
3647        return (error);
3648}
[6e4709b]3649
Note: See TracBrowser for help on using the repository browser.