]> CyberLeo.Net >> Repos - FreeBSD/stable/8.git/blob - sys/nfsserver/nfs_serv.c
MFC: Temporarily disable WARNS while addressing a non-issue with the
[FreeBSD/stable/8.git] / sys / nfsserver / nfs_serv.c
1 /*-
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rick Macklem at The University of Guelph.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 4. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  *      @(#)nfs_serv.c  8.8 (Berkeley) 7/31/95
33  */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 /*
39  * nfs version 2 and 3 server calls to vnode ops
40  * - these routines generally have 3 phases
41  *   1 - break down and validate rpc request in mbuf list
42  *   2 - do the vnode ops for the request
43  *       (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
44  *   3 - build the rpc reply in an mbuf list
45  *   nb:
46  *      - do not mix the phases, since the nfsm_?? macros can return failures
47  *        on a bad rpc or similar and do not do any vrele() or vput()'s
48  *
49  *      - the nfsm_reply() macro generates an nfs rpc reply with the nfs
50  *      error number iff error != 0 whereas
51  *      returning an error from the server function implies a fatal error
52  *      such as a badly constructed rpc request that should be dropped without
53  *      a reply.
54  *      For nfsm_reply(), the case where error == EBADRPC is treated
55  *      specially; after constructing a reply, it does an immediate
56  *      `goto nfsmout' to avoid getting any V3 post-op status appended.
57  *
58  * Other notes:
59  *      Warning: always pay careful attention to resource cleanup on return
60  *      and note that nfsm_*() macros can terminate a procedure on certain
61  *      errors.
62  *
63  *      lookup() and namei()
64  *      may return garbage in various structural fields/return elements
65  *      if an error is returned, and may garbage up nd.ni_dvp even if no
66  *      error is returned and you did not request LOCKPARENT or WANTPARENT.
67  *
68  *      We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
69  *      buffer has been freed or not.
70  */
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/proc.h>
75 #include <sys/namei.h>
76 #include <sys/unistd.h>
77 #include <sys/vnode.h>
78 #include <sys/mount.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/priv.h>
84 #include <sys/dirent.h>
85 #include <sys/stat.h>
86 #include <sys/kernel.h>
87 #include <sys/sysctl.h>
88 #include <sys/bio.h>
89 #include <sys/buf.h>
90
91 #include <vm/vm.h>
92 #include <vm/vm_extern.h>
93 #include <vm/vm_object.h>
94
95 #include <nfs/nfsproto.h>
96 #include <nfsserver/nfs.h>
97 #include <nfs/xdr_subs.h>
98 #include <nfsserver/nfsm_subs.h>
99
100 #ifdef NFSRV_DEBUG
101 #define nfsdbprintf(info)       printf info
102 #else
103 #define nfsdbprintf(info)
104 #endif
105
106 #define MAX_COMMIT_COUNT        (1024 * 1024)
107
108 #define MAX_REORDERED_RPC       16
109 #define NUM_HEURISTIC           1031
110 #define NHUSE_INIT              64
111 #define NHUSE_INC               16
112 #define NHUSE_MAX               2048
113
114 static struct nfsheur {
115         struct vnode *nh_vp;    /* vp to match (unreferenced pointer) */
116         off_t nh_nextoff;       /* next offset for sequential detection */
117         int nh_use;             /* use count for selection */
118         int nh_seqcount;        /* heuristic */
119 } nfsheur[NUM_HEURISTIC];
120
121 /* Global vars */
122
123 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
124 int nfsrvw_procrastinate_v3 = 0;
125
126 static struct timeval   nfsver = { 0 };
127
128 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
129
130 static int nfs_async;
131 static int nfs_commit_blks;
132 static int nfs_commit_miss;
133 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
134     "Tell client that writes were synced even though they were not");
135 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0,
136     "Number of completed commits");
137 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
138
139 struct nfsrvstats nfsrvstats;
140 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
141         &nfsrvstats, nfsrvstats, "S,nfsrvstats");
142
143 static int      nfsrv_access(struct vnode *, accmode_t, struct ucred *,
144                     int, int);
145
146 /*
147  * Clear nameidata fields that are tested in nsfmout cleanup code prior
148  * to using first nfsm macro (that might jump to the cleanup code).
149  */
150
151 static __inline void
152 ndclear(struct nameidata *nd)
153 {
154
155         nd->ni_cnd.cn_flags = 0;
156         nd->ni_vp = NULL;
157         nd->ni_dvp = NULL;
158         nd->ni_startdir = NULL;
159 }
160
161 /*
162  * Takes two vfslocked integers and returns with at most one
163  * reference to giant.  The return value indicates whether giant
164  * is held by either lock.  This simplifies nfsrv ops by allowing
165  * them to track only one vfslocked var.
166  */
167 static __inline int
168 nfsrv_lockedpair(int vfs1, int vfs2)
169 {
170
171         if (vfs1 && vfs2)
172                 VFS_UNLOCK_GIANT(vfs2);
173
174         return (vfs1 | vfs2);
175 }
176
177 static __inline int
178 nfsrv_lockedpair_nd(int vfs1, struct nameidata *nd)
179 {
180         int vfs2;
181
182         vfs2 = NDHASGIANT(nd);
183
184         return nfsrv_lockedpair(vfs1, vfs2);
185 }
186
187 /*
188  * Heuristic to detect sequential operation.
189  */
190 static struct nfsheur *
191 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp)
192 {
193         struct nfsheur *nh;
194         int hi, try;
195
196         /* Locate best candidate. */
197         try = 32;
198         hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
199         nh = &nfsheur[hi];
200         while (try--) {
201                 if (nfsheur[hi].nh_vp == vp) {
202                         nh = &nfsheur[hi];
203                         break;
204                 }
205                 if (nfsheur[hi].nh_use > 0)
206                         --nfsheur[hi].nh_use;
207                 hi = (hi + 1) % NUM_HEURISTIC;
208                 if (nfsheur[hi].nh_use < nh->nh_use)
209                         nh = &nfsheur[hi];
210         }
211
212         /* Initialize hint if this is a new file. */
213         if (nh->nh_vp != vp) {
214                 nh->nh_vp = vp;
215                 nh->nh_nextoff = uio->uio_offset;
216                 nh->nh_use = NHUSE_INIT;
217                 if (uio->uio_offset == 0)
218                         nh->nh_seqcount = 4;
219                 else
220                         nh->nh_seqcount = 1;
221         }
222
223         /* Calculate heuristic. */
224         if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) ||
225             uio->uio_offset == nh->nh_nextoff) {
226                 /* See comments in vfs_vnops.c:sequential_heuristic(). */
227                 nh->nh_seqcount += howmany(uio->uio_resid, 16384);
228                 if (nh->nh_seqcount > IO_SEQMAX)
229                         nh->nh_seqcount = IO_SEQMAX;
230         } else if (qabs(uio->uio_offset - nh->nh_nextoff) <= MAX_REORDERED_RPC *
231             imax(vp->v_mount->mnt_stat.f_iosize, uio->uio_resid)) {
232                 /* Probably a reordered RPC, leave seqcount alone. */
233         } else if (nh->nh_seqcount > 1) {
234                 nh->nh_seqcount /= 2;
235         } else {
236                 nh->nh_seqcount = 0;
237         }
238         nh->nh_use += NHUSE_INC;
239         if (nh->nh_use > NHUSE_MAX)
240                 nh->nh_use = NHUSE_MAX;
241         return (nh);
242 }
243
244 /*
245  * nfs v3 access service
246  */
247 int
248 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
249     struct mbuf **mrq)
250 {
251         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
252         struct sockaddr *nam = nfsd->nd_nam;
253         caddr_t dpos = nfsd->nd_dpos;
254         struct ucred *cred = nfsd->nd_cr;
255         struct vnode *vp = NULL;
256         nfsfh_t nfh;
257         fhandle_t *fhp;
258         u_int32_t *tl;
259         caddr_t bpos;
260         int error = 0, rdonly, getret;
261         struct mbuf *mb, *mreq;
262         struct vattr vattr, *vap = &vattr;
263         u_long testmode, nfsmode;
264         int v3 = (nfsd->nd_flag & ND_NFSV3);
265         int vfslocked;
266
267         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
268         if (!v3)
269                 panic("nfsrv3_access: v3 proc called on a v2 connection");
270         vfslocked = 0;
271         fhp = &nfh.fh_generic;
272         nfsm_srvmtofh(fhp);
273         tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
274         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
275         if (error) {
276                 nfsm_reply(NFSX_UNSIGNED);
277                 nfsm_srvpostop_attr(1, NULL);
278                 error = 0;
279                 goto nfsmout;
280         }
281         nfsmode = fxdr_unsigned(u_int32_t, *tl);
282         if ((nfsmode & NFSV3ACCESS_READ) &&
283                 nfsrv_access(vp, VREAD, cred, rdonly, 0))
284                 nfsmode &= ~NFSV3ACCESS_READ;
285         if (vp->v_type == VDIR)
286                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
287                         NFSV3ACCESS_DELETE);
288         else
289                 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
290         if ((nfsmode & testmode) &&
291                 nfsrv_access(vp, VWRITE, cred, rdonly, 0))
292                 nfsmode &= ~testmode;
293         if (vp->v_type == VDIR)
294                 testmode = NFSV3ACCESS_LOOKUP;
295         else
296                 testmode = NFSV3ACCESS_EXECUTE;
297         if ((nfsmode & testmode) &&
298                 nfsrv_access(vp, VEXEC, cred, rdonly, 0))
299                 nfsmode &= ~testmode;
300         getret = VOP_GETATTR(vp, vap, cred);
301         vput(vp);
302         vp = NULL;
303         nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
304         nfsm_srvpostop_attr(getret, vap);
305         tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
306         *tl = txdr_unsigned(nfsmode);
307 nfsmout:
308         if (vp)
309                 vput(vp);
310         VFS_UNLOCK_GIANT(vfslocked);
311         return(error);
312 }
313
314 /*
315  * nfs getattr service
316  */
317 int
318 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
319     struct mbuf **mrq)
320 {
321         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
322         struct sockaddr *nam = nfsd->nd_nam;
323         caddr_t dpos = nfsd->nd_dpos;
324         struct ucred *cred = nfsd->nd_cr;
325         struct nfs_fattr *fp;
326         struct vattr va;
327         struct vattr *vap = &va;
328         struct vnode *vp = NULL;
329         nfsfh_t nfh;
330         fhandle_t *fhp;
331         caddr_t bpos;
332         int error = 0, rdonly;
333         struct mbuf *mb, *mreq;
334         int vfslocked;
335
336         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
337         vfslocked = 0;
338         fhp = &nfh.fh_generic;
339         nfsm_srvmtofh(fhp);
340         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
341         if (error) {
342                 nfsm_reply(0);
343                 error = 0;
344                 goto nfsmout;
345         }
346         error = VOP_GETATTR(vp, vap, cred);
347         vput(vp);
348         vp = NULL;
349         nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
350         if (error) {
351                 error = 0;
352                 goto nfsmout;
353         }
354         fp = nfsm_build(struct nfs_fattr *,
355             NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
356         nfsm_srvfillattr(vap, fp);
357         /* fall through */
358
359 nfsmout:
360         if (vp)
361                 vput(vp);
362         VFS_UNLOCK_GIANT(vfslocked);
363         return(error);
364 }
365
366 /*
367  * nfs setattr service
368  */
369 int
370 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
371     struct mbuf **mrq)
372 {
373         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
374         struct sockaddr *nam = nfsd->nd_nam;
375         caddr_t dpos = nfsd->nd_dpos;
376         struct ucred *cred = nfsd->nd_cr;
377         struct vattr va, preat;
378         struct vattr *vap = &va;
379         struct nfsv2_sattr *sp;
380         struct nfs_fattr *fp;
381         struct vnode *vp = NULL;
382         nfsfh_t nfh;
383         fhandle_t *fhp;
384         u_int32_t *tl;
385         caddr_t bpos;
386         int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
387         int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
388         struct mbuf *mb, *mreq;
389         struct timespec guard = { 0, 0 };
390         struct mount *mp = NULL;
391         int tvfslocked;
392         int vfslocked;
393
394         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
395         vfslocked = 0;
396         fhp = &nfh.fh_generic;
397         nfsm_srvmtofh(fhp);
398         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
399                 error = ESTALE;
400                 goto out;
401         }
402         vfslocked = VFS_LOCK_GIANT(mp);
403         (void) vn_start_write(NULL, &mp, V_WAIT);
404         vfs_rel(mp);            /* The write holds a ref. */
405         VATTR_NULL(vap);
406         if (v3) {
407                 nfsm_srvsattr(vap);
408                 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
409                 gcheck = fxdr_unsigned(int, *tl);
410                 if (gcheck) {
411                         tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
412                         fxdr_nfsv3time(tl, &guard);
413                 }
414         } else {
415                 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
416                 /*
417                  * Nah nah nah nah na nah
418                  * There is a bug in the Sun client that puts 0xffff in the mode
419                  * field of sattr when it should put in 0xffffffff. The u_short
420                  * doesn't sign extend.
421                  * --> check the low order 2 bytes for 0xffff
422                  */
423                 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
424                         vap->va_mode = nfstov_mode(sp->sa_mode);
425                 if (sp->sa_uid != nfsrv_nfs_xdrneg1)
426                         vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
427                 if (sp->sa_gid != nfsrv_nfs_xdrneg1)
428                         vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
429                 if (sp->sa_size != nfsrv_nfs_xdrneg1)
430                         vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
431                 if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
432 #ifdef notyet
433                         fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
434 #else
435                         vap->va_atime.tv_sec =
436                                 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
437                         vap->va_atime.tv_nsec = 0;
438 #endif
439                 }
440                 if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
441                         fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
442
443         }
444
445         /*
446          * Now that we have all the fields, lets do it.
447          */
448         error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
449         vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
450         if (error) {
451                 nfsm_reply(2 * NFSX_UNSIGNED);
452                 if (v3)
453                         nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
454                 error = 0;
455                 goto nfsmout;
456         }
457
458         /*
459          * vp now an active resource, pay careful attention to cleanup
460          */
461         if (v3) {
462                 error = preat_ret = VOP_GETATTR(vp, &preat, cred);
463                 if (!error && gcheck &&
464                         (preat.va_ctime.tv_sec != guard.tv_sec ||
465                          preat.va_ctime.tv_nsec != guard.tv_nsec))
466                         error = NFSERR_NOT_SYNC;
467                 if (error) {
468                         vput(vp);
469                         vp = NULL;
470                         nfsm_reply(NFSX_WCCDATA(v3));
471                         if (v3)
472                                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
473                         error = 0;
474                         goto nfsmout;
475                 }
476         }
477
478         /*
479          * If the size is being changed write acces is required, otherwise
480          * just check for a read only filesystem.
481          */
482         if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
483                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
484                         error = EROFS;
485                         goto out;
486                 }
487         } else {
488                 if (vp->v_type == VDIR) {
489                         error = EISDIR;
490                         goto out;
491                 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
492                     0)) != 0)
493                         goto out;
494         }
495         error = VOP_SETATTR(vp, vap, cred);
496         postat_ret = VOP_GETATTR(vp, vap, cred);
497         if (!error)
498                 error = postat_ret;
499 out:
500         if (vp != NULL)
501                 vput(vp);
502
503         vp = NULL;
504         nfsm_reply(NFSX_WCCORFATTR(v3));
505         if (v3) {
506                 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
507         } else if (!error) {
508                 /* v2 non-error case. */
509                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
510                 nfsm_srvfillattr(vap, fp);
511         }
512         error = 0;
513         /* fall through */
514
515 nfsmout:
516         if (vp)
517                 vput(vp);
518         vn_finished_write(mp);
519         VFS_UNLOCK_GIANT(vfslocked);
520         return(error);
521 }
522
523 /*
524  * nfs lookup rpc
525  */
526 int
527 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
528     struct mbuf **mrq)
529 {
530         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
531         struct sockaddr *nam = nfsd->nd_nam;
532         caddr_t dpos = nfsd->nd_dpos;
533         struct ucred *cred = nfsd->nd_cr;
534         struct nfs_fattr *fp;
535         struct nameidata nd, ind, *ndp = &nd;
536         struct vnode *vp, *dirp = NULL;
537         nfsfh_t nfh;
538         fhandle_t *fhp;
539         caddr_t bpos;
540         int error = 0, len, dirattr_ret = 1;
541         int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
542         struct mbuf *mb, *mreq;
543         struct vattr va, dirattr, *vap = &va;
544         int tvfslocked;
545         int vfslocked;
546
547         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
548         ndclear(&nd);
549         vfslocked = 0;
550
551         fhp = &nfh.fh_generic;
552         nfsm_srvmtofh(fhp);
553         nfsm_srvnamesiz(len);
554
555         pubflag = nfs_ispublicfh(fhp);
556
557         nd.ni_cnd.cn_cred = cred;
558         nd.ni_cnd.cn_nameiop = LOOKUP;
559         nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART | MPSAFE;
560         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
561                 &dirp, v3, &dirattr, &dirattr_ret, pubflag);
562         vfslocked = NDHASGIANT(&nd);
563
564         /*
565          * namei failure, only dirp to cleanup.  Clear out garbarge from
566          * structure in case macros jump to nfsmout.
567          */
568
569         if (error) {
570                 if (dirp) {
571                         vrele(dirp);
572                         dirp = NULL;
573                 }
574                 nfsm_reply(NFSX_POSTOPATTR(v3));
575                 if (v3)
576                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
577                 error = 0;
578                 goto nfsmout;
579         }
580
581         /*
582          * Locate index file for public filehandle
583          *
584          * error is 0 on entry and 0 on exit from this block.
585          */
586
587         if (pubflag) {
588                 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
589                         /*
590                          * Setup call to lookup() to see if we can find
591                          * the index file. Arguably, this doesn't belong
592                          * in a kernel.. Ugh.  If an error occurs, do not
593                          * try to install an index file and then clear the
594                          * error.
595                          *
596                          * When we replace nd with ind and redirect ndp,
597                          * maintenance of ni_startdir and ni_vp shift to
598                          * ind and we have to clean them up in the old nd.
599                          * However, the cnd resource continues to be maintained
600                          * via the original nd.  Confused?  You aren't alone!
601                          */
602                         ind = nd;
603                         VOP_UNLOCK(nd.ni_vp, 0);
604                         ind.ni_pathlen = strlen(nfs_pub.np_index);
605                         ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
606                             nfs_pub.np_index;
607                         ind.ni_startdir = nd.ni_vp;
608                         VREF(ind.ni_startdir);
609                         ind.ni_cnd.cn_flags &= ~GIANTHELD;
610                         tvfslocked = VFS_LOCK_GIANT(ind.ni_startdir->v_mount);
611                         if (tvfslocked)
612                                 nd.ni_cnd.cn_flags |= GIANTHELD;
613                         error = lookup(&ind);
614                         ind.ni_dvp = NULL;
615                         vfslocked = nfsrv_lockedpair_nd(vfslocked, &ind);
616                         ind.ni_cnd.cn_flags &= ~GIANTHELD;
617
618                         if (error == 0) {
619                                 /*
620                                  * Found an index file. Get rid of
621                                  * the old references.  transfer nd.ni_vp'
622                                  */
623                                 if (dirp)
624                                         vrele(dirp);
625                                 dirp = nd.ni_vp;
626                                 nd.ni_vp = NULL;
627                                 vrele(nd.ni_startdir);
628                                 nd.ni_startdir = NULL;
629                                 ndp = &ind;
630                         }
631                         error = 0;
632                 }
633                 /*
634                  * If the public filehandle was used, check that this lookup
635                  * didn't result in a filehandle outside the publicly exported
636                  * filesystem.  We clear the poor vp here to avoid lockups due
637                  * to NFS I/O.
638                  */
639
640                 if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
641                         vput(nd.ni_vp);
642                         nd.ni_vp = NULL;
643                         error = EPERM;
644                 }
645         }
646
647         /*
648          * Resources at this point:
649          *      ndp->ni_vp      may not be NULL
650          */
651
652         if (error) {
653                 nfsm_reply(NFSX_POSTOPATTR(v3));
654                 if (v3)
655                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
656                 error = 0;
657                 goto nfsmout;
658         }
659
660         /*
661          * Get underlying attribute, then release remaining resources ( for
662          * the same potential blocking reason ) and reply.
663          */
664         vp = ndp->ni_vp;
665         bzero((caddr_t)fhp, sizeof(nfh));
666         fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
667         error = VOP_VPTOFH(vp, &fhp->fh_fid);
668         if (!error)
669                 error = VOP_GETATTR(vp, vap, cred);
670
671         vput(vp);
672         vrele(ndp->ni_startdir);
673         vrele(dirp);
674         ndp->ni_vp = NULL;
675         ndp->ni_startdir = NULL;
676         dirp = NULL;
677         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
678         if (error) {
679                 if (v3)
680                         nfsm_srvpostop_attr(dirattr_ret, &dirattr);
681                 error = 0;
682                 goto nfsmout;
683         }
684         nfsm_srvfhtom(fhp, v3);
685         if (v3) {
686                 nfsm_srvpostop_attr(0, vap);
687                 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
688         } else {
689                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
690                 nfsm_srvfillattr(vap, fp);
691         }
692
693 nfsmout:
694         if (ndp->ni_vp || dirp || ndp->ni_startdir) {
695                 if (ndp->ni_vp)
696                         vput(ndp->ni_vp);
697                 if (dirp)
698                         vrele(dirp);
699                 if (ndp->ni_startdir)
700                         vrele(ndp->ni_startdir);
701         }
702         NDFREE(&nd, NDF_ONLY_PNBUF);
703         VFS_UNLOCK_GIANT(vfslocked);
704         return (error);
705 }
706
707 /*
708  * nfs readlink service
709  */
710 int
711 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
712     struct mbuf **mrq)
713 {
714         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
715         struct sockaddr *nam = nfsd->nd_nam;
716         caddr_t dpos = nfsd->nd_dpos;
717         struct ucred *cred = nfsd->nd_cr;
718         struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
719         struct iovec *ivp = iv;
720         struct mbuf *mp;
721         u_int32_t *tl;
722         caddr_t bpos;
723         int error = 0, rdonly, i, tlen, len, getret;
724         int v3 = (nfsd->nd_flag & ND_NFSV3);
725         struct mbuf *mb, *mp3, *nmp, *mreq;
726         struct vnode *vp = NULL;
727         struct vattr attr;
728         nfsfh_t nfh;
729         fhandle_t *fhp;
730         struct uio io, *uiop = &io;
731         int vfslocked;
732
733         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
734         vfslocked = 0;
735 #ifndef nolint
736         mp = NULL;
737 #endif
738         mp3 = NULL;
739         fhp = &nfh.fh_generic;
740         nfsm_srvmtofh(fhp);
741         len = 0;
742         i = 0;
743         while (len < NFS_MAXPATHLEN) {
744                 MGET(nmp, M_WAIT, MT_DATA);
745                 MCLGET(nmp, M_WAIT);
746                 nmp->m_len = NFSMSIZ(nmp);
747                 if (len == 0)
748                         mp3 = mp = nmp;
749                 else {
750                         mp->m_next = nmp;
751                         mp = nmp;
752                 }
753                 if ((len + mp->m_len) > NFS_MAXPATHLEN) {
754                         mp->m_len = NFS_MAXPATHLEN - len;
755                         len = NFS_MAXPATHLEN;
756                 } else
757                         len += mp->m_len;
758                 ivp->iov_base = mtod(mp, caddr_t);
759                 ivp->iov_len = mp->m_len;
760                 i++;
761                 ivp++;
762         }
763         uiop->uio_iov = iv;
764         uiop->uio_iovcnt = i;
765         uiop->uio_offset = 0;
766         uiop->uio_resid = len;
767         uiop->uio_rw = UIO_READ;
768         uiop->uio_segflg = UIO_SYSSPACE;
769         uiop->uio_td = NULL;
770         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
771         if (error) {
772                 nfsm_reply(2 * NFSX_UNSIGNED);
773                 if (v3)
774                         nfsm_srvpostop_attr(1, NULL);
775                 error = 0;
776                 goto nfsmout;
777         }
778         if (vp->v_type != VLNK) {
779                 if (v3)
780                         error = EINVAL;
781                 else
782                         error = ENXIO;
783         } else 
784                 error = VOP_READLINK(vp, uiop, cred);
785         getret = VOP_GETATTR(vp, &attr, cred);
786         vput(vp);
787         vp = NULL;
788         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
789         if (v3)
790                 nfsm_srvpostop_attr(getret, &attr);
791         if (error) {
792                 error = 0;
793                 goto nfsmout;
794         }
795         if (uiop->uio_resid > 0) {
796                 len -= uiop->uio_resid;
797                 tlen = nfsm_rndup(len);
798                 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
799         }
800         tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
801         *tl = txdr_unsigned(len);
802         mb->m_next = mp3;
803         mp3 = NULL;
804 nfsmout:
805         if (mp3)
806                 m_freem(mp3);
807         if (vp)
808                 vput(vp);
809         VFS_UNLOCK_GIANT(vfslocked);
810         return(error);
811 }
812
813 /*
814  * nfs read service
815  */
816 int
817 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
818     struct mbuf **mrq)
819 {
820         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
821         struct sockaddr *nam = nfsd->nd_nam;
822         caddr_t dpos = nfsd->nd_dpos;
823         struct ucred *cred = nfsd->nd_cr;
824         struct iovec *iv;
825         struct iovec *iv2;
826         struct mbuf *m;
827         struct nfs_fattr *fp;
828         u_int32_t *tl;
829         int i;
830         caddr_t bpos;
831         int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
832         int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
833         struct mbuf *mb, *mreq;
834         struct mbuf *m2;
835         struct vnode *vp = NULL;
836         nfsfh_t nfh;
837         fhandle_t *fhp;
838         struct uio io, *uiop = &io;
839         struct vattr va, *vap = &va;
840         struct nfsheur *nh;
841         off_t off;
842         int ioflag = 0;
843         int vfslocked;
844
845
846         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
847         vfslocked = 0;
848         fhp = &nfh.fh_generic;
849         nfsm_srvmtofh(fhp);
850         if (v3) {
851                 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
852                 off = fxdr_hyper(tl);
853         } else {
854                 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
855                 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
856         }
857         nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
858
859         /*
860          * Reference vp.  If an error occurs, vp will be invalid, but we
861          * have to NULL it just in case.  The macros might goto nfsmout
862          * as well.
863          */
864
865         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
866         if (error) {
867                 vp = NULL;
868                 nfsm_reply(2 * NFSX_UNSIGNED);
869                 if (v3)
870                         nfsm_srvpostop_attr(1, NULL);
871                 error = 0;
872                 goto nfsmout;
873         }
874
875         if (vp->v_type != VREG) {
876                 if (v3)
877                         error = EINVAL;
878                 else
879                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
880         }
881         if (!error) {
882                 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, 1)) != 0)
883                         error = nfsrv_access(vp, VEXEC, cred, rdonly, 1);
884         }
885         getret = VOP_GETATTR(vp, vap, cred);
886         if (!error)
887                 error = getret;
888         if (error) {
889                 vput(vp);
890                 vp = NULL;
891                 nfsm_reply(NFSX_POSTOPATTR(v3));
892                 if (v3)
893                         nfsm_srvpostop_attr(getret, vap);
894                 error = 0;
895                 goto nfsmout;
896         }
897
898         /*
899          * Calculate byte count to read
900          */
901         if (off >= vap->va_size)
902                 cnt = 0;
903         else if ((off + reqlen) > vap->va_size)
904                 cnt = vap->va_size - off;
905         else
906                 cnt = reqlen;
907
908         nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
909         if (v3) {
910                 tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
911                 *tl++ = nfsrv_nfs_true;
912                 fp = (struct nfs_fattr *)tl;
913                 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
914         } else {
915                 tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
916                 fp = (struct nfs_fattr *)tl;
917                 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
918         }
919         len = left = nfsm_rndup(cnt);
920         if (cnt > 0) {
921                 /*
922                  * Generate the mbuf list with the uio_iov ref. to it.
923                  */
924                 i = 0;
925                 m = m2 = mb;
926                 while (left > 0) {
927                         siz = min(M_TRAILINGSPACE(m), left);
928                         if (siz > 0) {
929                                 left -= siz;
930                                 i++;
931                         }
932                         if (left > 0) {
933                                 MGET(m, M_WAIT, MT_DATA);
934                                 MCLGET(m, M_WAIT);
935                                 m->m_len = 0;
936                                 m2->m_next = m;
937                                 m2 = m;
938                         }
939                 }
940                 iv = malloc(i * sizeof (struct iovec),
941                        M_TEMP, M_WAITOK);
942                 uiop->uio_iov = iv2 = iv;
943                 m = mb;
944                 left = len;
945                 i = 0;
946                 while (left > 0) {
947                         if (m == NULL)
948                                 panic("nfsrv_read iov");
949                         siz = min(M_TRAILINGSPACE(m), left);
950                         if (siz > 0) {
951                                 iv->iov_base = mtod(m, caddr_t) + m->m_len;
952                                 iv->iov_len = siz;
953                                 m->m_len += siz;
954                                 left -= siz;
955                                 iv++;
956                                 i++;
957                         }
958                         m = m->m_next;
959                 }
960                 uiop->uio_iovcnt = i;
961                 uiop->uio_offset = off;
962                 uiop->uio_resid = len;
963                 uiop->uio_rw = UIO_READ;
964                 uiop->uio_segflg = UIO_SYSSPACE;
965                 nh = nfsrv_sequential_heuristic(uiop, vp);
966                 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
967                 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
968                 if (error == 0)
969                         nh->nh_nextoff = uiop->uio_offset;
970                 free((caddr_t)iv2, M_TEMP);
971                 if (error || (getret = VOP_GETATTR(vp, vap, cred))) {
972                         if (!error)
973                                 error = getret;
974                         m_freem(mreq);
975                         vput(vp);
976                         vp = NULL;
977                         nfsm_reply(NFSX_POSTOPATTR(v3));
978                         if (v3)
979                                 nfsm_srvpostop_attr(getret, vap);
980                         error = 0;
981                         goto nfsmout;
982                 }
983         } else
984                 uiop->uio_resid = 0;
985         vput(vp);
986         vp = NULL;
987         nfsm_srvfillattr(vap, fp);
988         tlen = len - uiop->uio_resid;
989         cnt = cnt < tlen ? cnt : tlen;
990         tlen = nfsm_rndup(cnt);
991         if (len != tlen || tlen != cnt)
992                 nfsm_adj(mb, len - tlen, tlen - cnt);
993         if (v3) {
994                 *tl++ = txdr_unsigned(cnt);
995                 if (cnt < reqlen)
996                         *tl++ = nfsrv_nfs_true;
997                 else
998                         *tl++ = nfsrv_nfs_false;
999         }
1000         *tl = txdr_unsigned(cnt);
1001 nfsmout:
1002         if (vp)
1003                 vput(vp);
1004         VFS_UNLOCK_GIANT(vfslocked);
1005         return(error);
1006 }
1007
1008 /*
1009  * nfs write service
1010  */
1011 int
1012 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1013     struct mbuf **mrq)
1014 {
1015         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1016         struct sockaddr *nam = nfsd->nd_nam;
1017         caddr_t dpos = nfsd->nd_dpos;
1018         struct ucred *cred = nfsd->nd_cr;
1019         struct iovec *ivp;
1020         int i, cnt;
1021         struct mbuf *mp;
1022         struct nfs_fattr *fp;
1023         struct iovec *iv;
1024         struct vattr va, forat;
1025         struct vattr *vap = &va;
1026         u_int32_t *tl;
1027         caddr_t bpos;
1028         int error = 0, rdonly, len, forat_ret = 1;
1029         int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
1030         int stable = NFSV3WRITE_FILESYNC;
1031         int v3 = (nfsd->nd_flag & ND_NFSV3);
1032         struct mbuf *mb, *mreq;
1033         struct vnode *vp = NULL;
1034         struct nfsheur *nh;
1035         nfsfh_t nfh;
1036         fhandle_t *fhp;
1037         struct uio io, *uiop = &io;
1038         off_t off;
1039         struct mount *mntp = NULL;
1040         int tvfslocked;
1041         int vfslocked;
1042
1043         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1044         vfslocked = 0;
1045         if (mrep == NULL) {
1046                 *mrq = NULL;
1047                 error = 0;
1048                 goto nfsmout;
1049         }
1050         fhp = &nfh.fh_generic;
1051         nfsm_srvmtofh(fhp);
1052         if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1053                 error = ESTALE;
1054                 goto ereply;
1055         }
1056         vfslocked = VFS_LOCK_GIANT(mntp);
1057         (void) vn_start_write(NULL, &mntp, V_WAIT);
1058         vfs_rel(mntp);          /* The write holds a ref. */
1059         if (v3) {
1060                 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1061                 off = fxdr_hyper(tl);
1062                 tl += 3;
1063                 stable = fxdr_unsigned(int, *tl++);
1064         } else {
1065                 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1066                 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1067                 tl += 2;
1068                 if (nfs_async)
1069                         stable = NFSV3WRITE_UNSTABLE;
1070         }
1071         retlen = len = fxdr_unsigned(int32_t, *tl);
1072         cnt = i = 0;
1073
1074         /*
1075          * For NFS Version 2, it is not obvious what a write of zero length
1076          * should do, but I might as well be consistent with Version 3,
1077          * which is to return ok so long as there are no permission problems.
1078          */
1079         if (len > 0) {
1080             zeroing = 1;
1081             mp = mrep;
1082             while (mp) {
1083                 if (mp == md) {
1084                         zeroing = 0;
1085                         adjust = dpos - mtod(mp, caddr_t);
1086                         mp->m_len -= adjust;
1087                         if (mp->m_len > 0 && adjust > 0)
1088                                 mp->m_data += adjust;
1089                 }
1090                 if (zeroing)
1091                         mp->m_len = 0;
1092                 else if (mp->m_len > 0) {
1093                         i += mp->m_len;
1094                         if (i > len) {
1095                                 mp->m_len -= (i - len);
1096                                 zeroing = 1;
1097                         }
1098                         if (mp->m_len > 0)
1099                                 cnt++;
1100                 }
1101                 mp = mp->m_next;
1102             }
1103         }
1104         if (len > NFS_MAXDATA || len < 0 || i < len) {
1105                 error = EIO;
1106                 nfsm_reply(2 * NFSX_UNSIGNED);
1107                 if (v3)
1108                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1109                 error = 0;
1110                 goto nfsmout;
1111         }
1112         error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
1113         vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
1114         if (error) {
1115                 vp = NULL;
1116                 nfsm_reply(2 * NFSX_UNSIGNED);
1117                 if (v3)
1118                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1119                 error = 0;
1120                 goto nfsmout;
1121         }
1122         if (v3)
1123                 forat_ret = VOP_GETATTR(vp, &forat, cred);
1124         if (vp->v_type != VREG) {
1125                 if (v3)
1126                         error = EINVAL;
1127                 else
1128                         error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1129         }
1130         if (!error)
1131                 error = nfsrv_access(vp, VWRITE, cred, rdonly, 1);
1132         if (error) {
1133                 vput(vp);
1134                 vp = NULL;
1135                 nfsm_reply(NFSX_WCCDATA(v3));
1136                 if (v3)
1137                         nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1138                 error = 0;
1139                 goto nfsmout;
1140         }
1141
1142         if (len > 0) {
1143             ivp = malloc(cnt * sizeof (struct iovec), M_TEMP,
1144                 M_WAITOK);
1145             uiop->uio_iov = iv = ivp;
1146             uiop->uio_iovcnt = cnt;
1147             mp = mrep;
1148             while (mp) {
1149                 if (mp->m_len > 0) {
1150                         ivp->iov_base = mtod(mp, caddr_t);
1151                         ivp->iov_len = mp->m_len;
1152                         ivp++;
1153                 }
1154                 mp = mp->m_next;
1155             }
1156
1157             /*
1158              * XXX
1159              * The IO_METASYNC flag indicates that all metadata (and not just
1160              * enough to ensure data integrity) mus be written to stable storage
1161              * synchronously.
1162              * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1163              */
1164             if (stable == NFSV3WRITE_UNSTABLE)
1165                 ioflags = IO_NODELOCKED;
1166             else if (stable == NFSV3WRITE_DATASYNC)
1167                 ioflags = (IO_SYNC | IO_NODELOCKED);
1168             else
1169                 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1170             uiop->uio_resid = len;
1171             uiop->uio_rw = UIO_WRITE;
1172             uiop->uio_segflg = UIO_SYSSPACE;
1173             uiop->uio_td = NULL;
1174             uiop->uio_offset = off;
1175             nh = nfsrv_sequential_heuristic(uiop, vp);
1176             ioflags |= nh->nh_seqcount << IO_SEQSHIFT;
1177             error = VOP_WRITE(vp, uiop, ioflags, cred);
1178             if (error == 0)
1179                     nh->nh_nextoff = uiop->uio_offset;
1180             /* Unlocked write. */
1181             nfsrvstats.srvvop_writes++;
1182             free((caddr_t)iv, M_TEMP);
1183         }
1184         aftat_ret = VOP_GETATTR(vp, vap, cred);
1185         vput(vp);
1186         vp = NULL;
1187         if (!error)
1188                 error = aftat_ret;
1189 ereply:
1190         nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1191                 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1192         if (v3) {
1193                 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1194                 if (error) {
1195                         error = 0;
1196                         goto nfsmout;
1197                 }
1198                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1199                 *tl++ = txdr_unsigned(retlen);
1200                 /*
1201                  * If nfs_async is set, then pretend the write was FILESYNC.
1202                  */
1203                 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1204                         *tl++ = txdr_unsigned(stable);
1205                 else
1206                         *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1207                 /*
1208                  * Actually, there is no need to txdr these fields,
1209                  * but it may make the values more human readable,
1210                  * for debugging purposes.
1211                  */
1212                 if (nfsver.tv_sec == 0)
1213                         nfsver = boottime;
1214                 *tl++ = txdr_unsigned(nfsver.tv_sec);
1215                 *tl = txdr_unsigned(nfsver.tv_usec);
1216         } else if (!error) {
1217                 /* v2 non-error case. */
1218                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1219                 nfsm_srvfillattr(vap, fp);
1220         }
1221         error = 0;
1222 nfsmout:
1223         if (vp)
1224                 vput(vp);
1225         vn_finished_write(mntp);
1226         VFS_UNLOCK_GIANT(vfslocked);
1227         return(error);
1228 }
1229
1230 /*
1231  * nfs create service
1232  * now does a truncate to 0 length via. setattr if it already exists
1233  */
1234 int
1235 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1236     struct mbuf **mrq)
1237 {
1238         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1239         struct sockaddr *nam = nfsd->nd_nam;
1240         caddr_t dpos = nfsd->nd_dpos;
1241         struct ucred *cred = nfsd->nd_cr;
1242         struct nfs_fattr *fp;
1243         struct vattr va, dirfor, diraft;
1244         struct vattr *vap = &va;
1245         struct nfsv2_sattr *sp;
1246         u_int32_t *tl;
1247         struct nameidata nd;
1248         caddr_t bpos;
1249         int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1250         int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1251         struct mbuf *mb, *mreq;
1252         struct vnode *dirp = NULL;
1253         nfsfh_t nfh;
1254         fhandle_t *fhp;
1255         u_quad_t tempsize;
1256         struct timespec cverf;
1257         struct mount *mp = NULL;
1258         int tvfslocked;
1259         int vfslocked;
1260
1261         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1262         vfslocked = 0;
1263 #ifndef nolint
1264         rdev = 0;
1265 #endif
1266         ndclear(&nd);
1267
1268         fhp = &nfh.fh_generic;
1269         nfsm_srvmtofh(fhp);
1270         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1271                 error = ESTALE;
1272                 goto ereply;
1273         }
1274         vfslocked = VFS_LOCK_GIANT(mp);
1275         (void) vn_start_write(NULL, &mp, V_WAIT);
1276         vfs_rel(mp);            /* The write holds a ref. */
1277         nfsm_srvnamesiz(len);
1278
1279         nd.ni_cnd.cn_cred = cred;
1280         nd.ni_cnd.cn_nameiop = CREATE;
1281         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
1282
1283         /*
1284          * Call namei and do initial cleanup to get a few things
1285          * out of the way.  If we get an initial error we cleanup
1286          * and return here to avoid special-casing the invalid nd
1287          * structure through the rest of the case.  dirp may be
1288          * set even if an error occurs, but the nd structure will not
1289          * be valid at all if an error occurs so we have to invalidate it
1290          * prior to calling nfsm_reply ( which might goto nfsmout ).
1291          */
1292         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1293                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
1294         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1295         if (dirp && !v3) {
1296                 vrele(dirp);
1297                 dirp = NULL;
1298         }
1299         if (error) {
1300                 nfsm_reply(NFSX_WCCDATA(v3));
1301                 if (v3)
1302                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1303                 error = 0;
1304                 goto nfsmout;
1305         }
1306
1307         /*
1308          * No error.  Continue.  State:
1309          *
1310          *      startdir        is valid ( we release this immediately )
1311          *      dirp            may be valid
1312          *      nd.ni_vp        may be valid
1313          *      nd.ni_dvp       is valid
1314          *
1315          * The error state is set through the code and we may also do some
1316          * opportunistic releasing of vnodes to avoid holding locks through
1317          * NFS I/O.  The cleanup at the end is a catch-all
1318          */
1319
1320         VATTR_NULL(vap);
1321         if (v3) {
1322                 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1323                 how = fxdr_unsigned(int, *tl);
1324                 switch (how) {
1325                 case NFSV3CREATE_GUARDED:
1326                         if (nd.ni_vp) {
1327                                 error = EEXIST;
1328                                 break;
1329                         }
1330                         /* fall through */
1331                 case NFSV3CREATE_UNCHECKED:
1332                         nfsm_srvsattr(vap);
1333                         break;
1334                 case NFSV3CREATE_EXCLUSIVE:
1335                         tl = nfsm_dissect_nonblock(u_int32_t *,
1336                             NFSX_V3CREATEVERF);
1337                         /* Unique bytes, endianness is not important. */
1338                         cverf.tv_sec  = (int32_t)tl[0];
1339                         cverf.tv_nsec = tl[1];
1340                         exclusive_flag = 1;
1341                         break;
1342                 };
1343                 vap->va_type = VREG;
1344         } else {
1345                 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
1346                 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1347                 if (vap->va_type == VNON)
1348                         vap->va_type = VREG;
1349                 vap->va_mode = nfstov_mode(sp->sa_mode);
1350                 switch (vap->va_type) {
1351                 case VREG:
1352                         tsize = fxdr_unsigned(int32_t, sp->sa_size);
1353                         if (tsize != -1)
1354                                 vap->va_size = (u_quad_t)tsize;
1355                         break;
1356                 case VCHR:
1357                 case VBLK:
1358                 case VFIFO:
1359                         rdev = fxdr_unsigned(long, sp->sa_size);
1360                         break;
1361                 default:
1362                         break;
1363                 };
1364         }
1365
1366         /*
1367          * Iff doesn't exist, create it
1368          * otherwise just truncate to 0 length
1369          *   should I set the mode too ?
1370          *
1371          * The only possible error we can have at this point is EEXIST.
1372          * nd.ni_vp will also be non-NULL in that case.
1373          */
1374         if (nd.ni_vp == NULL) {
1375                 if (vap->va_mode == (mode_t)VNOVAL)
1376                         vap->va_mode = 0;
1377                 if (vap->va_type == VREG || vap->va_type == VSOCK) {
1378                         error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1379                         if (error)
1380                                 NDFREE(&nd, NDF_ONLY_PNBUF);
1381                         else {
1382                                 if (exclusive_flag) {
1383                                         exclusive_flag = 0;
1384                                         VATTR_NULL(vap);
1385                                         vap->va_atime = cverf;
1386                                         error = VOP_SETATTR(nd.ni_vp, vap,
1387                                             cred);
1388                                 }
1389                         }
1390                 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
1391                     vap->va_type == VFIFO) {
1392                         /*
1393                          * NFSv2-specific code for creating device nodes
1394                          * and fifos.
1395                          *
1396                          * Handle SysV FIFO node special cases.  All other
1397                          * devices require super user to access.
1398                          */
1399                         if (vap->va_type == VCHR && rdev == 0xffffffff)
1400                                 vap->va_type = VFIFO;
1401                         if (vap->va_type != VFIFO &&
1402                             (error = priv_check_cred(cred, PRIV_VFS_MKNOD_DEV,
1403                             0))) {
1404                                 goto ereply;
1405                         }
1406                         vap->va_rdev = rdev;
1407                         error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1408                         if (error) {
1409                                 NDFREE(&nd, NDF_ONLY_PNBUF);
1410                                 goto ereply;
1411                         }
1412                         vput(nd.ni_vp);
1413                         nd.ni_vp = NULL;
1414
1415                         /*
1416                          * release dvp prior to lookup
1417                          */
1418                         vput(nd.ni_dvp);
1419                         nd.ni_dvp = NULL;
1420                         /*
1421                          * Setup for lookup.
1422                          *
1423                          * Even though LOCKPARENT was cleared, ni_dvp may
1424                          * be garbage.
1425                          */
1426                         nd.ni_cnd.cn_nameiop = LOOKUP;
1427                         nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1428                         nd.ni_cnd.cn_thread = curthread;
1429                         nd.ni_cnd.cn_cred = cred;
1430                         tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
1431                         if (tvfslocked)
1432                                 nd.ni_cnd.cn_flags |= GIANTHELD;
1433                         error = lookup(&nd);
1434                         nd.ni_dvp = NULL;
1435                         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1436                         nd.ni_cnd.cn_flags &= ~GIANTHELD;
1437                         if (error)
1438                                 goto ereply;
1439
1440                         if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1441                                 error = EINVAL;
1442                                 goto ereply;
1443                         }
1444                 } else {
1445                         error = ENXIO;
1446                 }
1447         } else {
1448                 if (vap->va_size != -1) {
1449                         error = nfsrv_access(nd.ni_vp, VWRITE,
1450                             cred, (nd.ni_cnd.cn_flags & RDONLY), 0);
1451                         if (!error) {
1452                                 tempsize = vap->va_size;
1453                                 VATTR_NULL(vap);
1454                                 vap->va_size = tempsize;
1455                                 error = VOP_SETATTR(nd.ni_vp, vap, cred);
1456                         }
1457                 }
1458         }
1459
1460         if (!error) {
1461                 bzero((caddr_t)fhp, sizeof(nfh));
1462                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1463                 error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1464                 if (!error)
1465                         error = VOP_GETATTR(nd.ni_vp, vap, cred);
1466         }
1467         if (v3) {
1468                 if (exclusive_flag && !error &&
1469                     bcmp(&cverf, &vap->va_atime, sizeof (cverf)))
1470                         error = EEXIST;
1471                 if (dirp == nd.ni_dvp)
1472                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1473                 else {
1474                         /* Drop the other locks to avoid deadlock. */
1475                         if (nd.ni_dvp) {
1476                                 if (nd.ni_dvp == nd.ni_vp)
1477                                         vrele(nd.ni_dvp);
1478                                 else
1479                                         vput(nd.ni_dvp);
1480                         }
1481                         if (nd.ni_vp)
1482                                 vput(nd.ni_vp);
1483                         nd.ni_dvp = NULL;
1484                         nd.ni_vp = NULL;
1485
1486                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1487                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1488                         VOP_UNLOCK(dirp, 0);
1489                 }
1490         }
1491 ereply:
1492         nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1493         if (v3) {
1494                 if (!error) {
1495                         nfsm_srvpostop_fh(fhp);
1496                         nfsm_srvpostop_attr(0, vap);
1497                 }
1498                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1499         } else if (!error) {
1500                 /* v2 non-error case. */
1501                 nfsm_srvfhtom(fhp, v3);
1502                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1503                 nfsm_srvfillattr(vap, fp);
1504         }
1505         error = 0;
1506
1507 nfsmout:
1508         if (nd.ni_dvp) {
1509                 if (nd.ni_dvp == nd.ni_vp)
1510                         vrele(nd.ni_dvp);
1511                 else
1512                         vput(nd.ni_dvp);
1513         }
1514         if (nd.ni_vp)
1515                 vput(nd.ni_vp);
1516         if (nd.ni_startdir) {
1517                 vrele(nd.ni_startdir);
1518                 nd.ni_startdir = NULL;
1519         }
1520         if (dirp)
1521                 vrele(dirp);
1522         NDFREE(&nd, NDF_ONLY_PNBUF);
1523         vn_finished_write(mp);
1524         VFS_UNLOCK_GIANT(vfslocked);
1525         return (error);
1526 }
1527
1528 /*
1529  * nfs v3 mknod service
1530  */
1531 int
1532 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1533     struct mbuf **mrq)
1534 {
1535         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1536         struct sockaddr *nam = nfsd->nd_nam;
1537         caddr_t dpos = nfsd->nd_dpos;
1538         struct ucred *cred = nfsd->nd_cr;
1539         struct vattr va, dirfor, diraft;
1540         struct vattr *vap = &va;
1541         struct thread *td = curthread;
1542         u_int32_t *tl;
1543         struct nameidata nd;
1544         caddr_t bpos;
1545         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1546         u_int32_t major, minor;
1547         enum vtype vtyp;
1548         struct mbuf *mb, *mreq;
1549         struct vnode *vp, *dirp = NULL;
1550         nfsfh_t nfh;
1551         fhandle_t *fhp;
1552         struct mount *mp = NULL;
1553         int v3 = (nfsd->nd_flag & ND_NFSV3);
1554         int tvfslocked;
1555         int vfslocked;
1556
1557         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1558         vfslocked = 0;
1559         if (!v3)
1560                 panic("nfsrv_mknod: v3 proc called on a v2 connection");
1561         ndclear(&nd);
1562
1563         fhp = &nfh.fh_generic;
1564         nfsm_srvmtofh(fhp);
1565         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1566                 error = ESTALE;
1567                 goto ereply;
1568         }
1569         vfslocked = VFS_LOCK_GIANT(mp);
1570         (void) vn_start_write(NULL, &mp, V_WAIT);
1571         vfs_rel(mp);            /* The write holds a ref. */
1572         nfsm_srvnamesiz(len);
1573
1574         nd.ni_cnd.cn_cred = cred;
1575         nd.ni_cnd.cn_nameiop = CREATE;
1576         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART | MPSAFE;
1577
1578         /*
1579          * Handle nfs_namei() call.  If an error occurs, the nd structure
1580          * is not valid.  However, nfsm_*() routines may still jump to
1581          * nfsmout.
1582          */
1583
1584         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1585                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
1586         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1587         if (error) {
1588                 nfsm_reply(NFSX_WCCDATA(1));
1589                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1590                 error = 0;
1591                 goto nfsmout;
1592         }
1593         tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1594         vtyp = nfsv3tov_type(*tl);
1595         if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1596                 error = NFSERR_BADTYPE;
1597                 goto out;
1598         }
1599         VATTR_NULL(vap);
1600         nfsm_srvsattr(vap);
1601         if (vtyp == VCHR || vtyp == VBLK) {
1602                 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
1603                 major = fxdr_unsigned(u_int32_t, *tl++);
1604                 minor = fxdr_unsigned(u_int32_t, *tl);
1605                 vap->va_rdev = makedev(major, minor);
1606         }
1607
1608         /*
1609          * Iff doesn't exist, create it.
1610          */
1611         if (nd.ni_vp) {
1612                 error = EEXIST;
1613                 goto out;
1614         }
1615         vap->va_type = vtyp;
1616         if (vap->va_mode == (mode_t)VNOVAL)
1617                 vap->va_mode = 0;
1618         if (vtyp == VSOCK) {
1619                 vrele(nd.ni_startdir);
1620                 nd.ni_startdir = NULL;
1621                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1622                 if (error)
1623                         NDFREE(&nd, NDF_ONLY_PNBUF);
1624         } else {
1625                 if (vtyp != VFIFO && (error = priv_check_cred(cred,
1626                     PRIV_VFS_MKNOD_DEV, 0)))
1627                         goto out;
1628                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1629                 if (error) {
1630                         NDFREE(&nd, NDF_ONLY_PNBUF);
1631                         goto out;
1632                 }
1633                 vput(nd.ni_vp);
1634                 nd.ni_vp = NULL;
1635
1636                 /*
1637                  * Release dvp prior to lookup
1638                  */
1639                 vput(nd.ni_dvp);
1640                 nd.ni_dvp = NULL;
1641
1642                 nd.ni_cnd.cn_nameiop = LOOKUP;
1643                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1644                 nd.ni_cnd.cn_thread = td;
1645                 nd.ni_cnd.cn_cred = td->td_ucred;
1646                 tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
1647                 if (tvfslocked)
1648                         nd.ni_cnd.cn_flags |= GIANTHELD;
1649                 error = lookup(&nd);
1650                 nd.ni_dvp = NULL;
1651                 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1652                 nd.ni_cnd.cn_flags &= ~GIANTHELD;
1653
1654                 if (error)
1655                         goto out;
1656                 if (nd.ni_cnd.cn_flags & ISSYMLINK)
1657                         error = EINVAL;
1658         }
1659
1660         /*
1661          * send response, cleanup, return.
1662          */
1663 out:
1664         vp = nd.ni_vp;
1665         if (!error) {
1666                 bzero((caddr_t)fhp, sizeof(nfh));
1667                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1668                 error = VOP_VPTOFH(vp, &fhp->fh_fid);
1669                 if (!error)
1670                         error = VOP_GETATTR(vp, vap, cred);
1671         }
1672         if (nd.ni_dvp) {
1673                 if (nd.ni_dvp == nd.ni_vp)
1674                         vrele(nd.ni_dvp);
1675                 else
1676                         vput(nd.ni_dvp);
1677                 nd.ni_dvp = NULL;
1678         }
1679         if (vp) {
1680                 vput(vp);
1681                 vp = NULL;
1682                 nd.ni_vp = NULL;
1683         }
1684         if (nd.ni_startdir) {
1685                 vrele(nd.ni_startdir);
1686                 nd.ni_startdir = NULL;
1687         }
1688         NDFREE(&nd, NDF_ONLY_PNBUF);
1689         if (dirp) {
1690                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1691                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1692                 vput(dirp);
1693         }
1694 ereply:
1695         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1696         if (v3) {
1697                 if (!error) {
1698                         nfsm_srvpostop_fh(fhp);
1699                         nfsm_srvpostop_attr(0, vap);
1700                 }
1701                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1702         }
1703         vn_finished_write(mp);
1704         VFS_UNLOCK_GIANT(vfslocked);
1705         return (0);
1706 nfsmout:
1707         if (nd.ni_dvp) {
1708                 if (nd.ni_dvp == nd.ni_vp)
1709                         vrele(nd.ni_dvp);
1710                 else
1711                         vput(nd.ni_dvp);
1712         }
1713         if (nd.ni_vp)
1714                 vput(nd.ni_vp);
1715         if (dirp)
1716                 vrele(dirp);
1717         if (nd.ni_startdir)
1718                 vrele(nd.ni_startdir);
1719         NDFREE(&nd, NDF_ONLY_PNBUF);
1720         vn_finished_write(mp);
1721         VFS_UNLOCK_GIANT(vfslocked);
1722         return (error);
1723 }
1724
1725 /*
1726  * nfs remove service
1727  */
1728 int
1729 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1730     struct mbuf **mrq)
1731 {
1732         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1733         struct sockaddr *nam = nfsd->nd_nam;
1734         caddr_t dpos = nfsd->nd_dpos;
1735         struct ucred *cred = nfsd->nd_cr;
1736         struct nameidata nd;
1737         caddr_t bpos;
1738         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1739         int v3 = (nfsd->nd_flag & ND_NFSV3);
1740         struct mbuf *mb, *mreq;
1741         struct vnode *dirp;
1742         struct vattr dirfor, diraft;
1743         nfsfh_t nfh;
1744         fhandle_t *fhp;
1745         struct mount *mp = NULL;
1746         int vfslocked;
1747
1748         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1749         ndclear(&nd);
1750         vfslocked = 0;
1751
1752         fhp = &nfh.fh_generic;
1753         nfsm_srvmtofh(fhp);
1754         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1755                 error = ESTALE;
1756                 goto ereply;
1757         }
1758         vfslocked = VFS_LOCK_GIANT(mp);
1759         (void) vn_start_write(NULL, &mp, V_WAIT);
1760         vfs_rel(mp);            /* The write holds a ref. */
1761         nfsm_srvnamesiz(len);
1762
1763         nd.ni_cnd.cn_cred = cred;
1764         nd.ni_cnd.cn_nameiop = DELETE;
1765         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
1766         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
1767                 &dirp, v3,  &dirfor, &dirfor_ret, FALSE);
1768         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
1769         if (dirp && !v3) {
1770                 vrele(dirp);
1771                 dirp = NULL;
1772         }
1773         if (error == 0) {
1774                 if (nd.ni_vp->v_type == VDIR) {
1775                         error = EPERM;          /* POSIX */
1776                         goto out;
1777                 }
1778                 /*
1779                  * The root of a mounted filesystem cannot be deleted.
1780                  */
1781                 if (nd.ni_vp->v_vflag & VV_ROOT) {
1782                         error = EBUSY;
1783                         goto out;
1784                 }
1785 out:
1786                 if (!error) {
1787                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1788                         NDFREE(&nd, NDF_ONLY_PNBUF);
1789                 }
1790         }
1791         if (dirp && v3) {
1792                 if (dirp == nd.ni_dvp)
1793                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1794                 else {
1795                         /* Drop the other locks to avoid deadlock. */
1796                         if (nd.ni_dvp) {
1797                                 if (nd.ni_dvp == nd.ni_vp)
1798                                         vrele(nd.ni_dvp);
1799                                 else
1800                                         vput(nd.ni_dvp);
1801                         }
1802                         if (nd.ni_vp)
1803                                 vput(nd.ni_vp);
1804                         nd.ni_dvp = NULL;
1805                         nd.ni_vp = NULL;
1806
1807                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
1808                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
1809                         VOP_UNLOCK(dirp, 0);
1810                 }
1811                 vrele(dirp);
1812                 dirp = NULL;
1813         }
1814 ereply:
1815         nfsm_reply(NFSX_WCCDATA(v3));
1816         if (v3)
1817                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1818         error = 0;
1819 nfsmout:
1820         NDFREE(&nd, NDF_ONLY_PNBUF);
1821         if (nd.ni_dvp) {
1822                 if (nd.ni_dvp == nd.ni_vp)
1823                         vrele(nd.ni_dvp);
1824                 else
1825                         vput(nd.ni_dvp);
1826         }
1827         if (nd.ni_vp)
1828                 vput(nd.ni_vp);
1829         vn_finished_write(mp);
1830         VFS_UNLOCK_GIANT(vfslocked);
1831         return(error);
1832 }
1833
1834 /*
1835  * nfs rename service
1836  */
1837 int
1838 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1839     struct mbuf **mrq)
1840 {
1841         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1842         struct sockaddr *nam = nfsd->nd_nam;
1843         caddr_t dpos = nfsd->nd_dpos;
1844         struct ucred *cred = nfsd->nd_cr;
1845         caddr_t bpos;
1846         int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
1847         int tdirfor_ret = 1, tdiraft_ret = 1;
1848         int v3 = (nfsd->nd_flag & ND_NFSV3);
1849         struct mbuf *mb, *mreq;
1850         struct nameidata fromnd, tond;
1851         struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
1852         struct vnode *tdirp = NULL;
1853         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1854         nfsfh_t fnfh, tnfh;
1855         fhandle_t *ffhp, *tfhp;
1856         uid_t saved_uid;
1857         struct mount *mp = NULL;
1858         int vfslocked;
1859
1860         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1861         vfslocked = 0;
1862 #ifndef nolint
1863         fvp = NULL;
1864 #endif
1865         ffhp = &fnfh.fh_generic;
1866         tfhp = &tnfh.fh_generic;
1867
1868         /*
1869          * Clear fields incase goto nfsmout occurs from macro.
1870          */
1871
1872         ndclear(&fromnd);
1873         ndclear(&tond);
1874
1875         nfsm_srvmtofh(ffhp);
1876         if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
1877                 error = ESTALE;
1878                 goto out1;
1879         }
1880         vfslocked = VFS_LOCK_GIANT(mp);
1881         (void) vn_start_write(NULL, &mp, V_WAIT);
1882         vfs_rel(mp);            /* The write holds a ref. */
1883         nfsm_srvnamesiz(len);
1884         /*
1885          * Remember our original uid so that we can reset cr_uid before
1886          * the second nfs_namei() call, in case it is remapped.
1887          */
1888         saved_uid = cred->cr_uid;
1889         fromnd.ni_cnd.cn_cred = cred;
1890         fromnd.ni_cnd.cn_nameiop = DELETE;
1891         fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART | MPSAFE;
1892         error = nfs_namei(&fromnd, nfsd, ffhp, len, slp, nam, &md,
1893                 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, FALSE);
1894         vfslocked = nfsrv_lockedpair_nd(vfslocked, &fromnd);
1895         if (fdirp && !v3) {
1896                 vrele(fdirp);
1897                 fdirp = NULL;
1898         }
1899         if (error) {
1900                 nfsm_reply(2 * NFSX_WCCDATA(v3));
1901                 if (v3) {
1902                         nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1903                         nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1904                 }
1905                 error = 0;
1906                 goto nfsmout;
1907         }
1908         fvp = fromnd.ni_vp;
1909         nfsm_srvmtofh(tfhp);
1910         nfsm_srvnamesiz(len2);
1911         cred->cr_uid = saved_uid;
1912         tond.ni_cnd.cn_cred = cred;
1913         tond.ni_cnd.cn_nameiop = RENAME;
1914         tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | MPSAFE;
1915         error = nfs_namei(&tond, nfsd, tfhp, len2, slp, nam, &md,
1916                 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, FALSE);
1917         vfslocked = nfsrv_lockedpair_nd(vfslocked, &tond);
1918         if (tdirp && !v3) {
1919                 vrele(tdirp);
1920                 tdirp = NULL;
1921         }
1922         if (error)
1923                 goto out1;
1924
1925         tdvp = tond.ni_dvp;
1926         tvp = tond.ni_vp;
1927         if (tvp != NULL) {
1928                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1929                         if (v3)
1930                                 error = EEXIST;
1931                         else
1932                                 error = EISDIR;
1933                         goto out;
1934                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1935                         if (v3)
1936                                 error = EEXIST;
1937                         else
1938                                 error = ENOTDIR;
1939                         goto out;
1940                 }
1941                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1942                         if (v3)
1943                                 error = EXDEV;
1944                         else
1945                                 error = ENOTEMPTY;
1946                         goto out;
1947                 }
1948         }
1949         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1950                 if (v3)
1951                         error = EXDEV;
1952                 else
1953                         error = ENOTEMPTY;
1954                 goto out;
1955         }
1956         if (fvp->v_mount != tdvp->v_mount) {
1957                 if (v3)
1958                         error = EXDEV;
1959                 else
1960                         error = ENOTEMPTY;
1961                 goto out;
1962         }
1963         if (fvp == tdvp) {
1964                 if (v3)
1965                         error = EINVAL;
1966                 else
1967                         error = ENOTEMPTY;
1968         }
1969         /*
1970          * If source is the same as the destination (that is the
1971          * same vnode with the same name in the same directory),
1972          * then there is nothing to do.
1973          */
1974         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1975             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1976             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1977               fromnd.ni_cnd.cn_namelen))
1978                 error = -1;
1979 out:
1980         if (!error) {
1981                 /*
1982                  * The VOP_RENAME function releases all vnode references &
1983                  * locks prior to returning so we need to clear the pointers
1984                  * to bypass cleanup code later on.
1985                  */
1986                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1987                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1988                 fromnd.ni_dvp = NULL;
1989                 fromnd.ni_vp = NULL;
1990                 tond.ni_dvp = NULL;
1991                 tond.ni_vp = NULL;
1992                 if (error) {
1993                         NDFREE(&fromnd, NDF_ONLY_PNBUF);
1994                         NDFREE(&tond, NDF_ONLY_PNBUF);
1995                 }
1996         } else {
1997                 if (error == -1)
1998                         error = 0;
1999         }
2000         /* fall through */
2001 out1:
2002         nfsm_reply(2 * NFSX_WCCDATA(v3));
2003         if (v3) {
2004                 /* Release existing locks to prevent deadlock. */
2005                 if (tond.ni_dvp) {
2006                         if (tond.ni_dvp == tond.ni_vp)
2007                                 vrele(tond.ni_dvp);
2008                         else
2009                                 vput(tond.ni_dvp);
2010                 }
2011                 if (tond.ni_vp)
2012                         vput(tond.ni_vp);
2013                 tond.ni_dvp = NULL;
2014                 tond.ni_vp = NULL;
2015
2016                 if (fdirp) {
2017                         vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY);
2018                         fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred);
2019                         VOP_UNLOCK(fdirp, 0);
2020                 }
2021                 if (tdirp) {
2022                         vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY);
2023                         tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred);
2024                         VOP_UNLOCK(tdirp, 0);
2025                 }
2026                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2027                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2028         }
2029         error = 0;
2030         /* fall through */
2031
2032 nfsmout:
2033         /*
2034          * Clear out tond related fields
2035          */
2036         if (tond.ni_dvp) {
2037                 if (tond.ni_dvp == tond.ni_vp)
2038                         vrele(tond.ni_dvp);
2039                 else
2040                         vput(tond.ni_dvp);
2041         }
2042         if (tond.ni_vp)
2043                 vput(tond.ni_vp);
2044         if (tdirp)
2045                 vrele(tdirp);
2046         if (tond.ni_startdir)
2047                 vrele(tond.ni_startdir);
2048         NDFREE(&tond, NDF_ONLY_PNBUF);
2049         /*
2050          * Clear out fromnd related fields
2051          */
2052         if (fdirp)
2053                 vrele(fdirp);
2054         if (fromnd.ni_startdir)
2055                 vrele(fromnd.ni_startdir);
2056         NDFREE(&fromnd, NDF_ONLY_PNBUF);
2057         if (fromnd.ni_dvp)
2058                 vrele(fromnd.ni_dvp);
2059         if (fromnd.ni_vp)
2060                 vrele(fromnd.ni_vp);
2061
2062         vn_finished_write(mp);
2063         VFS_UNLOCK_GIANT(vfslocked);
2064         return (error);
2065 }
2066
2067 /*
2068  * nfs link service
2069  */
2070 int
2071 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2072     struct mbuf **mrq)
2073 {
2074         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2075         struct sockaddr *nam = nfsd->nd_nam;
2076         caddr_t dpos = nfsd->nd_dpos;
2077         struct ucred *cred = nfsd->nd_cr;
2078         struct nameidata nd;
2079         caddr_t bpos;
2080         int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2081         int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2082         struct mbuf *mb, *mreq;
2083         struct vnode *vp = NULL, *xp, *dirp = NULL;
2084         struct vattr dirfor, diraft, at;
2085         nfsfh_t nfh, dnfh;
2086         fhandle_t *fhp, *dfhp;
2087         struct mount *mp = NULL;
2088         int tvfslocked;
2089         int vfslocked;
2090
2091         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2092         ndclear(&nd);
2093         vfslocked = 0;
2094
2095         fhp = &nfh.fh_generic;
2096         dfhp = &dnfh.fh_generic;
2097         nfsm_srvmtofh(fhp);
2098         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2099                 error = ESTALE;
2100                 goto ereply;
2101         }
2102         vfslocked = VFS_LOCK_GIANT(mp);
2103         (void) vn_start_write(NULL, &mp, V_WAIT);
2104         vfs_rel(mp);            /* The write holds a ref. */
2105         nfsm_srvmtofh(dfhp);
2106         nfsm_srvnamesiz(len);
2107
2108         error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
2109         vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
2110         if (error) {
2111                 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2112                 if (v3) {
2113                         nfsm_srvpostop_attr(getret, &at);
2114                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2115                 }
2116                 vp = NULL;
2117                 error = 0;
2118                 goto nfsmout;
2119         }
2120         if (v3)
2121                 getret = VOP_GETATTR(vp, &at, cred);
2122         if (vp->v_type == VDIR) {
2123                 error = EPERM;          /* POSIX */
2124                 goto out1;
2125         }
2126         VOP_UNLOCK(vp, 0);
2127         nd.ni_cnd.cn_cred = cred;
2128         nd.ni_cnd.cn_nameiop = CREATE;
2129         nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE | MPSAFE;
2130         error = nfs_namei(&nd, nfsd, dfhp, len, slp, nam, &md, &dpos,
2131                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2132         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2133         if (dirp && !v3) {
2134                 vrele(dirp);
2135                 dirp = NULL;
2136         }
2137         if (error) {
2138                 vrele(vp);
2139                 vp = NULL;
2140                 goto out2;
2141         }
2142         xp = nd.ni_vp;
2143         if (xp != NULL) {
2144                 error = EEXIST;
2145                 vrele(vp);
2146                 vp = NULL;
2147                 goto out2;
2148         }
2149         xp = nd.ni_dvp;
2150         if (vp->v_mount != xp->v_mount) {
2151                 error = EXDEV;
2152                 vrele(vp);
2153                 vp = NULL;
2154                 goto out2;
2155         }
2156         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2157         error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2158         NDFREE(&nd, NDF_ONLY_PNBUF);
2159         /* fall through */
2160
2161 out1:
2162         if (v3)
2163                 getret = VOP_GETATTR(vp, &at, cred);
2164 out2:
2165         if (dirp) {
2166                 if (dirp == nd.ni_dvp)
2167                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2168                 else {
2169                         /* Release existing locks to prevent deadlock. */
2170                         if (nd.ni_dvp) {
2171                                 if (nd.ni_dvp == nd.ni_vp)
2172                                         vrele(nd.ni_dvp);
2173                                 else
2174                                         vput(nd.ni_dvp);
2175                         }
2176                         if (nd.ni_vp)
2177                                 vrele(nd.ni_vp);
2178                         nd.ni_dvp = NULL;
2179                         nd.ni_vp = NULL;
2180
2181                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2182                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2183                         VOP_UNLOCK(dirp, 0);
2184                 }
2185         }
2186 ereply:
2187         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2188         if (v3) {
2189                 nfsm_srvpostop_attr(getret, &at);
2190                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2191         }
2192         error = 0;
2193         /* fall through */
2194
2195 nfsmout:
2196         NDFREE(&nd, NDF_ONLY_PNBUF);
2197         if (vp)
2198                 vput(vp);
2199         if (nd.ni_dvp) {
2200                 if (nd.ni_dvp == nd.ni_vp)
2201                         vrele(nd.ni_dvp);
2202                 else
2203                         vput(nd.ni_dvp);
2204         }
2205         if (dirp)
2206                 vrele(dirp);
2207         if (nd.ni_vp)
2208                 vrele(nd.ni_vp);
2209         vn_finished_write(mp);
2210         VFS_UNLOCK_GIANT(vfslocked);
2211         return(error);
2212 }
2213
2214 /*
2215  * nfs symbolic link service
2216  */
2217 int
2218 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2219     struct mbuf **mrq)
2220 {
2221         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2222         struct sockaddr *nam = nfsd->nd_nam;
2223         caddr_t dpos = nfsd->nd_dpos;
2224         struct ucred *cred = nfsd->nd_cr;
2225         struct vattr va, dirfor, diraft;
2226         struct nameidata nd;
2227         struct vattr *vap = &va;
2228         struct nfsv2_sattr *sp;
2229         char *bpos, *pathcp = NULL;
2230         struct uio io;
2231         struct iovec iv;
2232         int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2233         int v3 = (nfsd->nd_flag & ND_NFSV3);
2234         struct mbuf *mb, *mreq;
2235         struct vnode *dirp = NULL;
2236         nfsfh_t nfh;
2237         fhandle_t *fhp;
2238         struct mount *mp = NULL;
2239         int tvfslocked;
2240         int vfslocked;
2241
2242         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2243         ndclear(&nd);
2244         vfslocked = 0;
2245
2246         fhp = &nfh.fh_generic;
2247         nfsm_srvmtofh(fhp);
2248         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2249                 error = ESTALE;
2250                 goto out;
2251         }
2252         vfslocked = VFS_LOCK_GIANT(mp);
2253         (void) vn_start_write(NULL, &mp, V_WAIT);
2254         vfs_rel(mp);            /* The write holds a ref. */
2255         nfsm_srvnamesiz(len);
2256         nd.ni_cnd.cn_cred = cred;
2257         nd.ni_cnd.cn_nameiop = CREATE;
2258         nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART | MPSAFE;
2259         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2260                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2261         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2262         if (error == 0) {
2263                 VATTR_NULL(vap);
2264                 if (v3)
2265                         nfsm_srvsattr(vap);
2266                 nfsm_srvpathsiz(len2);
2267         }
2268         if (dirp && !v3) {
2269                 vrele(dirp);
2270                 dirp = NULL;
2271         }
2272         if (error)
2273                 goto out;
2274         pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
2275         iv.iov_base = pathcp;
2276         iv.iov_len = len2;
2277         io.uio_resid = len2;
2278         io.uio_offset = 0;
2279         io.uio_iov = &iv;
2280         io.uio_iovcnt = 1;
2281         io.uio_segflg = UIO_SYSSPACE;
2282         io.uio_rw = UIO_READ;
2283         io.uio_td = NULL;
2284         nfsm_mtouio(&io, len2);
2285         if (!v3) {
2286                 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2287                 vap->va_mode = nfstov_mode(sp->sa_mode);
2288         }
2289         *(pathcp + len2) = '\0';
2290         if (nd.ni_vp) {
2291                 error = EEXIST;
2292                 goto out;
2293         }
2294
2295         /*
2296          * issue symlink op.  SAVESTART is set so the underlying path component
2297          * is only freed by the VOP if an error occurs.
2298          */
2299         if (vap->va_mode == (mode_t)VNOVAL)
2300                 vap->va_mode = 0;
2301         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2302         if (error)
2303                 NDFREE(&nd, NDF_ONLY_PNBUF);
2304         else
2305                 vput(nd.ni_vp);
2306         nd.ni_vp = NULL;
2307         /*
2308          * releases directory prior to potential lookup op.
2309          */
2310         vput(nd.ni_dvp);
2311         nd.ni_dvp = NULL;
2312
2313         if (error == 0) {
2314             if (v3) {
2315                 /*
2316                  * Issue lookup.  Leave SAVESTART set so we can easily free
2317                  * the name buffer later on.
2318                  *
2319                  * since LOCKPARENT is not set, ni_dvp will be garbage on
2320                  * return whether an error occurs or not.
2321                  */
2322                 nd.ni_cnd.cn_nameiop = LOOKUP;
2323                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2324                 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2325                 nd.ni_cnd.cn_thread = curthread;
2326                 nd.ni_cnd.cn_cred = cred;
2327                 tvfslocked = VFS_LOCK_GIANT(nd.ni_startdir->v_mount);
2328                 if (tvfslocked)
2329                         nd.ni_cnd.cn_flags |= GIANTHELD;
2330                 error = lookup(&nd);
2331                 nd.ni_dvp = NULL;
2332                 vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2333                 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2334
2335                 if (error == 0) {
2336                         bzero((caddr_t)fhp, sizeof(nfh));
2337                         fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2338                         error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2339                         if (!error)
2340                                 error = VOP_GETATTR(nd.ni_vp, vap, cred);
2341                         vput(nd.ni_vp);
2342                         nd.ni_vp = NULL;
2343                 }
2344             }
2345         }
2346 out:
2347         /*
2348          * These releases aren't strictly required, does even doing them
2349          * make any sense? XXX can nfsm_reply() block?
2350          */
2351         if (pathcp) {
2352                 free(pathcp, M_TEMP);
2353                 pathcp = NULL;
2354         }
2355         if (dirp) {
2356                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2357                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2358                 VOP_UNLOCK(dirp, 0);
2359         }
2360         if (nd.ni_startdir) {
2361                 vrele(nd.ni_startdir);
2362                 nd.ni_startdir = NULL;
2363         }
2364         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2365         if (v3) {
2366                 if (!error) {
2367                         nfsm_srvpostop_fh(fhp);
2368                         nfsm_srvpostop_attr(0, vap);
2369                 }
2370                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2371         }
2372         error = 0;
2373         /* fall through */
2374
2375 nfsmout:
2376         NDFREE(&nd, NDF_ONLY_PNBUF);
2377         if (nd.ni_dvp) {
2378                 if (nd.ni_dvp == nd.ni_vp)
2379                         vrele(nd.ni_dvp);
2380                 else
2381                         vput(nd.ni_dvp);
2382         }
2383         if (nd.ni_vp)
2384                 vrele(nd.ni_vp);
2385         if (nd.ni_startdir)
2386                 vrele(nd.ni_startdir);
2387         if (dirp)
2388                 vrele(dirp);
2389         if (pathcp)
2390                 free(pathcp, M_TEMP);
2391
2392         vn_finished_write(mp);
2393         VFS_UNLOCK_GIANT(vfslocked);
2394         return (error);
2395 }
2396
2397 /*
2398  * nfs mkdir service
2399  */
2400 int
2401 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2402     struct mbuf **mrq)
2403 {
2404         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2405         struct sockaddr *nam = nfsd->nd_nam;
2406         caddr_t dpos = nfsd->nd_dpos;
2407         struct ucred *cred = nfsd->nd_cr;
2408         struct vattr va, dirfor, diraft;
2409         struct vattr *vap = &va;
2410         struct nfs_fattr *fp;
2411         struct nameidata nd;
2412         u_int32_t *tl;
2413         caddr_t bpos;
2414         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2415         int v3 = (nfsd->nd_flag & ND_NFSV3);
2416         struct mbuf *mb, *mreq;
2417         struct vnode *dirp = NULL;
2418         int vpexcl = 0;
2419         nfsfh_t nfh;
2420         fhandle_t *fhp;
2421         struct mount *mp = NULL;
2422         int vfslocked;
2423
2424         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2425         ndclear(&nd);
2426         vfslocked = 0;
2427
2428         fhp = &nfh.fh_generic;
2429         nfsm_srvmtofh(fhp);
2430         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2431                 error = ESTALE;
2432                 goto out;
2433         }
2434         vfslocked = VFS_LOCK_GIANT(mp);
2435         (void) vn_start_write(NULL, &mp, V_WAIT);
2436         vfs_rel(mp);            /* The write holds a ref. */
2437         nfsm_srvnamesiz(len);
2438         nd.ni_cnd.cn_cred = cred;
2439         nd.ni_cnd.cn_nameiop = CREATE;
2440         nd.ni_cnd.cn_flags = LOCKPARENT | MPSAFE;
2441
2442         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2443                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2444         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2445         if (dirp && !v3) {
2446                 vrele(dirp);
2447                 dirp = NULL;
2448         }
2449         if (error) {
2450                 nfsm_reply(NFSX_WCCDATA(v3));
2451                 if (v3)
2452                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2453                 error = 0;
2454                 goto nfsmout;
2455         }
2456         VATTR_NULL(vap);
2457         if (v3) {
2458                 nfsm_srvsattr(vap);
2459         } else {
2460                 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
2461                 vap->va_mode = nfstov_mode(*tl++);
2462         }
2463
2464         /*
2465          * At this point nd.ni_dvp is referenced and exclusively locked and
2466          * nd.ni_vp, if it exists, is referenced but not locked.
2467          */
2468
2469         vap->va_type = VDIR;
2470         if (nd.ni_vp != NULL) {
2471                 NDFREE(&nd, NDF_ONLY_PNBUF);
2472                 error = EEXIST;
2473                 goto out;
2474         }
2475
2476         /*
2477          * Issue mkdir op.  Since SAVESTART is not set, the pathname
2478          * component is freed by the VOP call.  This will fill-in
2479          * nd.ni_vp, reference, and exclusively lock it.
2480          */
2481         if (vap->va_mode == (mode_t)VNOVAL)
2482                 vap->va_mode = 0;
2483         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2484         NDFREE(&nd, NDF_ONLY_PNBUF);
2485         vpexcl = 1;
2486
2487         vput(nd.ni_dvp);
2488         nd.ni_dvp = NULL;
2489
2490         if (!error) {
2491                 bzero((caddr_t)fhp, sizeof(nfh));
2492                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2493                 error = VOP_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2494                 if (!error)
2495                         error = VOP_GETATTR(nd.ni_vp, vap, cred);
2496         }
2497 out:
2498         if (dirp) {
2499                 if (dirp == nd.ni_dvp) {
2500                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2501                 } else {
2502                         /* Release existing locks to prevent deadlock. */
2503                         if (nd.ni_dvp) {
2504                                 NDFREE(&nd, NDF_ONLY_PNBUF);
2505                                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
2506                                         vrele(nd.ni_dvp);
2507                                 else
2508                                         vput(nd.ni_dvp);
2509                         }
2510                         if (nd.ni_vp) {
2511                                 if (vpexcl)
2512                                         vput(nd.ni_vp);
2513                                 else
2514                                         vrele(nd.ni_vp);
2515                         }
2516                         nd.ni_dvp = NULL;
2517                         nd.ni_vp = NULL;
2518                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2519                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2520                         VOP_UNLOCK(dirp, 0);
2521                 }
2522         }
2523         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2524         if (v3) {
2525                 if (!error) {
2526                         nfsm_srvpostop_fh(fhp);
2527                         nfsm_srvpostop_attr(0, vap);
2528                 }
2529                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2530         } else if (!error) {
2531                 /* v2 non-error case. */
2532                 nfsm_srvfhtom(fhp, v3);
2533                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
2534                 nfsm_srvfillattr(vap, fp);
2535         }
2536         error = 0;
2537         /* fall through */
2538
2539 nfsmout:
2540         if (nd.ni_dvp) {
2541                 NDFREE(&nd, NDF_ONLY_PNBUF);
2542                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
2543                         vrele(nd.ni_dvp);
2544                 else
2545                         vput(nd.ni_dvp);
2546         }
2547         if (nd.ni_vp) {
2548                 if (vpexcl)
2549                         vput(nd.ni_vp);
2550                 else
2551                         vrele(nd.ni_vp);
2552         }
2553         if (dirp)
2554                 vrele(dirp);
2555         vn_finished_write(mp);
2556         VFS_UNLOCK_GIANT(vfslocked);
2557         return (error);
2558 }
2559
2560 /*
2561  * nfs rmdir service
2562  */
2563 int
2564 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2565     struct mbuf **mrq)
2566 {
2567         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2568         struct sockaddr *nam = nfsd->nd_nam;
2569         caddr_t dpos = nfsd->nd_dpos;
2570         struct ucred *cred = nfsd->nd_cr;
2571         caddr_t bpos;
2572         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2573         int v3 = (nfsd->nd_flag & ND_NFSV3);
2574         struct mbuf *mb, *mreq;
2575         struct vnode *vp, *dirp = NULL;
2576         struct vattr dirfor, diraft;
2577         nfsfh_t nfh;
2578         fhandle_t *fhp;
2579         struct nameidata nd;
2580         struct mount *mp = NULL;
2581         int vfslocked;
2582
2583         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2584         ndclear(&nd);
2585         vfslocked = 0;
2586
2587         fhp = &nfh.fh_generic;
2588         nfsm_srvmtofh(fhp);
2589         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2590                 error = ESTALE;
2591                 goto out;
2592         }
2593         vfslocked = VFS_LOCK_GIANT(mp);
2594         (void) vn_start_write(NULL, &mp, V_WAIT);
2595         vfs_rel(mp);            /* The write holds a ref. */
2596         nfsm_srvnamesiz(len);
2597         nd.ni_cnd.cn_cred = cred;
2598         nd.ni_cnd.cn_nameiop = DELETE;
2599         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | MPSAFE;
2600         error = nfs_namei(&nd, nfsd, fhp, len, slp, nam, &md, &dpos,
2601                 &dirp, v3, &dirfor, &dirfor_ret, FALSE);
2602         vfslocked = nfsrv_lockedpair_nd(vfslocked, &nd);
2603         if (dirp && !v3) {
2604                 vrele(dirp);
2605                 dirp = NULL;
2606         }
2607         if (error) {
2608                 nfsm_reply(NFSX_WCCDATA(v3));
2609                 if (v3)
2610                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2611                 error = 0;
2612                 goto nfsmout;
2613         }
2614         vp = nd.ni_vp;
2615         if (vp->v_type != VDIR) {
2616                 error = ENOTDIR;
2617                 goto out;
2618         }
2619         /*
2620          * No rmdir "." please.
2621          */
2622         if (nd.ni_dvp == vp) {
2623                 error = EINVAL;
2624                 goto out;
2625         }
2626         /*
2627          * The root of a mounted filesystem cannot be deleted.
2628          */
2629         if (vp->v_vflag & VV_ROOT)
2630                 error = EBUSY;
2631 out:
2632         /*
2633          * Issue or abort op.  Since SAVESTART is not set, path name
2634          * component is freed by the VOP after either.
2635          */
2636         if (!error)
2637                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2638         NDFREE(&nd, NDF_ONLY_PNBUF);
2639
2640         if (dirp) {
2641                 if (dirp == nd.ni_dvp)
2642                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2643                 else {
2644                         /* Release existing locks to prevent deadlock. */
2645                         if (nd.ni_dvp) {
2646                                 if (nd.ni_dvp == nd.ni_vp)
2647                                         vrele(nd.ni_dvp);
2648                                 else
2649                                         vput(nd.ni_dvp);
2650                         }
2651                         if (nd.ni_vp)
2652                                 vput(nd.ni_vp);
2653                         nd.ni_dvp = NULL;
2654                         nd.ni_vp = NULL;
2655                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY);
2656                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred);
2657                         VOP_UNLOCK(dirp, 0);
2658                 }
2659         }
2660         nfsm_reply(NFSX_WCCDATA(v3));
2661         error = 0;
2662         if (v3)
2663                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2664         /* fall through */
2665
2666 nfsmout:
2667         NDFREE(&nd, NDF_ONLY_PNBUF);
2668         if (nd.ni_dvp) {
2669                 if (nd.ni_dvp == nd.ni_vp)
2670                         vrele(nd.ni_dvp);
2671                 else
2672                         vput(nd.ni_dvp);
2673         }
2674         if (nd.ni_vp)
2675                 vput(nd.ni_vp);
2676         if (dirp)
2677                 vrele(dirp);
2678
2679         vn_finished_write(mp);
2680         VFS_UNLOCK_GIANT(vfslocked);
2681         return(error);
2682 }
2683
2684 /*
2685  * nfs readdir service
2686  * - mallocs what it thinks is enough to read
2687  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2688  * - calls VOP_READDIR()
2689  * - loops around building the reply
2690  *      if the output generated exceeds count break out of loop
2691  *      The nfsm_clget macro is used here so that the reply will be packed
2692  *      tightly in mbuf clusters.
2693  * - it only knows that it has encountered eof when the VOP_READDIR()
2694  *      reads nothing
2695  * - as such one readdir rpc will return eof false although you are there
2696  *      and then the next will return eof
2697  * - it trims out records with d_fileno == 0
2698  *      this doesn't matter for Unix clients, but they might confuse clients
2699  *      for other os'.
2700  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2701  *      than requested, but this may not apply to all filesystems. For
2702  *      example, client NFS does not { although it is never remote mounted
2703  *      anyhow }
2704  *     The alternate call nfsrv_readdirplus() does lookups as well.
2705  * PS: The NFS protocol spec. does not clarify what the "count" byte
2706  *      argument is a count of.. just name strings and file id's or the
2707  *      entire reply rpc or ...
2708  *      I tried just file name and id sizes and it confused the Sun client,
2709  *      so I am using the full rpc size now. The "paranoia.." comment refers
2710  *      to including the status longwords that are not a part of the dir.
2711  *      "entry" structures, but are in the rpc.
2712  */
2713 struct flrep {
2714         nfsuint64       fl_off;
2715         u_int32_t       fl_postopok;
2716         u_int32_t       fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2717         u_int32_t       fl_fhok;
2718         u_int32_t       fl_fhsize;
2719         u_int32_t       fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2720 };
2721
2722 int
2723 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2724     struct mbuf **mrq)
2725 {
2726         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2727         struct sockaddr *nam = nfsd->nd_nam;
2728         caddr_t dpos = nfsd->nd_dpos;
2729         struct ucred *cred = nfsd->nd_cr;
2730         char *bp, *be;
2731         struct mbuf *mp;
2732         struct dirent *dp;
2733         caddr_t cp;
2734         u_int32_t *tl;
2735         caddr_t bpos;
2736         struct mbuf *mb, *mreq;
2737         char *cpos, *cend, *rbuf;
2738         struct vnode *vp = NULL;
2739         struct vattr at;
2740         nfsfh_t nfh;
2741         fhandle_t *fhp;
2742         struct uio io;
2743         struct iovec iv;
2744         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2745         int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2746         int v3 = (nfsd->nd_flag & ND_NFSV3);
2747         u_quad_t off, toff, verf;
2748         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
2749         int vfslocked, not_zfs;
2750
2751         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2752         vfslocked = 0;
2753         fhp = &nfh.fh_generic;
2754         nfsm_srvmtofh(fhp);
2755         if (v3) {
2756                 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
2757                 toff = fxdr_hyper(tl);
2758                 tl += 2;
2759                 verf = fxdr_hyper(tl);
2760                 tl += 2;
2761         } else {
2762                 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2763                 toff = fxdr_unsigned(u_quad_t, *tl++);
2764                 verf = 0;       /* shut up gcc */
2765         }
2766         off = toff;
2767         cnt = fxdr_unsigned(int, *tl);
2768         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2769         xfer = NFS_SRVMAXDATA(nfsd);
2770         if (cnt > xfer)
2771                 cnt = xfer;
2772         if (siz > xfer)
2773                 siz = xfer;
2774         fullsiz = siz;
2775         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
2776         if (!error && vp->v_type != VDIR) {
2777                 error = ENOTDIR;
2778                 vput(vp);
2779                 vp = NULL;
2780         }
2781         if (error) {
2782                 nfsm_reply(NFSX_UNSIGNED);
2783                 if (v3)
2784                         nfsm_srvpostop_attr(getret, &at);
2785                 error = 0;
2786                 goto nfsmout;
2787         }
2788
2789         /*
2790          * Obtain lock on vnode for this section of the code
2791          */
2792         if (v3) {
2793                 error = getret = VOP_GETATTR(vp, &at, cred);
2794 #if 0
2795                 /*
2796                  * XXX This check may be too strict for Solaris 2.5 clients.
2797                  */
2798                 if (!error && toff && verf && verf != at.va_filerev)
2799                         error = NFSERR_BAD_COOKIE;
2800 #endif
2801         }
2802         if (!error)
2803                 error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
2804         if (error) {
2805                 vput(vp);
2806                 vp = NULL;
2807                 nfsm_reply(NFSX_POSTOPATTR(v3));
2808                 if (v3)
2809                         nfsm_srvpostop_attr(getret, &at);
2810                 error = 0;
2811                 goto nfsmout;
2812         }
2813         not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") != 0;
2814         VOP_UNLOCK(vp, 0);
2815
2816         /*
2817          * end section.  Allocate rbuf and continue
2818          */
2819         rbuf = malloc(siz, M_TEMP, M_WAITOK);
2820 again:
2821         iv.iov_base = rbuf;
2822         iv.iov_len = fullsiz;
2823         io.uio_iov = &iv;
2824         io.uio_iovcnt = 1;
2825         io.uio_offset = (off_t)off;
2826         io.uio_resid = fullsiz;
2827         io.uio_segflg = UIO_SYSSPACE;
2828         io.uio_rw = UIO_READ;
2829         io.uio_td = NULL;
2830         eofflag = 0;
2831         if (cookies) {
2832                 free((caddr_t)cookies, M_TEMP);
2833                 cookies = NULL;
2834         }
2835         vn_lock(vp, LK_SHARED | LK_RETRY);
2836         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2837         off = (off_t)io.uio_offset;
2838         if (!cookies && !error)
2839                 error = NFSERR_PERM;
2840         if (v3) {
2841                 getret = VOP_GETATTR(vp, &at, cred);
2842                 if (!error)
2843                         error = getret;
2844         }
2845         VOP_UNLOCK(vp, 0);
2846         if (error) {
2847                 vrele(vp);
2848                 vp = NULL;
2849                 free((caddr_t)rbuf, M_TEMP);
2850                 if (cookies)
2851                         free((caddr_t)cookies, M_TEMP);
2852                 nfsm_reply(NFSX_POSTOPATTR(v3));
2853                 if (v3)
2854                         nfsm_srvpostop_attr(getret, &at);
2855                 error = 0;
2856                 goto nfsmout;
2857         }
2858         if (io.uio_resid) {
2859                 siz -= io.uio_resid;
2860
2861                 /*
2862                  * If nothing read, return eof
2863                  * rpc reply
2864                  */
2865                 if (siz == 0) {
2866                         vrele(vp);
2867                         vp = NULL;
2868                         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2869                                 2 * NFSX_UNSIGNED);
2870                         if (v3) {
2871                                 nfsm_srvpostop_attr(getret, &at);
2872                                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
2873                                 txdr_hyper(at.va_filerev, tl);
2874                                 tl += 2;
2875                         } else
2876                                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2877                         *tl++ = nfsrv_nfs_false;
2878                         *tl = nfsrv_nfs_true;
2879                         free((caddr_t)rbuf, M_TEMP);
2880                         free((caddr_t)cookies, M_TEMP);
2881                         error = 0;
2882                         goto nfsmout;
2883                 }
2884         }
2885
2886         /*
2887          * Check for degenerate cases of nothing useful read.
2888          * If so go try again
2889          */
2890         cpos = rbuf;
2891         cend = rbuf + siz;
2892         dp = (struct dirent *)cpos;
2893         cookiep = cookies;
2894         /*
2895          * For some reason FreeBSD's ufs_readdir() chooses to back the
2896          * directory offset up to a block boundary, so it is necessary to
2897          * skip over the records that precede the requested offset. This
2898          * requires the assumption that file offset cookies monotonically
2899          * increase.
2900          * Since the offset cookies don't monotonically increase for ZFS,
2901          * this is not done when ZFS is the file system.
2902          */
2903         while (cpos < cend && ncookies > 0 &&
2904                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
2905                  (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) {
2906                 cpos += dp->d_reclen;
2907                 dp = (struct dirent *)cpos;
2908                 cookiep++;
2909                 ncookies--;
2910         }
2911         if (cpos >= cend || ncookies == 0) {
2912                 toff = off;
2913                 siz = fullsiz;
2914                 goto again;
2915         }
2916
2917         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
2918         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2919         if (v3) {
2920                 nfsm_srvpostop_attr(getret, &at);
2921                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
2922                 txdr_hyper(at.va_filerev, tl);
2923         }
2924         mp = mb;
2925         bp = bpos;
2926         be = bp + M_TRAILINGSPACE(mp);
2927
2928         /* Loop through the records and build reply */
2929         while (cpos < cend && ncookies > 0) {
2930                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2931                         nlen = dp->d_namlen;
2932                         rem = nfsm_rndup(nlen) - nlen;
2933                         len += (4 * NFSX_UNSIGNED + nlen + rem);
2934                         if (v3)
2935                                 len += 2 * NFSX_UNSIGNED;
2936                         if (len > cnt) {
2937                                 eofflag = 0;
2938                                 break;
2939                         }
2940                         /*
2941                          * Build the directory record xdr from
2942                          * the dirent entry.
2943                          */
2944                         nfsm_clget;
2945                         *tl = nfsrv_nfs_true;
2946                         bp += NFSX_UNSIGNED;
2947                         if (v3) {
2948                                 nfsm_clget;
2949                                 *tl = 0;
2950                                 bp += NFSX_UNSIGNED;
2951                         }
2952                         nfsm_clget;
2953                         *tl = txdr_unsigned(dp->d_fileno);
2954                         bp += NFSX_UNSIGNED;
2955                         nfsm_clget;
2956                         *tl = txdr_unsigned(nlen);
2957                         bp += NFSX_UNSIGNED;
2958
2959                         /* And loop around copying the name */
2960                         xfer = nlen;
2961                         cp = dp->d_name;
2962                         while (xfer > 0) {
2963                                 nfsm_clget;
2964                                 if ((bp+xfer) > be)
2965                                         tsiz = be-bp;
2966                                 else
2967                                         tsiz = xfer;
2968                                 bcopy(cp, bp, tsiz);
2969                                 bp += tsiz;
2970                                 xfer -= tsiz;
2971                                 if (xfer > 0)
2972                                         cp += tsiz;
2973                         }
2974                         /* And null pad to an int32_t boundary. */
2975                         for (i = 0; i < rem; i++)
2976                                 *bp++ = '\0';
2977                         nfsm_clget;
2978
2979                         /* Finish off the record */
2980                         if (v3) {
2981                                 *tl = 0;
2982                                 bp += NFSX_UNSIGNED;
2983                                 nfsm_clget;
2984                         }
2985                         *tl = txdr_unsigned(*cookiep);
2986                         bp += NFSX_UNSIGNED;
2987                 }
2988                 cpos += dp->d_reclen;
2989                 dp = (struct dirent *)cpos;
2990                 cookiep++;
2991                 ncookies--;
2992         }
2993         vrele(vp);
2994         vp = NULL;
2995         nfsm_clget;
2996         *tl = nfsrv_nfs_false;
2997         bp += NFSX_UNSIGNED;
2998         nfsm_clget;
2999         if (eofflag)
3000                 *tl = nfsrv_nfs_true;
3001         else
3002                 *tl = nfsrv_nfs_false;
3003         bp += NFSX_UNSIGNED;
3004         if (mp != mb) {
3005                 if (bp < be)
3006                         mp->m_len = bp - mtod(mp, caddr_t);
3007         } else
3008                 mp->m_len += bp - bpos;
3009         free((caddr_t)rbuf, M_TEMP);
3010         free((caddr_t)cookies, M_TEMP);
3011
3012 nfsmout:
3013         if (vp)
3014                 vrele(vp);
3015         VFS_UNLOCK_GIANT(vfslocked);
3016         return(error);
3017 }
3018
3019 int
3020 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3021     struct mbuf **mrq)
3022 {
3023         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3024         struct sockaddr *nam = nfsd->nd_nam;
3025         caddr_t dpos = nfsd->nd_dpos;
3026         struct ucred *cred = nfsd->nd_cr;
3027         char *bp, *be;
3028         struct mbuf *mp;
3029         struct dirent *dp;
3030         caddr_t cp;
3031         u_int32_t *tl;
3032         caddr_t bpos;
3033         struct mbuf *mb, *mreq;
3034         char *cpos, *cend, *rbuf;
3035         struct vnode *vp = NULL, *nvp;
3036         struct flrep fl;
3037         nfsfh_t nfh;
3038         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3039         struct uio io;
3040         struct iovec iv;
3041         struct vattr va, at, *vap = &va;
3042         struct nfs_fattr *fp;
3043         int len, nlen, rem, xfer, tsiz, i, error = 0, error1, getret = 1;
3044         int vp_locked;
3045         int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3046         u_quad_t off, toff, verf;
3047         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3048         int v3 = (nfsd->nd_flag & ND_NFSV3);
3049         int usevget = 1, vfslocked;
3050         struct componentname cn;
3051         struct mount *mntp = NULL;
3052         int not_zfs;
3053
3054         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3055         vfslocked = 0;
3056         vp_locked = 0;
3057         if (!v3)
3058                 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
3059         fhp = &nfh.fh_generic;
3060         nfsm_srvmtofh(fhp);
3061         tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
3062         toff = fxdr_hyper(tl);
3063         tl += 2;
3064         verf = fxdr_hyper(tl);
3065         tl += 2;
3066         siz = fxdr_unsigned(int, *tl++);
3067         cnt = fxdr_unsigned(int, *tl);
3068         off = toff;
3069         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3070         xfer = NFS_SRVMAXDATA(nfsd);
3071         if (cnt > xfer)
3072                 cnt = xfer;
3073         if (siz > xfer)
3074                 siz = xfer;
3075         fullsiz = siz;
3076         error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, &vfslocked, nfsd, slp,
3077             nam, &rdonly);
3078         if (!error) {
3079                 vp_locked = 1;
3080                 mntp = vp->v_mount;
3081                 if (vp->v_type != VDIR) {
3082                         error = ENOTDIR;
3083                         vput(vp);
3084                         vp = NULL;
3085                         vp_locked = 0;
3086                 }
3087         }
3088         if (error) {
3089                 nfsm_reply(NFSX_UNSIGNED);
3090                 nfsm_srvpostop_attr(getret, &at);
3091                 error = 0;
3092                 goto nfsmout;
3093         }
3094         error = getret = VOP_GETATTR(vp, &at, cred);
3095 #if 0
3096         /*
3097          * XXX This check may be too strict for Solaris 2.5 clients.
3098          */
3099         if (!error && toff && verf && verf != at.va_filerev)
3100                 error = NFSERR_BAD_COOKIE;
3101 #endif
3102         if (!error)
3103                 error = nfsrv_access(vp, VEXEC, cred, rdonly, 0);
3104         if (error) {
3105                 vput(vp);
3106                 vp_locked = 0;
3107                 vp = NULL;
3108                 nfsm_reply(NFSX_V3POSTOPATTR);
3109                 nfsm_srvpostop_attr(getret, &at);
3110                 error = 0;
3111                 goto nfsmout;
3112         }
3113         not_zfs = strcmp(vp->v_mount->mnt_vfc->vfc_name, "zfs") != 0;
3114         VOP_UNLOCK(vp, 0);
3115         vp_locked = 0;
3116         rbuf = malloc(siz, M_TEMP, M_WAITOK);
3117 again:
3118         iv.iov_base = rbuf;
3119         iv.iov_len = fullsiz;
3120         io.uio_iov = &iv;
3121         io.uio_iovcnt = 1;
3122         io.uio_offset = (off_t)off;
3123         io.uio_resid = fullsiz;
3124         io.uio_segflg = UIO_SYSSPACE;
3125         io.uio_rw = UIO_READ;
3126         io.uio_td = NULL;
3127         eofflag = 0;
3128         vp_locked = 1;
3129         if (cookies) {
3130                 free((caddr_t)cookies, M_TEMP);
3131                 cookies = NULL;
3132         }
3133         vn_lock(vp, LK_SHARED | LK_RETRY);
3134         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3135         off = (u_quad_t)io.uio_offset;
3136         getret = VOP_GETATTR(vp, &at, cred);
3137         VOP_UNLOCK(vp, 0);
3138         vp_locked = 0;
3139         if (!cookies && !error)
3140                 error = NFSERR_PERM;
3141         if (!error)
3142                 error = getret;
3143         if (error) {
3144                 vrele(vp);
3145                 vp = NULL;
3146                 if (cookies)
3147                         free((caddr_t)cookies, M_TEMP);
3148                 free((caddr_t)rbuf, M_TEMP);
3149                 nfsm_reply(NFSX_V3POSTOPATTR);
3150                 nfsm_srvpostop_attr(getret, &at);
3151                 error = 0;
3152                 goto nfsmout;
3153         }
3154         if (io.uio_resid) {
3155                 siz -= io.uio_resid;
3156
3157                 /*
3158                  * If nothing read, return eof
3159                  * rpc reply
3160                  */
3161                 if (siz == 0) {
3162                         vrele(vp);
3163                         vp = NULL;
3164                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3165                                 2 * NFSX_UNSIGNED);
3166                         nfsm_srvpostop_attr(getret, &at);
3167                         tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3168                         txdr_hyper(at.va_filerev, tl);
3169                         tl += 2;
3170                         *tl++ = nfsrv_nfs_false;
3171                         *tl = nfsrv_nfs_true;
3172                         free((caddr_t)cookies, M_TEMP);
3173                         free((caddr_t)rbuf, M_TEMP);
3174                         error = 0;
3175                         goto nfsmout;
3176                 }
3177         }
3178
3179         /*
3180          * Check for degenerate cases of nothing useful read.
3181          * If so go try again
3182          */
3183         cpos = rbuf;
3184         cend = rbuf + siz;
3185         dp = (struct dirent *)cpos;
3186         cookiep = cookies;
3187         /*
3188          * For some reason FreeBSD's ufs_readdir() chooses to back the
3189          * directory offset up to a block boundary, so it is necessary to
3190          * skip over the records that precede the requested offset. This
3191          * requires the assumption that file offset cookies monotonically
3192          * increase.
3193          * Since the offset cookies don't monotonically increase for ZFS,
3194          * this is not done when ZFS is the file system.
3195          */
3196         while (cpos < cend && ncookies > 0 &&
3197                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3198                  (not_zfs != 0 && ((u_quad_t)(*cookiep)) <= toff))) {
3199                 cpos += dp->d_reclen;
3200                 dp = (struct dirent *)cpos;
3201                 cookiep++;
3202                 ncookies--;
3203         }
3204         if (cpos >= cend || ncookies == 0) {
3205                 toff = off;
3206                 siz = fullsiz;
3207                 goto again;
3208         }
3209
3210         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3211             2 * NFSX_UNSIGNED;
3212         nfsm_reply(cnt);
3213         nfsm_srvpostop_attr(getret, &at);
3214         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3215         txdr_hyper(at.va_filerev, tl);
3216         mp = mb;
3217         bp = bpos;
3218         be = bp + M_TRAILINGSPACE(mp);
3219
3220         /* Loop through the records and build reply */
3221         while (cpos < cend && ncookies > 0) {
3222                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3223                         nlen = dp->d_namlen;
3224                         rem = nfsm_rndup(nlen)-nlen;
3225
3226                         if (usevget) {
3227                                 /*
3228                                  * For readdir_and_lookup get the vnode using
3229                                  * the file number.
3230                                  */
3231                                 error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED,
3232                                     &nvp);
3233                                 if (error != 0 && error != EOPNOTSUPP) {
3234                                         error = 0;
3235                                         goto invalid;
3236                                 } else if (error == EOPNOTSUPP) {
3237                                         /*
3238                                          * VFS_VGET() not supported?
3239                                          * Let's switch to VOP_LOOKUP().
3240                                          */
3241                                         error = 0;
3242                                         usevget = 0;
3243                                         cn.cn_nameiop = LOOKUP;
3244                                         cn.cn_flags = ISLASTCN | NOFOLLOW | \
3245                                             LOCKSHARED | LOCKLEAF | MPSAFE;
3246                                         cn.cn_lkflags = LK_SHARED | LK_RETRY;
3247                                         cn.cn_cred = cred;
3248                                         cn.cn_thread = curthread;
3249                                 }
3250                         }
3251                         if (!usevget) {
3252                                 cn.cn_nameptr = dp->d_name;
3253                                 cn.cn_namelen = dp->d_namlen;
3254                                 if (dp->d_namlen == 2 &&
3255                                     dp->d_name[0] == '.' &&
3256                                     dp->d_name[1] == '.') {
3257                                         cn.cn_flags |= ISDOTDOT;
3258                                 } else {
3259                                         cn.cn_flags &= ~ISDOTDOT;
3260                                 }
3261                                 if (!vp_locked) {
3262                                         vn_lock(vp, LK_SHARED | LK_RETRY);
3263                                         vp_locked = 1;
3264                                 }
3265                                 if ((vp->v_vflag & VV_ROOT) != 0 &&
3266                                     (cn.cn_flags & ISDOTDOT) != 0) {
3267                                         vref(vp);
3268                                         nvp = vp;
3269                                 } else if (VOP_LOOKUP(vp, &nvp, &cn) != 0)
3270                                         goto invalid;
3271                         }
3272
3273                         bzero((caddr_t)nfhp, NFSX_V3FH);
3274                         nfhp->fh_fsid = nvp->v_mount->mnt_stat.f_fsid;
3275                         if ((error1 = VOP_VPTOFH(nvp, &nfhp->fh_fid)) == 0)
3276                                 error1 = VOP_GETATTR(nvp, vap, cred);
3277                         if (!usevget && vp == nvp)
3278                                 vunref(nvp);
3279                         else
3280                                 vput(nvp);
3281                         nvp = NULL;
3282                         if (error1 != 0)
3283                                 goto invalid;
3284
3285                         /*
3286                          * If either the dircount or maxcount will be
3287                          * exceeded, get out now. Both of these lengths
3288                          * are calculated conservatively, including all
3289                          * XDR overheads.
3290                          */
3291                         len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3292                                 NFSX_V3POSTOPATTR);
3293                         dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3294                         if (len > cnt || dirlen > fullsiz) {
3295                                 eofflag = 0;
3296                                 break;
3297                         }
3298
3299                         /*
3300                          * Build the directory record xdr from
3301                          * the dirent entry.
3302                          */
3303                         fp = (struct nfs_fattr *)&fl.fl_fattr;
3304                         nfsm_srvfillattr(vap, fp);
3305                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3306                         fl.fl_fhok = nfsrv_nfs_true;
3307                         fl.fl_postopok = nfsrv_nfs_true;
3308                         fl.fl_off.nfsuquad[0] = 0;
3309                         fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3310
3311                         nfsm_clget;
3312                         *tl = nfsrv_nfs_true;
3313                         bp += NFSX_UNSIGNED;
3314                         nfsm_clget;
3315                         *tl = 0;
3316                         bp += NFSX_UNSIGNED;
3317                         nfsm_clget;
3318                         *tl = txdr_unsigned(dp->d_fileno);
3319                         bp += NFSX_UNSIGNED;
3320                         nfsm_clget;
3321                         *tl = txdr_unsigned(nlen);
3322                         bp += NFSX_UNSIGNED;
3323
3324                         /* And loop around copying the name */
3325                         xfer = nlen;
3326                         cp = dp->d_name;
3327                         while (xfer > 0) {
3328                                 nfsm_clget;
3329                                 if ((bp + xfer) > be)
3330                                         tsiz = be - bp;
3331                                 else
3332                                         tsiz = xfer;
3333                                 bcopy(cp, bp, tsiz);
3334                                 bp += tsiz;
3335                                 xfer -= tsiz;
3336                                 if (xfer > 0)
3337                                         cp += tsiz;
3338                         }
3339                         /* And null pad to an int32_t boundary. */
3340                         for (i = 0; i < rem; i++)
3341                                 *bp++ = '\0';
3342
3343                         /*
3344                          * Now copy the flrep structure out.
3345                          */
3346                         xfer = sizeof (struct flrep);
3347                         cp = (caddr_t)&fl;
3348                         while (xfer > 0) {
3349                                 nfsm_clget;
3350                                 if ((bp + xfer) > be)
3351                                         tsiz = be - bp;
3352                                 else
3353                                         tsiz = xfer;
3354                                 bcopy(cp, bp, tsiz);
3355                                 bp += tsiz;
3356                                 xfer -= tsiz;
3357                                 if (xfer > 0)
3358                                         cp += tsiz;
3359                         }
3360                 }
3361 invalid:
3362                 cpos += dp->d_reclen;
3363                 dp = (struct dirent *)cpos;
3364                 cookiep++;
3365                 ncookies--;
3366         }
3367         if (!usevget && vp_locked)
3368                 vput(vp);
3369         else
3370                 vrele(vp);
3371         vp = NULL;
3372         nfsm_clget;
3373         *tl = nfsrv_nfs_false;
3374         bp += NFSX_UNSIGNED;
3375         nfsm_clget;
3376         if (eofflag)
3377                 *tl = nfsrv_nfs_true;
3378         else
3379                 *tl = nfsrv_nfs_false;
3380         bp += NFSX_UNSIGNED;
3381         if (mp != mb) {
3382                 if (bp < be)
3383                         mp->m_len = bp - mtod(mp, caddr_t);
3384         } else
3385                 mp->m_len += bp - bpos;
3386         free((caddr_t)cookies, M_TEMP);
3387         free((caddr_t)rbuf, M_TEMP);
3388 nfsmout:
3389         if (vp)
3390                 vrele(vp);
3391         if (mntp)
3392                 vfs_unbusy(mntp);
3393         VFS_UNLOCK_GIANT(vfslocked);
3394         return(error);
3395 }
3396
3397 /*
3398  * nfs commit service
3399  */
3400 int
3401 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3402     struct mbuf **mrq)
3403 {
3404         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3405         struct sockaddr *nam = nfsd->nd_nam;
3406         caddr_t dpos = nfsd->nd_dpos;
3407         struct ucred *cred = nfsd->nd_cr;
3408         struct vattr bfor, aft;
3409         struct vnode *vp = NULL;
3410         nfsfh_t nfh;
3411         fhandle_t *fhp;
3412         u_int32_t *tl;
3413         caddr_t bpos;
3414         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
3415         struct mbuf *mb, *mreq;
3416         u_quad_t off;
3417         struct mount *mp = NULL;
3418         int v3 = (nfsd->nd_flag & ND_NFSV3);
3419         int tvfslocked;
3420         int vfslocked;
3421
3422         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3423         vfslocked = 0;
3424         if (!v3)
3425                 panic("nfsrv_commit: v3 proc called on a v2 connection");
3426         fhp = &nfh.fh_generic;
3427         nfsm_srvmtofh(fhp);
3428         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3429                 error = ESTALE;
3430                 goto ereply;
3431         }
3432         vfslocked = VFS_LOCK_GIANT(mp);
3433         (void) vn_start_write(NULL, &mp, V_WAIT);
3434         vfs_rel(mp);            /* The write holds a ref. */
3435         tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
3436
3437         /*
3438          * XXX At this time VOP_FSYNC() does not accept offset and byte
3439          * count parameters, so these arguments are useless (someday maybe).
3440          */
3441         off = fxdr_hyper(tl);
3442         tl += 2;
3443         cnt = fxdr_unsigned(int, *tl);
3444         error = nfsrv_fhtovp(fhp, 0, &vp, &tvfslocked, nfsd, slp, nam, &rdonly);
3445         vfslocked = nfsrv_lockedpair(vfslocked, tvfslocked);
3446         if (error) {
3447                 nfsm_reply(2 * NFSX_UNSIGNED);
3448                 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3449                 error = 0;
3450                 goto nfsmout;
3451         }
3452         for_ret = VOP_GETATTR(vp, &bfor, cred);
3453
3454         if (cnt > MAX_COMMIT_COUNT) {
3455                 /*
3456                  * Give up and do the whole thing
3457                  */
3458                 if (vp->v_object &&
3459                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3460                         VM_OBJECT_LOCK(vp->v_object);
3461                         vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3462                         VM_OBJECT_UNLOCK(vp->v_object);
3463                 }
3464                 error = VOP_FSYNC(vp, MNT_WAIT, curthread);
3465         } else {
3466                 /*
3467                  * Locate and synchronously write any buffers that fall
3468                  * into the requested range.  Note:  we are assuming that
3469                  * f_iosize is a power of 2.
3470                  */
3471                 int iosize = vp->v_mount->mnt_stat.f_iosize;
3472                 int iomask = iosize - 1;
3473                 struct bufobj *bo;
3474                 daddr_t lblkno;
3475
3476                 /*
3477                  * Align to iosize boundry, super-align to page boundry.
3478                  */
3479                 if (off & iomask) {
3480                         cnt += off & iomask;
3481                         off &= ~(u_quad_t)iomask;
3482                 }
3483                 if (off & PAGE_MASK) {
3484                         cnt += off & PAGE_MASK;
3485                         off &= ~(u_quad_t)PAGE_MASK;
3486                 }
3487                 lblkno = off / iosize;
3488
3489                 if (vp->v_object &&
3490                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3491                         VM_OBJECT_LOCK(vp->v_object);
3492                         vm_object_page_clean(vp->v_object, OFF_TO_IDX(off),
3493                             OFF_TO_IDX(off + cnt + PAGE_MASK), OBJPC_SYNC);
3494                         VM_OBJECT_UNLOCK(vp->v_object);
3495                 }
3496
3497                 bo = &vp->v_bufobj;
3498                 BO_LOCK(bo);
3499                 while (cnt > 0) {
3500                         struct buf *bp;
3501
3502                         /*
3503                          * If we have a buffer and it is marked B_DELWRI we
3504                          * have to lock and write it.  Otherwise the prior
3505                          * write is assumed to have already been committed.
3506                          *
3507                          * gbincore() can return invalid buffers now so we
3508                          * have to check that bit as well (though B_DELWRI
3509                          * should not be set if B_INVAL is set there could be
3510                          * a race here since we haven't locked the buffer).
3511                          */
3512                         if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
3513                                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
3514                                     LK_INTERLOCK, BO_MTX(bo)) == ENOLCK) {
3515                                         BO_LOCK(bo);
3516                                         continue; /* retry */
3517                                 }
3518                                 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
3519                                     B_DELWRI) {
3520                                         bremfree(bp);
3521                                         bp->b_flags &= ~B_ASYNC;
3522                                         bwrite(bp);
3523                                         ++nfs_commit_miss;
3524                                 } else
3525                                         BUF_UNLOCK(bp);
3526                                 BO_LOCK(bo);
3527                         }
3528                         ++nfs_commit_blks;
3529                         if (cnt < iosize)
3530                                 break;
3531                         cnt -= iosize;
3532                         ++lblkno;
3533                 }
3534                 BO_UNLOCK(bo);
3535         }
3536
3537         aft_ret = VOP_GETATTR(vp, &aft, cred);
3538         vput(vp);
3539         vp = NULL;
3540 ereply:
3541         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3542         nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3543         if (!error) {
3544                 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
3545                 if (nfsver.tv_sec == 0)
3546                         nfsver = boottime;
3547                 *tl++ = txdr_unsigned(nfsver.tv_sec);
3548                 *tl = txdr_unsigned(nfsver.tv_usec);
3549         } else {
3550                 error = 0;
3551         }
3552 nfsmout:
3553         if (vp)
3554                 vput(vp);
3555         vn_finished_write(mp);
3556         VFS_UNLOCK_GIANT(vfslocked);
3557         return(error);
3558 }
3559
3560 /*
3561  * nfs statfs service
3562  */
3563 int
3564 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3565     struct mbuf **mrq)
3566 {
3567         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3568         struct sockaddr *nam = nfsd->nd_nam;
3569         caddr_t dpos = nfsd->nd_dpos;
3570         struct ucred *cred = nfsd->nd_cr;
3571         struct statfs *sf;
3572         struct nfs_statfs *sfp;
3573         caddr_t bpos;
3574         int error = 0, rdonly, getret = 1;
3575         int v3 = (nfsd->nd_flag & ND_NFSV3);
3576         struct mbuf *mb, *mreq;
3577         struct vnode *vp = NULL;
3578         struct vattr at;
3579         nfsfh_t nfh;
3580         fhandle_t *fhp;
3581         struct statfs statfs;
3582         u_quad_t tval;
3583         int vfslocked;
3584
3585         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3586         vfslocked = 0;
3587         fhp = &nfh.fh_generic;
3588         nfsm_srvmtofh(fhp);
3589         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3590         if (error) {
3591                 nfsm_reply(NFSX_UNSIGNED);
3592                 if (v3)
3593                         nfsm_srvpostop_attr(getret, &at);
3594                 error = 0;
3595                 goto nfsmout;
3596         }
3597         sf = &statfs;
3598         error = VFS_STATFS(vp->v_mount, sf);
3599         getret = VOP_GETATTR(vp, &at, cred);
3600         vput(vp);
3601         vp = NULL;
3602         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3603         if (v3)
3604                 nfsm_srvpostop_attr(getret, &at);
3605         if (error) {
3606                 error = 0;
3607                 goto nfsmout;
3608         }
3609         sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
3610         if (v3) {
3611                 tval = (u_quad_t)sf->f_blocks;
3612                 tval *= (u_quad_t)sf->f_bsize;
3613                 txdr_hyper(tval, &sfp->sf_tbytes);
3614                 tval = (u_quad_t)sf->f_bfree;
3615                 tval *= (u_quad_t)sf->f_bsize;
3616                 txdr_hyper(tval, &sfp->sf_fbytes);
3617                 /*
3618                  * Don't send negative values for available space,
3619                  * since this field is unsigned in the NFS protocol.
3620                  * Otherwise, the client would see absurdly high
3621                  * numbers for free space.
3622                  */
3623                 if (sf->f_bavail < 0)
3624                         tval = 0;
3625                 else
3626                         tval = (u_quad_t)sf->f_bavail;
3627                 tval *= (u_quad_t)sf->f_bsize;
3628                 txdr_hyper(tval, &sfp->sf_abytes);
3629                 sfp->sf_tfiles.nfsuquad[0] = 0;
3630                 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3631                 sfp->sf_ffiles.nfsuquad[0] = 0;
3632                 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3633                 sfp->sf_afiles.nfsuquad[0] = 0;
3634                 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3635                 sfp->sf_invarsec = 0;
3636         } else {
3637                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3638                 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3639                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3640                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3641                 if (sf->f_bavail < 0)
3642                         sfp->sf_bavail = 0;
3643                 else
3644                         sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3645         }
3646 nfsmout:
3647         if (vp)
3648                 vput(vp);
3649         VFS_UNLOCK_GIANT(vfslocked);
3650         return(error);
3651 }
3652
3653 /*
3654  * nfs fsinfo service
3655  */
3656 int
3657 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3658     struct mbuf **mrq)
3659 {
3660         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3661         struct sockaddr *nam = nfsd->nd_nam;
3662         caddr_t dpos = nfsd->nd_dpos;
3663         struct ucred *cred = nfsd->nd_cr;
3664         struct nfsv3_fsinfo *sip;
3665         caddr_t bpos;
3666         int error = 0, rdonly, getret = 1, pref;
3667         struct mbuf *mb, *mreq;
3668         struct vnode *vp = NULL;
3669         struct vattr at;
3670         nfsfh_t nfh;
3671         fhandle_t *fhp;
3672         u_quad_t maxfsize;
3673         struct statfs sb;
3674         int v3 = (nfsd->nd_flag & ND_NFSV3);
3675         int vfslocked;
3676
3677         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3678         if (!v3)
3679                 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
3680         fhp = &nfh.fh_generic;
3681         vfslocked = 0;
3682         nfsm_srvmtofh(fhp);
3683         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3684         if (error) {
3685                 nfsm_reply(NFSX_UNSIGNED);
3686                 nfsm_srvpostop_attr(getret, &at);
3687                 error = 0;
3688                 goto nfsmout;
3689         }
3690
3691         /* XXX Try to make a guess on the max file size. */
3692         VFS_STATFS(vp->v_mount, &sb);
3693         maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3694
3695         getret = VOP_GETATTR(vp, &at, cred);
3696         vput(vp);
3697         vp = NULL;
3698         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3699         nfsm_srvpostop_attr(getret, &at);
3700         sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3701
3702         /*
3703          * XXX
3704          * There should be filesystem VFS OP(s) to get this information.
3705          * For now, assume ufs.
3706          */
3707         pref = NFS_SRVMAXDATA(nfsd);
3708         sip->fs_rtmax = txdr_unsigned(pref);
3709         sip->fs_rtpref = txdr_unsigned(pref);
3710         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3711         sip->fs_wtmax = txdr_unsigned(pref);
3712         sip->fs_wtpref = txdr_unsigned(pref);
3713         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3714         sip->fs_dtpref = txdr_unsigned(pref);
3715         txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3716         sip->fs_timedelta.nfsv3_sec = 0;
3717         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3718         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3719                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3720                 NFSV3FSINFO_CANSETTIME);
3721 nfsmout:
3722         if (vp)
3723                 vput(vp);
3724         VFS_UNLOCK_GIANT(vfslocked);
3725         return(error);
3726 }
3727
3728 /*
3729  * nfs pathconf service
3730  */
3731 int
3732 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3733     struct mbuf **mrq)
3734 {
3735         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3736         struct sockaddr *nam = nfsd->nd_nam;
3737         caddr_t dpos = nfsd->nd_dpos;
3738         struct ucred *cred = nfsd->nd_cr;
3739         struct nfsv3_pathconf *pc;
3740         caddr_t bpos;
3741         int error = 0, rdonly, getret = 1;
3742         register_t linkmax, namemax, chownres, notrunc;
3743         struct mbuf *mb, *mreq;
3744         struct vnode *vp = NULL;
3745         struct vattr at;
3746         nfsfh_t nfh;
3747         fhandle_t *fhp;
3748         int v3 = (nfsd->nd_flag & ND_NFSV3);
3749         int vfslocked;
3750
3751         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3752         if (!v3)
3753                 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
3754         vfslocked = 0;
3755         fhp = &nfh.fh_generic;
3756         nfsm_srvmtofh(fhp);
3757         error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, nam, &rdonly);
3758         if (error) {
3759                 nfsm_reply(NFSX_UNSIGNED);
3760                 nfsm_srvpostop_attr(getret, &at);
3761                 error = 0;
3762                 goto nfsmout;
3763         }
3764         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3765         if (!error)
3766                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3767         if (!error)
3768                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3769         if (!error)
3770                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
3771         getret = VOP_GETATTR(vp, &at, cred);
3772         vput(vp);
3773         vp = NULL;
3774         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3775         nfsm_srvpostop_attr(getret, &at);
3776         if (error) {
3777                 error = 0;
3778                 goto nfsmout;
3779         }
3780         pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3781
3782         pc->pc_linkmax = txdr_unsigned(linkmax);
3783         pc->pc_namemax = txdr_unsigned(namemax);
3784         pc->pc_notrunc = txdr_unsigned(notrunc);
3785         pc->pc_chownrestricted = txdr_unsigned(chownres);
3786
3787         /*
3788          * These should probably be supported by VOP_PATHCONF(), but
3789          * until msdosfs is exportable (why would you want to?), the
3790          * Unix defaults should be ok.
3791          */
3792         pc->pc_caseinsensitive = nfsrv_nfs_false;
3793         pc->pc_casepreserving = nfsrv_nfs_true;
3794 nfsmout:
3795         if (vp)
3796                 vput(vp);
3797         VFS_UNLOCK_GIANT(vfslocked);
3798         return(error);
3799 }
3800
3801 /*
3802  * Null operation, used by clients to ping server
3803  */
3804 /* ARGSUSED */
3805 int
3806 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3807     struct mbuf **mrq)
3808 {
3809         struct mbuf *mrep = nfsd->nd_mrep;
3810         caddr_t bpos;
3811         int error = NFSERR_RETVOID;
3812         struct mbuf *mb, *mreq;
3813
3814         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3815         nfsm_reply(0);
3816 nfsmout:
3817         return (error);
3818 }
3819
3820 /*
3821  * No operation, used for obsolete procedures
3822  */
3823 /* ARGSUSED */
3824 int
3825 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3826     struct mbuf **mrq)
3827 {
3828         struct mbuf *mrep = nfsd->nd_mrep;
3829         caddr_t bpos;
3830         int error;
3831         struct mbuf *mb, *mreq;
3832
3833         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3834         if (nfsd->nd_repstat)
3835                 error = nfsd->nd_repstat;
3836         else
3837                 error = EPROCUNAVAIL;
3838         nfsm_reply(0);
3839         error = 0;
3840 nfsmout:
3841         return (error);
3842 }
3843
3844 /*
3845  * Perform access checking for vnodes obtained from file handles that would
3846  * refer to files already opened by a Unix client. You cannot just use
3847  * vn_writechk() and VOP_ACCESS() for two reasons.
3848  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
3849  *     case.
3850  * 2 - The owner is to be given access irrespective of mode bits for some
3851  *     operations, so that processes that chmod after opening a file don't
3852  *     break. I don't like this because it opens a security hole, but since
3853  *     the nfs server opens a security hole the size of a barn door anyhow,
3854  *     what the heck.
3855  *
3856  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3857  * will return EPERM instead of EACCES. EPERM is always an error.
3858  */
3859 static int
3860 nfsrv_access(struct vnode *vp, accmode_t accmode, struct ucred *cred,
3861     int rdonly, int override)
3862 {
3863         struct vattr vattr;
3864         int error;
3865
3866         VFS_ASSERT_GIANT(vp->v_mount);
3867
3868         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3869
3870         if (accmode & VWRITE) {
3871                 /* Just vn_writechk() changed to check rdonly */
3872                 /*
3873                  * Disallow write attempts on read-only filesystems;
3874                  * unless the file is a socket or a block or character
3875                  * device resident on the filesystem.
3876                  */
3877                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3878                         switch (vp->v_type) {
3879                         case VREG:
3880                         case VDIR:
3881                         case VLNK:
3882                                 return (EROFS);
3883                         default:
3884                                 break;
3885                         }
3886                 }
3887                 /*
3888                  * If there's shared text associated with
3889                  * the inode, we can't allow writing.
3890                  */
3891                 if (vp->v_vflag & VV_TEXT)
3892                         return (ETXTBSY);
3893         }
3894
3895         error = VOP_GETATTR(vp, &vattr, cred);
3896         if (error)
3897                 return (error);
3898         error = VOP_ACCESS(vp, accmode, cred, curthread);
3899         /*
3900          * Allow certain operations for the owner (reads and writes
3901          * on files that are already open).
3902          */
3903         if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3904                 error = 0;
3905         return (error);
3906 }