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