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 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
37 * $FreeBSD: src/sys/nfs/nfs_serv.c,v 1.93.2.6 2002/12/29 18:19:53 dillon Exp $
41 * nfs version 2 and 3 server calls to vnode ops
42 * - these routines generally have 3 phases
43 * 1 - break down and validate rpc request in mbuf list
44 * 2 - do the vnode ops for the request
45 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
46 * 3 - build the rpc reply in an mbuf list
48 * - do not mix the phases, since the nfsm_?? macros can return failures
49 * on a bad rpc or similar and do not do any vrele() or vput()'s
51 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
52 * error number iff error != 0 whereas
53 * returning an error from the server function implies a fatal error
54 * such as a badly constructed rpc request that should be dropped without
56 * For Version 3, nfsm_reply() does not return for the error case, since
57 * most version 3 rpcs return more than the status for error cases.
60 * Warning: always pay careful attention to resource cleanup on return
61 * and note that nfsm_*() macros can terminate a procedure on certain
65 #include <sys/param.h>
66 #include <sys/systm.h>
69 #include <sys/nlookup.h>
70 #include <sys/namei.h>
71 #include <sys/unistd.h>
72 #include <sys/vnode.h>
73 #include <sys/mount.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/malloc.h>
78 #include <sys/dirent.h>
80 #include <sys/kernel.h>
81 #include <sys/sysctl.h>
85 #include <vm/vm_extern.h>
86 #include <vm/vm_object.h>
90 #include <sys/thread2.h>
96 #include "nfsm_subs.h"
99 #define nfsdbprintf(info) kprintf info
101 #define nfsdbprintf(info)
104 #define MAX_COMMIT_COUNT (1024 * 1024)
106 #define NUM_HEURISTIC 1031
107 #define NHUSE_INIT 64
109 #define NHUSE_MAX 2048
111 static struct nfsheur {
112 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
113 off_t nh_nextoff; /* next offset for sequential detection */
114 int nh_use; /* use count for selection */
115 int nh_seqcount; /* heuristic */
116 } nfsheur[NUM_HEURISTIC];
118 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK,
121 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON,
124 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
125 int nfsrvw_procrastinate_v3 = 0;
127 static struct timespec nfsver;
129 SYSCTL_DECL(_vfs_nfs);
132 SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0,
133 "Enable unstable and fast writes");
134 static int nfs_commit_blks;
135 static int nfs_commit_miss;
136 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0,
137 "Number of committed blocks");
138 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0,
139 "Number of nfs blocks committed from dirty buffers");
141 static int nfsrv_access (struct mount *, struct vnode *, int,
142 struct ucred *, int, struct thread *, int);
143 static void nfsrvw_coalesce (struct nfsrv_descript *,
144 struct nfsrv_descript *);
147 * Heuristic to detect sequential operation.
149 static struct nfsheur *
150 nfsrv_sequential_heuristic(struct uio *uio, struct vnode *vp, int writeop)
155 /* Locate best candidate */
157 hi = ((int)(vm_offset_t) vp / sizeof(struct vnode)) % NUM_HEURISTIC;
161 if (nfsheur[hi].nh_vp == vp) {
165 if (nfsheur[hi].nh_use > 0)
166 --nfsheur[hi].nh_use;
167 hi = (hi + 1) % NUM_HEURISTIC;
168 if (nfsheur[hi].nh_use < nh->nh_use)
172 /* Initialize hint if this is a new file */
173 if (nh->nh_vp != vp) {
175 nh->nh_nextoff = uio->uio_offset;
176 nh->nh_use = NHUSE_INIT;
177 if (uio->uio_offset == 0)
184 * Calculate heuristic
186 * See vfs_vnops.c:sequential_heuristic().
188 if ((uio->uio_offset == 0 && nh->nh_seqcount > 0) ||
189 uio->uio_offset == nh->nh_nextoff) {
190 nh->nh_seqcount += howmany(uio->uio_resid, 16384);
191 if (nh->nh_seqcount > IO_SEQMAX)
192 nh->nh_seqcount = IO_SEQMAX;
193 } else if (nh->nh_seqcount > 1) {
198 nh->nh_use += NHUSE_INC;
199 if (nh->nh_use > NHUSE_MAX)
200 nh->nh_use = NHUSE_MAX;
205 * nfs v3 access service
208 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
209 struct thread *td, struct mbuf **mrq)
211 struct sockaddr *nam = nfsd->nd_nam;
212 struct ucred *cred = &nfsd->nd_cr;
213 struct vnode *vp = NULL;
214 struct mount *mp = NULL;
217 int error = 0, rdonly, getret;
218 struct vattr vattr, *vap = &vattr;
219 u_long testmode, nfsmode;
220 struct nfsm_info info;
223 info.dpos = nfsd->nd_dpos;
224 info.md = nfsd->nd_md;
225 info.mrep = nfsd->nd_mrep;
228 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
229 fhp = &nfh.fh_generic;
230 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
231 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
232 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, &rdonly,
233 (nfsd->nd_flag & ND_KERBAUTH), TRUE);
235 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
236 nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
240 nfsmode = fxdr_unsigned(u_int32_t, *tl);
241 if ((nfsmode & NFSV3ACCESS_READ) &&
242 nfsrv_access(mp, vp, VREAD, cred, rdonly, td, 0))
243 nfsmode &= ~NFSV3ACCESS_READ;
244 if (vp->v_type == VDIR)
245 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
248 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
249 if ((nfsmode & testmode) &&
250 nfsrv_access(mp, vp, VWRITE, cred, rdonly, td, 0))
251 nfsmode &= ~testmode;
252 if (vp->v_type == VDIR)
253 testmode = NFSV3ACCESS_LOOKUP;
255 testmode = NFSV3ACCESS_EXECUTE;
256 if ((nfsmode & testmode) &&
257 nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 0))
258 nfsmode &= ~testmode;
259 getret = VOP_GETATTR(vp, vap);
262 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
263 NFSX_POSTOPATTR(1) + NFSX_UNSIGNED, &error));
264 nfsm_srvpostop_attr(&info, nfsd, getret, vap);
265 tl = nfsm_build(&info, NFSX_UNSIGNED);
266 *tl = txdr_unsigned(nfsmode);
275 * nfs getattr service
278 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
279 struct thread *td, struct mbuf **mrq)
281 struct sockaddr *nam = nfsd->nd_nam;
282 struct ucred *cred = &nfsd->nd_cr;
283 struct nfs_fattr *fp;
285 struct vattr *vap = &va;
286 struct vnode *vp = NULL;
287 struct mount *mp = NULL;
290 int error = 0, rdonly;
291 struct nfsm_info info;
293 info.mrep = nfsd->nd_mrep;
294 info.md = nfsd->nd_md;
295 info.dpos = nfsd->nd_dpos;
298 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
299 fhp = &nfh.fh_generic;
300 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
301 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
302 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
304 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
308 error = VOP_GETATTR(vp, vap);
311 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
312 NFSX_FATTR(nfsd->nd_flag & ND_NFSV3), &error));
317 fp = nfsm_build(&info, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
318 nfsm_srvfattr(nfsd, vap, fp);
329 * nfs setattr service
332 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
333 struct thread *td, struct mbuf **mrq)
335 struct sockaddr *nam = nfsd->nd_nam;
336 struct ucred *cred = &nfsd->nd_cr;
337 struct vattr va, preat;
338 struct vattr *vap = &va;
339 struct nfsv2_sattr *sp;
340 struct nfs_fattr *fp;
341 struct vnode *vp = NULL;
342 struct mount *mp = NULL;
346 int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
348 struct timespec guard;
349 struct nfsm_info info;
351 info.mrep = nfsd->nd_mrep;
353 info.md = nfsd->nd_md;
354 info.dpos = nfsd->nd_dpos;
355 info.v3 = (nfsd->nd_flag & ND_NFSV3);
357 guard.tv_sec = 0; /* fix compiler warning */
360 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
361 fhp = &nfh.fh_generic;
362 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
365 ERROROUT(nfsm_srvsattr(&info, vap));
366 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
367 gcheck = fxdr_unsigned(int, *tl);
369 NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
370 fxdr_nfsv3time(tl, &guard);
373 NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
375 * Nah nah nah nah na nah
376 * There is a bug in the Sun client that puts 0xffff in the mode
377 * field of sattr when it should put in 0xffffffff. The u_short
378 * doesn't sign extend.
379 * --> check the low order 2 bytes for 0xffff
381 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
382 vap->va_mode = nfstov_mode(sp->sa_mode);
383 if (sp->sa_uid != nfs_xdrneg1)
384 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
385 if (sp->sa_gid != nfs_xdrneg1)
386 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
387 if (sp->sa_size != nfs_xdrneg1)
388 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
389 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
391 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
393 vap->va_atime.tv_sec =
394 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
395 vap->va_atime.tv_nsec = 0;
398 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
399 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
404 * Now that we have all the fields, lets do it.
406 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, &rdonly,
407 (nfsd->nd_flag & ND_KERBAUTH), TRUE);
409 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
410 2 * NFSX_UNSIGNED, &error));
411 nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
418 * vp now an active resource, pay careful attention to cleanup
422 error = preat_ret = VOP_GETATTR(vp, &preat);
423 if (!error && gcheck &&
424 (preat.va_ctime.tv_sec != guard.tv_sec ||
425 preat.va_ctime.tv_nsec != guard.tv_nsec))
426 error = NFSERR_NOT_SYNC;
430 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
431 NFSX_WCCDATA(info.v3), &error));
432 nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
440 * If the size is being changed write acces is required, otherwise
441 * just check for a read only file system.
443 if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
444 if (rdonly || (mp->mnt_flag & MNT_RDONLY)) {
449 if (vp->v_type == VDIR) {
452 } else if ((error = nfsrv_access(mp, vp, VWRITE, cred, rdonly,
457 error = VOP_SETATTR(vp, vap, cred);
458 postat_ret = VOP_GETATTR(vp, vap);
464 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
465 NFSX_WCCORFATTR(info.v3), &error));
467 nfsm_srvwcc_data(&info, nfsd, preat_ret, &preat,
472 fp = nfsm_build(&info, NFSX_V2FATTR);
473 nfsm_srvfattr(nfsd, vap, fp);
488 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
489 struct thread *td, struct mbuf **mrq)
491 struct sockaddr *nam = nfsd->nd_nam;
492 struct ucred *cred = &nfsd->nd_cr;
493 struct nfs_fattr *fp;
494 struct nlookupdata nd;
500 int error = 0, len, dirattr_ret = 1;
502 struct vattr va, dirattr, *vap = &va;
503 struct nfsm_info info;
505 info.mrep = nfsd->nd_mrep;
507 info.md = nfsd->nd_md;
508 info.dpos = nfsd->nd_dpos;
509 info.v3 = (nfsd->nd_flag & ND_NFSV3);
511 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
516 fhp = &nfh.fh_generic;
517 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
518 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
520 pubflag = nfs_ispublicfh(fhp);
522 error = nfs_namei(&nd, cred, 0, NULL, &vp,
523 fhp, len, slp, nam, &info.md, &info.dpos,
524 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
527 * namei failure, only dirp to cleanup. Clear out garbarge from
528 * structure in case macros jump to nfsmout.
534 dirattr_ret = VOP_GETATTR(dirp, &dirattr);
538 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
539 NFSX_POSTOPATTR(info.v3), &error));
540 nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
546 * Locate index file for public filehandle
548 * error is 0 on entry and 0 on exit from this block.
552 if (vp->v_type == VDIR && nfs_pub.np_index != NULL) {
554 * Setup call to lookup() to see if we can find
555 * the index file. Arguably, this doesn't belong
556 * in a kernel.. Ugh. If an error occurs, do not
557 * try to install an index file and then clear the
560 * When we replace nd with ind and redirect ndp,
561 * maintenance of ni_startdir and ni_vp shift to
562 * ind and we have to clean them up in the old nd.
563 * However, the cnd resource continues to be maintained
564 * via the original nd. Confused? You aren't alone!
567 cache_copy(&nd.nl_nch, &nch);
569 error = nlookup_init_raw(&nd, nfs_pub.np_index,
570 UIO_SYSSPACE, 0, cred, &nch);
573 error = nlookup(&nd);
577 * Found an index file. Get rid of
578 * the old references. transfer vp and
579 * load up the new vp. Fortunately we do
580 * not have to deal with dvp, that would be
587 error = cache_vget(&nd.nl_nch, nd.nl_cred,
589 KKASSERT(error == 0);
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 (vp->v_mount != nfs_pub.np_mount) {
609 dirattr_ret = VOP_GETATTR(dirp, &dirattr);
615 * Resources at this point:
616 * ndp->ni_vp may not be NULL
621 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
622 NFSX_POSTOPATTR(info.v3), &error));
623 nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
629 * Clear out some resources prior to potentially blocking. This
630 * is not as critical as ni_dvp resources in other routines, but
636 * Get underlying attribute, then release remaining resources ( for
637 * the same potential blocking reason ) and reply.
639 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid));
640 error = VFS_VPTOFH(vp, &fhp->fh_fid);
642 error = VOP_GETATTR(vp, vap);
646 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
647 NFSX_SRVFH(info.v3) +
648 NFSX_POSTOPORFATTR(info.v3) +
649 NFSX_POSTOPATTR(info.v3),
652 nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
656 nfsm_srvfhtom(&info, fhp);
658 nfsm_srvpostop_attr(&info, nfsd, 0, vap);
659 nfsm_srvpostop_attr(&info, nfsd, dirattr_ret, &dirattr);
661 fp = nfsm_build(&info, NFSX_V2FATTR);
662 nfsm_srvfattr(nfsd, vap, fp);
669 nlookup_done(&nd); /* may be called twice */
676 * nfs readlink service
679 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
680 struct thread *td, struct mbuf **mrq)
682 struct sockaddr *nam = nfsd->nd_nam;
683 struct ucred *cred = &nfsd->nd_cr;
684 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
685 struct iovec *ivp = iv;
687 int error = 0, rdonly, i, tlen, len, getret;
688 struct mbuf *mp1, *mp2, *mp3;
689 struct vnode *vp = NULL;
690 struct mount *mp = NULL;
694 struct uio io, *uiop = &io;
695 struct nfsm_info info;
697 info.mrep = nfsd->nd_mrep;
699 info.md = nfsd->nd_md;
700 info.dpos = nfsd->nd_dpos;
701 info.v3 = (nfsd->nd_flag & ND_NFSV3);
703 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
708 fhp = &nfh.fh_generic;
709 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
712 while (len < NFS_MAXPATHLEN) {
713 mp1 = m_getcl(MB_WAIT, MT_DATA, 0);
714 mp1->m_len = MCLBYTES;
721 if ((len + mp1->m_len) > NFS_MAXPATHLEN) {
722 mp1->m_len = NFS_MAXPATHLEN-len;
723 len = NFS_MAXPATHLEN;
726 ivp->iov_base = mtod(mp1, caddr_t);
727 ivp->iov_len = mp1->m_len;
732 uiop->uio_iovcnt = i;
733 uiop->uio_offset = 0;
734 uiop->uio_resid = len;
735 uiop->uio_rw = UIO_READ;
736 uiop->uio_segflg = UIO_SYSSPACE;
738 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
739 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
741 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
742 2 * NFSX_UNSIGNED, &error));
743 nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
747 if (vp->v_type != VLNK) {
754 error = VOP_READLINK(vp, uiop, cred);
756 getret = VOP_GETATTR(vp, &attr);
759 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
760 NFSX_POSTOPATTR(info.v3) + NFSX_UNSIGNED,
763 nfsm_srvpostop_attr(&info, nfsd, 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(&info, NFSX_UNSIGNED);
775 *tl = txdr_unsigned(len);
776 info.mb->m_next = mp3;
791 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
792 struct thread *td, struct mbuf **mrq)
794 struct nfsm_info info;
795 struct sockaddr *nam = nfsd->nd_nam;
796 struct ucred *cred = &nfsd->nd_cr;
800 struct nfs_fattr *fp;
804 int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
806 struct vnode *vp = NULL;
807 struct mount *mp = NULL;
810 struct uio io, *uiop = &io;
811 struct vattr va, *vap = &va;
816 info.mrep = nfsd->nd_mrep;
818 info.md = nfsd->nd_md;
819 info.dpos = nfsd->nd_dpos;
820 info.v3 = (nfsd->nd_flag & ND_NFSV3);
822 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
823 fhp = &nfh.fh_generic;
824 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
826 NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
827 off = fxdr_hyper(tl);
829 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
830 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
832 NEGREPLYOUT(reqlen = nfsm_srvstrsiz(&info,
833 NFS_SRVMAXDATA(nfsd), &error));
836 * Reference vp. If an error occurs, vp will be invalid, but we
837 * have to NULL it just in case. The macros might goto nfsmout
841 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
842 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
845 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
846 2 * NFSX_UNSIGNED, &error));
847 nfsm_srvpostop_attr(&info, nfsd, 1, NULL);
852 if (vp->v_type != VREG) {
856 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
859 if ((error = nfsrv_access(mp, vp, VREAD, cred, rdonly, td, 1)) != 0)
860 error = nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 1);
862 getret = VOP_GETATTR(vp, vap);
868 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
869 NFSX_POSTOPATTR(info.v3), &error));
870 nfsm_srvpostop_attr(&info, nfsd, getret, vap);
876 * Calculate byte count to read
879 if (off >= vap->va_size)
881 else if ((off + reqlen) > vap->va_size)
882 cnt = vap->va_size - off;
886 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
887 NFSX_POSTOPORFATTR(info.v3) +
888 3 * NFSX_UNSIGNED + nfsm_rndup(cnt),
891 tl = nfsm_build(&info, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
893 fp = (struct nfs_fattr *)tl;
894 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
896 tl = nfsm_build(&info, NFSX_V2FATTR + NFSX_UNSIGNED);
897 fp = (struct nfs_fattr *)tl;
898 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
900 len = left = nfsm_rndup(cnt);
903 * Generate the mbuf list with the uio_iov ref. to it.
908 siz = min(M_TRAILINGSPACE(m), left);
914 m = m_getcl(MB_WAIT, MT_DATA, 0);
920 iv = kmalloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
921 uiop->uio_iov = iv2 = iv;
927 panic("nfsrv_read iov");
928 siz = min(M_TRAILINGSPACE(m), left);
930 iv->iov_base = mtod(m, caddr_t) + m->m_len;
939 uiop->uio_iovcnt = i;
940 uiop->uio_offset = off;
941 uiop->uio_resid = len;
942 uiop->uio_rw = UIO_READ;
943 uiop->uio_segflg = UIO_SYSSPACE;
944 nh = nfsrv_sequential_heuristic(uiop, vp, 0);
945 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
946 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
948 off = uiop->uio_offset;
949 nh->nh_nextoff = off;
951 kfree((caddr_t)iv2, M_TEMP);
952 if (error || (getret = VOP_GETATTR(vp, vap))) {
959 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
960 NFSX_POSTOPATTR(info.v3),
962 nfsm_srvpostop_attr(&info, nfsd, getret, vap);
971 nfsm_srvfattr(nfsd, vap, fp);
972 tlen = len - uiop->uio_resid;
973 cnt = cnt < tlen ? cnt : tlen;
974 tlen = nfsm_rndup(cnt);
975 if (len != tlen || tlen != cnt)
976 nfsm_adj(info.mb, len - tlen, tlen - cnt);
978 *tl++ = txdr_unsigned(cnt);
984 *tl = txdr_unsigned(cnt);
996 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
997 struct thread *td, struct mbuf **mrq)
999 struct sockaddr *nam = nfsd->nd_nam;
1000 struct ucred *cred = &nfsd->nd_cr;
1004 struct nfs_fattr *fp;
1006 struct vattr va, forat;
1007 struct vattr *vap = &va;
1009 int error = 0, rdonly, len, forat_ret = 1;
1010 int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
1011 int stable = NFSV3WRITE_FILESYNC;
1012 struct vnode *vp = NULL;
1013 struct mount *mp = NULL;
1017 struct uio io, *uiop = &io;
1018 struct nfsm_info info;
1021 info.mrep = nfsd->nd_mrep;
1023 info.md = nfsd->nd_md;
1024 info.dpos = nfsd->nd_dpos;
1025 info.v3 = (nfsd->nd_flag & ND_NFSV3);
1027 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1028 if (info.mrep == NULL) {
1032 fhp = &nfh.fh_generic;
1033 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
1035 NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
1036 off = fxdr_hyper(tl);
1038 stable = fxdr_unsigned(int, *tl++);
1040 NULLOUT(tl = nfsm_dissect(&info, 4 * NFSX_UNSIGNED));
1041 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1044 stable = NFSV3WRITE_UNSTABLE;
1046 retlen = len = fxdr_unsigned(int32_t, *tl);
1050 * For NFS Version 2, it is not obvious what a write of zero length
1051 * should do, but I might as well be consistent with Version 3,
1052 * which is to return ok so long as there are no permission problems.
1058 if (mp1 == info.md) {
1060 adjust = info.dpos - mtod(mp1, caddr_t);
1061 mp1->m_len -= adjust;
1062 if (mp1->m_len > 0 && adjust > 0)
1063 mp1->m_data += adjust;
1067 else if (mp1->m_len > 0) {
1070 mp1->m_len -= (i - len);
1079 if (len > NFS_MAXDATA || len < 0 || i < len) {
1081 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1082 2 * NFSX_UNSIGNED, &error));
1083 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1088 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
1089 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
1092 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1093 2 * NFSX_UNSIGNED, &error));
1094 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1100 forat_ret = VOP_GETATTR(vp, &forat);
1101 if (vp->v_type != VREG) {
1105 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1108 error = nfsrv_access(mp, vp, VWRITE, cred, rdonly, td, 1);
1113 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1114 NFSX_WCCDATA(info.v3), &error));
1115 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1122 ivp = kmalloc(cnt * sizeof(struct iovec), M_TEMP, M_WAITOK);
1123 uiop->uio_iov = iv = ivp;
1124 uiop->uio_iovcnt = cnt;
1127 if (mp1->m_len > 0) {
1128 ivp->iov_base = mtod(mp1, caddr_t);
1129 ivp->iov_len = mp1->m_len;
1137 * The IO_METASYNC flag indicates that all metadata (and not just
1138 * enough to ensure data integrity) mus be written to stable storage
1140 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1142 if (stable == NFSV3WRITE_UNSTABLE)
1143 ioflags = IO_NODELOCKED;
1144 else if (stable == NFSV3WRITE_DATASYNC)
1145 ioflags = (IO_SYNC | IO_NODELOCKED);
1147 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1148 uiop->uio_resid = len;
1149 uiop->uio_rw = UIO_WRITE;
1150 uiop->uio_segflg = UIO_SYSSPACE;
1151 uiop->uio_td = NULL;
1152 uiop->uio_offset = off;
1153 nh = nfsrv_sequential_heuristic(uiop, vp, 1);
1154 ioflags |= nh->nh_seqcount << IO_SEQSHIFT;
1155 error = VOP_WRITE(vp, uiop, ioflags, cred);
1157 nh->nh_nextoff = uiop->uio_offset;
1158 nfsstats.srvvop_writes++;
1159 kfree((caddr_t)iv, M_TEMP);
1161 aftat_ret = VOP_GETATTR(vp, vap);
1166 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1167 NFSX_PREOPATTR(info.v3) +
1168 NFSX_POSTOPORFATTR(info.v3) +
1169 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(info.v3),
1172 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1178 tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
1179 *tl++ = txdr_unsigned(retlen);
1181 * If nfs_async is set, then pretend the write was FILESYNC.
1183 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1184 *tl++ = txdr_unsigned(stable);
1186 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1188 * Actually, there is no need to txdr these fields,
1189 * but it may make the values more human readable,
1190 * for debugging purposes.
1192 if (nfsver.tv_sec == 0)
1194 *tl++ = txdr_unsigned(nfsver.tv_sec);
1195 *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
1197 fp = nfsm_build(&info, NFSX_V2FATTR);
1198 nfsm_srvfattr(nfsd, vap, fp);
1208 * NFS write service with write gathering support. Called when
1209 * nfsrvw_procrastinate > 0.
1210 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1211 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1215 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
1216 struct thread *td, struct mbuf **mrq)
1219 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1220 struct nfs_fattr *fp;
1223 struct nfsrvw_delayhash *wpp;
1225 struct vattr va, forat;
1227 int error = 0, rdonly, len, forat_ret = 1;
1228 int ioflags, aftat_ret = 1, adjust, zeroing;
1230 struct vnode *vp = NULL;
1231 struct mount *mp = NULL;
1232 struct uio io, *uiop = &io;
1234 struct nfsm_info info;
1238 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1246 info.mrep = nfsd->nd_mrep;
1248 info.md = nfsd->nd_md;
1249 info.dpos = nfsd->nd_dpos;
1250 info.v3 = (nfsd->nd_flag & ND_NFSV3);
1251 cred = &nfsd->nd_cr;
1252 LIST_INIT(&nfsd->nd_coalesce);
1253 nfsd->nd_mreq = NULL;
1254 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1255 cur_usec = nfs_curusec();
1256 nfsd->nd_time = cur_usec +
1257 (info.v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
1260 * Now, get the write header..
1262 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, &nfsd->nd_fh, &error));
1264 NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
1265 nfsd->nd_off = fxdr_hyper(tl);
1267 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1269 NULLOUT(tl = nfsm_dissect(&info, 4 * NFSX_UNSIGNED));
1270 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1273 nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
1275 len = fxdr_unsigned(int32_t, *tl);
1277 nfsd->nd_eoff = nfsd->nd_off + len;
1280 * Trim the header out of the mbuf list and trim off any trailing
1281 * junk so that the mbuf list has only the write data.
1287 if (mp1 == info.md) {
1289 adjust = info.dpos - mtod(mp1, caddr_t);
1290 mp1->m_len -= adjust;
1291 if (mp1->m_len > 0 && adjust > 0)
1292 mp1->m_data += adjust;
1299 mp1->m_len -= (i - len);
1305 if (len > NFS_MAXDATA || len < 0 || i < len) {
1310 nfsm_writereply(&info, nfsd, slp, error, 2 * NFSX_UNSIGNED);
1312 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1315 nfsd->nd_mreq = info.mreq;
1316 nfsd->nd_mrep = NULL;
1321 * Add this entry to the hash and time queues.
1324 wp = slp->ns_tq.lh_first;
1325 while (wp && wp->nd_time < nfsd->nd_time) {
1327 wp = wp->nd_tq.le_next;
1329 NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
1331 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1333 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1335 if (nfsd->nd_mrep) {
1336 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1340 bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
1342 wp = wp->nd_hash.le_next;
1344 while (wp && wp->nd_off < nfsd->nd_off &&
1345 !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) {
1347 wp = wp->nd_hash.le_next;
1350 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1353 * Search the hash list for overlapping entries and
1356 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1357 wp = nfsd->nd_hash.le_next;
1358 if (NFSW_SAMECRED(owp, nfsd))
1359 nfsrvw_coalesce(owp, nfsd);
1362 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1368 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1369 * and generate the associated reply mbuf list(s).
1372 cur_usec = nfs_curusec();
1373 for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) {
1374 owp = nfsd->nd_tq.le_next;
1375 if (nfsd->nd_time > cur_usec)
1379 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
1380 LIST_REMOVE(nfsd, nd_tq);
1381 LIST_REMOVE(nfsd, nd_hash);
1382 info.mrep = nfsd->nd_mrep;
1384 info.v3 = (nfsd->nd_flag & ND_NFSV3);
1385 nfsd->nd_mrep = NULL;
1386 cred = &nfsd->nd_cr;
1387 forat_ret = aftat_ret = 1;
1388 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &mp, &vp, cred, slp,
1389 nfsd->nd_nam, &rdonly,
1390 (nfsd->nd_flag & ND_KERBAUTH), TRUE);
1393 forat_ret = VOP_GETATTR(vp, &forat);
1394 if (vp->v_type != VREG) {
1398 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1404 error = nfsrv_access(mp, vp, VWRITE, cred, rdonly, td, 1);
1407 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1408 ioflags = IO_NODELOCKED;
1409 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1410 ioflags = (IO_SYNC | IO_NODELOCKED);
1412 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1413 uiop->uio_rw = UIO_WRITE;
1414 uiop->uio_segflg = UIO_SYSSPACE;
1415 uiop->uio_td = NULL;
1416 uiop->uio_offset = nfsd->nd_off;
1417 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1418 if (uiop->uio_resid > 0) {
1426 uiop->uio_iovcnt = i;
1427 iov = kmalloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
1428 uiop->uio_iov = ivp = iov;
1431 if (mp1->m_len > 0) {
1432 ivp->iov_base = mtod(mp1, caddr_t);
1433 ivp->iov_len = mp1->m_len;
1439 error = VOP_WRITE(vp, uiop, ioflags, cred);
1440 nfsstats.srvvop_writes++;
1442 kfree((caddr_t)iov, M_TEMP);
1447 aftat_ret = VOP_GETATTR(vp, &va);
1453 * Loop around generating replies for all write rpcs that have
1454 * now been completed.
1458 NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
1460 nfsm_writereply(&info, nfsd, slp, error,
1461 NFSX_WCCDATA(info.v3));
1463 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1467 nfsm_writereply(&info, nfsd, slp, error,
1468 NFSX_PREOPATTR(info.v3) +
1469 NFSX_POSTOPORFATTR(info.v3) +
1471 NFSX_WRITEVERF(info.v3));
1473 nfsm_srvwcc_data(&info, nfsd, forat_ret, &forat,
1475 tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
1476 *tl++ = txdr_unsigned(nfsd->nd_len);
1477 *tl++ = txdr_unsigned(swp->nd_stable);
1479 * Actually, there is no need to txdr these fields,
1480 * but it may make the values more human readable,
1481 * for debugging purposes.
1483 if (nfsver.tv_sec == 0)
1485 *tl++ = txdr_unsigned(nfsver.tv_sec);
1486 *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
1488 fp = nfsm_build(&info, NFSX_V2FATTR);
1489 nfsm_srvfattr(nfsd, &va, fp);
1492 nfsd->nd_mreq = info.mreq;
1494 panic("nfsrv_write: nd_mrep not free");
1497 * Done. Put it at the head of the timer queue so that
1498 * the final phase can return the reply.
1502 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1504 nfsd = swp->nd_coalesce.lh_first;
1506 LIST_REMOVE(nfsd, nd_tq);
1510 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1515 * Search for a reply to return.
1517 for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next) {
1518 if (nfsd->nd_mreq) {
1519 NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
1520 LIST_REMOVE(nfsd, nd_tq);
1526 *mrq = nfsd->nd_mreq;
1535 * Coalesce the write request nfsd into owp. To do this we must:
1536 * - remove nfsd from the queues
1537 * - merge nfsd->nd_mrep into owp->nd_mrep
1538 * - update the nd_eoff and nd_stable for owp
1539 * - put nfsd on owp's nd_coalesce list
1540 * NB: Must be called at splsoftclock().
1543 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
1547 struct nfsrv_descript *p;
1549 NFS_DPF(WG, ("C%03x-%03x",
1550 nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
1551 LIST_REMOVE(nfsd, nd_hash);
1552 LIST_REMOVE(nfsd, nd_tq);
1553 if (owp->nd_eoff < nfsd->nd_eoff) {
1554 overlap = owp->nd_eoff - nfsd->nd_off;
1556 panic("nfsrv_coalesce: bad off");
1558 m_adj(nfsd->nd_mrep, overlap);
1562 mp1->m_next = nfsd->nd_mrep;
1563 owp->nd_eoff = nfsd->nd_eoff;
1565 m_freem(nfsd->nd_mrep);
1566 nfsd->nd_mrep = NULL;
1567 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1568 owp->nd_stable = NFSV3WRITE_FILESYNC;
1569 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1570 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1571 owp->nd_stable = NFSV3WRITE_DATASYNC;
1572 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1575 * If nfsd had anything else coalesced into it, transfer them
1576 * to owp, otherwise their replies will never get sent.
1578 for (p = nfsd->nd_coalesce.lh_first; p;
1579 p = nfsd->nd_coalesce.lh_first) {
1580 LIST_REMOVE(p, nd_tq);
1581 LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
1586 * nfs create service
1587 * now does a truncate to 0 length via. setattr if it already exists
1590 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1591 struct thread *td, struct mbuf **mrq)
1593 struct sockaddr *nam = nfsd->nd_nam;
1594 struct ucred *cred = &nfsd->nd_cr;
1595 struct nfs_fattr *fp;
1596 struct vattr va, dirfor, diraft;
1597 struct vattr *vap = &va;
1598 struct nfsv2_sattr *sp;
1600 struct nlookupdata nd;
1601 int error = 0, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1602 udev_t rdev = NOUDEV;
1604 int how, exclusive_flag = 0;
1612 u_char cverf[NFSX_V3CREATEVERF];
1613 struct nfsm_info info;
1615 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1621 info.mrep = nfsd->nd_mrep;
1623 info.md = nfsd->nd_md;
1624 info.dpos = nfsd->nd_dpos;
1625 info.v3 = (nfsd->nd_flag & ND_NFSV3);
1627 fhp = &nfh.fh_generic;
1628 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
1629 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
1632 * Call namei and do initial cleanup to get a few things
1633 * out of the way. If we get an initial error we cleanup
1634 * and return here to avoid special-casing the invalid nd
1635 * structure through the rest of the case. dirp may be
1636 * set even if an error occurs, but the nd structure will not
1637 * be valid at all if an error occurs so we have to invalidate it
1638 * prior to calling nfsm_reply ( which might goto nfsmout ).
1640 error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
1641 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
1642 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1643 mp = vfs_getvfs(&fhp->fh_fsid);
1647 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
1654 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1655 NFSX_WCCDATA(info.v3), &error));
1656 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
1657 diraft_ret, &diraft);
1663 * No error. Continue. State:
1666 * vp may be valid or NULL if the target does not
1670 * The error state is set through the code and we may also do some
1671 * opportunistic releasing of vnodes to avoid holding locks through
1672 * NFS I/O. The cleanup at the end is a catch-all
1677 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
1678 how = fxdr_unsigned(int, *tl);
1680 case NFSV3CREATE_GUARDED:
1686 case NFSV3CREATE_UNCHECKED:
1687 ERROROUT(nfsm_srvsattr(&info, vap));
1689 case NFSV3CREATE_EXCLUSIVE:
1690 NULLOUT(cp = nfsm_dissect(&info, NFSX_V3CREATEVERF));
1691 bcopy(cp, cverf, NFSX_V3CREATEVERF);
1695 vap->va_type = VREG;
1697 NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
1698 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1699 if (vap->va_type == VNON)
1700 vap->va_type = VREG;
1701 vap->va_mode = nfstov_mode(sp->sa_mode);
1702 switch (vap->va_type) {
1704 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1706 vap->va_size = (u_quad_t)tsize;
1711 rdev = fxdr_unsigned(long, sp->sa_size);
1719 * Iff doesn't exist, create it
1720 * otherwise just truncate to 0 length
1721 * should I set the mode too ?
1723 * The only possible error we can have at this point is EEXIST.
1724 * nd.ni_vp will also be non-NULL in that case.
1727 if (vap->va_mode == (mode_t)VNOVAL)
1729 if (vap->va_type == VREG || vap->va_type == VSOCK) {
1731 error = VOP_NCREATE(&nd.nl_nch, dvp, &vp,
1736 if (exclusive_flag) {
1739 bcopy(cverf, (caddr_t)&vap->va_atime,
1741 error = VOP_SETATTR(vp, vap, cred);
1745 vap->va_type == VCHR ||
1746 vap->va_type == VBLK ||
1747 vap->va_type == VFIFO
1750 * Handle SysV FIFO node special cases. All other
1751 * devices require super user to access.
1753 if (vap->va_type == VCHR && rdev == 0xffffffff)
1754 vap->va_type = VFIFO;
1755 if (vap->va_type != VFIFO &&
1756 (error = priv_check_cred(cred, PRIV_ROOT, 0))) {
1759 vap->va_rmajor = umajor(rdev);
1760 vap->va_rminor = uminor(rdev);
1763 error = VOP_NMKNOD(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1770 * XXX what is this junk supposed to do ?
1777 * release dvp prior to lookup
1785 * Even though LOCKPARENT was cleared, ni_dvp may
1788 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP;
1789 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT);
1790 nd.ni_cnd.cn_td = td;
1791 nd.ni_cnd.cn_cred = cred;
1793 error = lookup(&nd);
1797 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1799 /* fall through on certain errors */
1801 nfsrv_object_create(nd.ni_vp);
1802 if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) {
1811 if (vap->va_size != -1) {
1812 error = nfsrv_access(mp, vp, VWRITE, cred,
1813 (nd.nl_flags & NLC_NFS_RDONLY), td, 0);
1815 tempsize = vap->va_size;
1817 vap->va_size = tempsize;
1818 error = VOP_SETATTR(vp, vap, cred);
1824 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid));
1825 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1827 error = VOP_GETATTR(vp, vap);
1830 if (exclusive_flag && !error &&
1831 bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
1833 diraft_ret = VOP_GETATTR(dirp, &diraft);
1837 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1838 NFSX_SRVFH(info.v3) + NFSX_FATTR(info.v3) +
1839 NFSX_WCCDATA(info.v3),
1843 nfsm_srvpostop_fh(&info, fhp);
1844 nfsm_srvpostop_attr(&info, nfsd, 0, vap);
1846 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
1847 diraft_ret, &diraft);
1850 nfsm_srvfhtom(&info, fhp);
1851 fp = nfsm_build(&info, NFSX_V2FATTR);
1852 nfsm_srvfattr(nfsd, vap, fp);
1857 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
1878 * nfs v3 mknod service
1881 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1882 struct thread *td, struct mbuf **mrq)
1884 struct sockaddr *nam = nfsd->nd_nam;
1885 struct ucred *cred = &nfsd->nd_cr;
1886 struct vattr va, dirfor, diraft;
1887 struct vattr *vap = &va;
1889 struct nlookupdata nd;
1890 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
1897 struct nfsm_info info;
1899 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1905 info.mrep = nfsd->nd_mrep;
1907 info.md = nfsd->nd_md;
1908 info.dpos = nfsd->nd_dpos;
1910 fhp = &nfh.fh_generic;
1911 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
1912 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
1915 * Handle nfs_namei() call. If an error occurs, the nd structure
1916 * is not valid. However, nfsm_*() routines may still jump to
1920 error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
1921 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
1922 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1924 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
1926 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
1927 NFSX_WCCDATA(1), &error));
1928 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
1929 diraft_ret, &diraft);
1933 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
1934 vtyp = nfsv3tov_type(*tl);
1935 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1936 error = NFSERR_BADTYPE;
1940 ERROROUT(nfsm_srvsattr(&info, vap));
1941 if (vtyp == VCHR || vtyp == VBLK) {
1942 NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
1943 vap->va_rmajor = fxdr_unsigned(u_int32_t, *tl++);
1944 vap->va_rminor = fxdr_unsigned(u_int32_t, *tl);
1948 * Iff doesn't exist, create it.
1954 vap->va_type = vtyp;
1955 if (vap->va_mode == (mode_t)VNOVAL)
1957 if (vtyp == VSOCK) {
1959 error = VOP_NCREATE(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1963 if (vtyp != VFIFO && (error = priv_check_cred(cred, PRIV_ROOT, 0)))
1967 error = VOP_NMKNOD(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
1975 * send response, cleanup, return.
1987 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid));
1988 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1990 error = VOP_GETATTR(vp, vap);
1996 diraft_ret = VOP_GETATTR(dirp, &diraft);
2001 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2002 NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) +
2003 NFSX_WCCDATA(1), &error));
2005 nfsm_srvpostop_fh(&info, fhp);
2006 nfsm_srvpostop_attr(&info, nfsd, 0, vap);
2008 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2009 diraft_ret, &diraft);
2029 * nfs remove service
2032 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2033 struct thread *td, struct mbuf **mrq)
2035 struct sockaddr *nam = nfsd->nd_nam;
2036 struct ucred *cred = &nfsd->nd_cr;
2037 struct nlookupdata nd;
2038 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2042 struct vattr dirfor, diraft;
2045 struct nfsm_info info;
2047 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2053 info.mrep = nfsd->nd_mrep;
2055 info.md = nfsd->nd_md;
2056 info.dpos = nfsd->nd_dpos;
2057 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2059 fhp = &nfh.fh_generic;
2060 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2061 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2063 error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp,
2064 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
2065 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2068 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2071 if (vp->v_type == VDIR) {
2072 error = EPERM; /* POSIX */
2076 * The root of a mounted filesystem cannot be deleted.
2078 if (vp->v_flag & VROOT) {
2090 error = VOP_NREMOVE(&nd.nl_nch, dvp, nd.nl_cred);
2095 if (dirp && info.v3)
2096 diraft_ret = VOP_GETATTR(dirp, &diraft);
2097 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_WCCDATA(info.v3), &error));
2099 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2100 diraft_ret, &diraft);
2120 * nfs rename service
2123 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2124 struct thread *td, struct mbuf **mrq)
2126 struct sockaddr *nam = nfsd->nd_nam;
2127 struct ucred *cred = &nfsd->nd_cr;
2128 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2129 int tdirfor_ret = 1, tdiraft_ret = 1;
2130 struct nlookupdata fromnd, tond;
2131 struct vnode *fvp, *fdirp, *fdvp;
2132 struct vnode *tvp, *tdirp, *tdvp;
2133 struct namecache *ncp;
2134 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2136 fhandle_t *ffhp, *tfhp;
2138 struct nfsm_info info;
2140 info.mrep = nfsd->nd_mrep;
2142 info.md = nfsd->nd_md;
2143 info.dpos = nfsd->nd_dpos;
2144 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2146 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2150 ffhp = &fnfh.fh_generic;
2151 tfhp = &tnfh.fh_generic;
2154 * Clear fields incase goto nfsmout occurs from macro.
2157 nlookup_zero(&fromnd);
2158 nlookup_zero(&tond);
2162 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, ffhp, &error));
2163 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2166 * Remember our original uid so that we can reset cr_uid before
2167 * the second nfs_namei() call, in case it is remapped.
2169 saved_uid = cred->cr_uid;
2170 error = nfs_namei(&fromnd, cred, NLC_RENAME_SRC,
2172 ffhp, len, slp, nam, &info.md, &info.dpos, &fdirp,
2173 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2176 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor);
2179 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2180 2 * NFSX_WCCDATA(info.v3), &error));
2181 nfsm_srvwcc_data(&info, nfsd, fdirfor_ret, &fdirfor,
2182 fdiraft_ret, &fdiraft);
2183 nfsm_srvwcc_data(&info, nfsd, tdirfor_ret, &tdirfor,
2184 tdiraft_ret, &tdiraft);
2190 * We have to unlock the from ncp before we can safely lookup
2193 KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED);
2194 cache_unlock(&fromnd.nl_nch);
2195 fromnd.nl_flags &= ~NLC_NCPISLOCKED;
2196 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, tfhp, &error));
2197 NEGATIVEOUT(len2 = nfsm_strsiz(&info, NFS_MAXNAMLEN));
2198 cred->cr_uid = saved_uid;
2200 error = nfs_namei(&tond, cred, NLC_RENAME_DST, NULL, NULL,
2201 tfhp, len2, slp, nam, &info.md, &info.dpos, &tdirp,
2202 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2205 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor);
2213 if (cache_lock_nonblock(&fromnd.nl_nch) == 0) {
2214 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2215 } else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) {
2216 cache_lock(&fromnd.nl_nch);
2217 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2219 cache_unlock(&tond.nl_nch);
2220 cache_lock(&fromnd.nl_nch);
2221 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred);
2222 cache_lock(&tond.nl_nch);
2223 cache_resolve(&tond.nl_nch, tond.nl_cred);
2225 fromnd.nl_flags |= NLC_NCPISLOCKED;
2227 fvp = fromnd.nl_nch.ncp->nc_vp;
2228 tvp = tond.nl_nch.ncp->nc_vp;
2231 * Set fdvp and tdvp. We haven't done all the topology checks
2232 * so these can wind up NULL (e.g. if either fvp or tvp is a mount
2233 * point). If we get through the checks these will be guarenteed
2236 * Holding the children ncp's should be sufficient to prevent
2237 * fdvp and tdvp ripouts.
2239 if (fromnd.nl_nch.ncp->nc_parent)
2240 fdvp = fromnd.nl_nch.ncp->nc_parent->nc_vp;
2243 if (tond.nl_nch.ncp->nc_parent)
2244 tdvp = tond.nl_nch.ncp->nc_parent->nc_vp;
2249 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2255 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2262 if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
2270 if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) {
2277 if (fromnd.nl_nch.mount != tond.nl_nch.mount) {
2284 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) {
2292 * You cannot rename a source into itself or a subdirectory of itself.
2293 * We check this by travsering the target directory upwards looking
2294 * for a match against the source.
2297 for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) {
2298 if (fromnd.nl_nch.ncp == ncp) {
2306 * If source is the same as the destination (that is the
2307 * same vnode with the same name in the same directory),
2308 * then there is nothing to do.
2310 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp)
2315 * The VOP_NRENAME function releases all vnode references &
2316 * locks prior to returning so we need to clear the pointers
2317 * to bypass cleanup code later on.
2319 error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch,
2320 fdvp, tdvp, tond.nl_cred);
2329 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft);
2331 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft);
2332 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2333 2 * NFSX_WCCDATA(info.v3), &error));
2335 nfsm_srvwcc_data(&info, nfsd, fdirfor_ret, &fdirfor,
2336 fdiraft_ret, &fdiraft);
2337 nfsm_srvwcc_data(&info, nfsd, tdirfor_ret, &tdirfor,
2338 tdiraft_ret, &tdiraft);
2347 nlookup_done(&tond);
2350 nlookup_done(&fromnd);
2358 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2359 struct thread *td, struct mbuf **mrq)
2361 struct sockaddr *nam = nfsd->nd_nam;
2362 struct ucred *cred = &nfsd->nd_cr;
2363 struct nlookupdata nd;
2364 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2372 struct vattr dirfor, diraft, at;
2374 fhandle_t *fhp, *dfhp;
2375 struct nfsm_info info;
2377 info.mrep = nfsd->nd_mrep;
2379 info.md = nfsd->nd_md;
2380 info.dpos = nfsd->nd_dpos;
2381 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2383 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2385 dirp = dvp = vp = xp = NULL;
2388 fhp = &nfh.fh_generic;
2389 dfhp = &dnfh.fh_generic;
2390 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2391 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, dfhp, &error));
2392 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2394 error = nfsrv_fhtovp(fhp, FALSE, &xmp, &xp, cred, slp, nam,
2395 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2397 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2398 NFSX_POSTOPATTR(info.v3) +
2399 NFSX_WCCDATA(info.v3),
2401 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
2402 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2403 diraft_ret, &diraft);
2408 if (xp->v_type == VDIR) {
2409 error = EPERM; /* POSIX */
2413 error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
2414 dfhp, len, slp, nam, &info.md, &info.dpos, &dirp,
2415 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2418 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2427 if (xp->v_mount != dvp->v_mount)
2432 error = VOP_NLINK(&nd.nl_nch, dvp, xp, nd.nl_cred);
2440 getret = VOP_GETATTR(xp, &at);
2442 diraft_ret = VOP_GETATTR(dirp, &diraft);
2443 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2444 NFSX_POSTOPATTR(info.v3) + NFSX_WCCDATA(info.v3),
2447 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
2448 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2449 diraft_ret, &diraft);
2473 * nfs symbolic link service
2476 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2477 struct thread *td, struct mbuf **mrq)
2479 struct sockaddr *nam = nfsd->nd_nam;
2480 struct ucred *cred = &nfsd->nd_cr;
2481 struct vattr va, dirfor, diraft;
2482 struct nlookupdata nd;
2483 struct vattr *vap = &va;
2484 struct nfsv2_sattr *sp;
2485 char *pathcp = NULL;
2488 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2494 struct nfsm_info info;
2496 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2502 info.mrep = nfsd->nd_mrep;
2504 info.md = nfsd->nd_md;
2505 info.dpos = nfsd->nd_dpos;
2506 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2508 fhp = &nfh.fh_generic;
2509 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2510 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2512 error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
2513 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
2514 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2517 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2524 ERROROUT(nfsm_srvsattr(&info, vap));
2526 NEGATIVEOUT(len2 = nfsm_strsiz(&info, NFS_MAXPATHLEN));
2527 pathcp = kmalloc(len2 + 1, M_TEMP, M_WAITOK);
2528 iv.iov_base = pathcp;
2530 io.uio_resid = len2;
2534 io.uio_segflg = UIO_SYSSPACE;
2535 io.uio_rw = UIO_READ;
2537 ERROROUT(nfsm_mtouio(&info, &io, len2));
2539 NULLOUT(sp = nfsm_dissect(&info, NFSX_V2SATTR));
2540 vap->va_mode = nfstov_mode(sp->sa_mode);
2542 *(pathcp + len2) = '\0';
2548 if (vap->va_mode == (mode_t)VNOVAL)
2552 error = VOP_NSYMLINK(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap, pathcp);
2556 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid));
2557 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2559 error = VOP_GETATTR(vp, vap);
2574 kfree(pathcp, M_TEMP);
2578 diraft_ret = VOP_GETATTR(dirp, &diraft);
2582 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2583 NFSX_SRVFH(info.v3) + NFSX_POSTOPATTR(info.v3) +
2584 NFSX_WCCDATA(info.v3),
2588 nfsm_srvpostop_fh(&info, fhp);
2589 nfsm_srvpostop_attr(&info, nfsd, 0, vap);
2591 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2592 diraft_ret, &diraft);
2605 kfree(pathcp, M_TEMP);
2613 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2614 struct thread *td, struct mbuf **mrq)
2616 struct sockaddr *nam = nfsd->nd_nam;
2617 struct ucred *cred = &nfsd->nd_cr;
2618 struct vattr va, dirfor, diraft;
2619 struct vattr *vap = &va;
2620 struct nfs_fattr *fp;
2621 struct nlookupdata nd;
2623 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2629 struct nfsm_info info;
2631 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2637 info.dpos = nfsd->nd_dpos;
2638 info.mrep = nfsd->nd_mrep;
2640 info.md = nfsd->nd_md;
2641 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2643 fhp = &nfh.fh_generic;
2644 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2645 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2647 error = nfs_namei(&nd, cred, NLC_CREATE, &dvp, &vp,
2648 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
2649 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2652 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2655 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2656 NFSX_WCCDATA(info.v3), &error));
2657 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2658 diraft_ret, &diraft);
2664 ERROROUT(nfsm_srvsattr(&info, vap));
2666 NULLOUT(tl = nfsm_dissect(&info, NFSX_UNSIGNED));
2667 vap->va_mode = nfstov_mode(*tl++);
2671 * At this point nd.ni_dvp is referenced and exclusively locked and
2672 * nd.ni_vp, if it exists, is referenced but not locked.
2675 vap->va_type = VDIR;
2682 * Issue mkdir op. Since SAVESTART is not set, the pathname
2683 * component is freed by the VOP call. This will fill-in
2684 * nd.ni_vp, reference, and exclusively lock it.
2686 if (vap->va_mode == (mode_t)VNOVAL)
2689 error = VOP_NMKDIR(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap);
2694 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid));
2695 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2697 error = VOP_GETATTR(vp, vap);
2701 diraft_ret = VOP_GETATTR(dirp, &diraft);
2702 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2703 NFSX_SRVFH(info.v3) + NFSX_POSTOPATTR(info.v3) +
2704 NFSX_WCCDATA(info.v3),
2708 nfsm_srvpostop_fh(&info, fhp);
2709 nfsm_srvpostop_attr(&info, nfsd, 0, vap);
2711 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2712 diraft_ret, &diraft);
2714 nfsm_srvfhtom(&info, fhp);
2715 fp = nfsm_build(&info, NFSX_V2FATTR);
2716 nfsm_srvfattr(nfsd, vap, fp);
2741 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2742 struct thread *td, struct mbuf **mrq)
2744 struct sockaddr *nam = nfsd->nd_nam;
2745 struct ucred *cred = &nfsd->nd_cr;
2746 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2750 struct vattr dirfor, diraft;
2753 struct nlookupdata nd;
2754 struct nfsm_info info;
2756 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2762 info.mrep = nfsd->nd_mrep;
2764 info.md = nfsd->nd_md;
2765 info.dpos = nfsd->nd_dpos;
2766 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2768 fhp = &nfh.fh_generic;
2769 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2770 NEGREPLYOUT(len = nfsm_srvnamesiz(&info, &error));
2772 error = nfs_namei(&nd, cred, NLC_DELETE, &dvp, &vp,
2773 fhp, len, slp, nam, &info.md, &info.dpos, &dirp,
2774 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2777 dirfor_ret = VOP_GETATTR(dirp, &dirfor);
2780 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2781 NFSX_WCCDATA(info.v3), &error));
2782 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2783 diraft_ret, &diraft);
2787 if (vp->v_type != VDIR) {
2793 * The root of a mounted filesystem cannot be deleted.
2795 if (vp->v_flag & VROOT)
2799 * Issue or abort op. Since SAVESTART is not set, path name
2800 * component is freed by the VOP after either.
2807 error = VOP_NRMDIR(&nd.nl_nch, dvp, nd.nl_cred);
2814 diraft_ret = VOP_GETATTR(dirp, &diraft);
2815 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_WCCDATA(info.v3), &error));
2817 nfsm_srvwcc_data(&info, nfsd, dirfor_ret, &dirfor,
2818 diraft_ret, &diraft);
2840 * nfs readdir service
2841 * - mallocs what it thinks is enough to read
2842 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2843 * - calls VOP_READDIR()
2844 * - loops around building the reply
2845 * if the output generated exceeds count break out of loop
2846 * The nfsm_clget macro is used here so that the reply will be packed
2847 * tightly in mbuf clusters.
2848 * - it only knows that it has encountered eof when the VOP_READDIR()
2850 * - as such one readdir rpc will return eof false although you are there
2851 * and then the next will return eof
2852 * - it trims out records with d_fileno == 0
2853 * this doesn't matter for Unix clients, but they might confuse clients
2855 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2856 * than requested, but this may not apply to all filesystems. For
2857 * example, client NFS does not { although it is never remote mounted
2859 * The alternate call nfsrv_readdirplus() does lookups as well.
2860 * PS: The NFS protocol spec. does not clarify what the "count" byte
2861 * argument is a count of.. just name strings and file id's or the
2862 * entire reply rpc or ...
2863 * I tried just file name and id sizes and it confused the Sun client,
2864 * so I am using the full rpc size now. The "paranoia.." comment refers
2865 * to including the status longwords that are not a part of the dir.
2866 * "entry" structures, but are in the rpc.
2870 u_int32_t fl_postopok;
2871 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2873 u_int32_t fl_fhsize;
2874 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2878 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2879 struct thread *td, struct mbuf **mrq)
2881 struct sockaddr *nam = nfsd->nd_nam;
2882 struct ucred *cred = &nfsd->nd_cr;
2887 struct mbuf *mp1, *mp2;
2888 char *cpos, *cend, *rbuf;
2889 struct vnode *vp = NULL;
2890 struct mount *mp = NULL;
2896 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2897 int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
2898 u_quad_t off, toff, verf;
2899 off_t *cookies = NULL, *cookiep;
2900 struct nfsm_info info;
2902 info.mrep = nfsd->nd_mrep;
2904 info.md = nfsd->nd_md;
2905 info.dpos = nfsd->nd_dpos;
2906 info.v3 = (nfsd->nd_flag & ND_NFSV3);
2908 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2909 fhp = &nfh.fh_generic;
2910 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
2912 NULLOUT(tl = nfsm_dissect(&info, 5 * NFSX_UNSIGNED));
2913 toff = fxdr_hyper(tl);
2915 verf = fxdr_hyper(tl);
2918 NULLOUT(tl = nfsm_dissect(&info, 2 * NFSX_UNSIGNED));
2919 toff = fxdr_unsigned(u_quad_t, *tl++);
2920 verf = 0; /* shut up gcc */
2923 cnt = fxdr_unsigned(int, *tl);
2924 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2925 xfer = NFS_SRVMAXDATA(nfsd);
2926 if ((unsigned)cnt > xfer)
2928 if ((unsigned)siz > xfer)
2931 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
2932 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
2933 if (!error && vp->v_type != VDIR) {
2939 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
2940 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
2946 * Obtain lock on vnode for this section of the code
2950 error = getret = VOP_GETATTR(vp, &at);
2953 * XXX This check may be too strict for Solaris 2.5 clients.
2955 if (!error && toff && verf && verf != at.va_filerev)
2956 error = NFSERR_BAD_COOKIE;
2960 error = nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 0);
2964 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
2965 NFSX_POSTOPATTR(info.v3), &error));
2966 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
2973 * end section. Allocate rbuf and continue
2975 rbuf = kmalloc(siz, M_TEMP, M_WAITOK);
2978 iv.iov_len = fullsiz;
2981 io.uio_offset = (off_t)off;
2982 io.uio_resid = fullsiz;
2983 io.uio_segflg = UIO_SYSSPACE;
2984 io.uio_rw = UIO_READ;
2988 kfree((caddr_t)cookies, M_TEMP);
2991 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
2992 off = (off_t)io.uio_offset;
2993 if (!cookies && !error)
2994 error = NFSERR_PERM;
2996 getret = VOP_GETATTR(vp, &at);
3003 kfree((caddr_t)rbuf, M_TEMP);
3005 kfree((caddr_t)cookies, M_TEMP);
3006 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3007 NFSX_POSTOPATTR(info.v3), &error));
3008 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3013 siz -= io.uio_resid;
3016 * If nothing read, return eof
3022 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3023 NFSX_POSTOPATTR(info.v3) +
3024 NFSX_COOKIEVERF(info.v3) +
3028 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3029 tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
3030 txdr_hyper(at.va_filerev, tl);
3033 tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
3036 kfree((caddr_t)rbuf, M_TEMP);
3037 kfree((caddr_t)cookies, M_TEMP);
3044 * Check for degenerate cases of nothing useful read.
3045 * If so go try again
3049 dp = (struct dirent *)cpos;
3052 * For some reason FreeBSD's ufs_readdir() chooses to back the
3053 * directory offset up to a block boundary, so it is necessary to
3054 * skip over the records that preceed the requested offset. This
3055 * requires the assumption that file offset cookies monotonically
3058 while (cpos < cend && ncookies > 0 &&
3059 (dp->d_ino == 0 || dp->d_type == DT_WHT ||
3060 ((u_quad_t)(*cookiep)) <= toff)) {
3061 dp = _DIRENT_NEXT(dp);
3066 if (cpos >= cend || ncookies == 0) {
3072 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
3073 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3074 NFSX_POSTOPATTR(info.v3) +
3075 NFSX_COOKIEVERF(info.v3) + siz,
3078 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3079 tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
3080 txdr_hyper(at.va_filerev, tl);
3082 mp1 = mp2 = info.mb;
3084 be = bp + M_TRAILINGSPACE(mp1);
3086 /* Loop through the records and build reply */
3087 while (cpos < cend && ncookies > 0) {
3088 if (dp->d_ino != 0 && dp->d_type != DT_WHT) {
3089 nlen = dp->d_namlen;
3090 rem = nfsm_rndup(nlen) - nlen;
3091 len += (4 * NFSX_UNSIGNED + nlen + rem);
3093 len += 2 * NFSX_UNSIGNED;
3099 * Build the directory record xdr from
3102 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3104 bp += NFSX_UNSIGNED;
3106 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3107 *tl = txdr_unsigned(dp->d_ino >> 32);
3108 bp += NFSX_UNSIGNED;
3110 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3111 *tl = txdr_unsigned(dp->d_ino);
3112 bp += NFSX_UNSIGNED;
3113 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3114 *tl = txdr_unsigned(nlen);
3115 bp += NFSX_UNSIGNED;
3117 /* And loop around copying the name */
3121 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3126 bcopy(cp, bp, tsiz);
3132 /* And null pad to a int32_t boundary */
3133 for (i = 0; i < rem; i++)
3135 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3137 /* Finish off the record */
3139 *tl = txdr_unsigned(*cookiep >> 32);
3140 bp += NFSX_UNSIGNED;
3141 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3143 *tl = txdr_unsigned(*cookiep);
3144 bp += NFSX_UNSIGNED;
3146 dp = _DIRENT_NEXT(dp);
3153 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3155 bp += NFSX_UNSIGNED;
3156 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3161 bp += NFSX_UNSIGNED;
3162 if (mp1 != info.mb) {
3164 mp1->m_len = bp - mtod(mp1, caddr_t);
3166 mp1->m_len += bp - info.bpos;
3167 kfree((caddr_t)rbuf, M_TEMP);
3168 kfree((caddr_t)cookies, M_TEMP);
3178 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3179 struct thread *td, struct mbuf **mrq)
3181 struct sockaddr *nam = nfsd->nd_nam;
3182 struct ucred *cred = &nfsd->nd_cr;
3187 struct mbuf *mp1, *mp2;
3188 char *cpos, *cend, *rbuf;
3189 struct vnode *vp = NULL, *nvp;
3190 struct mount *mp = NULL;
3193 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3196 struct vattr va, at, *vap = &va;
3197 struct nfs_fattr *fp;
3198 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3199 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3200 u_quad_t off, toff, verf;
3201 off_t *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3202 struct nfsm_info info;
3204 info.mrep = nfsd->nd_mrep;
3206 info.md = nfsd->nd_md;
3207 info.dpos = nfsd->nd_dpos;
3208 info.v3 = (nfsd->nd_flag & ND_NFSV3);
3210 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3211 fhp = &nfh.fh_generic;
3212 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
3213 NULLOUT(tl = nfsm_dissect(&info, 6 * NFSX_UNSIGNED));
3214 toff = fxdr_hyper(tl);
3216 verf = fxdr_hyper(tl);
3218 siz = fxdr_unsigned(int, *tl++);
3219 cnt = fxdr_unsigned(int, *tl);
3221 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3222 xfer = NFS_SRVMAXDATA(nfsd);
3223 if ((unsigned)cnt > xfer)
3225 if ((unsigned)siz > xfer)
3228 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
3229 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3230 if (!error && vp->v_type != VDIR) {
3236 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
3237 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3241 error = getret = VOP_GETATTR(vp, &at);
3244 * XXX This check may be too strict for Solaris 2.5 clients.
3246 if (!error && toff && verf && verf != at.va_filerev)
3247 error = NFSERR_BAD_COOKIE;
3250 error = nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 0);
3255 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3256 NFSX_V3POSTOPATTR, &error));
3257 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3262 rbuf = kmalloc(siz, M_TEMP, M_WAITOK);
3265 iv.iov_len = fullsiz;
3268 io.uio_offset = (off_t)off;
3269 io.uio_resid = fullsiz;
3270 io.uio_segflg = UIO_SYSSPACE;
3271 io.uio_rw = UIO_READ;
3275 kfree((caddr_t)cookies, M_TEMP);
3278 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3279 off = (u_quad_t)io.uio_offset;
3280 getret = VOP_GETATTR(vp, &at);
3281 if (!cookies && !error)
3282 error = NFSERR_PERM;
3289 kfree((caddr_t)cookies, M_TEMP);
3290 kfree((caddr_t)rbuf, M_TEMP);
3291 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3292 NFSX_V3POSTOPATTR, &error));
3293 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3298 siz -= io.uio_resid;
3301 * If nothing read, return eof
3307 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3312 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3313 tl = nfsm_build(&info, 4 * NFSX_UNSIGNED);
3314 txdr_hyper(at.va_filerev, tl);
3318 kfree((caddr_t)cookies, M_TEMP);
3319 kfree((caddr_t)rbuf, M_TEMP);
3326 * Check for degenerate cases of nothing useful read.
3327 * If so go try again
3331 dp = (struct dirent *)cpos;
3334 * For some reason FreeBSD's ufs_readdir() chooses to back the
3335 * directory offset up to a block boundary, so it is necessary to
3336 * skip over the records that preceed the requested offset. This
3337 * requires the assumption that file offset cookies monotonically
3340 while (cpos < cend && ncookies > 0 &&
3341 (dp->d_ino == 0 || dp->d_type == DT_WHT ||
3342 ((u_quad_t)(*cookiep)) <= toff)) {
3343 dp = _DIRENT_NEXT(dp);
3348 if (cpos >= cend || ncookies == 0) {
3355 * Probe one of the directory entries to see if the filesystem
3358 if (VFS_VGET(vp->v_mount, vp, dp->d_ino, &nvp) == EOPNOTSUPP) {
3359 error = NFSERR_NOTSUPP;
3362 kfree((caddr_t)cookies, M_TEMP);
3363 kfree((caddr_t)rbuf, M_TEMP);
3364 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3365 NFSX_V3POSTOPATTR, &error));
3366 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3375 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3377 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, cnt, &error));
3378 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3379 tl = nfsm_build(&info, 2 * NFSX_UNSIGNED);
3380 txdr_hyper(at.va_filerev, tl);
3381 mp1 = mp2 = info.mb;
3383 be = bp + M_TRAILINGSPACE(mp1);
3385 /* Loop through the records and build reply */
3386 while (cpos < cend && ncookies > 0) {
3387 if (dp->d_ino != 0 && dp->d_type != DT_WHT) {
3388 nlen = dp->d_namlen;
3389 rem = nfsm_rndup(nlen) - nlen;
3392 * For readdir_and_lookup get the vnode using
3395 if (VFS_VGET(vp->v_mount, vp, dp->d_ino, &nvp))
3397 bzero((caddr_t)nfhp, NFSX_V3FH);
3398 nfhp->fh_fsid = fhp->fh_fsid;
3399 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3404 if (VOP_GETATTR(nvp, vap)) {
3413 * If either the dircount or maxcount will be
3414 * exceeded, get out now. Both of these lengths
3415 * are calculated conservatively, including all
3418 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3420 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3421 if (len > cnt || dirlen > fullsiz) {
3427 * Build the directory record xdr from
3430 fp = (struct nfs_fattr *)&fl.fl_fattr;
3431 nfsm_srvfattr(nfsd, vap, fp);
3432 fl.fl_off.nfsuquad[0] = txdr_unsigned(*cookiep >> 32);
3433 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3434 fl.fl_postopok = nfs_true;
3435 fl.fl_fhok = nfs_true;
3436 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3438 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3440 bp += NFSX_UNSIGNED;
3441 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3442 *tl = txdr_unsigned(dp->d_ino >> 32);
3443 bp += NFSX_UNSIGNED;
3444 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3445 *tl = txdr_unsigned(dp->d_ino);
3446 bp += NFSX_UNSIGNED;
3447 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3448 *tl = txdr_unsigned(nlen);
3449 bp += NFSX_UNSIGNED;
3451 /* And loop around copying the name */
3455 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3456 if ((bp + xfer) > be)
3460 bcopy(cp, bp, tsiz);
3465 /* And null pad to a int32_t boundary */
3466 for (i = 0; i < rem; i++)
3470 * Now copy the flrep structure out.
3472 xfer = sizeof (struct flrep);
3475 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3476 if ((bp + xfer) > be)
3480 bcopy(cp, bp, tsiz);
3487 dp = _DIRENT_NEXT(dp);
3494 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3496 bp += NFSX_UNSIGNED;
3497 tl = nfsm_clget(&info, mp1, mp2, bp, be);
3502 bp += NFSX_UNSIGNED;
3503 if (mp1 != info.mb) {
3505 mp1->m_len = bp - mtod(mp1, caddr_t);
3507 mp1->m_len += bp - info.bpos;
3508 kfree((caddr_t)cookies, M_TEMP);
3509 kfree((caddr_t)rbuf, M_TEMP);
3518 * nfs commit service
3521 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3522 struct thread *td, struct mbuf **mrq)
3524 struct sockaddr *nam = nfsd->nd_nam;
3525 struct ucred *cred = &nfsd->nd_cr;
3526 struct vattr bfor, aft;
3527 struct vnode *vp = NULL;
3528 struct mount *mp = NULL;
3532 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
3534 struct nfsm_info info;
3536 info.mrep = nfsd->nd_mrep;
3538 info.md = nfsd->nd_md;
3539 info.dpos = nfsd->nd_dpos;
3541 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3542 fhp = &nfh.fh_generic;
3543 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
3544 NULLOUT(tl = nfsm_dissect(&info, 3 * NFSX_UNSIGNED));
3547 * XXX At this time VOP_FSYNC() does not accept offset and byte
3548 * count parameters, so these arguments are useless (someday maybe).
3550 off = fxdr_hyper(tl);
3552 cnt = fxdr_unsigned(int, *tl);
3553 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
3554 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3556 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3557 2 * NFSX_UNSIGNED, &error));
3558 nfsm_srvwcc_data(&info, nfsd, for_ret, &bfor,
3563 for_ret = VOP_GETATTR(vp, &bfor);
3566 * RFC 1813 3.3.21: If count is 0, a flush from offset to the end of
3567 * file is done. At this time VOP_FSYNC does not accept offset and
3568 * byte count parameters, so call VOP_FSYNC the whole file for now.
3570 if (cnt == 0 || cnt > MAX_COMMIT_COUNT) {
3572 * Give up and do the whole thing
3575 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3576 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
3578 error = VOP_FSYNC(vp, MNT_WAIT, 0);
3581 * Locate and synchronously write any buffers that fall
3582 * into the requested range. Note: we are assuming that
3583 * f_iosize is a power of 2.
3585 int iosize = vp->v_mount->mnt_stat.f_iosize;
3586 int iomask = iosize - 1;
3590 * Align to iosize boundry, super-align to page boundry.
3593 cnt += off & iomask;
3594 off &= ~(u_quad_t)iomask;
3596 if (off & PAGE_MASK) {
3597 cnt += off & PAGE_MASK;
3598 off &= ~(u_quad_t)PAGE_MASK;
3603 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
3604 vm_object_page_clean(vp->v_object, off / PAGE_SIZE,
3605 (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
3613 * If we have a buffer and it is marked B_DELWRI we
3614 * have to lock and write it. Otherwise the prior
3615 * write is assumed to have already been committed.
3617 * WARNING: FINDBLK_TEST buffers represent stable
3618 * storage but not necessarily stable
3619 * content. It is ok in this case.
3621 if ((bp = findblk(vp, loffset, FINDBLK_TEST)) != NULL) {
3622 if (bp->b_flags & B_DELWRI)
3623 bp = findblk(vp, loffset, 0);
3628 if (bp->b_flags & B_DELWRI) {
3645 aft_ret = VOP_GETATTR(vp, &aft);
3648 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3649 NFSX_V3WCCDATA + NFSX_V3WRITEVERF,
3651 nfsm_srvwcc_data(&info, nfsd, for_ret, &bfor,
3654 tl = nfsm_build(&info, NFSX_V3WRITEVERF);
3655 if (nfsver.tv_sec == 0)
3657 *tl++ = txdr_unsigned(nfsver.tv_sec);
3658 *tl = txdr_unsigned(nfsver.tv_nsec / 1000);
3670 * nfs statfs service
3673 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3674 struct thread *td, struct mbuf **mrq)
3676 struct sockaddr *nam = nfsd->nd_nam;
3677 struct ucred *cred = &nfsd->nd_cr;
3679 struct nfs_statfs *sfp;
3680 int error = 0, rdonly, getret = 1;
3681 struct vnode *vp = NULL;
3682 struct mount *mp = NULL;
3686 struct statfs statfs;
3688 struct nfsm_info info;
3690 info.mrep = nfsd->nd_mrep;
3692 info.md = nfsd->nd_md;
3693 info.dpos = nfsd->nd_dpos;
3694 info.v3 = (nfsd->nd_flag & ND_NFSV3);
3696 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3697 fhp = &nfh.fh_generic;
3698 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
3699 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
3700 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3702 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
3703 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3708 error = VFS_STATFS(vp->v_mount, sf, proc0.p_ucred);
3709 getret = VOP_GETATTR(vp, &at);
3712 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3713 NFSX_POSTOPATTR(info.v3) + NFSX_STATFS(info.v3),
3716 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3721 sfp = nfsm_build(&info, NFSX_STATFS(info.v3));
3723 tval = (u_quad_t)sf->f_blocks;
3724 tval *= (u_quad_t)sf->f_bsize;
3725 txdr_hyper(tval, &sfp->sf_tbytes);
3726 tval = (u_quad_t)sf->f_bfree;
3727 tval *= (u_quad_t)sf->f_bsize;
3728 txdr_hyper(tval, &sfp->sf_fbytes);
3729 tval = (u_quad_t)sf->f_bavail;
3730 tval *= (u_quad_t)sf->f_bsize;
3731 txdr_hyper(tval, &sfp->sf_abytes);
3732 sfp->sf_tfiles.nfsuquad[0] = 0;
3733 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
3734 sfp->sf_ffiles.nfsuquad[0] = 0;
3735 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3736 sfp->sf_afiles.nfsuquad[0] = 0;
3737 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
3738 sfp->sf_invarsec = 0;
3740 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3741 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3742 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3743 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3744 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3754 * nfs fsinfo service
3757 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3758 struct thread *td, struct mbuf **mrq)
3760 struct sockaddr *nam = nfsd->nd_nam;
3761 struct ucred *cred = &nfsd->nd_cr;
3762 struct nfsv3_fsinfo *sip;
3763 int error = 0, rdonly, getret = 1, pref;
3764 struct vnode *vp = NULL;
3765 struct mount *mp = NULL;
3771 struct nfsm_info info;
3773 info.mrep = nfsd->nd_mrep;
3775 info.md = nfsd->nd_md;
3776 info.dpos = nfsd->nd_dpos;
3778 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3779 fhp = &nfh.fh_generic;
3780 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
3781 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
3782 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3784 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
3785 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3790 /* XXX Try to make a guess on the max file size. */
3791 VFS_STATFS(vp->v_mount, &sb, proc0.p_ucred);
3792 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3794 getret = VOP_GETATTR(vp, &at);
3797 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3798 NFSX_V3POSTOPATTR + NFSX_V3FSINFO, &error));
3799 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3800 sip = nfsm_build(&info, NFSX_V3FSINFO);
3804 * There should be file system VFS OP(s) to get this information.
3805 * For now, assume ufs.
3807 if (slp->ns_so->so_type == SOCK_DGRAM)
3808 pref = NFS_MAXDGRAMDATA;
3811 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA);
3812 sip->fs_rtpref = txdr_unsigned(pref);
3813 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3814 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA);
3815 sip->fs_wtpref = txdr_unsigned(pref);
3816 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3817 sip->fs_dtpref = txdr_unsigned(pref);
3818 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3819 sip->fs_timedelta.nfsv3_sec = 0;
3820 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3821 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3822 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3823 NFSV3FSINFO_CANSETTIME);
3832 * nfs pathconf service
3835 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3836 struct thread *td, struct mbuf **mrq)
3838 struct sockaddr *nam = nfsd->nd_nam;
3839 struct ucred *cred = &nfsd->nd_cr;
3840 struct nfsv3_pathconf *pc;
3841 int error = 0, rdonly, getret = 1;
3842 register_t linkmax, namemax, chownres, notrunc;
3843 struct vnode *vp = NULL;
3844 struct mount *mp = NULL;
3848 struct nfsm_info info;
3850 info.mrep = nfsd->nd_mrep;
3852 info.md = nfsd->nd_md;
3853 info.dpos = nfsd->nd_dpos;
3855 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3856 fhp = &nfh.fh_generic;
3857 NEGREPLYOUT(nfsm_srvmtofh(&info, nfsd, fhp, &error));
3858 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam,
3859 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE);
3861 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, NFSX_UNSIGNED, &error));
3862 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3866 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3868 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3870 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3872 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
3873 getret = VOP_GETATTR(vp, &at);
3876 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp,
3877 NFSX_V3POSTOPATTR + NFSX_V3PATHCONF,
3879 nfsm_srvpostop_attr(&info, nfsd, getret, &at);
3884 pc = nfsm_build(&info, NFSX_V3PATHCONF);
3886 pc->pc_linkmax = txdr_unsigned(linkmax);
3887 pc->pc_namemax = txdr_unsigned(namemax);
3888 pc->pc_notrunc = txdr_unsigned(notrunc);
3889 pc->pc_chownrestricted = txdr_unsigned(chownres);
3892 * These should probably be supported by VOP_PATHCONF(), but
3893 * until msdosfs is exportable (why would you want to?), the
3894 * Unix defaults should be ok.
3896 pc->pc_caseinsensitive = nfs_false;
3897 pc->pc_casepreserving = nfs_true;
3906 * Null operation, used by clients to ping server
3910 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3911 struct thread *td, struct mbuf **mrq)
3913 struct nfsm_info info;
3914 int error = NFSERR_RETVOID;
3916 info.mrep = nfsd->nd_mrep;
3919 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3920 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
3927 * No operation, used for obsolete procedures
3931 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3932 struct thread *td, struct mbuf **mrq)
3934 struct nfsm_info info;
3937 info.mrep = nfsd->nd_mrep;
3940 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3941 if (nfsd->nd_repstat)
3942 error = nfsd->nd_repstat;
3944 error = EPROCUNAVAIL;
3945 NEGKEEPOUT(nfsm_reply(&info, nfsd, slp, 0, &error));
3953 * Perform access checking for vnodes obtained from file handles that would
3954 * refer to files already opened by a Unix client. You cannot just use
3955 * vn_writechk() and VOP_ACCESS() for two reasons.
3956 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3957 * 2 - The owner is to be given access irrespective of mode bits for some
3958 * operations, so that processes that chmod after opening a file don't
3959 * break. I don't like this because it opens a security hole, but since
3960 * the nfs server opens a security hole the size of a barn door anyhow,
3963 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3964 * will return EPERM instead of EACCESS. EPERM is always an error.
3967 nfsrv_access(struct mount *mp, struct vnode *vp, int flags, struct ucred *cred,
3968 int rdonly, struct thread *td, int override)
3973 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3974 if (flags & VWRITE) {
3975 /* Just vn_writechk() changed to check rdonly */
3977 * Disallow write attempts on read-only file systems;
3978 * unless the file is a socket or a block or character
3979 * device resident on the file system.
3982 ((mp->mnt_flag | vp->v_mount->mnt_flag) & MNT_RDONLY)) {
3983 switch (vp->v_type) {
3993 * If there's shared text associated with
3994 * the inode, we can't allow writing.
3996 if (vp->v_flag & VTEXT)
3999 error = VOP_GETATTR(vp, &vattr);
4002 error = VOP_ACCESS(vp, flags, cred); /* XXX ruid/rgid vs uid/gid */
4004 * Allow certain operations for the owner (reads and writes
4005 * on files that are already open).
4007 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
4011 #endif /* NFS_NOSERVER */