2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
32 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
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
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
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
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.
59 * Warning: always pay careful attention to resource cleanup on return
60 * and note that nfsm_*() macros can terminate a procedure on certain
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.
68 * We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
69 * buffer has been freed or not.
72 #include <sys/param.h>
73 #include <sys/systm.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>
83 #include <sys/dirent.h>
85 #include <sys/kernel.h>
86 #include <sys/sysctl.h>
91 #include <vm/vm_extern.h>
92 #include <vm/vm_object.h>
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>
101 #define nfsdbprintf(info) printf info
103 #define nfsdbprintf(info)
106 #define MAX_COMMIT_COUNT (1024 * 1024)
108 #define NUM_HEURISTIC 1017
109 #define NHUSE_INIT 64
111 #define NHUSE_MAX 2048
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];
122 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
123 int nfsrvw_procrastinate_v3 = 0;
125 static struct timeval nfsver = { 0 };
127 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
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, "");
136 struct nfsrvstats nfsrvstats;
137 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
138 &nfsrvstats, nfsrvstats, "S,nfsrvstats");
140 static int nfsrv_access_withgiant(struct vnode *vp, int flags,
141 struct ucred *cred, int rdonly, struct thread *td,
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 *);
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).
154 ndclear(struct nameidata *nd)
157 nd->ni_cnd.cn_flags = 0;
160 nd->ni_startdir = NULL;
164 * nfs v3 access service
167 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
168 struct thread *td, struct mbuf **mrq)
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;
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);
187 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
189 panic("nfsrv3_access: v3 proc called on a v2 connection");
190 fhp = &nfh.fh_generic;
192 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
193 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
195 nfsm_reply(NFSX_UNSIGNED);
196 nfsm_srvpostop_attr(1, NULL);
200 nfsmode = fxdr_unsigned(u_int32_t, *tl);
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 |
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;
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);
223 mtx_unlock(&Giant); /* VFS */
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);
234 mtx_lock(&Giant); /* VFS */
236 mtx_unlock(&Giant); /* VFS */
243 * nfs getattr service
246 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
247 struct thread *td, struct mbuf **mrq)
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;
255 struct vattr *vap = &va;
256 struct vnode *vp = NULL;
260 int error = 0, rdonly;
261 struct mbuf *mb, *mreq;
265 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
266 fhp = &nfh.fh_generic;
268 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
275 mtx_lock(&Giant); /* VFS */
276 error = VOP_GETATTR(vp, vap, cred, td);
278 mtx_unlock(&Giant); /* VFS */
281 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
286 fp = nfsm_build(struct nfs_fattr *,
287 NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
288 nfsm_srvfillattr(vap, fp);
295 mtx_lock(&Giant); /* VFS */
297 mtx_unlock(&Giant); /* VFS */
304 * nfs setattr service
307 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
308 struct thread *td, struct mbuf **mrq)
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;
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;
331 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
332 fhp = &nfh.fh_generic;
334 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
339 mtx_lock(&Giant); /* VFS */
340 (void) vn_start_write(NULL, &mp, V_WAIT);
341 vfs_rel(mp); /* The write holds a ref. */
342 mtx_unlock(&Giant); /* VFS */
347 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
348 gcheck = fxdr_unsigned(int, *tl);
350 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
351 fxdr_nfsv3time(tl, &guard);
354 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
356 * Nah nah nah nah na nah
357 * There is a bug in the Sun client that puts 0xffff in the mode
358 * field of sattr when it should put in 0xffffffff. The u_short
359 * doesn't sign extend.
360 * --> check the low order 2 bytes for 0xffff
362 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
363 vap->va_mode = nfstov_mode(sp->sa_mode);
364 if (sp->sa_uid != nfsrv_nfs_xdrneg1)
365 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
366 if (sp->sa_gid != nfsrv_nfs_xdrneg1)
367 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
368 if (sp->sa_size != nfsrv_nfs_xdrneg1)
369 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
370 if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
372 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
374 vap->va_atime.tv_sec =
375 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
376 vap->va_atime.tv_nsec = 0;
379 if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
380 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
385 * Now that we have all the fields, lets do it.
387 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
389 nfsm_reply(2 * NFSX_UNSIGNED);
391 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
397 * vp now an active resource, pay careful attention to cleanup
401 mtx_lock(&Giant); /* VFS */
402 error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
403 if (!error && gcheck &&
404 (preat.va_ctime.tv_sec != guard.tv_sec ||
405 preat.va_ctime.tv_nsec != guard.tv_nsec))
406 error = NFSERR_NOT_SYNC;
409 mtx_unlock(&Giant); /* VFS */
412 nfsm_reply(NFSX_WCCDATA(v3));
414 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
418 mtx_unlock(&Giant); /* VFS */
424 * If the size is being changed write acces is required, otherwise
425 * just check for a read only filesystem.
427 if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
428 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
433 if (vp->v_type == VDIR) {
436 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
441 mtx_lock(&Giant); /* VFS */
442 error = VOP_SETATTR(vp, vap, cred, td);
443 postat_ret = VOP_GETATTR(vp, vap, cred, td);
444 mtx_unlock(&Giant); /* VFS */
452 mtx_lock(&Giant); /* VFS */
454 mtx_unlock(&Giant); /* VFS */
459 nfsm_reply(NFSX_WCCORFATTR(v3));
461 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
463 /* v2 non-error case. */
464 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
465 nfsm_srvfillattr(vap, fp);
473 mtx_lock(&Giant); /* VFS */
476 vn_finished_write(mp);
477 mtx_unlock(&Giant); /* VFS */
486 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
487 struct thread *td, struct mbuf **mrq)
489 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
490 struct sockaddr *nam = nfsd->nd_nam;
491 caddr_t dpos = nfsd->nd_dpos;
492 struct ucred *cred = nfsd->nd_cr;
493 struct nfs_fattr *fp;
494 struct nameidata nd, ind, *ndp = &nd;
495 struct vnode *vp, *dirp = NULL;
499 int error = 0, len, dirattr_ret = 1;
500 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
501 struct mbuf *mb, *mreq;
502 struct vattr va, dirattr, *vap = &va;
506 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
509 fhp = &nfh.fh_generic;
511 nfsm_srvnamesiz(len);
513 pubflag = nfs_ispublicfh(fhp);
515 nd.ni_cnd.cn_cred = cred;
516 nd.ni_cnd.cn_nameiop = LOOKUP;
517 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
518 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
519 &dirp, v3, &dirattr, &dirattr_ret, td, pubflag);
522 * namei failure, only dirp to cleanup. Clear out garbarge from
523 * structure in case macros jump to nfsmout.
527 mtx_lock(&Giant); /* VFS */
533 mtx_unlock(&Giant); /* VFS */
535 nfsm_reply(NFSX_POSTOPATTR(v3));
537 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
543 * Locate index file for public filehandle
545 * error is 0 on entry and 0 on exit from this block.
549 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
551 * Setup call to lookup() to see if we can find
552 * the index file. Arguably, this doesn't belong
553 * in a kernel.. Ugh. If an error occurs, do not
554 * try to install an index file and then clear the
557 * When we replace nd with ind and redirect ndp,
558 * maintenance of ni_startdir and ni_vp shift to
559 * ind and we have to clean them up in the old nd.
560 * However, the cnd resource continues to be maintained
561 * via the original nd. Confused? You aren't alone!
564 VOP_UNLOCK(nd.ni_vp, 0, td);
565 ind.ni_pathlen = strlen(nfs_pub.np_index);
566 ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
568 ind.ni_startdir = nd.ni_vp;
569 VREF(ind.ni_startdir);
571 error = lookup(&ind);
573 if (ind.ni_cnd.cn_flags & GIANTHELD) {
575 ind.ni_cnd.cn_flags &= ~GIANTHELD;
580 * Found an index file. Get rid of
581 * the old references. transfer nd.ni_vp'
587 vrele(nd.ni_startdir);
588 nd.ni_startdir = NULL;
594 * If the public filehandle was used, check that this lookup
595 * didn't result in a filehandle outside the publicly exported
596 * filesystem. We clear the poor vp here to avoid lockups due
600 if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
608 * Resources at this point:
609 * ndp->ni_vp may not be NULL
613 mtx_unlock(&Giant); /* VFS */
615 nfsm_reply(NFSX_POSTOPATTR(v3));
617 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
623 * Get underlying attribute, then release remaining resources ( for
624 * the same potential blocking reason ) and reply.
627 bzero((caddr_t)fhp, sizeof(nfh));
628 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
629 error = VFS_VPTOFH(vp, &fhp->fh_fid);
631 error = VOP_GETATTR(vp, vap, cred, td);
634 vrele(ndp->ni_startdir);
637 ndp->ni_startdir = NULL;
639 mtx_unlock(&Giant); /* VFS */
641 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
644 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
648 nfsm_srvfhtom(fhp, v3);
650 nfsm_srvpostop_attr(0, vap);
651 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
653 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
654 nfsm_srvfillattr(vap, fp);
659 if (ndp->ni_vp || dirp || ndp->ni_startdir) {
661 mtx_lock(&Giant); /* VFS */
666 if (ndp->ni_startdir)
667 vrele(ndp->ni_startdir);
668 mtx_unlock(&Giant); /* VFS */
671 NDFREE(&nd, NDF_ONLY_PNBUF);
676 * nfs readlink service
679 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
680 struct thread *td, struct mbuf **mrq)
682 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
683 struct sockaddr *nam = nfsd->nd_nam;
684 caddr_t dpos = nfsd->nd_dpos;
685 struct ucred *cred = nfsd->nd_cr;
686 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
687 struct iovec *ivp = iv;
691 int error = 0, rdonly, i, tlen, len, getret;
692 int v3 = (nfsd->nd_flag & ND_NFSV3);
693 struct mbuf *mb, *mp3, *nmp, *mreq;
694 struct vnode *vp = NULL;
698 struct uio io, *uiop = &io;
702 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
707 fhp = &nfh.fh_generic;
712 while (len < NFS_MAXPATHLEN) {
713 MGET(nmp, M_TRYWAIT, MT_DATA);
714 MCLGET(nmp, M_TRYWAIT);
715 nmp->m_len = NFSMSIZ(nmp);
722 if ((len + mp->m_len) > NFS_MAXPATHLEN) {
723 mp->m_len = NFS_MAXPATHLEN - len;
724 len = NFS_MAXPATHLEN;
727 ivp->iov_base = mtod(mp, caddr_t);
728 ivp->iov_len = mp->m_len;
733 uiop->uio_iovcnt = i;
734 uiop->uio_offset = 0;
735 uiop->uio_resid = len;
736 uiop->uio_rw = UIO_READ;
737 uiop->uio_segflg = UIO_SYSSPACE;
740 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
742 nfsm_reply(2 * NFSX_UNSIGNED);
744 nfsm_srvpostop_attr(1, NULL);
749 mtx_lock(&Giant); /* VFS */
750 if (vp->v_type != VLNK) {
756 error = VOP_READLINK(vp, uiop, cred);
757 getret = VOP_GETATTR(vp, &attr, cred, td);
759 mtx_unlock(&Giant); /* VFS */
762 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
764 nfsm_srvpostop_attr(getret, &attr);
769 if (uiop->uio_resid > 0) {
770 len -= uiop->uio_resid;
771 tlen = nfsm_rndup(len);
772 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
774 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
775 *tl = txdr_unsigned(len);
784 mtx_lock(&Giant); /* VFS */
786 mtx_unlock(&Giant); /* VFS */
796 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
797 struct thread *td, struct mbuf **mrq)
799 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
800 struct sockaddr *nam = nfsd->nd_nam;
801 caddr_t dpos = nfsd->nd_dpos;
802 struct ucred *cred = nfsd->nd_cr;
806 struct nfs_fattr *fp;
810 int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
811 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
812 struct mbuf *mb, *mreq;
814 struct vnode *vp = NULL;
817 struct uio io, *uiop = &io;
818 struct vattr va, *vap = &va;
825 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
826 fhp = &nfh.fh_generic;
829 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
830 off = fxdr_hyper(tl);
832 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
833 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
835 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
838 * Reference vp. If an error occurs, vp will be invalid, but we
839 * have to NULL it just in case. The macros might goto nfsmout
843 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
846 nfsm_reply(2 * NFSX_UNSIGNED);
848 nfsm_srvpostop_attr(1, NULL);
853 if (vp->v_type != VREG) {
857 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
860 mtx_lock(&Giant); /* VFS */
862 if ((error = nfsrv_access_withgiant(vp, VREAD, cred, rdonly,
864 error = nfsrv_access_withgiant(vp, VEXEC, cred,
867 getret = VOP_GETATTR(vp, vap, cred, td);
872 mtx_unlock(&Giant); /* VFS */
875 nfsm_reply(NFSX_POSTOPATTR(v3));
877 nfsm_srvpostop_attr(getret, vap);
881 mtx_unlock(&Giant); /* VFS */
885 * Calculate byte count to read
888 if (off >= vap->va_size)
890 else if ((off + reqlen) > vap->va_size)
891 cnt = vap->va_size - off;
896 * Calculate seqcount for heuristic
904 * Locate best candidate
907 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
911 if (nfsheur[hi].nh_vp == vp) {
915 if (nfsheur[hi].nh_use > 0)
916 --nfsheur[hi].nh_use;
917 hi = (hi + 1) % NUM_HEURISTIC;
918 if (nfsheur[hi].nh_use < nh->nh_use)
922 if (nh->nh_vp != vp) {
925 nh->nh_use = NHUSE_INIT;
933 * Calculate heuristic
936 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
937 if (++nh->nh_seqcount > IO_SEQMAX)
938 nh->nh_seqcount = IO_SEQMAX;
939 } else if (nh->nh_seqcount > 1) {
944 nh->nh_use += NHUSE_INC;
945 if (nh->nh_use > NHUSE_MAX)
946 nh->nh_use = NHUSE_MAX;
947 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
950 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
952 tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
953 *tl++ = nfsrv_nfs_true;
954 fp = (struct nfs_fattr *)tl;
955 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
957 tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
958 fp = (struct nfs_fattr *)tl;
959 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
961 len = left = nfsm_rndup(cnt);
965 * Generate the mbuf list with the uio_iov ref. to it.
970 siz = min(M_TRAILINGSPACE(m), left);
976 MGET(m, M_TRYWAIT, MT_DATA);
977 MCLGET(m, M_TRYWAIT);
983 MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
985 uiop->uio_iov = iv2 = iv;
991 panic("nfsrv_read iov");
992 siz = min(M_TRAILINGSPACE(m), left);
994 iv->iov_base = mtod(m, caddr_t) + m->m_len;
1003 uiop->uio_iovcnt = i;
1004 uiop->uio_offset = off;
1005 uiop->uio_resid = len;
1006 uiop->uio_rw = UIO_READ;
1007 uiop->uio_segflg = UIO_SYSSPACE;
1008 mtx_lock(&Giant); /* VFS */
1009 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
1010 off = uiop->uio_offset;
1012 FREE((caddr_t)iv2, M_TEMP);
1013 if (error || (getret = VOP_GETATTR(vp, vap, cred, td))) {
1018 mtx_unlock(&Giant); /* VFS */
1021 nfsm_reply(NFSX_POSTOPATTR(v3));
1023 nfsm_srvpostop_attr(getret, vap);
1028 uiop->uio_resid = 0;
1029 mtx_lock(&Giant); /* VFS */
1031 mtx_assert(&Giant, MA_OWNED); /* VFS */
1033 mtx_unlock(&Giant); /* VFS */
1036 nfsm_srvfillattr(vap, fp);
1037 tlen = len - uiop->uio_resid;
1038 cnt = cnt < tlen ? cnt : tlen;
1039 tlen = nfsm_rndup(cnt);
1040 if (len != tlen || tlen != cnt)
1041 nfsm_adj(mb, len - tlen, tlen - cnt);
1043 *tl++ = txdr_unsigned(cnt);
1045 *tl++ = nfsrv_nfs_true;
1047 *tl++ = nfsrv_nfs_false;
1049 *tl = txdr_unsigned(cnt);
1054 mtx_lock(&Giant); /* VFS */
1056 mtx_unlock(&Giant); /* VFS */
1066 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1067 struct thread *td, struct mbuf **mrq)
1069 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1070 struct sockaddr *nam = nfsd->nd_nam;
1071 caddr_t dpos = nfsd->nd_dpos;
1072 struct ucred *cred = nfsd->nd_cr;
1076 struct nfs_fattr *fp;
1078 struct vattr va, forat;
1079 struct vattr *vap = &va;
1082 int error = 0, rdonly, len, forat_ret = 1;
1083 int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
1084 int stable = NFSV3WRITE_FILESYNC;
1085 int v3 = (nfsd->nd_flag & ND_NFSV3);
1086 struct mbuf *mb, *mreq;
1087 struct vnode *vp = NULL;
1090 struct uio io, *uiop = &io;
1092 struct mount *mntp = NULL;
1096 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1102 fhp = &nfh.fh_generic;
1104 if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1109 mtx_lock(&Giant); /* VFS */
1110 (void) vn_start_write(NULL, &mntp, V_WAIT);
1111 vfs_rel(mntp); /* The write holds a ref. */
1112 mtx_unlock(&Giant); /* VFS */
1115 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1116 off = fxdr_hyper(tl);
1118 stable = fxdr_unsigned(int, *tl++);
1120 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1121 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1124 stable = NFSV3WRITE_UNSTABLE;
1126 retlen = len = fxdr_unsigned(int32_t, *tl);
1130 * For NFS Version 2, it is not obvious what a write of zero length
1131 * should do, but I might as well be consistent with Version 3,
1132 * which is to return ok so long as there are no permission problems.
1140 adjust = dpos - mtod(mp, caddr_t);
1141 mp->m_len -= adjust;
1142 if (mp->m_len > 0 && adjust > 0)
1143 mp->m_data += adjust;
1147 else if (mp->m_len > 0) {
1150 mp->m_len -= (i - len);
1159 if (len > NFS_MAXDATA || len < 0 || i < len) {
1161 nfsm_reply(2 * NFSX_UNSIGNED);
1163 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1167 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
1170 nfsm_reply(2 * NFSX_UNSIGNED);
1172 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1178 mtx_lock(&Giant); /* VFS */
1179 forat_ret = VOP_GETATTR(vp, &forat, cred, td);
1180 mtx_unlock(&Giant); /* VFS */
1183 if (vp->v_type != VREG) {
1187 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1190 error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
1193 mtx_lock(&Giant); /* VFS */
1195 mtx_unlock(&Giant); /* VFS */
1198 nfsm_reply(NFSX_WCCDATA(v3));
1200 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1207 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
1209 uiop->uio_iov = iv = ivp;
1210 uiop->uio_iovcnt = cnt;
1213 if (mp->m_len > 0) {
1214 ivp->iov_base = mtod(mp, caddr_t);
1215 ivp->iov_len = mp->m_len;
1223 * The IO_METASYNC flag indicates that all metadata (and not just
1224 * enough to ensure data integrity) mus be written to stable storage
1226 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1228 if (stable == NFSV3WRITE_UNSTABLE)
1229 ioflags = IO_NODELOCKED;
1230 else if (stable == NFSV3WRITE_DATASYNC)
1231 ioflags = (IO_SYNC | IO_NODELOCKED);
1233 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1234 uiop->uio_resid = len;
1235 uiop->uio_rw = UIO_WRITE;
1236 uiop->uio_segflg = UIO_SYSSPACE;
1237 uiop->uio_td = NULL;
1238 uiop->uio_offset = off;
1239 mtx_lock(&Giant); /* VFS */
1240 error = VOP_WRITE(vp, uiop, ioflags, cred);
1241 /* XXXRW: unlocked write. */
1242 nfsrvstats.srvvop_writes++;
1243 FREE((caddr_t)iv, M_TEMP);
1245 mtx_lock(&Giant); /* VFS */
1246 mtx_assert(&Giant, MA_OWNED); /* VFS */
1247 aftat_ret = VOP_GETATTR(vp, vap, cred, td);
1249 mtx_unlock(&Giant); /* VFS */
1256 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1257 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1259 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1264 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1265 *tl++ = txdr_unsigned(retlen);
1267 * If nfs_async is set, then pretend the write was FILESYNC.
1269 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1270 *tl++ = txdr_unsigned(stable);
1272 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1274 * Actually, there is no need to txdr these fields,
1275 * but it may make the values more human readable,
1276 * for debugging purposes.
1278 if (nfsver.tv_sec == 0)
1280 *tl++ = txdr_unsigned(nfsver.tv_sec);
1281 *tl = txdr_unsigned(nfsver.tv_usec);
1282 } else if (!error) {
1283 /* v2 non-error case. */
1284 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1285 nfsm_srvfillattr(vap, fp);
1291 mtx_lock(&Giant); /* VFS */
1294 vn_finished_write(mntp);
1295 mtx_unlock(&Giant); /* VFS */
1301 * For the purposes of write gathering, we must decide if the credential
1302 * associated with two pending requests have equivilent privileges. Since
1303 * NFS only uses a subset of the BSD ucred -- the effective uid and group
1304 * IDs -- we have a compare routine that checks only the relevant fields.
1307 nfsrv_samecred(struct ucred *cr1, struct ucred *cr2)
1311 if (cr1->cr_uid != cr2->cr_uid)
1313 if (cr1->cr_ngroups != cr2->cr_ngroups)
1315 for (i = 0; i < cr1->cr_ngroups; i++) {
1316 if (cr1->cr_groups[i] != cr2->cr_groups[i])
1323 * NFS write service with write gathering support. Called when
1324 * nfsrvw_procrastinate > 0.
1325 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1326 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1330 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
1331 struct thread *td, struct mbuf **mrq)
1335 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1336 struct nfs_fattr *fp;
1339 struct nfsrvw_delayhash *wpp;
1341 struct vattr va, forat;
1344 int error = 0, rdonly, len, forat_ret = 1;
1345 int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
1346 struct mbuf *mb, *mreq, *mrep, *md;
1347 struct vnode *vp = NULL;
1348 struct uio io, *uiop = &io;
1350 struct mount *mntp = NULL;
1354 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1363 mrep = nfsd->nd_mrep;
1365 dpos = nfsd->nd_dpos;
1367 v3 = (nfsd->nd_flag & ND_NFSV3);
1368 LIST_INIT(&nfsd->nd_coalesce);
1369 nfsd->nd_mreq = NULL;
1370 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1371 cur_usec = nfs_curusec();
1372 nfsd->nd_time = cur_usec +
1373 (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
1376 * Now, get the write header..
1378 nfsm_srvmtofh(&nfsd->nd_fh);
1380 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1381 nfsd->nd_off = fxdr_hyper(tl);
1383 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1385 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1386 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1389 nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
1391 len = fxdr_unsigned(int32_t, *tl);
1393 nfsd->nd_eoff = nfsd->nd_off + len;
1396 * Trim the header out of the mbuf list and trim off any trailing
1397 * junk so that the mbuf list has only the write data.
1405 adjust = dpos - mtod(mp, caddr_t);
1406 mp->m_len -= adjust;
1407 if (mp->m_len > 0 && adjust > 0)
1408 mp->m_data += adjust;
1415 mp->m_len -= (i - len);
1421 if (len > NFS_MAXDATA || len < 0 || i < len) {
1426 nfsm_writereply(2 * NFSX_UNSIGNED);
1428 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1429 nfsd->nd_mreq = mreq;
1430 nfsd->nd_mrep = NULL;
1435 * Add this entry to the hash and time queues.
1439 wp = LIST_FIRST(&slp->ns_tq);
1440 while (wp && wp->nd_time < nfsd->nd_time) {
1442 wp = LIST_NEXT(wp, nd_tq);
1444 NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
1446 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1448 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1450 if (nfsd->nd_mrep) {
1451 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1453 wp = LIST_FIRST(wpp);
1455 bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
1457 wp = LIST_NEXT(wp, nd_hash);
1459 while (wp && wp->nd_off < nfsd->nd_off &&
1460 !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1462 wp = LIST_NEXT(wp, nd_hash);
1465 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1468 * Search the hash list for overlapping entries and
1471 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1472 wp = LIST_NEXT(nfsd, nd_hash);
1473 if (nfsrv_samecred(owp->nd_cr, nfsd->nd_cr))
1474 nfsrvw_coalesce(owp, nfsd);
1477 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1484 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1485 * and generate the associated reply mbuf list(s).
1488 cur_usec = nfs_curusec();
1490 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
1491 owp = LIST_NEXT(nfsd, nd_tq);
1492 if (nfsd->nd_time > cur_usec)
1496 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
1497 LIST_REMOVE(nfsd, nd_tq);
1498 LIST_REMOVE(nfsd, nd_hash);
1500 mrep = nfsd->nd_mrep;
1501 nfsd->nd_mrep = NULL;
1503 v3 = (nfsd->nd_flag & ND_NFSV3);
1504 forat_ret = aftat_ret = 1;
1505 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1506 nfsd->nd_nam, &rdonly, TRUE);
1510 mtx_lock(&Giant); /* VFS */
1511 forat_ret = VOP_GETATTR(vp, &forat, cred, td);
1512 mtx_unlock(&Giant); /* VFS */
1515 if (vp->v_type != VREG) {
1519 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1525 mtx_lock(&Giant); /* VFS */
1527 error = nfsrv_access_withgiant(vp, VWRITE, cred, rdonly,
1529 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1530 ioflags = IO_NODELOCKED;
1531 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1532 ioflags = (IO_SYNC | IO_NODELOCKED);
1534 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1535 uiop->uio_rw = UIO_WRITE;
1536 uiop->uio_segflg = UIO_SYSSPACE;
1537 uiop->uio_td = NULL;
1538 uiop->uio_offset = nfsd->nd_off;
1539 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1540 if (uiop->uio_resid > 0) {
1548 uiop->uio_iovcnt = i;
1549 MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
1551 uiop->uio_iov = ivp = iov;
1554 if (mp->m_len > 0) {
1555 ivp->iov_base = mtod(mp, caddr_t);
1556 ivp->iov_len = mp->m_len;
1562 if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
1563 VOP_UNLOCK(vp, 0, td);
1564 error = vn_start_write(NULL, &mntp, V_WAIT);
1565 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1569 error = VOP_WRITE(vp, uiop, ioflags, cred);
1570 /* XXXRW: unlocked write. */
1571 nfsrvstats.srvvop_writes++;
1572 vn_finished_write(mntp);
1574 FREE((caddr_t)iov, M_TEMP);
1578 aftat_ret = VOP_GETATTR(vp, &va, cred, td);
1582 mtx_unlock(&Giant); /* VFS */
1586 * Loop around generating replies for all write rpcs that have
1587 * now been completed.
1591 NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
1593 nfsm_writereply(NFSX_WCCDATA(v3));
1595 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1598 nfsm_writereply(NFSX_PREOPATTR(v3) +
1599 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1600 NFSX_WRITEVERF(v3));
1602 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1603 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1604 *tl++ = txdr_unsigned(nfsd->nd_len);
1605 *tl++ = txdr_unsigned(swp->nd_stable);
1607 * Actually, there is no need to txdr these fields,
1608 * but it may make the values more human readable,
1609 * for debugging purposes.
1611 if (nfsver.tv_sec == 0)
1613 *tl++ = txdr_unsigned(nfsver.tv_sec);
1614 *tl = txdr_unsigned(nfsver.tv_usec);
1616 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1617 nfsm_srvfillattr(&va, fp);
1620 nfsd->nd_mreq = mreq;
1622 panic("nfsrv_write: nd_mrep not free");
1625 * Done. Put it at the head of the timer queue so that
1626 * the final phase can return the reply.
1631 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1633 nfsd = LIST_FIRST(&swp->nd_coalesce);
1635 LIST_REMOVE(nfsd, nd_tq);
1641 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1648 * Search for a reply to return.
1651 LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
1652 if (nfsd->nd_mreq) {
1653 NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
1654 LIST_REMOVE(nfsd, nd_tq);
1655 *mrq = nfsd->nd_mreq;
1664 * Coalesce the write request nfsd into owp. To do this we must:
1665 * - remove nfsd from the queues
1666 * - merge nfsd->nd_mrep into owp->nd_mrep
1667 * - update the nd_eoff and nd_stable for owp
1668 * - put nfsd on owp's nd_coalesce list
1669 * NB: Must be called at splsoftclock().
1672 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
1676 struct nfsrv_descript *p;
1680 NFS_DPF(WG, ("C%03x-%03x",
1681 nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
1682 LIST_REMOVE(nfsd, nd_hash);
1683 LIST_REMOVE(nfsd, nd_tq);
1684 if (owp->nd_eoff < nfsd->nd_eoff) {
1685 overlap = owp->nd_eoff - nfsd->nd_off;
1687 panic("nfsrv_coalesce: bad off");
1689 m_adj(nfsd->nd_mrep, overlap);
1693 mp->m_next = nfsd->nd_mrep;
1694 owp->nd_eoff = nfsd->nd_eoff;
1696 m_freem(nfsd->nd_mrep);
1697 nfsd->nd_mrep = NULL;
1698 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1699 owp->nd_stable = NFSV3WRITE_FILESYNC;
1700 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1701 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1702 owp->nd_stable = NFSV3WRITE_DATASYNC;
1703 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1706 * If nfsd had anything else coalesced into it, transfer them
1707 * to owp, otherwise their replies will never get sent.
1709 for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
1710 p = LIST_FIRST(&nfsd->nd_coalesce)) {
1711 LIST_REMOVE(p, nd_tq);
1712 LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
1717 * nfs create service
1718 * now does a truncate to 0 length via. setattr if it already exists
1721 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1722 struct thread *td, struct mbuf **mrq)
1724 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1725 struct sockaddr *nam = nfsd->nd_nam;
1726 caddr_t dpos = nfsd->nd_dpos;
1727 struct ucred *cred = nfsd->nd_cr;
1728 struct nfs_fattr *fp;
1729 struct vattr va, dirfor, diraft;
1730 struct vattr *vap = &va;
1731 struct nfsv2_sattr *sp;
1733 struct nameidata nd;
1735 int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1736 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1738 struct mbuf *mb, *mreq;
1739 struct vnode *dirp = NULL;
1743 u_char cverf[NFSX_V3CREATEVERF];
1744 struct mount *mp = NULL;
1748 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1754 fhp = &nfh.fh_generic;
1756 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1761 mtx_lock(&Giant); /* VFS */
1762 (void) vn_start_write(NULL, &mp, V_WAIT);
1763 vfs_rel(mp); /* The write holds a ref. */
1764 mtx_unlock(&Giant); /* VFS */
1766 nfsm_srvnamesiz(len);
1768 nd.ni_cnd.cn_cred = cred;
1769 nd.ni_cnd.cn_nameiop = CREATE;
1770 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
1773 * Call namei and do initial cleanup to get a few things
1774 * out of the way. If we get an initial error we cleanup
1775 * and return here to avoid special-casing the invalid nd
1776 * structure through the rest of the case. dirp may be
1777 * set even if an error occurs, but the nd structure will not
1778 * be valid at all if an error occurs so we have to invalidate it
1779 * prior to calling nfsm_reply ( which might goto nfsmout ).
1781 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1782 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
1785 mtx_lock(&Giant); /* VFS */
1787 mtx_unlock(&Giant); /* VFS */
1792 nfsm_reply(NFSX_WCCDATA(v3));
1794 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1800 * No error. Continue. State:
1802 * startdir is valid ( we release this immediately )
1804 * nd.ni_vp may be valid
1805 * nd.ni_dvp is valid
1807 * The error state is set through the code and we may also do some
1808 * opportunistic releasing of vnodes to avoid holding locks through
1809 * NFS I/O. The cleanup at the end is a catch-all
1814 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1815 how = fxdr_unsigned(int, *tl);
1817 case NFSV3CREATE_GUARDED:
1823 case NFSV3CREATE_UNCHECKED:
1826 case NFSV3CREATE_EXCLUSIVE:
1827 cp = nfsm_dissect_nonblock(caddr_t, NFSX_V3CREATEVERF);
1828 bcopy(cp, cverf, NFSX_V3CREATEVERF);
1832 vap->va_type = VREG;
1834 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
1835 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1836 if (vap->va_type == VNON)
1837 vap->va_type = VREG;
1838 vap->va_mode = nfstov_mode(sp->sa_mode);
1839 switch (vap->va_type) {
1841 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1843 vap->va_size = (u_quad_t)tsize;
1848 rdev = fxdr_unsigned(long, sp->sa_size);
1856 * Iff doesn't exist, create it
1857 * otherwise just truncate to 0 length
1858 * should I set the mode too ?
1860 * The only possible error we can have at this point is EEXIST.
1861 * nd.ni_vp will also be non-NULL in that case.
1864 mtx_lock(&Giant); /* VFS */
1865 if (nd.ni_vp == NULL) {
1866 if (vap->va_mode == (mode_t)VNOVAL)
1868 if (vap->va_type == VREG || vap->va_type == VSOCK) {
1869 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1871 NDFREE(&nd, NDF_ONLY_PNBUF);
1873 if (exclusive_flag) {
1876 bcopy(cverf, (caddr_t)&vap->va_atime,
1878 error = VOP_SETATTR(nd.ni_vp, vap, cred,
1882 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
1883 vap->va_type == VFIFO) {
1885 * NFSv2-specific code for creating device nodes
1888 * Handle SysV FIFO node special cases. All other
1889 * devices require super user to access.
1891 if (vap->va_type == VCHR && rdev == 0xffffffff)
1892 vap->va_type = VFIFO;
1893 if (vap->va_type != VFIFO &&
1894 (error = suser_cred(cred, 0))) {
1897 vap->va_rdev = rdev;
1898 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1900 NDFREE(&nd, NDF_ONLY_PNBUF);
1907 * release dvp prior to lookup
1915 * Even though LOCKPARENT was cleared, ni_dvp may
1918 nd.ni_cnd.cn_nameiop = LOOKUP;
1919 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1920 nd.ni_cnd.cn_thread = td;
1921 nd.ni_cnd.cn_cred = cred;
1923 error = lookup(&nd);
1925 if (nd.ni_cnd.cn_flags & GIANTHELD) {
1927 nd.ni_cnd.cn_flags &= ~GIANTHELD;
1932 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1940 if (vap->va_size != -1) {
1941 error = nfsrv_access_withgiant(nd.ni_vp, VWRITE,
1942 cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0);
1944 tempsize = vap->va_size;
1946 vap->va_size = tempsize;
1947 error = VOP_SETATTR(nd.ni_vp, vap, cred,
1954 bzero((caddr_t)fhp, sizeof(nfh));
1955 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1956 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1958 error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
1961 if (exclusive_flag && !error &&
1962 bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
1964 if (dirp == nd.ni_dvp)
1965 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
1967 /* Drop the other locks to avoid deadlock. */
1969 if (nd.ni_dvp == nd.ni_vp)
1979 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
1980 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
1981 VOP_UNLOCK(dirp, 0, td);
1985 NFSD_UNLOCK_ASSERT();
1986 mtx_unlock(&Giant); /* VFS */
1990 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1993 nfsm_srvpostop_fh(fhp);
1994 nfsm_srvpostop_attr(0, vap);
1996 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1997 } else if (!error) {
1998 /* v2 non-error case. */
1999 nfsm_srvfhtom(fhp, v3);
2000 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
2001 nfsm_srvfillattr(vap, fp);
2008 mtx_lock(&Giant); /* VFS */
2010 if (nd.ni_dvp == nd.ni_vp)
2017 if (nd.ni_startdir) {
2018 vrele(nd.ni_startdir);
2019 nd.ni_startdir = NULL;
2023 NDFREE(&nd, NDF_ONLY_PNBUF);
2024 vn_finished_write(mp);
2025 mtx_unlock(&Giant); /* VFS */
2031 * nfs v3 mknod service
2034 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2035 struct thread *td, struct mbuf **mrq)
2037 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2038 struct sockaddr *nam = nfsd->nd_nam;
2039 caddr_t dpos = nfsd->nd_dpos;
2040 struct ucred *cred = nfsd->nd_cr;
2041 struct vattr va, dirfor, diraft;
2042 struct vattr *vap = &va;
2044 struct nameidata nd;
2046 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2047 u_int32_t major, minor;
2049 struct mbuf *mb, *mreq;
2050 struct vnode *vp, *dirp = NULL;
2053 struct mount *mp = NULL;
2054 int v3 = (nfsd->nd_flag & ND_NFSV3);
2058 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2060 panic("nfsrv_mknod: v3 proc called on a v2 connection");
2063 fhp = &nfh.fh_generic;
2065 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2070 mtx_lock(&Giant); /* VFS */
2071 (void) vn_start_write(NULL, &mp, V_WAIT);
2072 vfs_rel(mp); /* The write holds a ref. */
2073 mtx_unlock(&Giant); /* VFS */
2075 nfsm_srvnamesiz(len);
2077 nd.ni_cnd.cn_cred = cred;
2078 nd.ni_cnd.cn_nameiop = CREATE;
2079 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
2082 * Handle nfs_namei() call. If an error occurs, the nd structure
2083 * is not valid. However, nfsm_*() routines may still jump to
2087 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2088 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2090 nfsm_reply(NFSX_WCCDATA(1));
2091 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2095 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
2096 vtyp = nfsv3tov_type(*tl);
2097 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
2099 mtx_lock(&Giant); /* VFS */
2100 error = NFSERR_BADTYPE;
2105 if (vtyp == VCHR || vtyp == VBLK) {
2106 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2107 major = fxdr_unsigned(u_int32_t, *tl++);
2108 minor = fxdr_unsigned(u_int32_t, *tl);
2109 vap->va_rdev = makedev(major, minor);
2113 * Iff doesn't exist, create it.
2117 mtx_lock(&Giant); /* VFS */
2121 vap->va_type = vtyp;
2122 if (vap->va_mode == (mode_t)VNOVAL)
2125 mtx_lock(&Giant); /* VFS */
2126 if (vtyp == VSOCK) {
2127 vrele(nd.ni_startdir);
2128 nd.ni_startdir = NULL;
2129 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2131 NDFREE(&nd, NDF_ONLY_PNBUF);
2133 if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
2135 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2137 NDFREE(&nd, NDF_ONLY_PNBUF);
2144 * Release dvp prior to lookup
2149 nd.ni_cnd.cn_nameiop = LOOKUP;
2150 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
2151 nd.ni_cnd.cn_thread = td;
2152 nd.ni_cnd.cn_cred = td->td_ucred;
2154 error = lookup(&nd);
2156 if (nd.ni_cnd.cn_flags & GIANTHELD) {
2158 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2163 if (nd.ni_cnd.cn_flags & ISSYMLINK)
2168 * send response, cleanup, return.
2171 NFSD_UNLOCK_ASSERT();
2174 bzero((caddr_t)fhp, sizeof(nfh));
2175 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2176 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2178 error = VOP_GETATTR(vp, vap, cred, td);
2181 if (nd.ni_dvp == nd.ni_vp)
2192 if (nd.ni_startdir) {
2193 vrele(nd.ni_startdir);
2194 nd.ni_startdir = NULL;
2196 NDFREE(&nd, NDF_ONLY_PNBUF);
2198 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2199 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2200 VOP_UNLOCK(dirp, 0, td);
2202 mtx_unlock(&Giant); /* VFS */
2206 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
2209 nfsm_srvpostop_fh(fhp);
2210 nfsm_srvpostop_attr(0, vap);
2212 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2215 mtx_lock(&Giant); /* VFS */
2216 vn_finished_write(mp);
2217 mtx_unlock(&Giant); /* VFS */
2223 mtx_lock(&Giant); /* VFS */
2225 if (nd.ni_dvp == nd.ni_vp)
2235 vrele(nd.ni_startdir);
2236 NDFREE(&nd, NDF_ONLY_PNBUF);
2237 vn_finished_write(mp);
2238 mtx_unlock(&Giant); /* VFS */
2244 * nfs remove service
2247 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2248 struct thread *td, struct mbuf **mrq)
2250 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2251 struct sockaddr *nam = nfsd->nd_nam;
2252 caddr_t dpos = nfsd->nd_dpos;
2253 struct ucred *cred = nfsd->nd_cr;
2254 struct nameidata nd;
2256 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2257 int v3 = (nfsd->nd_flag & ND_NFSV3);
2258 struct mbuf *mb, *mreq;
2260 struct vattr dirfor, diraft;
2263 struct mount *mp = NULL;
2267 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2270 fhp = &nfh.fh_generic;
2272 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2277 mtx_lock(&Giant); /* VFS */
2278 (void) vn_start_write(NULL, &mp, V_WAIT);
2279 vfs_rel(mp); /* The write holds a ref. */
2280 mtx_unlock(&Giant); /* VFS */
2282 nfsm_srvnamesiz(len);
2284 nd.ni_cnd.cn_cred = cred;
2285 nd.ni_cnd.cn_nameiop = DELETE;
2286 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2287 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2288 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2290 mtx_lock(&Giant); /* VFS */
2296 if (nd.ni_vp->v_type == VDIR) {
2297 error = EPERM; /* POSIX */
2301 * The root of a mounted filesystem cannot be deleted.
2303 if (nd.ni_vp->v_vflag & VV_ROOT) {
2308 NFSD_UNLOCK_ASSERT();
2310 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2311 NDFREE(&nd, NDF_ONLY_PNBUF);
2315 if (dirp == nd.ni_dvp)
2316 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2318 /* Drop the other locks to avoid deadlock. */
2320 if (nd.ni_dvp == nd.ni_vp)
2330 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2331 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2332 VOP_UNLOCK(dirp, 0, td);
2337 mtx_unlock(&Giant); /* VFS */
2341 nfsm_reply(NFSX_WCCDATA(v3));
2343 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2349 mtx_lock(&Giant); /* VFS */
2350 NDFREE(&nd, NDF_ONLY_PNBUF);
2352 if (nd.ni_dvp == nd.ni_vp)
2359 vn_finished_write(mp);
2360 mtx_unlock(&Giant); /* VFS */
2366 * nfs rename service
2369 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2370 struct thread *td, struct mbuf **mrq)
2372 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2373 struct sockaddr *nam = nfsd->nd_nam;
2374 caddr_t dpos = nfsd->nd_dpos;
2375 struct ucred *cred = nfsd->nd_cr;
2377 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2378 int tdirfor_ret = 1, tdiraft_ret = 1;
2379 int v3 = (nfsd->nd_flag & ND_NFSV3);
2380 struct mbuf *mb, *mreq;
2381 struct nameidata fromnd, tond;
2382 struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
2383 struct vnode *tdirp = NULL;
2384 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2386 fhandle_t *ffhp, *tfhp;
2388 struct mount *mp = NULL;
2392 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2396 ffhp = &fnfh.fh_generic;
2397 tfhp = &tnfh.fh_generic;
2400 * Clear fields incase goto nfsmout occurs from macro.
2406 nfsm_srvmtofh(ffhp);
2407 if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
2413 (void) vn_start_write(NULL, &mp, V_WAIT);
2414 vfs_rel(mp); /* The write holds a ref. */
2417 nfsm_srvnamesiz(len);
2419 * Remember our original uid so that we can reset cr_uid before
2420 * the second nfs_namei() call, in case it is remapped.
2422 saved_uid = cred->cr_uid;
2423 fromnd.ni_cnd.cn_cred = cred;
2424 fromnd.ni_cnd.cn_nameiop = DELETE;
2425 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
2426 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
2427 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
2430 mtx_lock(&Giant); /* VFS */
2432 mtx_unlock(&Giant); /* VFS */
2437 nfsm_reply(2 * NFSX_WCCDATA(v3));
2439 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2440 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2446 nfsm_srvmtofh(tfhp);
2447 nfsm_srvnamesiz(len2);
2448 cred->cr_uid = saved_uid;
2449 tond.ni_cnd.cn_cred = cred;
2450 tond.ni_cnd.cn_nameiop = RENAME;
2451 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
2452 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
2453 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
2455 mtx_lock(&Giant); /* VFS */
2461 mtx_unlock(&Giant); /* VFS */
2469 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2475 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2482 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
2490 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
2497 if (fvp->v_mount != tdvp->v_mount) {
2511 * If source is the same as the destination (that is the
2512 * same vnode with the same name in the same directory),
2513 * then there is nothing to do.
2515 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2516 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2517 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2518 fromnd.ni_cnd.cn_namelen))
2521 NFSD_UNLOCK_ASSERT();
2524 * The VOP_RENAME function releases all vnode references &
2525 * locks prior to returning so we need to clear the pointers
2526 * to bypass cleanup code later on.
2528 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2529 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2530 fromnd.ni_dvp = NULL;
2531 fromnd.ni_vp = NULL;
2535 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2536 NDFREE(&tond, NDF_ONLY_PNBUF);
2544 mtx_unlock(&Giant); /* VFS */
2548 nfsm_reply(2 * NFSX_WCCDATA(v3));
2550 /* Release existing locks to prevent deadlock. */
2552 mtx_lock(&Giant); /* VFS */
2554 if (tond.ni_dvp == tond.ni_vp)
2565 vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY, td);
2566 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
2567 VOP_UNLOCK(fdirp, 0, td);
2570 vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY, td);
2571 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
2572 VOP_UNLOCK(tdirp, 0, td);
2574 mtx_unlock(&Giant); /* VFS */
2576 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2577 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2584 * Clear out tond related fields
2588 mtx_lock(&Giant); /* VFS */
2590 if (tond.ni_dvp == tond.ni_vp)
2599 if (tond.ni_startdir)
2600 vrele(tond.ni_startdir);
2601 NDFREE(&tond, NDF_ONLY_PNBUF);
2603 * Clear out fromnd related fields
2607 if (fromnd.ni_startdir)
2608 vrele(fromnd.ni_startdir);
2609 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2611 vrele(fromnd.ni_dvp);
2613 vrele(fromnd.ni_vp);
2615 vn_finished_write(mp);
2616 mtx_unlock(&Giant); /* VFS */
2625 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2626 struct thread *td, struct mbuf **mrq)
2628 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2629 struct sockaddr *nam = nfsd->nd_nam;
2630 caddr_t dpos = nfsd->nd_dpos;
2631 struct ucred *cred = nfsd->nd_cr;
2632 struct nameidata nd;
2634 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2635 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2636 struct mbuf *mb, *mreq;
2637 struct vnode *vp = NULL, *xp, *dirp = NULL;
2638 struct vattr dirfor, diraft, at;
2640 fhandle_t *fhp, *dfhp;
2641 struct mount *mp = NULL;
2645 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2648 fhp = &nfh.fh_generic;
2649 dfhp = &dnfh.fh_generic;
2651 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2656 mtx_lock(&Giant); /* VFS */
2657 (void) vn_start_write(NULL, &mp, V_WAIT);
2658 vfs_rel(mp); /* The write holds a ref. */
2659 mtx_unlock(&Giant); /* VFS */
2661 nfsm_srvmtofh(dfhp);
2662 nfsm_srvnamesiz(len);
2664 error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE);
2666 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2668 nfsm_srvpostop_attr(getret, &at);
2669 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2676 mtx_lock(&Giant); /* VFS */
2678 getret = VOP_GETATTR(vp, &at, cred, td);
2679 if (vp->v_type == VDIR) {
2680 error = EPERM; /* POSIX */
2683 VOP_UNLOCK(vp, 0, td);
2684 nd.ni_cnd.cn_cred = cred;
2685 nd.ni_cnd.cn_nameiop = CREATE;
2686 nd.ni_cnd.cn_flags = LOCKPARENT;
2687 mtx_unlock(&Giant); /* VFS */
2689 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2690 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2692 mtx_lock(&Giant); /* VFS */
2710 if (vp->v_mount != xp->v_mount) {
2716 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2717 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2718 NDFREE(&nd, NDF_ONLY_PNBUF);
2723 getret = VOP_GETATTR(vp, &at, cred, td);
2726 if (dirp == nd.ni_dvp)
2727 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2729 /* Release existing locks to prevent deadlock. */
2731 if (nd.ni_dvp == nd.ni_vp)
2741 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2742 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2743 VOP_UNLOCK(dirp, 0, td);
2746 mtx_unlock(&Giant); /* VFS */
2750 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2752 nfsm_srvpostop_attr(getret, &at);
2753 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2761 mtx_lock(&Giant); /* VFS */
2762 NDFREE(&nd, NDF_ONLY_PNBUF);
2766 if (nd.ni_dvp == nd.ni_vp)
2775 vn_finished_write(mp);
2776 mtx_unlock(&Giant); /* VFS */
2782 * nfs symbolic link service
2785 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2786 struct thread *td, struct mbuf **mrq)
2788 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2789 struct sockaddr *nam = nfsd->nd_nam;
2790 caddr_t dpos = nfsd->nd_dpos;
2791 struct ucred *cred = nfsd->nd_cr;
2792 struct vattr va, dirfor, diraft;
2793 struct nameidata nd;
2794 struct vattr *vap = &va;
2795 struct nfsv2_sattr *sp;
2796 char *bpos, *pathcp = NULL;
2799 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2800 int v3 = (nfsd->nd_flag & ND_NFSV3);
2801 struct mbuf *mb, *mreq;
2802 struct vnode *dirp = NULL;
2805 struct mount *mp = NULL;
2809 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2812 fhp = &nfh.fh_generic;
2814 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2816 mtx_lock(&Giant); /* VFS */
2821 mtx_lock(&Giant); /* VFS */
2822 (void) vn_start_write(NULL, &mp, V_WAIT);
2823 vfs_rel(mp); /* The write holds a ref. */
2824 mtx_unlock(&Giant); /* VFS */
2826 nfsm_srvnamesiz(len);
2827 nd.ni_cnd.cn_cred = cred;
2828 nd.ni_cnd.cn_nameiop = CREATE;
2829 nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
2830 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2831 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2836 nfsm_srvpathsiz(len2);
2839 mtx_lock(&Giant); /* VFS */
2846 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2847 iv.iov_base = pathcp;
2849 io.uio_resid = len2;
2853 io.uio_segflg = UIO_SYSSPACE;
2854 io.uio_rw = UIO_READ;
2856 nfsm_mtouio(&io, len2);
2858 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2859 vap->va_mode = nfstov_mode(sp->sa_mode);
2861 *(pathcp + len2) = '\0';
2868 * issue symlink op. SAVESTART is set so the underlying path component
2869 * is only freed by the VOP if an error occurs.
2871 if (vap->va_mode == (mode_t)VNOVAL)
2873 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2875 NDFREE(&nd, NDF_ONLY_PNBUF);
2880 * releases directory prior to potential lookup op.
2888 * Issue lookup. Leave SAVESTART set so we can easily free
2889 * the name buffer later on.
2891 * since LOCKPARENT is not set, ni_dvp will be garbage on
2892 * return whether an error occurs or not.
2894 nd.ni_cnd.cn_nameiop = LOOKUP;
2895 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2896 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2897 nd.ni_cnd.cn_thread = td;
2898 nd.ni_cnd.cn_cred = cred;
2900 error = lookup(&nd);
2902 if (nd.ni_cnd.cn_flags & GIANTHELD) {
2904 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2908 bzero((caddr_t)fhp, sizeof(nfh));
2909 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2910 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2912 error = VOP_GETATTR(nd.ni_vp, vap, cred,
2920 NFSD_UNLOCK_ASSERT();
2922 * These releases aren't strictly required, does even doing them
2923 * make any sense? XXX can nfsm_reply() block?
2926 FREE(pathcp, M_TEMP);
2930 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2931 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2932 VOP_UNLOCK(dirp, 0, td);
2934 if (nd.ni_startdir) {
2935 vrele(nd.ni_startdir);
2936 nd.ni_startdir = NULL;
2938 mtx_unlock(&Giant); /* VFS */
2940 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2943 nfsm_srvpostop_fh(fhp);
2944 nfsm_srvpostop_attr(0, vap);
2946 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2954 mtx_lock(&Giant); /* VFS */
2955 NDFREE(&nd, NDF_ONLY_PNBUF);
2957 if (nd.ni_dvp == nd.ni_vp)
2965 vrele(nd.ni_startdir);
2969 FREE(pathcp, M_TEMP);
2971 vn_finished_write(mp);
2972 mtx_unlock(&Giant); /* VFS */
2981 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2982 struct thread *td, struct mbuf **mrq)
2984 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2985 struct sockaddr *nam = nfsd->nd_nam;
2986 caddr_t dpos = nfsd->nd_dpos;
2987 struct ucred *cred = nfsd->nd_cr;
2988 struct vattr va, dirfor, diraft;
2989 struct vattr *vap = &va;
2990 struct nfs_fattr *fp;
2991 struct nameidata nd;
2994 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2995 int v3 = (nfsd->nd_flag & ND_NFSV3);
2996 struct mbuf *mb, *mreq;
2997 struct vnode *dirp = NULL;
3001 struct mount *mp = NULL;
3005 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3008 fhp = &nfh.fh_generic;
3010 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3012 mtx_lock(&Giant); /* VFS */
3017 mtx_lock(&Giant); /* VFS */
3018 (void) vn_start_write(NULL, &mp, V_WAIT);
3019 vfs_rel(mp); /* The write holds a ref. */
3020 mtx_unlock(&Giant); /* VFS */
3022 nfsm_srvnamesiz(len);
3023 nd.ni_cnd.cn_cred = cred;
3024 nd.ni_cnd.cn_nameiop = CREATE;
3025 nd.ni_cnd.cn_flags = LOCKPARENT;
3027 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3028 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3031 mtx_lock(&Giant); /* VFS */
3033 mtx_unlock(&Giant); /* VFS */
3038 nfsm_reply(NFSX_WCCDATA(v3));
3040 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3048 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
3049 vap->va_mode = nfstov_mode(*tl++);
3053 * At this point nd.ni_dvp is referenced and exclusively locked and
3054 * nd.ni_vp, if it exists, is referenced but not locked.
3058 mtx_lock(&Giant); /* VFS */
3059 vap->va_type = VDIR;
3060 if (nd.ni_vp != NULL) {
3061 NDFREE(&nd, NDF_ONLY_PNBUF);
3067 * Issue mkdir op. Since SAVESTART is not set, the pathname
3068 * component is freed by the VOP call. This will fill-in
3069 * nd.ni_vp, reference, and exclusively lock it.
3071 if (vap->va_mode == (mode_t)VNOVAL)
3073 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
3074 NDFREE(&nd, NDF_ONLY_PNBUF);
3081 bzero((caddr_t)fhp, sizeof(nfh));
3082 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
3083 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
3085 error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
3088 NFSD_UNLOCK_ASSERT();
3090 if (dirp == nd.ni_dvp) {
3091 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3093 /* Release existing locks to prevent deadlock. */
3095 NDFREE(&nd, NDF_ONLY_PNBUF);
3096 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3109 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3110 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3111 VOP_UNLOCK(dirp, 0, td);
3114 mtx_unlock(&Giant); /* VFS */
3116 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
3119 nfsm_srvpostop_fh(fhp);
3120 nfsm_srvpostop_attr(0, vap);
3122 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3123 } else if (!error) {
3124 /* v2 non-error case. */
3125 nfsm_srvfhtom(fhp, v3);
3126 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
3127 nfsm_srvfillattr(vap, fp);
3135 mtx_lock(&Giant); /* VFS */
3137 NDFREE(&nd, NDF_ONLY_PNBUF);
3138 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3151 vn_finished_write(mp);
3152 mtx_unlock(&Giant); /* VFS */
3161 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3162 struct thread *td, struct mbuf **mrq)
3164 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3165 struct sockaddr *nam = nfsd->nd_nam;
3166 caddr_t dpos = nfsd->nd_dpos;
3167 struct ucred *cred = nfsd->nd_cr;
3169 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
3170 int v3 = (nfsd->nd_flag & ND_NFSV3);
3171 struct mbuf *mb, *mreq;
3172 struct vnode *vp, *dirp = NULL;
3173 struct vattr dirfor, diraft;
3176 struct nameidata nd;
3177 struct mount *mp = NULL;
3181 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3184 fhp = &nfh.fh_generic;
3186 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3191 mtx_lock(&Giant); /* VFS */
3192 (void) vn_start_write(NULL, &mp, V_WAIT);
3193 vfs_rel(mp); /* The write holds a ref. */
3194 mtx_unlock(&Giant); /* VFS */
3196 nfsm_srvnamesiz(len);
3197 nd.ni_cnd.cn_cred = cred;
3198 nd.ni_cnd.cn_nameiop = DELETE;
3199 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
3200 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3201 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3204 mtx_lock(&Giant); /* VFS */
3206 mtx_unlock(&Giant); /* VFS */
3211 nfsm_reply(NFSX_WCCDATA(v3));
3213 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3218 if (vp->v_type != VDIR) {
3223 * No rmdir "." please.
3225 if (nd.ni_dvp == vp) {
3230 * The root of a mounted filesystem cannot be deleted.
3232 if (vp->v_vflag & VV_ROOT)
3236 * Issue or abort op. Since SAVESTART is not set, path name
3237 * component is freed by the VOP after either.
3241 mtx_lock(&Giant); /* VFS */
3243 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3244 NDFREE(&nd, NDF_ONLY_PNBUF);
3247 if (dirp == nd.ni_dvp)
3248 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3250 /* Release existing locks to prevent deadlock. */
3252 if (nd.ni_dvp == nd.ni_vp)
3261 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3262 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3263 VOP_UNLOCK(dirp, 0, td);
3266 mtx_unlock(&Giant); /* VFS */
3268 nfsm_reply(NFSX_WCCDATA(v3));
3271 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3277 mtx_lock(&Giant); /* VFS */
3278 NDFREE(&nd, NDF_ONLY_PNBUF);
3280 if (nd.ni_dvp == nd.ni_vp)
3290 vn_finished_write(mp);
3291 mtx_unlock(&Giant); /* VFS */
3297 * nfs readdir service
3298 * - mallocs what it thinks is enough to read
3299 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
3300 * - calls VOP_READDIR()
3301 * - loops around building the reply
3302 * if the output generated exceeds count break out of loop
3303 * The nfsm_clget macro is used here so that the reply will be packed
3304 * tightly in mbuf clusters.
3305 * - it only knows that it has encountered eof when the VOP_READDIR()
3307 * - as such one readdir rpc will return eof false although you are there
3308 * and then the next will return eof
3309 * - it trims out records with d_fileno == 0
3310 * this doesn't matter for Unix clients, but they might confuse clients
3312 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
3313 * than requested, but this may not apply to all filesystems. For
3314 * example, client NFS does not { although it is never remote mounted
3316 * The alternate call nfsrv_readdirplus() does lookups as well.
3317 * PS: The NFS protocol spec. does not clarify what the "count" byte
3318 * argument is a count of.. just name strings and file id's or the
3319 * entire reply rpc or ...
3320 * I tried just file name and id sizes and it confused the Sun client,
3321 * so I am using the full rpc size now. The "paranoia.." comment refers
3322 * to including the status longwords that are not a part of the dir.
3323 * "entry" structures, but are in the rpc.
3327 u_int32_t fl_postopok;
3328 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
3330 u_int32_t fl_fhsize;
3331 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
3335 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3336 struct thread *td, struct mbuf **mrq)
3338 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3339 struct sockaddr *nam = nfsd->nd_nam;
3340 caddr_t dpos = nfsd->nd_dpos;
3341 struct ucred *cred = nfsd->nd_cr;
3348 struct mbuf *mb, *mreq;
3349 char *cpos, *cend, *rbuf;
3350 struct vnode *vp = NULL;
3356 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3357 int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
3358 int v3 = (nfsd->nd_flag & ND_NFSV3);
3359 u_quad_t off, toff, verf;
3360 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3364 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3365 fhp = &nfh.fh_generic;
3368 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
3369 toff = fxdr_hyper(tl);
3371 verf = fxdr_hyper(tl);
3374 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
3375 toff = fxdr_unsigned(u_quad_t, *tl++);
3376 verf = 0; /* shut up gcc */
3379 cnt = fxdr_unsigned(int, *tl);
3380 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3381 xfer = NFS_SRVMAXDATA(nfsd);
3387 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3388 if (!error && vp->v_type != VDIR) {
3391 mtx_lock(&Giant); /* VFS */
3393 mtx_unlock(&Giant); /* VFS */
3398 nfsm_reply(NFSX_UNSIGNED);
3400 nfsm_srvpostop_attr(getret, &at);
3406 * Obtain lock on vnode for this section of the code
3409 mtx_lock(&Giant); /* VFS */
3411 error = getret = VOP_GETATTR(vp, &at, cred, td);
3414 * XXX This check may be too strict for Solaris 2.5 clients.
3416 if (!error && toff && verf && verf != at.va_filerev)
3417 error = NFSERR_BAD_COOKIE;
3421 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3424 mtx_unlock(&Giant); /* VFS */
3427 nfsm_reply(NFSX_POSTOPATTR(v3));
3429 nfsm_srvpostop_attr(getret, &at);
3433 VOP_UNLOCK(vp, 0, td);
3436 * end section. Allocate rbuf and continue
3438 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3440 NFSD_UNLOCK_ASSERT();
3442 iv.iov_len = fullsiz;
3445 io.uio_offset = (off_t)off;
3446 io.uio_resid = fullsiz;
3447 io.uio_segflg = UIO_SYSSPACE;
3448 io.uio_rw = UIO_READ;
3451 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3453 free((caddr_t)cookies, M_TEMP);
3456 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3457 off = (off_t)io.uio_offset;
3458 if (!cookies && !error)
3459 error = NFSERR_PERM;
3461 getret = VOP_GETATTR(vp, &at, cred, td);
3465 VOP_UNLOCK(vp, 0, td);
3468 mtx_unlock(&Giant); /* VFS */
3470 free((caddr_t)rbuf, M_TEMP);
3472 free((caddr_t)cookies, M_TEMP);
3474 nfsm_reply(NFSX_POSTOPATTR(v3));
3476 nfsm_srvpostop_attr(getret, &at);
3481 siz -= io.uio_resid;
3484 * If nothing read, return eof
3489 mtx_unlock(&Giant); /* VFS */
3492 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
3495 nfsm_srvpostop_attr(getret, &at);
3496 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3497 txdr_hyper(at.va_filerev, tl);
3500 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3501 *tl++ = nfsrv_nfs_false;
3502 *tl = nfsrv_nfs_true;
3503 FREE((caddr_t)rbuf, M_TEMP);
3504 FREE((caddr_t)cookies, M_TEMP);
3511 * Check for degenerate cases of nothing useful read.
3512 * If so go try again
3516 dp = (struct dirent *)cpos;
3519 * For some reason FreeBSD's ufs_readdir() chooses to back the
3520 * directory offset up to a block boundary, so it is necessary to
3521 * skip over the records that precede the requested offset. This
3522 * requires the assumption that file offset cookies monotonically
3525 while (cpos < cend && ncookies > 0 &&
3526 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3527 ((u_quad_t)(*cookiep)) <= toff)) {
3528 cpos += dp->d_reclen;
3529 dp = (struct dirent *)cpos;
3533 if (cpos >= cend || ncookies == 0) {
3539 mtx_unlock(&Giant); /* VFS */
3541 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
3542 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
3544 nfsm_srvpostop_attr(getret, &at);
3545 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3546 txdr_hyper(at.va_filerev, tl);
3550 be = bp + M_TRAILINGSPACE(mp);
3552 /* Loop through the records and build reply */
3553 while (cpos < cend && ncookies > 0) {
3554 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3555 nlen = dp->d_namlen;
3556 rem = nfsm_rndup(nlen) - nlen;
3557 len += (4 * NFSX_UNSIGNED + nlen + rem);
3559 len += 2 * NFSX_UNSIGNED;
3565 * Build the directory record xdr from
3569 *tl = nfsrv_nfs_true;
3570 bp += NFSX_UNSIGNED;
3574 bp += NFSX_UNSIGNED;
3577 *tl = txdr_unsigned(dp->d_fileno);
3578 bp += NFSX_UNSIGNED;
3580 *tl = txdr_unsigned(nlen);
3581 bp += NFSX_UNSIGNED;
3583 /* And loop around copying the name */
3592 bcopy(cp, bp, tsiz);
3598 /* And null pad to an int32_t boundary. */
3599 for (i = 0; i < rem; i++)
3603 /* Finish off the record */
3606 bp += NFSX_UNSIGNED;
3609 *tl = txdr_unsigned(*cookiep);
3610 bp += NFSX_UNSIGNED;
3612 cpos += dp->d_reclen;
3613 dp = (struct dirent *)cpos;
3618 mtx_lock(&Giant); /* VFS */
3620 mtx_unlock(&Giant); /* VFS */
3624 *tl = nfsrv_nfs_false;
3625 bp += NFSX_UNSIGNED;
3628 *tl = nfsrv_nfs_true;
3630 *tl = nfsrv_nfs_false;
3631 bp += NFSX_UNSIGNED;
3634 mp->m_len = bp - mtod(mp, caddr_t);
3636 mp->m_len += bp - bpos;
3637 FREE((caddr_t)rbuf, M_TEMP);
3638 FREE((caddr_t)cookies, M_TEMP);
3644 mtx_lock(&Giant); /* VFS */
3646 mtx_unlock(&Giant); /* VFS */
3653 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3654 struct thread *td, struct mbuf **mrq)
3656 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3657 struct sockaddr *nam = nfsd->nd_nam;
3658 caddr_t dpos = nfsd->nd_dpos;
3659 struct ucred *cred = nfsd->nd_cr;
3666 struct mbuf *mb, *mreq;
3667 char *cpos, *cend, *rbuf;
3668 struct vnode *vp = NULL, *nvp;
3671 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3674 struct vattr va, at, *vap = &va;
3675 struct nfs_fattr *fp;
3676 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3677 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3678 u_quad_t off, toff, verf;
3679 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3680 int v3 = (nfsd->nd_flag & ND_NFSV3);
3684 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3686 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
3687 fhp = &nfh.fh_generic;
3689 tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
3690 toff = fxdr_hyper(tl);
3692 verf = fxdr_hyper(tl);
3694 siz = fxdr_unsigned(int, *tl++);
3695 cnt = fxdr_unsigned(int, *tl);
3697 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3698 xfer = NFS_SRVMAXDATA(nfsd);
3704 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3705 if (!error && vp->v_type != VDIR) {
3708 mtx_lock(&Giant); /* VFS */
3710 mtx_unlock(&Giant); /* VFS */
3715 nfsm_reply(NFSX_UNSIGNED);
3716 nfsm_srvpostop_attr(getret, &at);
3721 mtx_lock(&Giant); /* VFS */
3722 error = getret = VOP_GETATTR(vp, &at, cred, td);
3725 * XXX This check may be too strict for Solaris 2.5 clients.
3727 if (!error && toff && verf && verf != at.va_filerev)
3728 error = NFSERR_BAD_COOKIE;
3731 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3734 mtx_unlock(&Giant); /* VFS */
3737 nfsm_reply(NFSX_V3POSTOPATTR);
3738 nfsm_srvpostop_attr(getret, &at);
3742 VOP_UNLOCK(vp, 0, td);
3743 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3745 NFSD_UNLOCK_ASSERT();
3747 iv.iov_len = fullsiz;
3750 io.uio_offset = (off_t)off;
3751 io.uio_resid = fullsiz;
3752 io.uio_segflg = UIO_SYSSPACE;
3753 io.uio_rw = UIO_READ;
3756 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3758 free((caddr_t)cookies, M_TEMP);
3761 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3762 off = (u_quad_t)io.uio_offset;
3763 getret = VOP_GETATTR(vp, &at, cred, td);
3764 VOP_UNLOCK(vp, 0, td);
3765 if (!cookies && !error)
3766 error = NFSERR_PERM;
3771 mtx_unlock(&Giant); /* VFS */
3774 free((caddr_t)cookies, M_TEMP);
3775 free((caddr_t)rbuf, M_TEMP);
3777 nfsm_reply(NFSX_V3POSTOPATTR);
3778 nfsm_srvpostop_attr(getret, &at);
3783 siz -= io.uio_resid;
3786 * If nothing read, return eof
3791 mtx_unlock(&Giant); /* VFS */
3794 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3796 nfsm_srvpostop_attr(getret, &at);
3797 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3798 txdr_hyper(at.va_filerev, tl);
3800 *tl++ = nfsrv_nfs_false;
3801 *tl = nfsrv_nfs_true;
3802 FREE((caddr_t)cookies, M_TEMP);
3803 FREE((caddr_t)rbuf, M_TEMP);
3810 * Check for degenerate cases of nothing useful read.
3811 * If so go try again
3815 dp = (struct dirent *)cpos;
3818 * For some reason FreeBSD's ufs_readdir() chooses to back the
3819 * directory offset up to a block boundary, so it is necessary to
3820 * skip over the records that precede the requested offset. This
3821 * requires the assumption that file offset cookies monotonically
3824 while (cpos < cend && ncookies > 0 &&
3825 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3826 ((u_quad_t)(*cookiep)) <= toff)) {
3827 cpos += dp->d_reclen;
3828 dp = (struct dirent *)cpos;
3832 if (cpos >= cend || ncookies == 0) {
3839 * Probe one of the directory entries to see if the filesystem
3842 if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
3844 error = NFSERR_NOTSUPP;
3846 mtx_unlock(&Giant); /* VFS */
3848 free((caddr_t)cookies, M_TEMP);
3849 free((caddr_t)rbuf, M_TEMP);
3851 nfsm_reply(NFSX_V3POSTOPATTR);
3852 nfsm_srvpostop_attr(getret, &at);
3857 mtx_unlock(&Giant); /* VFS */
3860 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3864 nfsm_srvpostop_attr(getret, &at);
3865 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3866 txdr_hyper(at.va_filerev, tl);
3869 be = bp + M_TRAILINGSPACE(mp);
3872 mtx_lock(&Giant); /* VFS */
3873 /* Loop through the records and build reply */
3874 while (cpos < cend && ncookies > 0) {
3875 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3876 nlen = dp->d_namlen;
3877 rem = nfsm_rndup(nlen)-nlen;
3880 * For readdir_and_lookup get the vnode using
3883 if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
3886 bzero((caddr_t)nfhp, NFSX_V3FH);
3888 nvp->v_mount->mnt_stat.f_fsid;
3889 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3894 if (VOP_GETATTR(nvp, vap, cred, td)) {
3903 * If either the dircount or maxcount will be
3904 * exceeded, get out now. Both of these lengths
3905 * are calculated conservatively, including all
3908 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3910 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3911 if (len > cnt || dirlen > fullsiz) {
3917 * Build the directory record xdr from
3920 fp = (struct nfs_fattr *)&fl.fl_fattr;
3921 nfsm_srvfillattr(vap, fp);
3922 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3923 fl.fl_fhok = nfsrv_nfs_true;
3924 fl.fl_postopok = nfsrv_nfs_true;
3925 fl.fl_off.nfsuquad[0] = 0;
3926 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3929 *tl = nfsrv_nfs_true;
3930 bp += NFSX_UNSIGNED;
3933 bp += NFSX_UNSIGNED;
3935 *tl = txdr_unsigned(dp->d_fileno);
3936 bp += NFSX_UNSIGNED;
3938 *tl = txdr_unsigned(nlen);
3939 bp += NFSX_UNSIGNED;
3941 /* And loop around copying the name */
3946 if ((bp + xfer) > be)
3950 bcopy(cp, bp, tsiz);
3956 /* And null pad to an int32_t boundary. */
3957 for (i = 0; i < rem; i++)
3961 * Now copy the flrep structure out.
3963 xfer = sizeof (struct flrep);
3967 if ((bp + xfer) > be)
3971 bcopy(cp, bp, tsiz);
3979 NFSD_UNLOCK_ASSERT();
3980 cpos += dp->d_reclen;
3981 dp = (struct dirent *)cpos;
3986 mtx_unlock(&Giant); /* VFS */
3989 *tl = nfsrv_nfs_false;
3990 bp += NFSX_UNSIGNED;
3994 *tl = nfsrv_nfs_true;
3996 *tl = nfsrv_nfs_false;
3997 bp += NFSX_UNSIGNED;
4000 mp->m_len = bp - mtod(mp, caddr_t);
4002 mp->m_len += bp - bpos;
4003 FREE((caddr_t)cookies, M_TEMP);
4004 FREE((caddr_t)rbuf, M_TEMP);
4009 mtx_lock(&Giant); /* VFS */
4011 mtx_unlock(&Giant); /* VFS */
4018 * nfs commit service
4021 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4022 struct thread *td, struct mbuf **mrq)
4024 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4025 struct sockaddr *nam = nfsd->nd_nam;
4026 caddr_t dpos = nfsd->nd_dpos;
4027 struct ucred *cred = nfsd->nd_cr;
4028 struct vattr bfor, aft;
4029 struct vnode *vp = NULL;
4034 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
4035 struct mbuf *mb, *mreq;
4037 struct mount *mp = NULL;
4038 int v3 = (nfsd->nd_flag & ND_NFSV3);
4042 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4044 panic("nfsrv_commit: v3 proc called on a v2 connection");
4045 fhp = &nfh.fh_generic;
4047 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
4052 mtx_lock(&Giant); /* VFS */
4053 (void) vn_start_write(NULL, &mp, V_WAIT);
4054 vfs_rel(mp); /* The write holds a ref. */
4055 mtx_unlock(&Giant); /* VFS */
4057 tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
4060 * XXX At this time VOP_FSYNC() does not accept offset and byte
4061 * count parameters, so these arguments are useless (someday maybe).
4063 off = fxdr_hyper(tl);
4065 cnt = fxdr_unsigned(int, *tl);
4066 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4068 nfsm_reply(2 * NFSX_UNSIGNED);
4069 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4074 mtx_lock(&Giant); /* VFS */
4075 for_ret = VOP_GETATTR(vp, &bfor, cred, td);
4077 if (cnt > MAX_COMMIT_COUNT) {
4079 * Give up and do the whole thing
4082 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4083 VM_OBJECT_LOCK(vp->v_object);
4084 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
4085 VM_OBJECT_UNLOCK(vp->v_object);
4087 error = VOP_FSYNC(vp, MNT_WAIT, td);
4090 * Locate and synchronously write any buffers that fall
4091 * into the requested range. Note: we are assuming that
4092 * f_iosize is a power of 2.
4094 int iosize = vp->v_mount->mnt_stat.f_iosize;
4095 int iomask = iosize - 1;
4100 * Align to iosize boundry, super-align to page boundry.
4103 cnt += off & iomask;
4104 off &= ~(u_quad_t)iomask;
4106 if (off & PAGE_MASK) {
4107 cnt += off & PAGE_MASK;
4108 off &= ~(u_quad_t)PAGE_MASK;
4110 lblkno = off / iosize;
4113 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4114 VM_OBJECT_LOCK(vp->v_object);
4115 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
4116 VM_OBJECT_UNLOCK(vp->v_object);
4125 * If we have a buffer and it is marked B_DELWRI we
4126 * have to lock and write it. Otherwise the prior
4127 * write is assumed to have already been committed.
4129 * gbincore() can return invalid buffers now so we
4130 * have to check that bit as well (though B_DELWRI
4131 * should not be set if B_INVAL is set there could be
4132 * a race here since we haven't locked the buffer).
4134 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
4135 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
4136 LK_INTERLOCK, VI_MTX(vp)) == ENOLCK) {
4138 continue; /* retry */
4140 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
4143 bp->b_flags &= ~B_ASYNC;
4160 aft_ret = VOP_GETATTR(vp, &aft, cred, td);
4162 mtx_unlock(&Giant); /* VFS */
4167 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
4168 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4170 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
4171 if (nfsver.tv_sec == 0)
4173 *tl++ = txdr_unsigned(nfsver.tv_sec);
4174 *tl = txdr_unsigned(nfsver.tv_usec);
4181 mtx_lock(&Giant); /* VFS */
4184 vn_finished_write(mp);
4185 mtx_unlock(&Giant); /* VFS */
4191 * nfs statfs service
4194 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4195 struct thread *td, struct mbuf **mrq)
4197 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4198 struct sockaddr *nam = nfsd->nd_nam;
4199 caddr_t dpos = nfsd->nd_dpos;
4200 struct ucred *cred = nfsd->nd_cr;
4202 struct nfs_statfs *sfp;
4204 int error = 0, rdonly, getret = 1;
4205 int v3 = (nfsd->nd_flag & ND_NFSV3);
4206 struct mbuf *mb, *mreq;
4207 struct vnode *vp = NULL;
4211 struct statfs statfs;
4216 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4217 fhp = &nfh.fh_generic;
4219 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4221 nfsm_reply(NFSX_UNSIGNED);
4223 nfsm_srvpostop_attr(getret, &at);
4229 mtx_lock(&Giant); /* VFS */
4230 error = VFS_STATFS(vp->v_mount, sf, td);
4231 getret = VOP_GETATTR(vp, &at, cred, td);
4233 mtx_unlock(&Giant); /* VFS */
4236 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
4238 nfsm_srvpostop_attr(getret, &at);
4243 sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
4245 tval = (u_quad_t)sf->f_blocks;
4246 tval *= (u_quad_t)sf->f_bsize;
4247 txdr_hyper(tval, &sfp->sf_tbytes);
4248 tval = (u_quad_t)sf->f_bfree;
4249 tval *= (u_quad_t)sf->f_bsize;
4250 txdr_hyper(tval, &sfp->sf_fbytes);
4252 * Don't send negative values for available space,
4253 * since this field is unsigned in the NFS protocol.
4254 * Otherwise, the client would see absurdly high
4255 * numbers for free space.
4257 if (sf->f_bavail < 0)
4260 tval = (u_quad_t)sf->f_bavail;
4261 tval *= (u_quad_t)sf->f_bsize;
4262 txdr_hyper(tval, &sfp->sf_abytes);
4263 sfp->sf_tfiles.nfsuquad[0] = 0;
4264 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
4265 sfp->sf_ffiles.nfsuquad[0] = 0;
4266 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4267 sfp->sf_afiles.nfsuquad[0] = 0;
4268 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4269 sfp->sf_invarsec = 0;
4271 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
4272 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
4273 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
4274 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
4275 if (sf->f_bavail < 0)
4278 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
4284 mtx_lock(&Giant); /* VFS */
4286 mtx_unlock(&Giant); /* VFS */
4293 * nfs fsinfo service
4296 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4297 struct thread *td, struct mbuf **mrq)
4299 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4300 struct sockaddr *nam = nfsd->nd_nam;
4301 caddr_t dpos = nfsd->nd_dpos;
4302 struct ucred *cred = nfsd->nd_cr;
4303 struct nfsv3_fsinfo *sip;
4305 int error = 0, rdonly, getret = 1, pref;
4306 struct mbuf *mb, *mreq;
4307 struct vnode *vp = NULL;
4313 int v3 = (nfsd->nd_flag & ND_NFSV3);
4317 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4319 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
4320 fhp = &nfh.fh_generic;
4322 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4324 nfsm_reply(NFSX_UNSIGNED);
4325 nfsm_srvpostop_attr(getret, &at);
4331 mtx_lock(&Giant); /* VFS */
4332 /* XXX Try to make a guess on the max file size. */
4333 VFS_STATFS(vp->v_mount, &sb, td);
4334 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
4336 getret = VOP_GETATTR(vp, &at, cred, td);
4338 mtx_unlock(&Giant); /* VFS */
4341 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
4342 nfsm_srvpostop_attr(getret, &at);
4343 sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
4347 * There should be filesystem VFS OP(s) to get this information.
4348 * For now, assume ufs.
4350 if (slp->ns_so->so_type == SOCK_DGRAM)
4351 pref = NFS_MAXDGRAMDATA;
4354 sip->fs_rtmax = txdr_unsigned(pref);
4355 sip->fs_rtpref = txdr_unsigned(pref);
4356 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
4357 sip->fs_wtmax = txdr_unsigned(pref);
4358 sip->fs_wtpref = txdr_unsigned(pref);
4359 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
4360 sip->fs_dtpref = txdr_unsigned(pref);
4361 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
4362 sip->fs_timedelta.nfsv3_sec = 0;
4363 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
4364 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
4365 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
4366 NFSV3FSINFO_CANSETTIME);
4371 mtx_lock(&Giant); /* VFS */
4373 mtx_unlock(&Giant); /* VFS */
4380 * nfs pathconf service
4383 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4384 struct thread *td, struct mbuf **mrq)
4386 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4387 struct sockaddr *nam = nfsd->nd_nam;
4388 caddr_t dpos = nfsd->nd_dpos;
4389 struct ucred *cred = nfsd->nd_cr;
4390 struct nfsv3_pathconf *pc;
4392 int error = 0, rdonly, getret = 1;
4393 register_t linkmax, namemax, chownres, notrunc;
4394 struct mbuf *mb, *mreq;
4395 struct vnode *vp = NULL;
4399 int v3 = (nfsd->nd_flag & ND_NFSV3);
4403 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4405 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
4406 fhp = &nfh.fh_generic;
4408 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4410 nfsm_reply(NFSX_UNSIGNED);
4411 nfsm_srvpostop_attr(getret, &at);
4416 mtx_lock(&Giant); /* VFS */
4417 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
4419 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
4421 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
4423 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
4424 getret = VOP_GETATTR(vp, &at, cred, td);
4426 mtx_unlock(&Giant); /* VFS */
4429 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
4430 nfsm_srvpostop_attr(getret, &at);
4435 pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
4437 pc->pc_linkmax = txdr_unsigned(linkmax);
4438 pc->pc_namemax = txdr_unsigned(namemax);
4439 pc->pc_notrunc = txdr_unsigned(notrunc);
4440 pc->pc_chownrestricted = txdr_unsigned(chownres);
4443 * These should probably be supported by VOP_PATHCONF(), but
4444 * until msdosfs is exportable (why would you want to?), the
4445 * Unix defaults should be ok.
4447 pc->pc_caseinsensitive = nfsrv_nfs_false;
4448 pc->pc_casepreserving = nfsrv_nfs_true;
4453 mtx_lock(&Giant); /* VFS */
4455 mtx_unlock(&Giant); /* VFS */
4462 * Null operation, used by clients to ping server
4466 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4467 struct thread *td, struct mbuf **mrq)
4469 struct mbuf *mrep = nfsd->nd_mrep;
4471 int error = NFSERR_RETVOID;
4472 struct mbuf *mb, *mreq;
4476 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4484 * No operation, used for obsolete procedures
4488 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4489 struct thread *td, struct mbuf **mrq)
4491 struct mbuf *mrep = nfsd->nd_mrep;
4494 struct mbuf *mb, *mreq;
4498 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4499 if (nfsd->nd_repstat)
4500 error = nfsd->nd_repstat;
4502 error = EPROCUNAVAIL;
4511 * Perform access checking for vnodes obtained from file handles that would
4512 * refer to files already opened by a Unix client. You cannot just use
4513 * vn_writechk() and VOP_ACCESS() for two reasons.
4514 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
4516 * 2 - The owner is to be given access irrespective of mode bits for some
4517 * operations, so that processes that chmod after opening a file don't
4518 * break. I don't like this because it opens a security hole, but since
4519 * the nfs server opens a security hole the size of a barn door anyhow,
4522 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
4523 * will return EPERM instead of EACCESS. EPERM is always an error.
4525 * There are two versions: one to be called while holding Giant (which is
4526 * needed due to use of VFS), and the other called with the NFS server lock
4527 * (which will be dropped and reacquired). This is necessary because
4528 * nfsrv_access checks are required from both classes of contexts.
4531 nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred,
4532 int rdonly, struct thread *td, int override)
4539 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4541 if (flags & VWRITE) {
4542 /* Just vn_writechk() changed to check rdonly */
4544 * Disallow write attempts on read-only filesystems;
4545 * unless the file is a socket or a block or character
4546 * device resident on the filesystem.
4548 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
4549 switch (vp->v_type) {
4559 * If there's shared text associated with
4560 * the inode, we can't allow writing.
4562 if (vp->v_vflag & VV_TEXT)
4566 error = VOP_GETATTR(vp, &vattr, cred, td);
4569 error = VOP_ACCESS(vp, flags, cred, td);
4571 * Allow certain operations for the owner (reads and writes
4572 * on files that are already open).
4574 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
4580 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
4581 struct thread *td, int override)
4588 mtx_lock(&Giant); /* VFS */
4589 error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override);
4590 mtx_unlock(&Giant); /* VFS */