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