]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/nfsserver/nfs_serv.c
This commit was generated by cvs2svn to compensate for changes in r155518,
[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 (ndp->ni_vp)
668                 vput(ndp->ni_vp);
669         if (dirp)
670                 vrele(dirp);
671         NDFREE(&nd, NDF_ONLY_PNBUF);
672         if (ndp->ni_startdir)
673                 vrele(ndp->ni_startdir);
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_dvp) {
2008                 if (nd.ni_dvp == nd.ni_vp)
2009                         vrele(nd.ni_dvp);
2010                 else
2011                         vput(nd.ni_dvp);
2012         }
2013         if (nd.ni_vp)
2014                 vput(nd.ni_vp);
2015         if (nd.ni_startdir) {
2016                 vrele(nd.ni_startdir);
2017                 nd.ni_startdir = NULL;
2018         }
2019         if (dirp)
2020                 vrele(dirp);
2021         NDFREE(&nd, NDF_ONLY_PNBUF);
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                 NFSD_UNLOCK();
2096                 mtx_lock(&Giant);       /* VFS */
2097                 error = NFSERR_BADTYPE;
2098                 goto out;
2099         }
2100         VATTR_NULL(vap);
2101         nfsm_srvsattr(vap);
2102         if (vtyp == VCHR || vtyp == VBLK) {
2103                 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2104                 major = fxdr_unsigned(u_int32_t, *tl++);
2105                 minor = fxdr_unsigned(u_int32_t, *tl);
2106                 vap->va_rdev = makedev(major, minor);
2107         }
2108
2109         /*
2110          * Iff doesn't exist, create it.
2111          */
2112         if (nd.ni_vp) {
2113                 NFSD_UNLOCK();
2114                 mtx_lock(&Giant);       /* VFS */
2115                 error = EEXIST;
2116                 goto out;
2117         }
2118         vap->va_type = vtyp;
2119         if (vap->va_mode == (mode_t)VNOVAL)
2120                 vap->va_mode = 0;
2121         NFSD_UNLOCK();
2122         mtx_lock(&Giant);       /* VFS */
2123         if (vtyp == VSOCK) {
2124                 vrele(nd.ni_startdir);
2125                 nd.ni_startdir = NULL;
2126                 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2127                 if (error)
2128                         NDFREE(&nd, NDF_ONLY_PNBUF);
2129         } else {
2130                 if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
2131                         goto out;
2132                 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2133                 if (error) {
2134                         NDFREE(&nd, NDF_ONLY_PNBUF);
2135                         goto out;
2136                 }
2137                 vput(nd.ni_vp);
2138                 nd.ni_vp = NULL;
2139
2140                 /*
2141                  * Release dvp prior to lookup
2142                  */
2143                 vput(nd.ni_dvp);
2144                 nd.ni_dvp = NULL;
2145
2146                 nd.ni_cnd.cn_nameiop = LOOKUP;
2147                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
2148                 nd.ni_cnd.cn_thread = td;
2149                 nd.ni_cnd.cn_cred = td->td_ucred;
2150
2151                 error = lookup(&nd);
2152                 nd.ni_dvp = NULL;
2153
2154                 if (error)
2155                         goto out;
2156                 if (nd.ni_cnd.cn_flags & ISSYMLINK)
2157                         error = EINVAL;
2158         }
2159
2160         /*
2161          * send response, cleanup, return.
2162          */
2163 out:
2164         NFSD_UNLOCK_ASSERT();
2165         vp = nd.ni_vp;
2166         if (!error) {
2167                 bzero((caddr_t)fhp, sizeof(nfh));
2168                 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2169                 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2170                 if (!error)
2171                         error = VOP_GETATTR(vp, vap, cred, td);
2172         }
2173         if (nd.ni_dvp) {
2174                 if (nd.ni_dvp == nd.ni_vp)
2175                         vrele(nd.ni_dvp);
2176                 else
2177                         vput(nd.ni_dvp);
2178                 nd.ni_dvp = NULL;
2179         }
2180         if (vp) {
2181                 vput(vp);
2182                 vp = NULL;
2183                 nd.ni_vp = NULL;
2184         }
2185         if (nd.ni_startdir) {
2186                 vrele(nd.ni_startdir);
2187                 nd.ni_startdir = NULL;
2188         }
2189         NDFREE(&nd, NDF_ONLY_PNBUF);
2190         if (dirp) {
2191                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2192                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2193                 VOP_UNLOCK(dirp, 0, td);
2194         }
2195         mtx_unlock(&Giant);     /* VFS */
2196         NFSD_LOCK();
2197 ereply:
2198         NFSD_LOCK_ASSERT();
2199         nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
2200         if (v3) {
2201                 if (!error) {
2202                         nfsm_srvpostop_fh(fhp);
2203                         nfsm_srvpostop_attr(0, vap);
2204                 }
2205                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2206         }
2207         NFSD_UNLOCK();
2208         mtx_lock(&Giant);       /* VFS */
2209         vn_finished_write(mp);
2210         mtx_unlock(&Giant);     /* VFS */
2211         NFSD_LOCK();
2212         return (0);
2213 nfsmout:
2214         NFSD_LOCK_ASSERT();
2215         NFSD_UNLOCK();
2216         mtx_lock(&Giant);       /* VFS */
2217         if (nd.ni_dvp) {
2218                 if (nd.ni_dvp == nd.ni_vp)
2219                         vrele(nd.ni_dvp);
2220                 else
2221                         vput(nd.ni_dvp);
2222         }
2223         if (nd.ni_vp)
2224                 vput(nd.ni_vp);
2225         if (dirp)
2226                 vrele(dirp);
2227         if (nd.ni_startdir)
2228                 vrele(nd.ni_startdir);
2229         NDFREE(&nd, NDF_ONLY_PNBUF);
2230         vn_finished_write(mp);
2231         mtx_unlock(&Giant);     /* VFS */
2232         NFSD_LOCK();
2233         return (error);
2234 }
2235
2236 /*
2237  * nfs remove service
2238  */
2239 int
2240 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2241     struct thread *td, struct mbuf **mrq)
2242 {
2243         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2244         struct sockaddr *nam = nfsd->nd_nam;
2245         caddr_t dpos = nfsd->nd_dpos;
2246         struct ucred *cred = nfsd->nd_cr;
2247         struct nameidata nd;
2248         caddr_t bpos;
2249         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2250         int v3 = (nfsd->nd_flag & ND_NFSV3);
2251         struct mbuf *mb, *mreq;
2252         struct vnode *dirp;
2253         struct vattr dirfor, diraft;
2254         nfsfh_t nfh;
2255         fhandle_t *fhp;
2256         struct mount *mp = NULL;
2257
2258         NFSD_LOCK_ASSERT();
2259
2260         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2261         ndclear(&nd);
2262
2263         fhp = &nfh.fh_generic;
2264         nfsm_srvmtofh(fhp);
2265         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2266                 error = ESTALE;
2267                 goto ereply;
2268         }
2269         NFSD_UNLOCK();
2270         mtx_lock(&Giant);       /* VFS */
2271         (void) vn_start_write(NULL, &mp, V_WAIT);
2272         mtx_unlock(&Giant);     /* VFS */
2273         NFSD_LOCK();
2274         nfsm_srvnamesiz(len);
2275
2276         nd.ni_cnd.cn_cred = cred;
2277         nd.ni_cnd.cn_nameiop = DELETE;
2278         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2279         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2280                 &dirp, v3,  &dirfor, &dirfor_ret, td, FALSE);
2281         NFSD_UNLOCK();
2282         mtx_lock(&Giant);       /* VFS */
2283         if (dirp && !v3) {
2284                 vrele(dirp);
2285                 dirp = NULL;
2286         }
2287         if (error == 0) {
2288                 if (nd.ni_vp->v_type == VDIR) {
2289                         error = EPERM;          /* POSIX */
2290                         goto out;
2291                 }
2292                 /*
2293                  * The root of a mounted filesystem cannot be deleted.
2294                  */
2295                 if (nd.ni_vp->v_vflag & VV_ROOT) {
2296                         error = EBUSY;
2297                         goto out;
2298                 }
2299 out:
2300                 NFSD_UNLOCK_ASSERT();
2301                 if (!error) {
2302                         error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2303                         NDFREE(&nd, NDF_ONLY_PNBUF);
2304                 }
2305         }
2306         if (dirp && v3) {
2307                 if (dirp == nd.ni_dvp)
2308                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2309                 else {
2310                         /* Drop the other locks to avoid deadlock. */
2311                         if (nd.ni_dvp) {
2312                                 if (nd.ni_dvp == nd.ni_vp)
2313                                         vrele(nd.ni_dvp);
2314                                 else
2315                                         vput(nd.ni_dvp);
2316                         }
2317                         if (nd.ni_vp)
2318                                 vput(nd.ni_vp);
2319                         nd.ni_dvp = NULL;
2320                         nd.ni_vp = NULL;
2321
2322                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2323                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2324                         VOP_UNLOCK(dirp, 0, td);
2325                 }
2326                 vrele(dirp);
2327                 dirp = NULL;
2328         }
2329         mtx_unlock(&Giant);     /* VFS */
2330         NFSD_LOCK();
2331 ereply:
2332         NFSD_LOCK_ASSERT();
2333         nfsm_reply(NFSX_WCCDATA(v3));
2334         if (v3) {
2335                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2336                 error = 0;
2337         }
2338 nfsmout:
2339         NFSD_LOCK_ASSERT();
2340         NFSD_UNLOCK();
2341         mtx_lock(&Giant);       /* VFS */
2342         NDFREE(&nd, NDF_ONLY_PNBUF);
2343         if (nd.ni_dvp) {
2344                 if (nd.ni_dvp == nd.ni_vp)
2345                         vrele(nd.ni_dvp);
2346                 else
2347                         vput(nd.ni_dvp);
2348         }
2349         if (nd.ni_vp)
2350                 vput(nd.ni_vp);
2351         vn_finished_write(mp);
2352         mtx_unlock(&Giant);     /* VFS */
2353         NFSD_LOCK();
2354         return(error);
2355 }
2356
2357 /*
2358  * nfs rename service
2359  */
2360 int
2361 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2362     struct thread *td, struct mbuf **mrq)
2363 {
2364         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2365         struct sockaddr *nam = nfsd->nd_nam;
2366         caddr_t dpos = nfsd->nd_dpos;
2367         struct ucred *cred = nfsd->nd_cr;
2368         caddr_t bpos;
2369         int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2370         int tdirfor_ret = 1, tdiraft_ret = 1;
2371         int v3 = (nfsd->nd_flag & ND_NFSV3);
2372         struct mbuf *mb, *mreq;
2373         struct nameidata fromnd, tond;
2374         struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
2375         struct vnode *tdirp = NULL;
2376         struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2377         nfsfh_t fnfh, tnfh;
2378         fhandle_t *ffhp, *tfhp;
2379         uid_t saved_uid;
2380         struct mount *mp = NULL;
2381
2382         NFSD_LOCK_ASSERT();
2383
2384         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2385 #ifndef nolint
2386         fvp = NULL;
2387 #endif
2388         ffhp = &fnfh.fh_generic;
2389         tfhp = &tnfh.fh_generic;
2390
2391         /*
2392          * Clear fields incase goto nfsmout occurs from macro.
2393          */
2394
2395         ndclear(&fromnd);
2396         ndclear(&tond);
2397
2398         nfsm_srvmtofh(ffhp);
2399         if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
2400                 error = ESTALE;
2401                 goto out1;
2402         }
2403         NFSD_UNLOCK();
2404         mtx_lock(&Giant);
2405         (void) vn_start_write(NULL, &mp, V_WAIT);
2406         mtx_unlock(&Giant);
2407         NFSD_LOCK();
2408         nfsm_srvnamesiz(len);
2409         /*
2410          * Remember our original uid so that we can reset cr_uid before
2411          * the second nfs_namei() call, in case it is remapped.
2412          */
2413         saved_uid = cred->cr_uid;
2414         fromnd.ni_cnd.cn_cred = cred;
2415         fromnd.ni_cnd.cn_nameiop = DELETE;
2416         fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
2417         error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
2418                 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
2419         if (fdirp && !v3) {
2420                 NFSD_UNLOCK();
2421                 mtx_lock(&Giant);       /* VFS */
2422                 vrele(fdirp);
2423                 mtx_unlock(&Giant);     /* VFS */
2424                 NFSD_LOCK();
2425                 fdirp = NULL;
2426         }
2427         if (error) {
2428                 nfsm_reply(2 * NFSX_WCCDATA(v3));
2429                 if (v3) {
2430                         nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2431                         nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2432                 }
2433                 error = 0;
2434                 goto nfsmout;
2435         }
2436         fvp = fromnd.ni_vp;
2437         nfsm_srvmtofh(tfhp);
2438         nfsm_srvnamesiz(len2);
2439         cred->cr_uid = saved_uid;
2440         tond.ni_cnd.cn_cred = cred;
2441         tond.ni_cnd.cn_nameiop = RENAME;
2442         tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
2443         error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
2444                 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
2445         NFSD_UNLOCK();
2446         mtx_lock(&Giant);       /* VFS */
2447         if (tdirp && !v3) {
2448                 vrele(tdirp);
2449                 tdirp = NULL;
2450         }
2451         if (error) {
2452                 mtx_unlock(&Giant);     /* VFS */
2453                 NFSD_LOCK();
2454                 goto out1;
2455         }
2456
2457         tdvp = tond.ni_dvp;
2458         tvp = tond.ni_vp;
2459         if (tvp != NULL) {
2460                 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2461                         if (v3)
2462                                 error = EEXIST;
2463                         else
2464                                 error = EISDIR;
2465                         goto out;
2466                 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2467                         if (v3)
2468                                 error = EEXIST;
2469                         else
2470                                 error = ENOTDIR;
2471                         goto out;
2472                 }
2473                 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
2474                         if (v3)
2475                                 error = EXDEV;
2476                         else
2477                                 error = ENOTEMPTY;
2478                         goto out;
2479                 }
2480         }
2481         if (fvp->v_type == VDIR && fvp->v_mountedhere) {
2482                 if (v3)
2483                         error = EXDEV;
2484                 else
2485                         error = ENOTEMPTY;
2486                 goto out;
2487         }
2488         if (fvp->v_mount != tdvp->v_mount) {
2489                 if (v3)
2490                         error = EXDEV;
2491                 else
2492                         error = ENOTEMPTY;
2493                 goto out;
2494         }
2495         if (fvp == tdvp) {
2496                 if (v3)
2497                         error = EINVAL;
2498                 else
2499                         error = ENOTEMPTY;
2500         }
2501         /*
2502          * If source is the same as the destination (that is the
2503          * same vnode with the same name in the same directory),
2504          * then there is nothing to do.
2505          */
2506         if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2507             fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2508             !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2509               fromnd.ni_cnd.cn_namelen))
2510                 error = -1;
2511 out:
2512         NFSD_UNLOCK_ASSERT();
2513         if (!error) {
2514                 /*
2515                  * The VOP_RENAME function releases all vnode references &
2516                  * locks prior to returning so we need to clear the pointers
2517                  * to bypass cleanup code later on.
2518                  */
2519                 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2520                                    tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2521                 fromnd.ni_dvp = NULL;
2522                 fromnd.ni_vp = NULL;
2523                 tond.ni_dvp = NULL;
2524                 tond.ni_vp = NULL;
2525                 if (error) {
2526                         fromnd.ni_cnd.cn_flags &= ~HASBUF;
2527                         tond.ni_cnd.cn_flags &= ~HASBUF;
2528                 }
2529         } else {
2530                 if (error == -1)
2531                         error = 0;
2532         }
2533         /* fall through */
2534
2535         mtx_unlock(&Giant);     /* VFS */
2536         NFSD_LOCK();
2537 out1:
2538         NFSD_LOCK_ASSERT();
2539         nfsm_reply(2 * NFSX_WCCDATA(v3));
2540         if (v3) {
2541                 /* Release existing locks to prevent deadlock. */
2542                 NFSD_UNLOCK();
2543                 mtx_lock(&Giant);       /* VFS */
2544                 if (tond.ni_dvp) {
2545                         if (tond.ni_dvp == tond.ni_vp)
2546                                 vrele(tond.ni_dvp);
2547                         else
2548                                 vput(tond.ni_dvp);
2549                 }
2550                 if (tond.ni_vp)
2551                         vput(tond.ni_vp);
2552                 tond.ni_dvp = NULL;
2553                 tond.ni_vp = NULL;
2554
2555                 if (fdirp) {
2556                         vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY, td);
2557                         fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
2558                         VOP_UNLOCK(fdirp, 0, td);
2559                 }
2560                 if (tdirp) {
2561                         vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY, td);
2562                         tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
2563                         VOP_UNLOCK(tdirp, 0, td);
2564                 }
2565                 mtx_unlock(&Giant);     /* VFS */
2566                 NFSD_LOCK();
2567                 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2568                 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2569         }
2570         error = 0;
2571         /* fall through */
2572
2573 nfsmout:
2574         /*
2575          * Clear out tond related fields
2576          */
2577         NFSD_LOCK_ASSERT();
2578         NFSD_UNLOCK();
2579         mtx_lock(&Giant);       /* VFS */
2580         if (tond.ni_dvp) {
2581                 if (tond.ni_dvp == tond.ni_vp)
2582                         vrele(tond.ni_dvp);
2583                 else
2584                         vput(tond.ni_dvp);
2585         }
2586         if (tond.ni_vp)
2587                 vput(tond.ni_vp);
2588         if (tdirp)
2589                 vrele(tdirp);
2590         if (tond.ni_startdir)
2591                 vrele(tond.ni_startdir);
2592         NDFREE(&tond, NDF_ONLY_PNBUF);
2593         /*
2594          * Clear out fromnd related fields
2595          */
2596         if (fdirp)
2597                 vrele(fdirp);
2598         if (fromnd.ni_startdir)
2599                 vrele(fromnd.ni_startdir);
2600         NDFREE(&fromnd, NDF_ONLY_PNBUF);
2601         if (fromnd.ni_dvp)
2602                 vrele(fromnd.ni_dvp);
2603         if (fromnd.ni_vp)
2604                 vrele(fromnd.ni_vp);
2605
2606         vn_finished_write(mp);
2607         mtx_unlock(&Giant);     /* VFS */
2608         NFSD_LOCK();
2609         return (error);
2610 }
2611
2612 /*
2613  * nfs link service
2614  */
2615 int
2616 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2617     struct thread *td, struct mbuf **mrq)
2618 {
2619         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2620         struct sockaddr *nam = nfsd->nd_nam;
2621         caddr_t dpos = nfsd->nd_dpos;
2622         struct ucred *cred = nfsd->nd_cr;
2623         struct nameidata nd;
2624         caddr_t bpos;
2625         int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2626         int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2627         struct mbuf *mb, *mreq;
2628         struct vnode *vp = NULL, *xp, *dirp = NULL;
2629         struct vattr dirfor, diraft, at;
2630         nfsfh_t nfh, dnfh;
2631         fhandle_t *fhp, *dfhp;
2632         struct mount *mp = NULL;
2633
2634         NFSD_LOCK_ASSERT();
2635
2636         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2637         ndclear(&nd);
2638
2639         fhp = &nfh.fh_generic;
2640         dfhp = &dnfh.fh_generic;
2641         nfsm_srvmtofh(fhp);
2642         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2643                 error = ESTALE;
2644                 goto ereply;
2645         }
2646         NFSD_UNLOCK();
2647         mtx_lock(&Giant);       /* VFS */
2648         (void) vn_start_write(NULL, &mp, V_WAIT);
2649         mtx_unlock(&Giant);     /* VFS */
2650         NFSD_LOCK();
2651         nfsm_srvmtofh(dfhp);
2652         nfsm_srvnamesiz(len);
2653
2654         error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE);
2655         if (error) {
2656                 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2657                 if (v3) {
2658                         nfsm_srvpostop_attr(getret, &at);
2659                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2660                 }
2661                 vp = NULL;
2662                 error = 0;
2663                 goto nfsmout;
2664         }
2665         NFSD_UNLOCK();
2666         mtx_lock(&Giant);       /* VFS */
2667         if (v3)
2668                 getret = VOP_GETATTR(vp, &at, cred, td);
2669         if (vp->v_type == VDIR) {
2670                 error = EPERM;          /* POSIX */
2671                 goto out1;
2672         }
2673         VOP_UNLOCK(vp, 0, td);
2674         nd.ni_cnd.cn_cred = cred;
2675         nd.ni_cnd.cn_nameiop = CREATE;
2676         nd.ni_cnd.cn_flags = LOCKPARENT;
2677         mtx_unlock(&Giant);     /* VFS */
2678         NFSD_LOCK();
2679         error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2680                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2681         NFSD_UNLOCK();
2682         mtx_lock(&Giant);       /* VFS */
2683         if (dirp && !v3) {
2684                 vrele(dirp);
2685                 dirp = NULL;
2686         }
2687         if (error) {
2688                 vrele(vp);
2689                 vp = NULL;
2690                 goto out2;
2691         }
2692         xp = nd.ni_vp;
2693         if (xp != NULL) {
2694                 error = EEXIST;
2695                 vrele(vp);
2696                 vp = NULL;
2697                 goto out2;
2698         }
2699         xp = nd.ni_dvp;
2700         if (vp->v_mount != xp->v_mount) {
2701                 error = EXDEV;
2702                 vrele(vp);
2703                 vp = NULL;
2704                 goto out2;
2705         }
2706         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2707         error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2708         NDFREE(&nd, NDF_ONLY_PNBUF);
2709         /* fall through */
2710
2711 out1:
2712         if (v3)
2713                 getret = VOP_GETATTR(vp, &at, cred, td);
2714 out2:
2715         if (dirp) {
2716                 if (dirp == nd.ni_dvp)
2717                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2718                 else {
2719                         /* Release existing locks to prevent deadlock. */
2720                         if (nd.ni_dvp) {
2721                                 if (nd.ni_dvp == nd.ni_vp)
2722                                         vrele(nd.ni_dvp);
2723                                 else
2724                                         vput(nd.ni_dvp);
2725                         }
2726                         if (nd.ni_vp)
2727                                 vrele(nd.ni_vp);
2728                         nd.ni_dvp = NULL;
2729                         nd.ni_vp = NULL;
2730
2731                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2732                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2733                         VOP_UNLOCK(dirp, 0, td);
2734                 }
2735         }
2736         mtx_unlock(&Giant);     /* VFS */
2737         NFSD_LOCK();
2738 ereply:
2739         NFSD_LOCK_ASSERT();
2740         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2741         if (v3) {
2742                 nfsm_srvpostop_attr(getret, &at);
2743                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2744                 error = 0;
2745         }
2746         /* fall through */
2747
2748 nfsmout:
2749         NFSD_LOCK_ASSERT();
2750         NFSD_UNLOCK();
2751         mtx_lock(&Giant);       /* VFS */
2752         NDFREE(&nd, NDF_ONLY_PNBUF);
2753         if (vp)
2754                 vput(vp);
2755         if (nd.ni_dvp) {
2756                 if (nd.ni_dvp == nd.ni_vp)
2757                         vrele(nd.ni_dvp);
2758                 else
2759                         vput(nd.ni_dvp);
2760         }
2761         if (dirp)
2762                 vrele(dirp);
2763         if (nd.ni_vp)
2764                 vrele(nd.ni_vp);
2765         vn_finished_write(mp);
2766         mtx_unlock(&Giant);     /* VFS */
2767         NFSD_LOCK();
2768         return(error);
2769 }
2770
2771 /*
2772  * nfs symbolic link service
2773  */
2774 int
2775 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2776     struct thread *td, struct mbuf **mrq)
2777 {
2778         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2779         struct sockaddr *nam = nfsd->nd_nam;
2780         caddr_t dpos = nfsd->nd_dpos;
2781         struct ucred *cred = nfsd->nd_cr;
2782         struct vattr va, dirfor, diraft;
2783         struct nameidata nd;
2784         struct vattr *vap = &va;
2785         struct nfsv2_sattr *sp;
2786         char *bpos, *pathcp = NULL;
2787         struct uio io;
2788         struct iovec iv;
2789         int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2790         int v3 = (nfsd->nd_flag & ND_NFSV3);
2791         struct mbuf *mb, *mreq;
2792         struct vnode *dirp = NULL;
2793         nfsfh_t nfh;
2794         fhandle_t *fhp;
2795         struct mount *mp = NULL;
2796
2797         NFSD_LOCK_ASSERT();
2798
2799         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2800         ndclear(&nd);
2801
2802         fhp = &nfh.fh_generic;
2803         nfsm_srvmtofh(fhp);
2804         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2805                 NFSD_UNLOCK();
2806                 mtx_lock(&Giant);       /* VFS */
2807                 error = ESTALE;
2808                 goto out;
2809         }
2810         NFSD_UNLOCK();
2811         mtx_lock(&Giant);       /* VFS */
2812         (void) vn_start_write(NULL, &mp, V_WAIT);
2813         mtx_unlock(&Giant);     /* VFS */
2814         NFSD_LOCK();
2815         nfsm_srvnamesiz(len);
2816         nd.ni_cnd.cn_cred = cred;
2817         nd.ni_cnd.cn_nameiop = CREATE;
2818         nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
2819         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2820                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2821         NFSD_UNLOCK();
2822         mtx_lock(&Giant);       /* VFS */
2823         if (dirp && !v3) {
2824                 vrele(dirp);
2825                 dirp = NULL;
2826         }
2827         if (error)
2828                 goto out;
2829
2830         VATTR_NULL(vap);
2831         if (v3)
2832                 nfsm_srvsattr(vap);
2833         nfsm_srvpathsiz(len2);
2834         MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2835         iv.iov_base = pathcp;
2836         iv.iov_len = len2;
2837         io.uio_resid = len2;
2838         io.uio_offset = 0;
2839         io.uio_iov = &iv;
2840         io.uio_iovcnt = 1;
2841         io.uio_segflg = UIO_SYSSPACE;
2842         io.uio_rw = UIO_READ;
2843         io.uio_td = NULL;
2844         nfsm_mtouio(&io, len2);
2845         if (!v3) {
2846                 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2847                 vap->va_mode = nfstov_mode(sp->sa_mode);
2848         }
2849         *(pathcp + len2) = '\0';
2850         if (nd.ni_vp) {
2851                 error = EEXIST;
2852                 goto out;
2853         }
2854
2855         /*
2856          * issue symlink op.  SAVESTART is set so the underlying path component
2857          * is only freed by the VOP if an error occurs.
2858          */
2859         if (vap->va_mode == (mode_t)VNOVAL)
2860                 vap->va_mode = 0;
2861         error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2862         if (error)
2863                 NDFREE(&nd, NDF_ONLY_PNBUF);
2864         else
2865                 vput(nd.ni_vp);
2866         nd.ni_vp = NULL;
2867         /*
2868          * releases directory prior to potential lookup op.
2869          */
2870         vput(nd.ni_dvp);
2871         nd.ni_dvp = NULL;
2872
2873         if (error == 0) {
2874             if (v3) {
2875                 /*
2876                  * Issue lookup.  Leave SAVESTART set so we can easily free
2877                  * the name buffer later on.
2878                  *
2879                  * since LOCKPARENT is not set, ni_dvp will be garbage on
2880                  * return whether an error occurs or not.
2881                  */
2882                 nd.ni_cnd.cn_nameiop = LOOKUP;
2883                 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2884                 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2885                 nd.ni_cnd.cn_thread = td;
2886                 nd.ni_cnd.cn_cred = cred;
2887
2888                 error = lookup(&nd);
2889                 nd.ni_dvp = NULL;
2890
2891                 if (error == 0) {
2892                         bzero((caddr_t)fhp, sizeof(nfh));
2893                         fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2894                         error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2895                         if (!error)
2896                                 error = VOP_GETATTR(nd.ni_vp, vap, cred,
2897                                         td);
2898                         vput(nd.ni_vp);
2899                         nd.ni_vp = NULL;
2900                 }
2901             }
2902         }
2903 out:
2904         NFSD_UNLOCK_ASSERT();
2905         /*
2906          * These releases aren't strictly required, does even doing them
2907          * make any sense? XXX can nfsm_reply() block?
2908          */
2909         if (pathcp) {
2910                 FREE(pathcp, M_TEMP);
2911                 pathcp = NULL;
2912         }
2913         if (dirp) {
2914                 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2915                 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2916                 VOP_UNLOCK(dirp, 0, td);
2917         }
2918         if (nd.ni_startdir) {
2919                 vrele(nd.ni_startdir);
2920                 nd.ni_startdir = NULL;
2921         }
2922         mtx_unlock(&Giant);     /* VFS */
2923         NFSD_LOCK();
2924         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2925         if (v3) {
2926                 if (!error) {
2927                         nfsm_srvpostop_fh(fhp);
2928                         nfsm_srvpostop_attr(0, vap);
2929                 }
2930                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2931         }
2932         error = 0;
2933         /* fall through */
2934
2935 nfsmout:
2936         NFSD_LOCK_ASSERT();
2937         NFSD_UNLOCK();
2938         mtx_lock(&Giant);       /* VFS */
2939         NDFREE(&nd, NDF_ONLY_PNBUF);
2940         if (nd.ni_dvp) {
2941                 if (nd.ni_dvp == nd.ni_vp)
2942                         vrele(nd.ni_dvp);
2943                 else
2944                         vput(nd.ni_dvp);
2945         }
2946         if (nd.ni_vp)
2947                 vrele(nd.ni_vp);
2948         if (nd.ni_startdir)
2949                 vrele(nd.ni_startdir);
2950         if (dirp)
2951                 vrele(dirp);
2952         if (pathcp)
2953                 FREE(pathcp, M_TEMP);
2954
2955         vn_finished_write(mp);
2956         mtx_unlock(&Giant);     /* VFS */
2957         NFSD_LOCK();
2958         return (error);
2959 }
2960
2961 /*
2962  * nfs mkdir service
2963  */
2964 int
2965 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2966     struct thread *td, struct mbuf **mrq)
2967 {
2968         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2969         struct sockaddr *nam = nfsd->nd_nam;
2970         caddr_t dpos = nfsd->nd_dpos;
2971         struct ucred *cred = nfsd->nd_cr;
2972         struct vattr va, dirfor, diraft;
2973         struct vattr *vap = &va;
2974         struct nfs_fattr *fp;
2975         struct nameidata nd;
2976         u_int32_t *tl;
2977         caddr_t bpos;
2978         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2979         int v3 = (nfsd->nd_flag & ND_NFSV3);
2980         struct mbuf *mb, *mreq;
2981         struct vnode *dirp = NULL;
2982         int vpexcl = 0;
2983         nfsfh_t nfh;
2984         fhandle_t *fhp;
2985         struct mount *mp = NULL;
2986
2987         NFSD_LOCK_ASSERT();
2988
2989         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2990         ndclear(&nd);
2991
2992         fhp = &nfh.fh_generic;
2993         nfsm_srvmtofh(fhp);
2994         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2995                 NFSD_UNLOCK();
2996                 mtx_lock(&Giant);       /* VFS */
2997                 error = ESTALE;
2998                 goto out;
2999         }
3000         NFSD_UNLOCK();
3001         mtx_lock(&Giant);       /* VFS */
3002         (void) vn_start_write(NULL, &mp, V_WAIT);
3003         mtx_unlock(&Giant);     /* VFS */
3004         NFSD_LOCK();
3005         nfsm_srvnamesiz(len);
3006         nd.ni_cnd.cn_cred = cred;
3007         nd.ni_cnd.cn_nameiop = CREATE;
3008         nd.ni_cnd.cn_flags = LOCKPARENT;
3009
3010         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3011                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3012         if (dirp && !v3) {
3013                 NFSD_UNLOCK();
3014                 mtx_lock(&Giant);       /* VFS */
3015                 vrele(dirp);
3016                 mtx_unlock(&Giant);     /* VFS */
3017                 NFSD_LOCK();
3018                 dirp = NULL;
3019         }
3020         if (error) {
3021                 nfsm_reply(NFSX_WCCDATA(v3));
3022                 if (v3)
3023                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3024                 error = 0;
3025                 goto nfsmout;
3026         }
3027         VATTR_NULL(vap);
3028         if (v3) {
3029                 nfsm_srvsattr(vap);
3030         } else {
3031                 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
3032                 vap->va_mode = nfstov_mode(*tl++);
3033         }
3034
3035         /*
3036          * At this point nd.ni_dvp is referenced and exclusively locked and
3037          * nd.ni_vp, if it exists, is referenced but not locked.
3038          */
3039
3040         NFSD_UNLOCK();
3041         mtx_lock(&Giant);       /* VFS */
3042         vap->va_type = VDIR;
3043         if (nd.ni_vp != NULL) {
3044                 NDFREE(&nd, NDF_ONLY_PNBUF);
3045                 error = EEXIST;
3046                 goto out;
3047         }
3048
3049         /*
3050          * Issue mkdir op.  Since SAVESTART is not set, the pathname
3051          * component is freed by the VOP call.  This will fill-in
3052          * nd.ni_vp, reference, and exclusively lock it.
3053          */
3054         if (vap->va_mode == (mode_t)VNOVAL)
3055                 vap->va_mode = 0;
3056         error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
3057         NDFREE(&nd, NDF_ONLY_PNBUF);
3058         vpexcl = 1;
3059
3060         vput(nd.ni_dvp);
3061         nd.ni_dvp = NULL;
3062
3063         if (!error) {
3064                 bzero((caddr_t)fhp, sizeof(nfh));
3065                 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
3066                 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
3067                 if (!error)
3068                         error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
3069         }
3070 out:
3071         NFSD_UNLOCK_ASSERT();
3072         if (dirp) {
3073                 if (dirp == nd.ni_dvp) {
3074                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3075                 } else {
3076                         /* Release existing locks to prevent deadlock. */
3077                         if (nd.ni_dvp) {
3078                                 NDFREE(&nd, NDF_ONLY_PNBUF);
3079                                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3080                                         vrele(nd.ni_dvp);
3081                                 else
3082                                         vput(nd.ni_dvp);
3083                         }
3084                         if (nd.ni_vp) {
3085                                 if (vpexcl)
3086                                         vput(nd.ni_vp);
3087                                 else
3088                                         vrele(nd.ni_vp);
3089                         }
3090                         nd.ni_dvp = NULL;
3091                         nd.ni_vp = NULL;
3092                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3093                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3094                         VOP_UNLOCK(dirp, 0, td);
3095                 }
3096         }
3097         mtx_unlock(&Giant);     /* VFS */
3098         NFSD_LOCK();
3099         nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
3100         if (v3) {
3101                 if (!error) {
3102                         nfsm_srvpostop_fh(fhp);
3103                         nfsm_srvpostop_attr(0, vap);
3104                 }
3105                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3106         } else if (!error) {
3107                 /* v2 non-error case. */
3108                 nfsm_srvfhtom(fhp, v3);
3109                 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
3110                 nfsm_srvfillattr(vap, fp);
3111         }
3112         error = 0;
3113         /* fall through */
3114
3115 nfsmout:
3116         NFSD_LOCK_ASSERT();
3117         NFSD_UNLOCK();
3118         mtx_lock(&Giant);       /* VFS */
3119         if (nd.ni_dvp) {
3120                 NDFREE(&nd, NDF_ONLY_PNBUF);
3121                 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3122                         vrele(nd.ni_dvp);
3123                 else
3124                         vput(nd.ni_dvp);
3125         }
3126         if (nd.ni_vp) {
3127                 if (vpexcl)
3128                         vput(nd.ni_vp);
3129                 else
3130                         vrele(nd.ni_vp);
3131         }
3132         if (dirp)
3133                 vrele(dirp);
3134         vn_finished_write(mp);
3135         mtx_unlock(&Giant);     /* VFS */
3136         NFSD_LOCK();
3137         return (error);
3138 }
3139
3140 /*
3141  * nfs rmdir service
3142  */
3143 int
3144 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3145     struct thread *td, struct mbuf **mrq)
3146 {
3147         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3148         struct sockaddr *nam = nfsd->nd_nam;
3149         caddr_t dpos = nfsd->nd_dpos;
3150         struct ucred *cred = nfsd->nd_cr;
3151         caddr_t bpos;
3152         int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
3153         int v3 = (nfsd->nd_flag & ND_NFSV3);
3154         struct mbuf *mb, *mreq;
3155         struct vnode *vp, *dirp = NULL;
3156         struct vattr dirfor, diraft;
3157         nfsfh_t nfh;
3158         fhandle_t *fhp;
3159         struct nameidata nd;
3160         struct mount *mp = NULL;
3161
3162         NFSD_LOCK_ASSERT();
3163
3164         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3165         ndclear(&nd);
3166
3167         fhp = &nfh.fh_generic;
3168         nfsm_srvmtofh(fhp);
3169         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3170                 error = ESTALE;
3171                 goto out;
3172         }
3173         NFSD_UNLOCK();
3174         mtx_lock(&Giant);       /* VFS */
3175         (void) vn_start_write(NULL, &mp, V_WAIT);
3176         mtx_unlock(&Giant);     /* VFS */
3177         NFSD_LOCK();
3178         nfsm_srvnamesiz(len);
3179         nd.ni_cnd.cn_cred = cred;
3180         nd.ni_cnd.cn_nameiop = DELETE;
3181         nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
3182         error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3183                 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3184         if (dirp && !v3) {
3185                 NFSD_UNLOCK();
3186                 mtx_lock(&Giant);       /* VFS */
3187                 vrele(dirp);
3188                 mtx_unlock(&Giant);     /* VFS */
3189                 NFSD_LOCK();
3190                 dirp = NULL;
3191         }
3192         if (error) {
3193                 nfsm_reply(NFSX_WCCDATA(v3));
3194                 if (v3)
3195                         nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3196                 error = 0;
3197                 goto nfsmout;
3198         }
3199         vp = nd.ni_vp;
3200         if (vp->v_type != VDIR) {
3201                 error = ENOTDIR;
3202                 goto out;
3203         }
3204         /*
3205          * No rmdir "." please.
3206          */
3207         if (nd.ni_dvp == vp) {
3208                 error = EINVAL;
3209                 goto out;
3210         }
3211         /*
3212          * The root of a mounted filesystem cannot be deleted.
3213          */
3214         if (vp->v_vflag & VV_ROOT)
3215                 error = EBUSY;
3216 out:
3217         /*
3218          * Issue or abort op.  Since SAVESTART is not set, path name
3219          * component is freed by the VOP after either.
3220          */
3221         NFSD_LOCK_ASSERT();
3222         NFSD_UNLOCK();
3223         mtx_lock(&Giant);       /* VFS */
3224         if (!error)
3225                 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3226         NDFREE(&nd, NDF_ONLY_PNBUF);
3227
3228         if (dirp) {
3229                 if (dirp == nd.ni_dvp)
3230                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3231                 else {
3232                         /* Release existing locks to prevent deadlock. */
3233                         if (nd.ni_dvp) {
3234                                 if (nd.ni_dvp == nd.ni_vp)
3235                                         vrele(nd.ni_dvp);
3236                                 else
3237                                         vput(nd.ni_dvp);
3238                         }
3239                         if (nd.ni_vp)
3240                                 vput(nd.ni_vp);
3241                         nd.ni_dvp = NULL;
3242                         nd.ni_vp = NULL;
3243                         vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3244                         diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3245                         VOP_UNLOCK(dirp, 0, td);
3246                 }
3247         }
3248         mtx_unlock(&Giant);     /* VFS */
3249         NFSD_LOCK();
3250         nfsm_reply(NFSX_WCCDATA(v3));
3251         error = 0;
3252         if (v3)
3253                 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3254         /* fall through */
3255
3256 nfsmout:
3257         NFSD_LOCK_ASSERT();
3258         NFSD_UNLOCK();
3259         mtx_lock(&Giant);       /* VFS */
3260         NDFREE(&nd, NDF_ONLY_PNBUF);
3261         if (nd.ni_dvp) {
3262                 if (nd.ni_dvp == nd.ni_vp)
3263                         vrele(nd.ni_dvp);
3264                 else
3265                         vput(nd.ni_dvp);
3266         }
3267         if (nd.ni_vp)
3268                 vput(nd.ni_vp);
3269         if (dirp)
3270                 vrele(dirp);
3271
3272         vn_finished_write(mp);
3273         mtx_unlock(&Giant);     /* VFS */
3274         NFSD_LOCK();
3275         return(error);
3276 }
3277
3278 /*
3279  * nfs readdir service
3280  * - mallocs what it thinks is enough to read
3281  *      count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
3282  * - calls VOP_READDIR()
3283  * - loops around building the reply
3284  *      if the output generated exceeds count break out of loop
3285  *      The nfsm_clget macro is used here so that the reply will be packed
3286  *      tightly in mbuf clusters.
3287  * - it only knows that it has encountered eof when the VOP_READDIR()
3288  *      reads nothing
3289  * - as such one readdir rpc will return eof false although you are there
3290  *      and then the next will return eof
3291  * - it trims out records with d_fileno == 0
3292  *      this doesn't matter for Unix clients, but they might confuse clients
3293  *      for other os'.
3294  * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
3295  *      than requested, but this may not apply to all filesystems. For
3296  *      example, client NFS does not { although it is never remote mounted
3297  *      anyhow }
3298  *     The alternate call nfsrv_readdirplus() does lookups as well.
3299  * PS: The NFS protocol spec. does not clarify what the "count" byte
3300  *      argument is a count of.. just name strings and file id's or the
3301  *      entire reply rpc or ...
3302  *      I tried just file name and id sizes and it confused the Sun client,
3303  *      so I am using the full rpc size now. The "paranoia.." comment refers
3304  *      to including the status longwords that are not a part of the dir.
3305  *      "entry" structures, but are in the rpc.
3306  */
3307 struct flrep {
3308         nfsuint64       fl_off;
3309         u_int32_t       fl_postopok;
3310         u_int32_t       fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
3311         u_int32_t       fl_fhok;
3312         u_int32_t       fl_fhsize;
3313         u_int32_t       fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
3314 };
3315
3316 int
3317 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3318     struct thread *td, struct mbuf **mrq)
3319 {
3320         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3321         struct sockaddr *nam = nfsd->nd_nam;
3322         caddr_t dpos = nfsd->nd_dpos;
3323         struct ucred *cred = nfsd->nd_cr;
3324         char *bp, *be;
3325         struct mbuf *mp;
3326         struct dirent *dp;
3327         caddr_t cp;
3328         u_int32_t *tl;
3329         caddr_t bpos;
3330         struct mbuf *mb, *mreq;
3331         char *cpos, *cend, *rbuf;
3332         struct vnode *vp = NULL;
3333         struct vattr at;
3334         nfsfh_t nfh;
3335         fhandle_t *fhp;
3336         struct uio io;
3337         struct iovec iv;
3338         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3339         int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
3340         int v3 = (nfsd->nd_flag & ND_NFSV3);
3341         u_quad_t off, toff, verf;
3342         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3343
3344         NFSD_LOCK_ASSERT();
3345
3346         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3347         fhp = &nfh.fh_generic;
3348         nfsm_srvmtofh(fhp);
3349         if (v3) {
3350                 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
3351                 toff = fxdr_hyper(tl);
3352                 tl += 2;
3353                 verf = fxdr_hyper(tl);
3354                 tl += 2;
3355         } else {
3356                 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
3357                 toff = fxdr_unsigned(u_quad_t, *tl++);
3358                 verf = 0;       /* shut up gcc */
3359         }
3360         off = toff;
3361         cnt = fxdr_unsigned(int, *tl);
3362         siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3363         xfer = NFS_SRVMAXDATA(nfsd);
3364         if (cnt > xfer)
3365                 cnt = xfer;
3366         if (siz > xfer)
3367                 siz = xfer;
3368         fullsiz = siz;
3369         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3370         if (!error && vp->v_type != VDIR) {
3371                 error = ENOTDIR;
3372                 NFSD_UNLOCK();
3373                 mtx_lock(&Giant);       /* VFS */
3374                 vput(vp);
3375                 mtx_unlock(&Giant);     /* VFS */
3376                 NFSD_LOCK();
3377                 vp = NULL;
3378         }
3379         if (error) {
3380                 nfsm_reply(NFSX_UNSIGNED);
3381                 if (v3)
3382                         nfsm_srvpostop_attr(getret, &at);
3383                 error = 0;
3384                 goto nfsmout;
3385         }
3386
3387         /*
3388          * Obtain lock on vnode for this section of the code
3389          */
3390         NFSD_UNLOCK();
3391         mtx_lock(&Giant);       /* VFS */
3392         if (v3) {
3393                 error = getret = VOP_GETATTR(vp, &at, cred, td);
3394 #if 0
3395                 /*
3396                  * XXX This check may be too strict for Solaris 2.5 clients.
3397                  */
3398                 if (!error && toff && verf && verf != at.va_filerev)
3399                         error = NFSERR_BAD_COOKIE;
3400 #endif
3401         }
3402         if (!error)
3403                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3404         if (error) {
3405                 vput(vp);
3406                 mtx_unlock(&Giant);     /* VFS */
3407                 NFSD_LOCK();
3408                 vp = NULL;
3409                 nfsm_reply(NFSX_POSTOPATTR(v3));
3410                 if (v3)
3411                         nfsm_srvpostop_attr(getret, &at);
3412                 error = 0;
3413                 goto nfsmout;
3414         }
3415         VOP_UNLOCK(vp, 0, td);
3416
3417         /*
3418          * end section.  Allocate rbuf and continue
3419          */
3420         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3421 again:
3422         NFSD_UNLOCK_ASSERT();
3423         iv.iov_base = rbuf;
3424         iv.iov_len = fullsiz;
3425         io.uio_iov = &iv;
3426         io.uio_iovcnt = 1;
3427         io.uio_offset = (off_t)off;
3428         io.uio_resid = fullsiz;
3429         io.uio_segflg = UIO_SYSSPACE;
3430         io.uio_rw = UIO_READ;
3431         io.uio_td = NULL;
3432         eofflag = 0;
3433         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3434         if (cookies) {
3435                 free((caddr_t)cookies, M_TEMP);
3436                 cookies = NULL;
3437         }
3438         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3439         off = (off_t)io.uio_offset;
3440         if (!cookies && !error)
3441                 error = NFSERR_PERM;
3442         if (v3) {
3443                 getret = VOP_GETATTR(vp, &at, cred, td);
3444                 if (!error)
3445                         error = getret;
3446         }
3447         VOP_UNLOCK(vp, 0, td);
3448         if (error) {
3449                 vrele(vp);
3450                 mtx_unlock(&Giant);     /* VFS */
3451                 vp = NULL;
3452                 free((caddr_t)rbuf, M_TEMP);
3453                 if (cookies)
3454                         free((caddr_t)cookies, M_TEMP);
3455                 NFSD_LOCK();
3456                 nfsm_reply(NFSX_POSTOPATTR(v3));
3457                 if (v3)
3458                         nfsm_srvpostop_attr(getret, &at);
3459                 error = 0;
3460                 goto nfsmout;
3461         }
3462         if (io.uio_resid) {
3463                 siz -= io.uio_resid;
3464
3465                 /*
3466                  * If nothing read, return eof
3467                  * rpc reply
3468                  */
3469                 if (siz == 0) {
3470                         vrele(vp);
3471                         mtx_unlock(&Giant);     /* VFS */
3472                         vp = NULL;
3473                         NFSD_LOCK();
3474                         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
3475                                 2 * NFSX_UNSIGNED);
3476                         if (v3) {
3477                                 nfsm_srvpostop_attr(getret, &at);
3478                                 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3479                                 txdr_hyper(at.va_filerev, tl);
3480                                 tl += 2;
3481                         } else
3482                                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3483                         *tl++ = nfsrv_nfs_false;
3484                         *tl = nfsrv_nfs_true;
3485                         FREE((caddr_t)rbuf, M_TEMP);
3486                         FREE((caddr_t)cookies, M_TEMP);
3487                         error = 0;
3488                         goto nfsmout;
3489                 }
3490         }
3491
3492         /*
3493          * Check for degenerate cases of nothing useful read.
3494          * If so go try again
3495          */
3496         cpos = rbuf;
3497         cend = rbuf + siz;
3498         dp = (struct dirent *)cpos;
3499         cookiep = cookies;
3500         /*
3501          * For some reason FreeBSD's ufs_readdir() chooses to back the
3502          * directory offset up to a block boundary, so it is necessary to
3503          * skip over the records that precede the requested offset. This
3504          * requires the assumption that file offset cookies monotonically
3505          * increase.
3506          */
3507         while (cpos < cend && ncookies > 0 &&
3508                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3509                  ((u_quad_t)(*cookiep)) <= toff)) {
3510                 cpos += dp->d_reclen;
3511                 dp = (struct dirent *)cpos;
3512                 cookiep++;
3513                 ncookies--;
3514         }
3515         if (cpos >= cend || ncookies == 0) {
3516                 toff = off;
3517                 siz = fullsiz;
3518                 goto again;
3519         }
3520
3521         mtx_unlock(&Giant);     /* VFS */
3522         NFSD_LOCK();
3523         len = 3 * NFSX_UNSIGNED;        /* paranoia, probably can be 0 */
3524         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
3525         if (v3) {
3526                 nfsm_srvpostop_attr(getret, &at);
3527                 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3528                 txdr_hyper(at.va_filerev, tl);
3529         }
3530         mp = mb;
3531         bp = bpos;
3532         be = bp + M_TRAILINGSPACE(mp);
3533
3534         /* Loop through the records and build reply */
3535         while (cpos < cend && ncookies > 0) {
3536                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3537                         nlen = dp->d_namlen;
3538                         rem = nfsm_rndup(nlen) - nlen;
3539                         len += (4 * NFSX_UNSIGNED + nlen + rem);
3540                         if (v3)
3541                                 len += 2 * NFSX_UNSIGNED;
3542                         if (len > cnt) {
3543                                 eofflag = 0;
3544                                 break;
3545                         }
3546                         /*
3547                          * Build the directory record xdr from
3548                          * the dirent entry.
3549                          */
3550                         nfsm_clget;
3551                         *tl = nfsrv_nfs_true;
3552                         bp += NFSX_UNSIGNED;
3553                         if (v3) {
3554                                 nfsm_clget;
3555                                 *tl = 0;
3556                                 bp += NFSX_UNSIGNED;
3557                         }
3558                         nfsm_clget;
3559                         *tl = txdr_unsigned(dp->d_fileno);
3560                         bp += NFSX_UNSIGNED;
3561                         nfsm_clget;
3562                         *tl = txdr_unsigned(nlen);
3563                         bp += NFSX_UNSIGNED;
3564
3565                         /* And loop around copying the name */
3566                         xfer = nlen;
3567                         cp = dp->d_name;
3568                         while (xfer > 0) {
3569                                 nfsm_clget;
3570                                 if ((bp+xfer) > be)
3571                                         tsiz = be-bp;
3572                                 else
3573                                         tsiz = xfer;
3574                                 bcopy(cp, bp, tsiz);
3575                                 bp += tsiz;
3576                                 xfer -= tsiz;
3577                                 if (xfer > 0)
3578                                         cp += tsiz;
3579                         }
3580                         /* And null pad to an int32_t boundary. */
3581                         for (i = 0; i < rem; i++)
3582                                 *bp++ = '\0';
3583                         nfsm_clget;
3584
3585                         /* Finish off the record */
3586                         if (v3) {
3587                                 *tl = 0;
3588                                 bp += NFSX_UNSIGNED;
3589                                 nfsm_clget;
3590                         }
3591                         *tl = txdr_unsigned(*cookiep);
3592                         bp += NFSX_UNSIGNED;
3593                 }
3594                 cpos += dp->d_reclen;
3595                 dp = (struct dirent *)cpos;
3596                 cookiep++;
3597                 ncookies--;
3598         }
3599         NFSD_UNLOCK();
3600         mtx_lock(&Giant);       /* VFS */
3601         vrele(vp);
3602         mtx_unlock(&Giant);     /* VFS */
3603         NFSD_LOCK();
3604         vp = NULL;
3605         nfsm_clget;
3606         *tl = nfsrv_nfs_false;
3607         bp += NFSX_UNSIGNED;
3608         nfsm_clget;
3609         if (eofflag)
3610                 *tl = nfsrv_nfs_true;
3611         else
3612                 *tl = nfsrv_nfs_false;
3613         bp += NFSX_UNSIGNED;
3614         if (mp != mb) {
3615                 if (bp < be)
3616                         mp->m_len = bp - mtod(mp, caddr_t);
3617         } else
3618                 mp->m_len += bp - bpos;
3619         FREE((caddr_t)rbuf, M_TEMP);
3620         FREE((caddr_t)cookies, M_TEMP);
3621
3622 nfsmout:
3623         NFSD_LOCK_ASSERT();
3624         if (vp) {
3625                 NFSD_UNLOCK();
3626                 mtx_lock(&Giant);       /* VFS */
3627                 vrele(vp);
3628                 mtx_unlock(&Giant);     /* VFS */
3629                 NFSD_LOCK();
3630         }
3631         return(error);
3632 }
3633
3634 int
3635 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3636     struct thread *td, struct mbuf **mrq)
3637 {
3638         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3639         struct sockaddr *nam = nfsd->nd_nam;
3640         caddr_t dpos = nfsd->nd_dpos;
3641         struct ucred *cred = nfsd->nd_cr;
3642         char *bp, *be;
3643         struct mbuf *mp;
3644         struct dirent *dp;
3645         caddr_t cp;
3646         u_int32_t *tl;
3647         caddr_t bpos;
3648         struct mbuf *mb, *mreq;
3649         char *cpos, *cend, *rbuf;
3650         struct vnode *vp = NULL, *nvp;
3651         struct flrep fl;
3652         nfsfh_t nfh;
3653         fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3654         struct uio io;
3655         struct iovec iv;
3656         struct vattr va, at, *vap = &va;
3657         struct nfs_fattr *fp;
3658         int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3659         int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3660         u_quad_t off, toff, verf;
3661         u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3662         int v3 = (nfsd->nd_flag & ND_NFSV3);
3663
3664         NFSD_LOCK_ASSERT();
3665
3666         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3667         if (!v3)
3668                 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
3669         fhp = &nfh.fh_generic;
3670         nfsm_srvmtofh(fhp);
3671         tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
3672         toff = fxdr_hyper(tl);
3673         tl += 2;
3674         verf = fxdr_hyper(tl);
3675         tl += 2;
3676         siz = fxdr_unsigned(int, *tl++);
3677         cnt = fxdr_unsigned(int, *tl);
3678         off = toff;
3679         siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3680         xfer = NFS_SRVMAXDATA(nfsd);
3681         if (cnt > xfer)
3682                 cnt = xfer;
3683         if (siz > xfer)
3684                 siz = xfer;
3685         fullsiz = siz;
3686         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3687         if (!error && vp->v_type != VDIR) {
3688                 error = ENOTDIR;
3689                 NFSD_UNLOCK();
3690                 mtx_lock(&Giant);       /* VFS */
3691                 vput(vp);
3692                 mtx_unlock(&Giant);     /* VFS */
3693                 vp = NULL;
3694                 NFSD_LOCK();
3695         }
3696         if (error) {
3697                 nfsm_reply(NFSX_UNSIGNED);
3698                 nfsm_srvpostop_attr(getret, &at);
3699                 error = 0;
3700                 goto nfsmout;
3701         }
3702         NFSD_UNLOCK();
3703         mtx_lock(&Giant);       /* VFS */
3704         error = getret = VOP_GETATTR(vp, &at, cred, td);
3705 #if 0
3706         /*
3707          * XXX This check may be too strict for Solaris 2.5 clients.
3708          */
3709         if (!error && toff && verf && verf != at.va_filerev)
3710                 error = NFSERR_BAD_COOKIE;
3711 #endif
3712         if (!error)
3713                 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3714         if (error) {
3715                 vput(vp);
3716                 mtx_unlock(&Giant);     /* VFS */
3717                 NFSD_LOCK();
3718                 vp = NULL;
3719                 nfsm_reply(NFSX_V3POSTOPATTR);
3720                 nfsm_srvpostop_attr(getret, &at);
3721                 error = 0;
3722                 goto nfsmout;
3723         }
3724         VOP_UNLOCK(vp, 0, td);
3725         MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3726 again:
3727         NFSD_UNLOCK_ASSERT();
3728         iv.iov_base = rbuf;
3729         iv.iov_len = fullsiz;
3730         io.uio_iov = &iv;
3731         io.uio_iovcnt = 1;
3732         io.uio_offset = (off_t)off;
3733         io.uio_resid = fullsiz;
3734         io.uio_segflg = UIO_SYSSPACE;
3735         io.uio_rw = UIO_READ;
3736         io.uio_td = NULL;
3737         eofflag = 0;
3738         vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3739         if (cookies) {
3740                 free((caddr_t)cookies, M_TEMP);
3741                 cookies = NULL;
3742         }
3743         error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3744         off = (u_quad_t)io.uio_offset;
3745         getret = VOP_GETATTR(vp, &at, cred, td);
3746         VOP_UNLOCK(vp, 0, td);
3747         if (!cookies && !error)
3748                 error = NFSERR_PERM;
3749         if (!error)
3750                 error = getret;
3751         if (error) {
3752                 vrele(vp);
3753                 mtx_unlock(&Giant);     /* VFS */
3754                 vp = NULL;
3755                 if (cookies)
3756                         free((caddr_t)cookies, M_TEMP);
3757                 free((caddr_t)rbuf, M_TEMP);
3758                 NFSD_LOCK();
3759                 nfsm_reply(NFSX_V3POSTOPATTR);
3760                 nfsm_srvpostop_attr(getret, &at);
3761                 error = 0;
3762                 goto nfsmout;
3763         }
3764         if (io.uio_resid) {
3765                 siz -= io.uio_resid;
3766
3767                 /*
3768                  * If nothing read, return eof
3769                  * rpc reply
3770                  */
3771                 if (siz == 0) {
3772                         vrele(vp);
3773                         mtx_unlock(&Giant);     /* VFS */
3774                         NFSD_LOCK();
3775                         vp = NULL;
3776                         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3777                                 2 * NFSX_UNSIGNED);
3778                         nfsm_srvpostop_attr(getret, &at);
3779                         tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3780                         txdr_hyper(at.va_filerev, tl);
3781                         tl += 2;
3782                         *tl++ = nfsrv_nfs_false;
3783                         *tl = nfsrv_nfs_true;
3784                         FREE((caddr_t)cookies, M_TEMP);
3785                         FREE((caddr_t)rbuf, M_TEMP);
3786                         error = 0;
3787                         goto nfsmout;
3788                 }
3789         }
3790
3791         /*
3792          * Check for degenerate cases of nothing useful read.
3793          * If so go try again
3794          */
3795         cpos = rbuf;
3796         cend = rbuf + siz;
3797         dp = (struct dirent *)cpos;
3798         cookiep = cookies;
3799         /*
3800          * For some reason FreeBSD's ufs_readdir() chooses to back the
3801          * directory offset up to a block boundary, so it is necessary to
3802          * skip over the records that precede the requested offset. This
3803          * requires the assumption that file offset cookies monotonically
3804          * increase.
3805          */
3806         while (cpos < cend && ncookies > 0 &&
3807                 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3808                  ((u_quad_t)(*cookiep)) <= toff)) {
3809                 cpos += dp->d_reclen;
3810                 dp = (struct dirent *)cpos;
3811                 cookiep++;
3812                 ncookies--;
3813         }
3814         if (cpos >= cend || ncookies == 0) {
3815                 toff = off;
3816                 siz = fullsiz;
3817                 goto again;
3818         }
3819
3820         /*
3821          * Probe one of the directory entries to see if the filesystem
3822          * supports VGET.
3823          */
3824         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
3825             EOPNOTSUPP) {
3826                 error = NFSERR_NOTSUPP;
3827                 vrele(vp);
3828                 mtx_unlock(&Giant);     /* VFS */
3829                 vp = NULL;
3830                 free((caddr_t)cookies, M_TEMP);
3831                 free((caddr_t)rbuf, M_TEMP);
3832                 NFSD_LOCK();
3833                 nfsm_reply(NFSX_V3POSTOPATTR);
3834                 nfsm_srvpostop_attr(getret, &at);
3835                 error = 0;
3836                 goto nfsmout;
3837         }
3838         vput(nvp);
3839         mtx_unlock(&Giant);     /* VFS */
3840         nvp = NULL;
3841
3842         dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3843             2 * NFSX_UNSIGNED;
3844         NFSD_LOCK();
3845         nfsm_reply(cnt);
3846         nfsm_srvpostop_attr(getret, &at);
3847         tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3848         txdr_hyper(at.va_filerev, tl);
3849         mp = mb;
3850         bp = bpos;
3851         be = bp + M_TRAILINGSPACE(mp);
3852
3853         NFSD_UNLOCK();
3854         mtx_lock(&Giant);       /* VFS */
3855         /* Loop through the records and build reply */
3856         while (cpos < cend && ncookies > 0) {
3857                 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3858                         nlen = dp->d_namlen;
3859                         rem = nfsm_rndup(nlen)-nlen;
3860
3861                         /*
3862                          * For readdir_and_lookup get the vnode using
3863                          * the file number.
3864                          */
3865                         if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
3866                             &nvp))
3867                                 goto invalid;
3868                         bzero((caddr_t)nfhp, NFSX_V3FH);
3869                         nfhp->fh_fsid =
3870                                 nvp->v_mount->mnt_stat.f_fsid;
3871                         if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3872                                 vput(nvp);
3873                                 nvp = NULL;
3874                                 goto invalid;
3875                         }
3876                         if (VOP_GETATTR(nvp, vap, cred, td)) {
3877                                 vput(nvp);
3878                                 nvp = NULL;
3879                                 goto invalid;
3880                         }
3881                         vput(nvp);
3882                         nvp = NULL;
3883
3884                         /*
3885                          * If either the dircount or maxcount will be
3886                          * exceeded, get out now. Both of these lengths
3887                          * are calculated conservatively, including all
3888                          * XDR overheads.
3889                          */
3890                         len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3891                                 NFSX_V3POSTOPATTR);
3892                         dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3893                         if (len > cnt || dirlen > fullsiz) {
3894                                 eofflag = 0;
3895                                 break;
3896                         }
3897
3898                         /*
3899                          * Build the directory record xdr from
3900                          * the dirent entry.
3901                          */
3902                         fp = (struct nfs_fattr *)&fl.fl_fattr;
3903                         nfsm_srvfillattr(vap, fp);
3904                         fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3905                         fl.fl_fhok = nfsrv_nfs_true;
3906                         fl.fl_postopok = nfsrv_nfs_true;
3907                         fl.fl_off.nfsuquad[0] = 0;
3908                         fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3909
3910                         nfsm_clget_nolock;
3911                         *tl = nfsrv_nfs_true;
3912                         bp += NFSX_UNSIGNED;
3913                         nfsm_clget_nolock;
3914                         *tl = 0;
3915                         bp += NFSX_UNSIGNED;
3916                         nfsm_clget_nolock;
3917                         *tl = txdr_unsigned(dp->d_fileno);
3918                         bp += NFSX_UNSIGNED;
3919                         nfsm_clget_nolock;
3920                         *tl = txdr_unsigned(nlen);
3921                         bp += NFSX_UNSIGNED;
3922
3923                         /* And loop around copying the name */
3924                         xfer = nlen;
3925                         cp = dp->d_name;
3926                         while (xfer > 0) {
3927                                 nfsm_clget_nolock;
3928                                 if ((bp + xfer) > be)
3929                                         tsiz = be - bp;
3930                                 else
3931                                         tsiz = xfer;
3932                                 bcopy(cp, bp, tsiz);
3933                                 bp += tsiz;
3934                                 xfer -= tsiz;
3935                                 if (xfer > 0)
3936                                         cp += tsiz;
3937                         }
3938                         /* And null pad to an int32_t boundary. */
3939                         for (i = 0; i < rem; i++)
3940                                 *bp++ = '\0';
3941
3942                         /*
3943                          * Now copy the flrep structure out.
3944                          */
3945                         xfer = sizeof (struct flrep);
3946                         cp = (caddr_t)&fl;
3947                         while (xfer > 0) {
3948                                 nfsm_clget_nolock;
3949                                 if ((bp + xfer) > be)
3950                                         tsiz = be - bp;
3951                                 else
3952                                         tsiz = xfer;
3953                                 bcopy(cp, bp, tsiz);
3954                                 bp += tsiz;
3955                                 xfer -= tsiz;
3956                                 if (xfer > 0)
3957                                         cp += tsiz;
3958                         }
3959                 }
3960 invalid:
3961                 NFSD_UNLOCK_ASSERT();
3962                 cpos += dp->d_reclen;
3963                 dp = (struct dirent *)cpos;
3964                 cookiep++;
3965                 ncookies--;
3966         }
3967         vrele(vp);
3968         mtx_unlock(&Giant);     /* VFS */
3969         vp = NULL;
3970         nfsm_clget_nolock;
3971         *tl = nfsrv_nfs_false;
3972         bp += NFSX_UNSIGNED;
3973         NFSD_LOCK();
3974         nfsm_clget;
3975         if (eofflag)
3976                 *tl = nfsrv_nfs_true;
3977         else
3978                 *tl = nfsrv_nfs_false;
3979         bp += NFSX_UNSIGNED;
3980         if (mp != mb) {
3981                 if (bp < be)
3982                         mp->m_len = bp - mtod(mp, caddr_t);
3983         } else
3984                 mp->m_len += bp - bpos;
3985         FREE((caddr_t)cookies, M_TEMP);
3986         FREE((caddr_t)rbuf, M_TEMP);
3987 nfsmout:
3988         NFSD_LOCK_ASSERT();
3989         if (vp) {
3990                 NFSD_UNLOCK();
3991                 mtx_lock(&Giant);       /* VFS */
3992                 vrele(vp);
3993                 mtx_unlock(&Giant);     /* VFS */
3994                 NFSD_LOCK();
3995         }
3996         return(error);
3997 }
3998
3999 /*
4000  * nfs commit service
4001  */
4002 int
4003 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4004     struct thread *td, struct mbuf **mrq)
4005 {
4006         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4007         struct sockaddr *nam = nfsd->nd_nam;
4008         caddr_t dpos = nfsd->nd_dpos;
4009         struct ucred *cred = nfsd->nd_cr;
4010         struct vattr bfor, aft;
4011         struct vnode *vp = NULL;
4012         nfsfh_t nfh;
4013         fhandle_t *fhp;
4014         u_int32_t *tl;
4015         caddr_t bpos;
4016         int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
4017         struct mbuf *mb, *mreq;
4018         u_quad_t off;
4019         struct mount *mp = NULL;
4020         int v3 = (nfsd->nd_flag & ND_NFSV3);
4021
4022         NFSD_LOCK_ASSERT();
4023
4024         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4025         if (!v3)
4026                 panic("nfsrv_commit: v3 proc called on a v2 connection");
4027         fhp = &nfh.fh_generic;
4028         nfsm_srvmtofh(fhp);
4029         if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
4030                 error = ESTALE;
4031                 goto ereply;
4032         }
4033         NFSD_UNLOCK();
4034         mtx_lock(&Giant);       /* VFS */
4035         (void) vn_start_write(NULL, &mp, V_WAIT);
4036         mtx_unlock(&Giant);     /* VFS */
4037         NFSD_LOCK();
4038         tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
4039
4040         /*
4041          * XXX At this time VOP_FSYNC() does not accept offset and byte
4042          * count parameters, so these arguments are useless (someday maybe).
4043          */
4044         off = fxdr_hyper(tl);
4045         tl += 2;
4046         cnt = fxdr_unsigned(int, *tl);
4047         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4048         if (error) {
4049                 nfsm_reply(2 * NFSX_UNSIGNED);
4050                 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4051                 error = 0;
4052                 goto nfsmout;
4053         }
4054         NFSD_UNLOCK();
4055         mtx_lock(&Giant);       /* VFS */
4056         for_ret = VOP_GETATTR(vp, &bfor, cred, td);
4057
4058         if (cnt > MAX_COMMIT_COUNT) {
4059                 /*
4060                  * Give up and do the whole thing
4061                  */
4062                 if (vp->v_object &&
4063                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4064                         VM_OBJECT_LOCK(vp->v_object);
4065                         vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
4066                         VM_OBJECT_UNLOCK(vp->v_object);
4067                 }
4068                 error = VOP_FSYNC(vp, MNT_WAIT, td);
4069         } else {
4070                 /*
4071                  * Locate and synchronously write any buffers that fall
4072                  * into the requested range.  Note:  we are assuming that
4073                  * f_iosize is a power of 2.
4074                  */
4075                 int iosize = vp->v_mount->mnt_stat.f_iosize;
4076                 int iomask = iosize - 1;
4077                 int s;
4078                 daddr_t lblkno;
4079
4080                 /*
4081                  * Align to iosize boundry, super-align to page boundry.
4082                  */
4083                 if (off & iomask) {
4084                         cnt += off & iomask;
4085                         off &= ~(u_quad_t)iomask;
4086                 }
4087                 if (off & PAGE_MASK) {
4088                         cnt += off & PAGE_MASK;
4089                         off &= ~(u_quad_t)PAGE_MASK;
4090                 }
4091                 lblkno = off / iosize;
4092
4093                 if (vp->v_object &&
4094                    (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4095                         VM_OBJECT_LOCK(vp->v_object);
4096                         vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
4097                         VM_OBJECT_UNLOCK(vp->v_object);
4098                 }
4099
4100                 s = splbio();
4101                 VI_LOCK(vp);
4102                 while (cnt > 0) {
4103                         struct buf *bp;
4104
4105                         /*
4106                          * If we have a buffer and it is marked B_DELWRI we
4107                          * have to lock and write it.  Otherwise the prior
4108                          * write is assumed to have already been committed.
4109                          *
4110                          * gbincore() can return invalid buffers now so we
4111                          * have to check that bit as well (though B_DELWRI
4112                          * should not be set if B_INVAL is set there could be
4113                          * a race here since we haven't locked the buffer).
4114                          */
4115                         if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
4116                                 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
4117                                     LK_INTERLOCK, VI_MTX(vp)) == ENOLCK) {
4118                                         VI_LOCK(vp);
4119                                         continue; /* retry */
4120                                 }
4121                                 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
4122                                     B_DELWRI) {
4123                                         bremfree(bp);
4124                                         bp->b_flags &= ~B_ASYNC;
4125                                         bwrite(bp);
4126                                         ++nfs_commit_miss;
4127                                 } else
4128                                         BUF_UNLOCK(bp);
4129                                 VI_LOCK(vp);
4130                         }
4131                         ++nfs_commit_blks;
4132                         if (cnt < iosize)
4133                                 break;
4134                         cnt -= iosize;
4135                         ++lblkno;
4136                 }
4137                 VI_UNLOCK(vp);
4138                 splx(s);
4139         }
4140
4141         aft_ret = VOP_GETATTR(vp, &aft, cred, td);
4142         vput(vp);
4143         mtx_unlock(&Giant);     /* VFS */
4144         vp = NULL;
4145         NFSD_LOCK();
4146 ereply:
4147         NFSD_LOCK_ASSERT();
4148         nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
4149         nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4150         if (!error) {
4151                 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
4152                 if (nfsver.tv_sec == 0)
4153                         nfsver = boottime;
4154                 *tl++ = txdr_unsigned(nfsver.tv_sec);
4155                 *tl = txdr_unsigned(nfsver.tv_usec);
4156         } else {
4157                 error = 0;
4158         }
4159 nfsmout:
4160         NFSD_LOCK_ASSERT();
4161         NFSD_UNLOCK();
4162         mtx_lock(&Giant);       /* VFS */
4163         if (vp)
4164                 vput(vp);
4165         vn_finished_write(mp);
4166         mtx_unlock(&Giant);     /* VFS */
4167         NFSD_LOCK();
4168         return(error);
4169 }
4170
4171 /*
4172  * nfs statfs service
4173  */
4174 int
4175 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4176     struct thread *td, struct mbuf **mrq)
4177 {
4178         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4179         struct sockaddr *nam = nfsd->nd_nam;
4180         caddr_t dpos = nfsd->nd_dpos;
4181         struct ucred *cred = nfsd->nd_cr;
4182         struct statfs *sf;
4183         struct nfs_statfs *sfp;
4184         caddr_t bpos;
4185         int error = 0, rdonly, getret = 1;
4186         int v3 = (nfsd->nd_flag & ND_NFSV3);
4187         struct mbuf *mb, *mreq;
4188         struct vnode *vp = NULL;
4189         struct vattr at;
4190         nfsfh_t nfh;
4191         fhandle_t *fhp;
4192         struct statfs statfs;
4193         u_quad_t tval;
4194
4195         NFSD_LOCK_ASSERT();
4196
4197         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4198         fhp = &nfh.fh_generic;
4199         nfsm_srvmtofh(fhp);
4200         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4201         if (error) {
4202                 nfsm_reply(NFSX_UNSIGNED);
4203                 if (v3)
4204                         nfsm_srvpostop_attr(getret, &at);
4205                 error = 0;
4206                 goto nfsmout;
4207         }
4208         sf = &statfs;
4209         NFSD_UNLOCK();
4210         mtx_lock(&Giant);       /* VFS */
4211         error = VFS_STATFS(vp->v_mount, sf, td);
4212         getret = VOP_GETATTR(vp, &at, cred, td);
4213         vput(vp);
4214         mtx_unlock(&Giant);     /* VFS */
4215         vp = NULL;
4216         NFSD_LOCK();
4217         nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
4218         if (v3)
4219                 nfsm_srvpostop_attr(getret, &at);
4220         if (error) {
4221                 error = 0;
4222                 goto nfsmout;
4223         }
4224         sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
4225         if (v3) {
4226                 tval = (u_quad_t)sf->f_blocks;
4227                 tval *= (u_quad_t)sf->f_bsize;
4228                 txdr_hyper(tval, &sfp->sf_tbytes);
4229                 tval = (u_quad_t)sf->f_bfree;
4230                 tval *= (u_quad_t)sf->f_bsize;
4231                 txdr_hyper(tval, &sfp->sf_fbytes);
4232                 /*
4233                  * Don't send negative values for available space,
4234                  * since this field is unsigned in the NFS protocol.
4235                  * Otherwise, the client would see absurdly high
4236                  * numbers for free space.
4237                  */
4238                 if (sf->f_bavail < 0)
4239                         tval = 0;
4240                 else
4241                         tval = (u_quad_t)sf->f_bavail;
4242                 tval *= (u_quad_t)sf->f_bsize;
4243                 txdr_hyper(tval, &sfp->sf_abytes);
4244                 sfp->sf_tfiles.nfsuquad[0] = 0;
4245                 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
4246                 sfp->sf_ffiles.nfsuquad[0] = 0;
4247                 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4248                 sfp->sf_afiles.nfsuquad[0] = 0;
4249                 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4250                 sfp->sf_invarsec = 0;
4251         } else {
4252                 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
4253                 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
4254                 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
4255                 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
4256                 if (sf->f_bavail < 0)
4257                         sfp->sf_bavail = 0;
4258                 else
4259                         sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
4260         }
4261 nfsmout:
4262         NFSD_LOCK_ASSERT();
4263         if (vp) {
4264                 NFSD_UNLOCK();
4265                 mtx_lock(&Giant);       /* VFS */
4266                 vput(vp);
4267                 mtx_unlock(&Giant);     /* VFS */
4268                 NFSD_LOCK();
4269         }
4270         return(error);
4271 }
4272
4273 /*
4274  * nfs fsinfo service
4275  */
4276 int
4277 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4278     struct thread *td, struct mbuf **mrq)
4279 {
4280         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4281         struct sockaddr *nam = nfsd->nd_nam;
4282         caddr_t dpos = nfsd->nd_dpos;
4283         struct ucred *cred = nfsd->nd_cr;
4284         struct nfsv3_fsinfo *sip;
4285         caddr_t bpos;
4286         int error = 0, rdonly, getret = 1, pref;
4287         struct mbuf *mb, *mreq;
4288         struct vnode *vp = NULL;
4289         struct vattr at;
4290         nfsfh_t nfh;
4291         fhandle_t *fhp;
4292         u_quad_t maxfsize;
4293         struct statfs sb;
4294         int v3 = (nfsd->nd_flag & ND_NFSV3);
4295
4296         NFSD_LOCK_ASSERT();
4297
4298         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4299         if (!v3)
4300                 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
4301         fhp = &nfh.fh_generic;
4302         nfsm_srvmtofh(fhp);
4303         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4304         if (error) {
4305                 nfsm_reply(NFSX_UNSIGNED);
4306                 nfsm_srvpostop_attr(getret, &at);
4307                 error = 0;
4308                 goto nfsmout;
4309         }
4310
4311         NFSD_UNLOCK();
4312         mtx_lock(&Giant);       /* VFS */
4313         /* XXX Try to make a guess on the max file size. */
4314         VFS_STATFS(vp->v_mount, &sb, td);
4315         maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
4316
4317         getret = VOP_GETATTR(vp, &at, cred, td);
4318         vput(vp);
4319         mtx_unlock(&Giant);     /* VFS */
4320         vp = NULL;
4321         NFSD_LOCK();
4322         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
4323         nfsm_srvpostop_attr(getret, &at);
4324         sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
4325
4326         /*
4327          * XXX
4328          * There should be filesystem VFS OP(s) to get this information.
4329          * For now, assume ufs.
4330          */
4331         if (slp->ns_so->so_type == SOCK_DGRAM)
4332                 pref = NFS_MAXDGRAMDATA;
4333         else
4334                 pref = NFS_MAXDATA;
4335         sip->fs_rtmax = txdr_unsigned(pref);
4336         sip->fs_rtpref = txdr_unsigned(pref);
4337         sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
4338         sip->fs_wtmax = txdr_unsigned(pref);
4339         sip->fs_wtpref = txdr_unsigned(pref);
4340         sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
4341         sip->fs_dtpref = txdr_unsigned(pref);
4342         txdr_hyper(maxfsize, &sip->fs_maxfilesize);
4343         sip->fs_timedelta.nfsv3_sec = 0;
4344         sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
4345         sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
4346                 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
4347                 NFSV3FSINFO_CANSETTIME);
4348 nfsmout:
4349         NFSD_LOCK_ASSERT();
4350         if (vp) {
4351                 NFSD_UNLOCK();
4352                 mtx_lock(&Giant);       /* VFS */
4353                 vput(vp);
4354                 mtx_unlock(&Giant);     /* VFS */
4355                 NFSD_LOCK();
4356         }
4357         return(error);
4358 }
4359
4360 /*
4361  * nfs pathconf service
4362  */
4363 int
4364 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4365     struct thread *td, struct mbuf **mrq)
4366 {
4367         struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4368         struct sockaddr *nam = nfsd->nd_nam;
4369         caddr_t dpos = nfsd->nd_dpos;
4370         struct ucred *cred = nfsd->nd_cr;
4371         struct nfsv3_pathconf *pc;
4372         caddr_t bpos;
4373         int error = 0, rdonly, getret = 1;
4374         register_t linkmax, namemax, chownres, notrunc;
4375         struct mbuf *mb, *mreq;
4376         struct vnode *vp = NULL;
4377         struct vattr at;
4378         nfsfh_t nfh;
4379         fhandle_t *fhp;
4380         int v3 = (nfsd->nd_flag & ND_NFSV3);
4381
4382         NFSD_LOCK_ASSERT();
4383
4384         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4385         if (!v3)
4386                 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
4387         fhp = &nfh.fh_generic;
4388         nfsm_srvmtofh(fhp);
4389         error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4390         if (error) {
4391                 nfsm_reply(NFSX_UNSIGNED);
4392                 nfsm_srvpostop_attr(getret, &at);
4393                 error = 0;
4394                 goto nfsmout;
4395         }
4396         NFSD_UNLOCK();
4397         mtx_lock(&Giant);       /* VFS */
4398         error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
4399         if (!error)
4400                 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
4401         if (!error)
4402                 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
4403         if (!error)
4404                 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, &notrunc);
4405         getret = VOP_GETATTR(vp, &at, cred, td);
4406         vput(vp);
4407         mtx_unlock(&Giant);     /* VFS */
4408         vp = NULL;
4409         NFSD_LOCK();
4410         nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
4411         nfsm_srvpostop_attr(getret, &at);
4412         if (error) {
4413                 error = 0;
4414                 goto nfsmout;
4415         }
4416         pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
4417
4418         pc->pc_linkmax = txdr_unsigned(linkmax);
4419         pc->pc_namemax = txdr_unsigned(namemax);
4420         pc->pc_notrunc = txdr_unsigned(notrunc);
4421         pc->pc_chownrestricted = txdr_unsigned(chownres);
4422
4423         /*
4424          * These should probably be supported by VOP_PATHCONF(), but
4425          * until msdosfs is exportable (why would you want to?), the
4426          * Unix defaults should be ok.
4427          */
4428         pc->pc_caseinsensitive = nfsrv_nfs_false;
4429         pc->pc_casepreserving = nfsrv_nfs_true;
4430 nfsmout:
4431         NFSD_LOCK_ASSERT();
4432         if (vp) {
4433                 NFSD_UNLOCK();
4434                 mtx_lock(&Giant);       /* VFS */
4435                 vput(vp);
4436                 mtx_unlock(&Giant);     /* VFS */
4437                 NFSD_LOCK();
4438         }
4439         return(error);
4440 }
4441
4442 /*
4443  * Null operation, used by clients to ping server
4444  */
4445 /* ARGSUSED */
4446 int
4447 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4448     struct thread *td, struct mbuf **mrq)
4449 {
4450         struct mbuf *mrep = nfsd->nd_mrep;
4451         caddr_t bpos;
4452         int error = NFSERR_RETVOID;
4453         struct mbuf *mb, *mreq;
4454
4455         NFSD_LOCK_ASSERT();
4456
4457         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4458         nfsm_reply(0);
4459 nfsmout:
4460         NFSD_LOCK_ASSERT();
4461         return (error);
4462 }
4463
4464 /*
4465  * No operation, used for obsolete procedures
4466  */
4467 /* ARGSUSED */
4468 int
4469 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4470     struct thread *td, struct mbuf **mrq)
4471 {
4472         struct mbuf *mrep = nfsd->nd_mrep;
4473         caddr_t bpos;
4474         int error;
4475         struct mbuf *mb, *mreq;
4476
4477         NFSD_LOCK_ASSERT();
4478
4479         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4480         if (nfsd->nd_repstat)
4481                 error = nfsd->nd_repstat;
4482         else
4483                 error = EPROCUNAVAIL;
4484         nfsm_reply(0);
4485         error = 0;
4486 nfsmout:
4487         NFSD_LOCK_ASSERT();
4488         return (error);
4489 }
4490
4491 /*
4492  * Perform access checking for vnodes obtained from file handles that would
4493  * refer to files already opened by a Unix client. You cannot just use
4494  * vn_writechk() and VOP_ACCESS() for two reasons.
4495  * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
4496  *     case.
4497  * 2 - The owner is to be given access irrespective of mode bits for some
4498  *     operations, so that processes that chmod after opening a file don't
4499  *     break. I don't like this because it opens a security hole, but since
4500  *     the nfs server opens a security hole the size of a barn door anyhow,
4501  *     what the heck.
4502  *
4503  * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
4504  * will return EPERM instead of EACCESS. EPERM is always an error.
4505  *
4506  * There are two versions: one to be called while holding Giant (which is
4507  * needed due to use of VFS), and the other called with the NFS server lock
4508  * (which will be dropped and reacquired).  This is necessary because
4509  * nfsrv_access checks are required from both classes of contexts.
4510  */
4511 static int
4512 nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred,
4513     int rdonly, struct thread *td, int override)
4514 {
4515         struct vattr vattr;
4516         int error;
4517
4518         GIANT_REQUIRED;
4519
4520         nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4521
4522         if (flags & VWRITE) {
4523                 /* Just vn_writechk() changed to check rdonly */
4524                 /*
4525                  * Disallow write attempts on read-only filesystems;
4526                  * unless the file is a socket or a block or character
4527                  * device resident on the filesystem.
4528                  */
4529                 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
4530                         switch (vp->v_type) {
4531                         case VREG:
4532                         case VDIR:
4533                         case VLNK:
4534                                 return (EROFS);
4535                         default:
4536                                 break;
4537                         }
4538                 }
4539                 /*
4540                  * If there's shared text associated with
4541                  * the inode, we can't allow writing.
4542                  */
4543                 if (vp->v_vflag & VV_TEXT)
4544                         return (ETXTBSY);
4545         }
4546
4547         error = VOP_GETATTR(vp, &vattr, cred, td);
4548         if (error)
4549                 return (error);
4550         error = VOP_ACCESS(vp, flags, cred, td);
4551         /*
4552          * Allow certain operations for the owner (reads and writes
4553          * on files that are already open).
4554          */
4555         if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
4556                 error = 0;
4557         return (error);
4558 }
4559
4560 static int
4561 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
4562     struct thread *td, int override)
4563 {
4564         int error;
4565
4566         NFSD_LOCK_ASSERT();
4567
4568         NFSD_UNLOCK();
4569         mtx_lock(&Giant);       /* VFS */
4570         error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override);
4571         mtx_unlock(&Giant);     /* VFS */
4572         NFSD_LOCK();
4573         return (error);
4574 }