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