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 $
38 * $DragonFly: src/sys/vfs/nfs/nfs_serv.c,v 1.47 2008/07/14 17:45:49 dillon Exp $
42 * nfs version 2 and 3 server calls to vnode ops
43 * - these routines generally have 3 phases
44 * 1 - break down and validate rpc request in mbuf list
45 * 2 - do the vnode ops for the request
46 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
47 * 3 - build the rpc reply in an mbuf list
49 * - do not mix the phases, since the nfsm_?? macros can return failures
50 * on a bad rpc or similar and do not do any vrele() or vput()'s
52 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
53 * error number iff error != 0 whereas
54 * returning an error from the server function implies a fatal error
55 * such as a badly constructed rpc request that should be dropped without
57 * For Version 3, nfsm_reply() does not return for the error case, since
58 * most version 3 rpcs return more than the status for error cases.
61 * Warning: always pay careful attention to resource cleanup on return
62 * and note that nfsm_*() macros can terminate a procedure on certain
66 #include <sys/param.h>
67 #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_zone.h>
87 #include <vm/vm_object.h>
91 #include <sys/thread2.h>
97 #include "nfsm_subs.h"
100 #define nfsdbprintf(info) kprintf info
102 #define nfsdbprintf(info)
105 #define MAX_COMMIT_COUNT (1024 * 1024)
107 #define NUM_HEURISTIC 1017
108 #define NHUSE_INIT 64
110 #define NHUSE_MAX 2048
112 static struct nfsheur
{
113 struct vnode
*nh_vp
; /* vp to match (unreferenced pointer) */
114 off_t nh_nextr
; /* next offset for sequential detection */
115 int nh_use
; /* use count for selection */
116 int nh_seqcount
; /* heuristic */
117 } nfsheur
[NUM_HEURISTIC
];
119 nfstype nfsv3_type
[9] = { NFNON
, NFREG
, NFDIR
, NFBLK
, NFCHR
, NFLNK
, NFSOCK
,
122 nfstype nfsv2_type
[9] = { NFNON
, NFREG
, NFDIR
, NFBLK
, NFCHR
, NFLNK
, NFNON
,
125 extern u_int32_t nfs_xdrneg1
;
126 extern u_int32_t nfs_false
, nfs_true
;
127 extern enum vtype nv3tov_type
[8];
128 extern struct nfsstats nfsstats
;
130 int nfsrvw_procrastinate
= NFS_GATHERDELAY
* 1000;
131 int nfsrvw_procrastinate_v3
= 0;
133 static struct timespec nfsver
;
135 SYSCTL_DECL(_vfs_nfs
);
138 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, async
, CTLFLAG_RW
, &nfs_async
, 0, "");
139 static int nfs_commit_blks
;
140 static int nfs_commit_miss
;
141 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, commit_blks
, CTLFLAG_RW
, &nfs_commit_blks
, 0, "");
142 SYSCTL_INT(_vfs_nfs
, OID_AUTO
, commit_miss
, CTLFLAG_RW
, &nfs_commit_miss
, 0, "");
144 static int nfsrv_access (struct vnode
*,int,struct ucred
*,int,
145 struct thread
*, int);
146 static void nfsrvw_coalesce (struct nfsrv_descript
*,
147 struct nfsrv_descript
*);
150 * nfs v3 access service
153 nfsrv3_access(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
154 struct thread
*td
, struct mbuf
**mrq
)
156 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
157 struct sockaddr
*nam
= nfsd
->nd_nam
;
158 caddr_t dpos
= nfsd
->nd_dpos
;
159 struct ucred
*cred
= &nfsd
->nd_cr
;
160 struct vnode
*vp
= NULL
;
166 int error
= 0, rdonly
, getret
;
168 struct mbuf
*mb
, *mreq
, *mb2
;
169 struct vattr vattr
, *vap
= &vattr
;
170 u_long testmode
, nfsmode
;
172 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
173 fhp
= &nfh
.fh_generic
;
175 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
176 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
, &rdonly
,
177 (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
179 nfsm_reply(NFSX_UNSIGNED
);
180 nfsm_srvpostop_attr(1, (struct vattr
*)0);
184 nfsmode
= fxdr_unsigned(u_int32_t
, *tl
);
185 if ((nfsmode
& NFSV3ACCESS_READ
) &&
186 nfsrv_access(vp
, VREAD
, cred
, rdonly
, td
, 0))
187 nfsmode
&= ~NFSV3ACCESS_READ
;
188 if (vp
->v_type
== VDIR
)
189 testmode
= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
|
192 testmode
= (NFSV3ACCESS_MODIFY
| NFSV3ACCESS_EXTEND
);
193 if ((nfsmode
& testmode
) &&
194 nfsrv_access(vp
, VWRITE
, cred
, rdonly
, td
, 0))
195 nfsmode
&= ~testmode
;
196 if (vp
->v_type
== VDIR
)
197 testmode
= NFSV3ACCESS_LOOKUP
;
199 testmode
= NFSV3ACCESS_EXECUTE
;
200 if ((nfsmode
& testmode
) &&
201 nfsrv_access(vp
, VEXEC
, cred
, rdonly
, td
, 0))
202 nfsmode
&= ~testmode
;
203 getret
= VOP_GETATTR(vp
, vap
);
206 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED
);
207 nfsm_srvpostop_attr(getret
, vap
);
208 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
209 *tl
= txdr_unsigned(nfsmode
);
217 * nfs getattr service
220 nfsrv_getattr(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
221 struct thread
*td
, struct mbuf
**mrq
)
223 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
224 struct sockaddr
*nam
= nfsd
->nd_nam
;
225 caddr_t dpos
= nfsd
->nd_dpos
;
226 struct ucred
*cred
= &nfsd
->nd_cr
;
227 struct nfs_fattr
*fp
;
229 struct vattr
*vap
= &va
;
230 struct vnode
*vp
= NULL
;
236 int error
= 0, rdonly
;
238 struct mbuf
*mb
, *mb2
, *mreq
;
240 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
241 fhp
= &nfh
.fh_generic
;
243 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
244 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
250 error
= VOP_GETATTR(vp
, vap
);
253 nfsm_reply(NFSX_FATTR(nfsd
->nd_flag
& ND_NFSV3
));
258 nfsm_build(fp
, struct nfs_fattr
*, NFSX_FATTR(nfsd
->nd_flag
& ND_NFSV3
));
259 nfsm_srvfillattr(vap
, fp
);
269 * nfs setattr service
272 nfsrv_setattr(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
273 struct thread
*td
, struct mbuf
**mrq
)
275 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
276 struct sockaddr
*nam
= nfsd
->nd_nam
;
277 caddr_t dpos
= nfsd
->nd_dpos
;
278 struct ucred
*cred
= &nfsd
->nd_cr
;
279 struct vattr va
, preat
;
280 struct vattr
*vap
= &va
;
281 struct nfsv2_sattr
*sp
;
282 struct nfs_fattr
*fp
;
283 struct vnode
*vp
= NULL
;
289 int error
= 0, rdonly
, preat_ret
= 1, postat_ret
= 1;
290 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), gcheck
= 0;
292 struct mbuf
*mb
, *mb2
, *mreq
;
293 struct timespec guard
;
295 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
296 fhp
= &nfh
.fh_generic
;
301 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
302 gcheck
= fxdr_unsigned(int, *tl
);
304 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
305 fxdr_nfsv3time(tl
, &guard
);
308 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
310 * Nah nah nah nah na nah
311 * There is a bug in the Sun client that puts 0xffff in the mode
312 * field of sattr when it should put in 0xffffffff. The u_short
313 * doesn't sign extend.
314 * --> check the low order 2 bytes for 0xffff
316 if ((fxdr_unsigned(int, sp
->sa_mode
) & 0xffff) != 0xffff)
317 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
318 if (sp
->sa_uid
!= nfs_xdrneg1
)
319 vap
->va_uid
= fxdr_unsigned(uid_t
, sp
->sa_uid
);
320 if (sp
->sa_gid
!= nfs_xdrneg1
)
321 vap
->va_gid
= fxdr_unsigned(gid_t
, sp
->sa_gid
);
322 if (sp
->sa_size
!= nfs_xdrneg1
)
323 vap
->va_size
= fxdr_unsigned(u_quad_t
, sp
->sa_size
);
324 if (sp
->sa_atime
.nfsv2_sec
!= nfs_xdrneg1
) {
326 fxdr_nfsv2time(&sp
->sa_atime
, &vap
->va_atime
);
328 vap
->va_atime
.tv_sec
=
329 fxdr_unsigned(int32_t, sp
->sa_atime
.nfsv2_sec
);
330 vap
->va_atime
.tv_nsec
= 0;
333 if (sp
->sa_mtime
.nfsv2_sec
!= nfs_xdrneg1
)
334 fxdr_nfsv2time(&sp
->sa_mtime
, &vap
->va_mtime
);
339 * Now that we have all the fields, lets do it.
341 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
, &rdonly
,
342 (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
344 nfsm_reply(2 * NFSX_UNSIGNED
);
345 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
351 * vp now an active resource, pay careful attention to cleanup
355 error
= preat_ret
= VOP_GETATTR(vp
, &preat
);
356 if (!error
&& gcheck
&&
357 (preat
.va_ctime
.tv_sec
!= guard
.tv_sec
||
358 preat
.va_ctime
.tv_nsec
!= guard
.tv_nsec
))
359 error
= NFSERR_NOT_SYNC
;
363 nfsm_reply(NFSX_WCCDATA(v3
));
364 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
371 * If the size is being changed write acces is required, otherwise
372 * just check for a read only file system.
374 if (vap
->va_size
== ((u_quad_t
)((quad_t
) -1))) {
375 if (rdonly
|| (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
380 if (vp
->v_type
== VDIR
) {
383 } else if ((error
= nfsrv_access(vp
, VWRITE
, cred
, rdonly
,
388 error
= VOP_SETATTR(vp
, vap
, cred
);
389 postat_ret
= VOP_GETATTR(vp
, vap
);
395 nfsm_reply(NFSX_WCCORFATTR(v3
));
397 nfsm_srvwcc_data(preat_ret
, &preat
, postat_ret
, vap
);
401 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
402 nfsm_srvfillattr(vap
, fp
);
416 nfsrv_lookup(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
417 struct thread
*td
, struct mbuf
**mrq
)
419 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
420 struct sockaddr
*nam
= nfsd
->nd_nam
;
421 caddr_t dpos
= nfsd
->nd_dpos
;
422 struct ucred
*cred
= &nfsd
->nd_cr
;
423 struct nfs_fattr
*fp
;
424 struct nlookupdata nd
;
434 int error
= 0, len
, dirattr_ret
= 1;
435 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), pubflag
;
437 struct mbuf
*mb
, *mb2
, *mreq
;
438 struct vattr va
, dirattr
, *vap
= &va
;
440 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
445 fhp
= &nfh
.fh_generic
;
447 nfsm_srvnamesiz(len
);
449 pubflag
= nfs_ispublicfh(fhp
);
451 error
= nfs_namei(&nd
, cred
, NAMEI_LOOKUP
, NULL
, &vp
,
452 fhp
, len
, slp
, nam
, &md
, &dpos
,
453 &dirp
, td
, (nfsd
->nd_flag
& ND_KERBAUTH
), pubflag
);
456 * namei failure, only dirp to cleanup. Clear out garbarge from
457 * structure in case macros jump to nfsmout.
463 dirattr_ret
= VOP_GETATTR(dirp
, &dirattr
);
467 nfsm_reply(NFSX_POSTOPATTR(v3
));
468 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
474 * Locate index file for public filehandle
476 * error is 0 on entry and 0 on exit from this block.
480 if (vp
->v_type
== VDIR
&& nfs_pub
.np_index
!= NULL
) {
482 * Setup call to lookup() to see if we can find
483 * the index file. Arguably, this doesn't belong
484 * in a kernel.. Ugh. If an error occurs, do not
485 * try to install an index file and then clear the
488 * When we replace nd with ind and redirect ndp,
489 * maintenance of ni_startdir and ni_vp shift to
490 * ind and we have to clean them up in the old nd.
491 * However, the cnd resource continues to be maintained
492 * via the original nd. Confused? You aren't alone!
495 cache_copy(&nd
.nl_nch
, &nch
);
497 error
= nlookup_init_raw(&nd
, nfs_pub
.np_index
,
498 UIO_SYSSPACE
, 0, cred
, &nch
);
501 error
= nlookup(&nd
);
505 * Found an index file. Get rid of
506 * the old references. transfer vp and
507 * load up the new vp. Fortunately we do
508 * not have to deal with dvp, that would be
515 error
= cache_vget(&nd
.nl_nch
, nd
.nl_cred
,
517 KKASSERT(error
== 0);
522 * If the public filehandle was used, check that this lookup
523 * didn't result in a filehandle outside the publicly exported
524 * filesystem. We clear the poor vp here to avoid lockups due
528 if (vp
->v_mount
!= nfs_pub
.np_mount
) {
537 dirattr_ret
= VOP_GETATTR(dirp
, &dirattr
);
543 * Resources at this point:
544 * ndp->ni_vp may not be NULL
549 nfsm_reply(NFSX_POSTOPATTR(v3
));
550 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
556 * Clear out some resources prior to potentially blocking. This
557 * is not as critical as ni_dvp resources in other routines, but
563 * Get underlying attribute, then release remaining resources ( for
564 * the same potential blocking reason ) and reply.
566 bzero((caddr_t
)fhp
, sizeof(nfh
));
567 fhp
->fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
568 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
570 error
= VOP_GETATTR(vp
, vap
);
574 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPORFATTR(v3
) + NFSX_POSTOPATTR(v3
));
576 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
580 nfsm_srvfhtom(fhp
, v3
);
582 nfsm_srvpostop_attr(0, vap
);
583 nfsm_srvpostop_attr(dirattr_ret
, &dirattr
);
585 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
586 nfsm_srvfillattr(vap
, fp
);
592 nlookup_done(&nd
); /* may be called twice */
599 * nfs readlink service
602 nfsrv_readlink(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
603 struct thread
*td
, struct mbuf
**mrq
)
605 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
606 struct sockaddr
*nam
= nfsd
->nd_nam
;
607 caddr_t dpos
= nfsd
->nd_dpos
;
608 struct ucred
*cred
= &nfsd
->nd_cr
;
609 struct iovec iv
[(NFS_MAXPATHLEN
+MLEN
-1)/MLEN
];
610 struct iovec
*ivp
= iv
;
615 int error
= 0, rdonly
, i
, tlen
, len
, getret
;
616 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
618 struct mbuf
*mb
, *mb2
, *mp2
, *mp3
, *mreq
;
619 struct vnode
*vp
= NULL
;
623 struct uio io
, *uiop
= &io
;
625 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
627 mp2
= (struct mbuf
*)0;
630 fhp
= &nfh
.fh_generic
;
634 while (len
< NFS_MAXPATHLEN
) {
635 mp
= m_getcl(MB_WAIT
, MT_DATA
, 0);
636 mp
->m_len
= MCLBYTES
;
643 if ((len
+mp
->m_len
) > NFS_MAXPATHLEN
) {
644 mp
->m_len
= NFS_MAXPATHLEN
-len
;
645 len
= NFS_MAXPATHLEN
;
648 ivp
->iov_base
= mtod(mp
, caddr_t
);
649 ivp
->iov_len
= mp
->m_len
;
654 uiop
->uio_iovcnt
= i
;
655 uiop
->uio_offset
= 0;
656 uiop
->uio_resid
= len
;
657 uiop
->uio_rw
= UIO_READ
;
658 uiop
->uio_segflg
= UIO_SYSSPACE
;
660 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
661 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
663 nfsm_reply(2 * NFSX_UNSIGNED
);
664 nfsm_srvpostop_attr(1, (struct vattr
*)0);
668 if (vp
->v_type
!= VLNK
) {
675 error
= VOP_READLINK(vp
, uiop
, cred
);
677 getret
= VOP_GETATTR(vp
, &attr
);
680 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_UNSIGNED
);
682 nfsm_srvpostop_attr(getret
, &attr
);
688 if (uiop
->uio_resid
> 0) {
689 len
-= uiop
->uio_resid
;
690 tlen
= nfsm_rndup(len
);
691 nfsm_adj(mp3
, NFS_MAXPATHLEN
-tlen
, tlen
-len
);
693 nfsm_build(tl
, u_int32_t
*, NFSX_UNSIGNED
);
694 *tl
= txdr_unsigned(len
);
709 nfsrv_read(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
710 struct thread
*td
, struct mbuf
**mrq
)
712 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
713 struct sockaddr
*nam
= nfsd
->nd_nam
;
714 caddr_t dpos
= nfsd
->nd_dpos
;
715 struct ucred
*cred
= &nfsd
->nd_cr
;
719 struct nfs_fattr
*fp
;
724 int error
= 0, rdonly
, cnt
, len
, left
, siz
, tlen
, getret
;
725 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), reqlen
;
727 struct mbuf
*mb
, *mb2
, *mreq
;
729 struct vnode
*vp
= NULL
;
732 struct uio io
, *uiop
= &io
;
733 struct vattr va
, *vap
= &va
;
738 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
739 fhp
= &nfh
.fh_generic
;
742 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
743 off
= fxdr_hyper(tl
);
745 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
746 off
= (off_t
)fxdr_unsigned(u_int32_t
, *tl
);
748 nfsm_srvstrsiz(reqlen
, NFS_SRVMAXDATA(nfsd
));
751 * Reference vp. If an error occurs, vp will be invalid, but we
752 * have to NULL it just in case. The macros might goto nfsmout
756 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
757 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
760 nfsm_reply(2 * NFSX_UNSIGNED
);
761 nfsm_srvpostop_attr(1, (struct vattr
*)0);
766 if (vp
->v_type
!= VREG
) {
770 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
773 if ((error
= nfsrv_access(vp
, VREAD
, cred
, rdonly
, td
, 1)) != 0)
774 error
= nfsrv_access(vp
, VEXEC
, cred
, rdonly
, td
, 1);
776 getret
= VOP_GETATTR(vp
, vap
);
782 nfsm_reply(NFSX_POSTOPATTR(v3
));
783 nfsm_srvpostop_attr(getret
, vap
);
789 * Calculate byte count to read
792 if (off
>= vap
->va_size
)
794 else if ((off
+ reqlen
) > vap
->va_size
)
795 cnt
= vap
->va_size
- off
;
800 * Calculate seqcount for heuristic
808 * Locate best candidate
811 hi
= ((int)(vm_offset_t
)vp
/ sizeof(struct vnode
)) % NUM_HEURISTIC
;
815 if (nfsheur
[hi
].nh_vp
== vp
) {
819 if (nfsheur
[hi
].nh_use
> 0)
820 --nfsheur
[hi
].nh_use
;
821 hi
= (hi
+ 1) % NUM_HEURISTIC
;
822 if (nfsheur
[hi
].nh_use
< nh
->nh_use
)
826 if (nh
->nh_vp
!= vp
) {
829 nh
->nh_use
= NHUSE_INIT
;
837 * Calculate heuristic
840 if ((off
== 0 && nh
->nh_seqcount
> 0) || off
== nh
->nh_nextr
) {
841 if (++nh
->nh_seqcount
> IO_SEQMAX
)
842 nh
->nh_seqcount
= IO_SEQMAX
;
843 } else if (nh
->nh_seqcount
> 1) {
848 nh
->nh_use
+= NHUSE_INC
;
849 if (nh
->nh_use
> NHUSE_MAX
)
850 nh
->nh_use
= NHUSE_MAX
;
851 ioflag
|= nh
->nh_seqcount
<< IO_SEQSHIFT
;
854 nfsm_reply(NFSX_POSTOPORFATTR(v3
) + 3 * NFSX_UNSIGNED
+nfsm_rndup(cnt
));
856 nfsm_build(tl
, u_int32_t
*, NFSX_V3FATTR
+ 4 * NFSX_UNSIGNED
);
858 fp
= (struct nfs_fattr
*)tl
;
859 tl
+= (NFSX_V3FATTR
/ sizeof (u_int32_t
));
861 nfsm_build(tl
, u_int32_t
*, NFSX_V2FATTR
+ NFSX_UNSIGNED
);
862 fp
= (struct nfs_fattr
*)tl
;
863 tl
+= (NFSX_V2FATTR
/ sizeof (u_int32_t
));
865 len
= left
= nfsm_rndup(cnt
);
868 * Generate the mbuf list with the uio_iov ref. to it.
873 siz
= min(M_TRAILINGSPACE(m
), left
);
879 m
= m_getcl(MB_WAIT
, MT_DATA
, 0);
885 MALLOC(iv
, struct iovec
*, i
* sizeof (struct iovec
),
887 uiop
->uio_iov
= iv2
= iv
;
893 panic("nfsrv_read iov");
894 siz
= min(M_TRAILINGSPACE(m
), left
);
896 iv
->iov_base
= mtod(m
, caddr_t
) + m
->m_len
;
905 uiop
->uio_iovcnt
= i
;
906 uiop
->uio_offset
= off
;
907 uiop
->uio_resid
= len
;
908 uiop
->uio_rw
= UIO_READ
;
909 uiop
->uio_segflg
= UIO_SYSSPACE
;
910 error
= VOP_READ(vp
, uiop
, IO_NODELOCKED
| ioflag
, cred
);
911 off
= uiop
->uio_offset
;
913 FREE((caddr_t
)iv2
, M_TEMP
);
914 if (error
|| (getret
= VOP_GETATTR(vp
, vap
))) {
920 nfsm_reply(NFSX_POSTOPATTR(v3
));
921 nfsm_srvpostop_attr(getret
, vap
);
930 nfsm_srvfillattr(vap
, fp
);
931 tlen
= len
- uiop
->uio_resid
;
932 cnt
= cnt
< tlen
? cnt
: tlen
;
933 tlen
= nfsm_rndup(cnt
);
934 if (len
!= tlen
|| tlen
!= cnt
)
935 nfsm_adj(mb
, len
- tlen
, tlen
- cnt
);
937 *tl
++ = txdr_unsigned(cnt
);
943 *tl
= txdr_unsigned(cnt
);
954 nfsrv_write(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
955 struct thread
*td
, struct mbuf
**mrq
)
957 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
958 struct sockaddr
*nam
= nfsd
->nd_nam
;
959 caddr_t dpos
= nfsd
->nd_dpos
;
960 struct ucred
*cred
= &nfsd
->nd_cr
;
964 struct nfs_fattr
*fp
;
966 struct vattr va
, forat
;
967 struct vattr
*vap
= &va
;
971 int error
= 0, rdonly
, len
, forat_ret
= 1;
972 int ioflags
, aftat_ret
= 1, retlen
, zeroing
, adjust
;
973 int stable
= NFSV3WRITE_FILESYNC
;
974 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
976 struct mbuf
*mb
, *mb2
, *mreq
;
977 struct vnode
*vp
= NULL
;
980 struct uio io
, *uiop
= &io
;
983 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
989 fhp
= &nfh
.fh_generic
;
992 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
993 off
= fxdr_hyper(tl
);
995 stable
= fxdr_unsigned(int, *tl
++);
997 nfsm_dissect(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
998 off
= (off_t
)fxdr_unsigned(u_int32_t
, *++tl
);
1001 stable
= NFSV3WRITE_UNSTABLE
;
1003 retlen
= len
= fxdr_unsigned(int32_t, *tl
);
1007 * For NFS Version 2, it is not obvious what a write of zero length
1008 * should do, but I might as well be consistent with Version 3,
1009 * which is to return ok so long as there are no permission problems.
1017 adjust
= dpos
- mtod(mp
, caddr_t
);
1018 mp
->m_len
-= adjust
;
1019 if (mp
->m_len
> 0 && adjust
> 0)
1020 NFSMADV(mp
, adjust
);
1024 else if (mp
->m_len
> 0) {
1027 mp
->m_len
-= (i
- len
);
1036 if (len
> NFS_MAXDATA
|| len
< 0 || i
< len
) {
1038 nfsm_reply(2 * NFSX_UNSIGNED
);
1039 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1043 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
1044 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
1047 nfsm_reply(2 * NFSX_UNSIGNED
);
1048 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1053 forat_ret
= VOP_GETATTR(vp
, &forat
);
1054 if (vp
->v_type
!= VREG
) {
1058 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
1061 error
= nfsrv_access(vp
, VWRITE
, cred
, rdonly
, td
, 1);
1066 nfsm_reply(NFSX_WCCDATA(v3
));
1067 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1073 MALLOC(ivp
, struct iovec
*, cnt
* sizeof (struct iovec
), M_TEMP
,
1075 uiop
->uio_iov
= iv
= ivp
;
1076 uiop
->uio_iovcnt
= cnt
;
1079 if (mp
->m_len
> 0) {
1080 ivp
->iov_base
= mtod(mp
, caddr_t
);
1081 ivp
->iov_len
= mp
->m_len
;
1089 * The IO_METASYNC flag indicates that all metadata (and not just
1090 * enough to ensure data integrity) mus be written to stable storage
1092 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1094 if (stable
== NFSV3WRITE_UNSTABLE
)
1095 ioflags
= IO_NODELOCKED
;
1096 else if (stable
== NFSV3WRITE_DATASYNC
)
1097 ioflags
= (IO_SYNC
| IO_NODELOCKED
);
1099 ioflags
= (IO_METASYNC
| IO_SYNC
| IO_NODELOCKED
);
1100 uiop
->uio_resid
= len
;
1101 uiop
->uio_rw
= UIO_WRITE
;
1102 uiop
->uio_segflg
= UIO_SYSSPACE
;
1103 uiop
->uio_td
= NULL
;
1104 uiop
->uio_offset
= off
;
1105 error
= VOP_WRITE(vp
, uiop
, ioflags
, cred
);
1106 nfsstats
.srvvop_writes
++;
1107 FREE((caddr_t
)iv
, M_TEMP
);
1109 aftat_ret
= VOP_GETATTR(vp
, vap
);
1114 nfsm_reply(NFSX_PREOPATTR(v3
) + NFSX_POSTOPORFATTR(v3
) +
1115 2 * NFSX_UNSIGNED
+ NFSX_WRITEVERF(v3
));
1117 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, vap
);
1122 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1123 *tl
++ = txdr_unsigned(retlen
);
1125 * If nfs_async is set, then pretend the write was FILESYNC.
1127 if (stable
== NFSV3WRITE_UNSTABLE
&& !nfs_async
)
1128 *tl
++ = txdr_unsigned(stable
);
1130 *tl
++ = txdr_unsigned(NFSV3WRITE_FILESYNC
);
1132 * Actually, there is no need to txdr these fields,
1133 * but it may make the values more human readable,
1134 * for debugging purposes.
1136 if (nfsver
.tv_sec
== 0)
1138 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
1139 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
1141 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1142 nfsm_srvfillattr(vap
, fp
);
1151 * NFS write service with write gathering support. Called when
1152 * nfsrvw_procrastinate > 0.
1153 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1154 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1158 nfsrv_writegather(struct nfsrv_descript
**ndp
, struct nfssvc_sock
*slp
,
1159 struct thread
*td
, struct mbuf
**mrq
)
1163 struct nfsrv_descript
*wp
, *nfsd
, *owp
, *swp
;
1164 struct nfs_fattr
*fp
;
1167 struct nfsrvw_delayhash
*wpp
;
1169 struct vattr va
, forat
;
1173 int error
= 0, rdonly
, len
, forat_ret
= 1;
1174 int ioflags
, aftat_ret
= 1, adjust
, v3
, zeroing
;
1176 struct mbuf
*mb
, *mb2
, *mreq
, *mrep
, *md
;
1177 struct vnode
*vp
= NULL
;
1178 struct uio io
, *uiop
= &io
;
1181 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1190 mrep
= nfsd
->nd_mrep
;
1192 dpos
= nfsd
->nd_dpos
;
1193 cred
= &nfsd
->nd_cr
;
1194 v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1195 LIST_INIT(&nfsd
->nd_coalesce
);
1196 nfsd
->nd_mreq
= NULL
;
1197 nfsd
->nd_stable
= NFSV3WRITE_FILESYNC
;
1198 cur_usec
= nfs_curusec();
1199 nfsd
->nd_time
= cur_usec
+
1200 (v3
? nfsrvw_procrastinate_v3
: nfsrvw_procrastinate
);
1203 * Now, get the write header..
1205 nfsm_srvmtofh(&nfsd
->nd_fh
);
1207 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
1208 nfsd
->nd_off
= fxdr_hyper(tl
);
1210 nfsd
->nd_stable
= fxdr_unsigned(int, *tl
++);
1212 nfsm_dissect(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1213 nfsd
->nd_off
= (off_t
)fxdr_unsigned(u_int32_t
, *++tl
);
1216 nfsd
->nd_stable
= NFSV3WRITE_UNSTABLE
;
1218 len
= fxdr_unsigned(int32_t, *tl
);
1220 nfsd
->nd_eoff
= nfsd
->nd_off
+ len
;
1223 * Trim the header out of the mbuf list and trim off any trailing
1224 * junk so that the mbuf list has only the write data.
1232 adjust
= dpos
- mtod(mp
, caddr_t
);
1233 mp
->m_len
-= adjust
;
1234 if (mp
->m_len
> 0 && adjust
> 0)
1235 NFSMADV(mp
, adjust
);
1242 mp
->m_len
-= (i
- len
);
1248 if (len
> NFS_MAXDATA
|| len
< 0 || i
< len
) {
1252 nfsm_writereply(2 * NFSX_UNSIGNED
, v3
);
1254 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1255 nfsd
->nd_mreq
= mreq
;
1256 nfsd
->nd_mrep
= NULL
;
1261 * Add this entry to the hash and time queues.
1265 wp
= slp
->ns_tq
.lh_first
;
1266 while (wp
&& wp
->nd_time
< nfsd
->nd_time
) {
1268 wp
= wp
->nd_tq
.le_next
;
1270 NFS_DPF(WG
, ("Q%03x", nfsd
->nd_retxid
& 0xfff));
1272 LIST_INSERT_AFTER(owp
, nfsd
, nd_tq
);
1274 LIST_INSERT_HEAD(&slp
->ns_tq
, nfsd
, nd_tq
);
1276 if (nfsd
->nd_mrep
) {
1277 wpp
= NWDELAYHASH(slp
, nfsd
->nd_fh
.fh_fid
.fid_data
);
1281 bcmp((caddr_t
)&nfsd
->nd_fh
,(caddr_t
)&wp
->nd_fh
,NFSX_V3FH
)) {
1283 wp
= wp
->nd_hash
.le_next
;
1285 while (wp
&& wp
->nd_off
< nfsd
->nd_off
&&
1286 !bcmp((caddr_t
)&nfsd
->nd_fh
,(caddr_t
)&wp
->nd_fh
,NFSX_V3FH
)) {
1288 wp
= wp
->nd_hash
.le_next
;
1291 LIST_INSERT_AFTER(owp
, nfsd
, nd_hash
);
1294 * Search the hash list for overlapping entries and
1297 for(; nfsd
&& NFSW_CONTIG(owp
, nfsd
); nfsd
= wp
) {
1298 wp
= nfsd
->nd_hash
.le_next
;
1299 if (NFSW_SAMECRED(owp
, nfsd
))
1300 nfsrvw_coalesce(owp
, nfsd
);
1303 LIST_INSERT_HEAD(wpp
, nfsd
, nd_hash
);
1310 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1311 * and generate the associated reply mbuf list(s).
1314 cur_usec
= nfs_curusec();
1316 for (nfsd
= slp
->ns_tq
.lh_first
; nfsd
; nfsd
= owp
) {
1317 owp
= nfsd
->nd_tq
.le_next
;
1318 if (nfsd
->nd_time
> cur_usec
)
1322 NFS_DPF(WG
, ("P%03x", nfsd
->nd_retxid
& 0xfff));
1323 LIST_REMOVE(nfsd
, nd_tq
);
1324 LIST_REMOVE(nfsd
, nd_hash
);
1326 mrep
= nfsd
->nd_mrep
;
1327 nfsd
->nd_mrep
= NULL
;
1328 cred
= &nfsd
->nd_cr
;
1329 v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1330 forat_ret
= aftat_ret
= 1;
1331 error
= nfsrv_fhtovp(&nfsd
->nd_fh
, 1, &vp
, cred
, slp
,
1332 nfsd
->nd_nam
, &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
1335 forat_ret
= VOP_GETATTR(vp
, &forat
);
1336 if (vp
->v_type
!= VREG
) {
1340 error
= (vp
->v_type
== VDIR
) ? EISDIR
: EACCES
;
1346 error
= nfsrv_access(vp
, VWRITE
, cred
, rdonly
, td
, 1);
1349 if (nfsd
->nd_stable
== NFSV3WRITE_UNSTABLE
)
1350 ioflags
= IO_NODELOCKED
;
1351 else if (nfsd
->nd_stable
== NFSV3WRITE_DATASYNC
)
1352 ioflags
= (IO_SYNC
| IO_NODELOCKED
);
1354 ioflags
= (IO_METASYNC
| IO_SYNC
| IO_NODELOCKED
);
1355 uiop
->uio_rw
= UIO_WRITE
;
1356 uiop
->uio_segflg
= UIO_SYSSPACE
;
1357 uiop
->uio_td
= NULL
;
1358 uiop
->uio_offset
= nfsd
->nd_off
;
1359 uiop
->uio_resid
= nfsd
->nd_eoff
- nfsd
->nd_off
;
1360 if (uiop
->uio_resid
> 0) {
1368 uiop
->uio_iovcnt
= i
;
1369 MALLOC(iov
, struct iovec
*, i
* sizeof (struct iovec
),
1371 uiop
->uio_iov
= ivp
= iov
;
1374 if (mp
->m_len
> 0) {
1375 ivp
->iov_base
= mtod(mp
, caddr_t
);
1376 ivp
->iov_len
= mp
->m_len
;
1382 error
= VOP_WRITE(vp
, uiop
, ioflags
, cred
);
1383 nfsstats
.srvvop_writes
++;
1385 FREE((caddr_t
)iov
, M_TEMP
);
1389 aftat_ret
= VOP_GETATTR(vp
, &va
);
1395 * Loop around generating replies for all write rpcs that have
1396 * now been completed.
1400 NFS_DPF(WG
, ("R%03x", nfsd
->nd_retxid
& 0xfff));
1402 nfsm_writereply(NFSX_WCCDATA(v3
), v3
);
1404 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1407 nfsm_writereply(NFSX_PREOPATTR(v3
) +
1408 NFSX_POSTOPORFATTR(v3
) + 2 * NFSX_UNSIGNED
+
1409 NFSX_WRITEVERF(v3
), v3
);
1411 nfsm_srvwcc_data(forat_ret
, &forat
, aftat_ret
, &va
);
1412 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
1413 *tl
++ = txdr_unsigned(nfsd
->nd_len
);
1414 *tl
++ = txdr_unsigned(swp
->nd_stable
);
1416 * Actually, there is no need to txdr these fields,
1417 * but it may make the values more human readable,
1418 * for debugging purposes.
1420 if (nfsver
.tv_sec
== 0)
1422 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
1423 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
1425 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1426 nfsm_srvfillattr(&va
, fp
);
1429 nfsd
->nd_mreq
= mreq
;
1431 panic("nfsrv_write: nd_mrep not free");
1434 * Done. Put it at the head of the timer queue so that
1435 * the final phase can return the reply.
1440 LIST_INSERT_HEAD(&slp
->ns_tq
, nfsd
, nd_tq
);
1442 nfsd
= swp
->nd_coalesce
.lh_first
;
1444 LIST_REMOVE(nfsd
, nd_tq
);
1450 LIST_INSERT_HEAD(&slp
->ns_tq
, swp
, nd_tq
);
1457 * Search for a reply to return.
1460 for (nfsd
= slp
->ns_tq
.lh_first
; nfsd
; nfsd
= nfsd
->nd_tq
.le_next
)
1461 if (nfsd
->nd_mreq
) {
1462 NFS_DPF(WG
, ("X%03x", nfsd
->nd_retxid
& 0xfff));
1463 LIST_REMOVE(nfsd
, nd_tq
);
1464 *mrq
= nfsd
->nd_mreq
;
1473 * Coalesce the write request nfsd into owp. To do this we must:
1474 * - remove nfsd from the queues
1475 * - merge nfsd->nd_mrep into owp->nd_mrep
1476 * - update the nd_eoff and nd_stable for owp
1477 * - put nfsd on owp's nd_coalesce list
1478 * NB: Must be called at splsoftclock().
1481 nfsrvw_coalesce(struct nfsrv_descript
*owp
, struct nfsrv_descript
*nfsd
)
1485 struct nfsrv_descript
*p
;
1487 NFS_DPF(WG
, ("C%03x-%03x",
1488 nfsd
->nd_retxid
& 0xfff, owp
->nd_retxid
& 0xfff));
1489 LIST_REMOVE(nfsd
, nd_hash
);
1490 LIST_REMOVE(nfsd
, nd_tq
);
1491 if (owp
->nd_eoff
< nfsd
->nd_eoff
) {
1492 overlap
= owp
->nd_eoff
- nfsd
->nd_off
;
1494 panic("nfsrv_coalesce: bad off");
1496 m_adj(nfsd
->nd_mrep
, overlap
);
1500 mp
->m_next
= nfsd
->nd_mrep
;
1501 owp
->nd_eoff
= nfsd
->nd_eoff
;
1503 m_freem(nfsd
->nd_mrep
);
1504 nfsd
->nd_mrep
= NULL
;
1505 if (nfsd
->nd_stable
== NFSV3WRITE_FILESYNC
)
1506 owp
->nd_stable
= NFSV3WRITE_FILESYNC
;
1507 else if (nfsd
->nd_stable
== NFSV3WRITE_DATASYNC
&&
1508 owp
->nd_stable
== NFSV3WRITE_UNSTABLE
)
1509 owp
->nd_stable
= NFSV3WRITE_DATASYNC
;
1510 LIST_INSERT_HEAD(&owp
->nd_coalesce
, nfsd
, nd_tq
);
1513 * If nfsd had anything else coalesced into it, transfer them
1514 * to owp, otherwise their replies will never get sent.
1516 for (p
= nfsd
->nd_coalesce
.lh_first
; p
;
1517 p
= nfsd
->nd_coalesce
.lh_first
) {
1518 LIST_REMOVE(p
, nd_tq
);
1519 LIST_INSERT_HEAD(&owp
->nd_coalesce
, p
, nd_tq
);
1524 * nfs create service
1525 * now does a truncate to 0 length via. setattr if it already exists
1528 nfsrv_create(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1529 struct thread
*td
, struct mbuf
**mrq
)
1531 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1532 struct sockaddr
*nam
= nfsd
->nd_nam
;
1533 caddr_t dpos
= nfsd
->nd_dpos
;
1534 struct ucred
*cred
= &nfsd
->nd_cr
;
1535 struct nfs_fattr
*fp
;
1536 struct vattr va
, dirfor
, diraft
;
1537 struct vattr
*vap
= &va
;
1538 struct nfsv2_sattr
*sp
;
1540 struct nlookupdata nd
;
1543 int error
= 0, len
, tsize
, dirfor_ret
= 1, diraft_ret
= 1;
1544 udev_t rdev
= NOUDEV
;
1545 int v3
= (nfsd
->nd_flag
& ND_NFSV3
), how
, exclusive_flag
= 0;
1548 struct mbuf
*mb
, *mb2
, *mreq
;
1555 u_char cverf
[NFSX_V3CREATEVERF
];
1557 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1563 fhp
= &nfh
.fh_generic
;
1565 nfsm_srvnamesiz(len
);
1568 * Call namei and do initial cleanup to get a few things
1569 * out of the way. If we get an initial error we cleanup
1570 * and return here to avoid special-casing the invalid nd
1571 * structure through the rest of the case. dirp may be
1572 * set even if an error occurs, but the nd structure will not
1573 * be valid at all if an error occurs so we have to invalidate it
1574 * prior to calling nfsm_reply ( which might goto nfsmout ).
1576 error
= nfs_namei(&nd
, cred
, NAMEI_CREATE
, &dvp
, &vp
,
1577 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1578 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1581 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1588 nfsm_reply(NFSX_WCCDATA(v3
));
1589 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1595 * No error. Continue. State:
1598 * vp may be valid or NULL if the target does not
1602 * The error state is set through the code and we may also do some
1603 * opportunistic releasing of vnodes to avoid holding locks through
1604 * NFS I/O. The cleanup at the end is a catch-all
1609 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
1610 how
= fxdr_unsigned(int, *tl
);
1612 case NFSV3CREATE_GUARDED
:
1618 case NFSV3CREATE_UNCHECKED
:
1621 case NFSV3CREATE_EXCLUSIVE
:
1622 nfsm_dissect(cp
, caddr_t
, NFSX_V3CREATEVERF
);
1623 bcopy(cp
, cverf
, NFSX_V3CREATEVERF
);
1627 vap
->va_type
= VREG
;
1629 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
1630 vap
->va_type
= IFTOVT(fxdr_unsigned(u_int32_t
, sp
->sa_mode
));
1631 if (vap
->va_type
== VNON
)
1632 vap
->va_type
= VREG
;
1633 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
1634 switch (vap
->va_type
) {
1636 tsize
= fxdr_unsigned(int32_t, sp
->sa_size
);
1638 vap
->va_size
= (u_quad_t
)tsize
;
1643 rdev
= fxdr_unsigned(long, sp
->sa_size
);
1651 * Iff doesn't exist, create it
1652 * otherwise just truncate to 0 length
1653 * should I set the mode too ?
1655 * The only possible error we can have at this point is EEXIST.
1656 * nd.ni_vp will also be non-NULL in that case.
1659 if (vap
->va_mode
== (mode_t
)VNOVAL
)
1661 if (vap
->va_type
== VREG
|| vap
->va_type
== VSOCK
) {
1663 error
= VOP_NCREATE(&nd
.nl_nch
, dvp
, &vp
,
1668 if (exclusive_flag
) {
1671 bcopy(cverf
, (caddr_t
)&vap
->va_atime
,
1673 error
= VOP_SETATTR(vp
, vap
, cred
);
1677 vap
->va_type
== VCHR
||
1678 vap
->va_type
== VBLK
||
1679 vap
->va_type
== VFIFO
1682 * Handle SysV FIFO node special cases. All other
1683 * devices require super user to access.
1685 if (vap
->va_type
== VCHR
&& rdev
== 0xffffffff)
1686 vap
->va_type
= VFIFO
;
1687 if (vap
->va_type
!= VFIFO
&&
1688 (error
= suser_cred(cred
, 0))) {
1691 vap
->va_rmajor
= umajor(rdev
);
1692 vap
->va_rminor
= uminor(rdev
);
1695 error
= VOP_NMKNOD(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1702 * XXX what is this junk supposed to do ?
1709 * release dvp prior to lookup
1717 * Even though LOCKPARENT was cleared, ni_dvp may
1720 nd
.ni_cnd
.cn_nameiop
= NAMEI_LOOKUP
;
1721 nd
.ni_cnd
.cn_flags
&= ~(CNP_LOCKPARENT
);
1722 nd
.ni_cnd
.cn_td
= td
;
1723 nd
.ni_cnd
.cn_cred
= cred
;
1725 error
= lookup(&nd
);
1730 /* fall through on certain errors */
1732 nfsrv_object_create(nd
.ni_vp
);
1733 if (nd
.ni_cnd
.cn_flags
& CNP_ISSYMLINK
) {
1742 if (vap
->va_size
!= -1) {
1743 error
= nfsrv_access(vp
, VWRITE
, cred
,
1744 (nd
.nl_flags
& NLC_NFS_RDONLY
), td
, 0);
1746 tempsize
= vap
->va_size
;
1748 vap
->va_size
= tempsize
;
1749 error
= VOP_SETATTR(vp
, vap
, cred
);
1755 bzero((caddr_t
)fhp
, sizeof(nfh
));
1756 fhp
->fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
1757 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
1759 error
= VOP_GETATTR(vp
, vap
);
1762 if (exclusive_flag
&& !error
&&
1763 bcmp(cverf
, (caddr_t
)&vap
->va_atime
, NFSX_V3CREATEVERF
))
1765 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
1769 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_FATTR(v3
) + NFSX_WCCDATA(v3
));
1772 nfsm_srvpostop_fh(fhp
);
1773 nfsm_srvpostop_attr(0, vap
);
1775 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1778 nfsm_srvfhtom(fhp
, v3
);
1779 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
1780 nfsm_srvfillattr(vap
, fp
);
1805 * nfs v3 mknod service
1808 nfsrv_mknod(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1809 struct thread
*td
, struct mbuf
**mrq
)
1811 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1812 struct sockaddr
*nam
= nfsd
->nd_nam
;
1813 caddr_t dpos
= nfsd
->nd_dpos
;
1814 struct ucred
*cred
= &nfsd
->nd_cr
;
1815 struct vattr va
, dirfor
, diraft
;
1816 struct vattr
*vap
= &va
;
1818 struct nlookupdata nd
;
1821 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
1824 struct mbuf
*mb
, *mb2
, *mreq
;
1831 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1837 fhp
= &nfh
.fh_generic
;
1839 nfsm_srvnamesiz(len
);
1842 * Handle nfs_namei() call. If an error occurs, the nd structure
1843 * is not valid. However, nfsm_*() routines may still jump to
1847 error
= nfs_namei(&nd
, cred
, NAMEI_CREATE
, &dvp
, &vp
,
1848 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1849 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1851 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1853 nfsm_reply(NFSX_WCCDATA(1));
1854 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1858 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
1859 vtyp
= nfsv3tov_type(*tl
);
1860 if (vtyp
!= VCHR
&& vtyp
!= VBLK
&& vtyp
!= VSOCK
&& vtyp
!= VFIFO
) {
1861 error
= NFSERR_BADTYPE
;
1866 if (vtyp
== VCHR
|| vtyp
== VBLK
) {
1867 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
1868 vap
->va_rmajor
= fxdr_unsigned(u_int32_t
, *tl
++);
1869 vap
->va_rminor
= fxdr_unsigned(u_int32_t
, *tl
);
1873 * Iff doesn't exist, create it.
1879 vap
->va_type
= vtyp
;
1880 if (vap
->va_mode
== (mode_t
)VNOVAL
)
1882 if (vtyp
== VSOCK
) {
1884 error
= VOP_NCREATE(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1888 if (vtyp
!= VFIFO
&& (error
= suser_cred(cred
, 0)))
1892 error
= VOP_NMKNOD(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
1900 * send response, cleanup, return.
1912 bzero((caddr_t
)fhp
, sizeof(nfh
));
1913 fhp
->fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
1914 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
1916 error
= VOP_GETATTR(vp
, vap
);
1922 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
1927 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1929 nfsm_srvpostop_fh(fhp
);
1930 nfsm_srvpostop_attr(0, vap
);
1932 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
1950 * nfs remove service
1953 nfsrv_remove(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
1954 struct thread
*td
, struct mbuf
**mrq
)
1956 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
1957 struct sockaddr
*nam
= nfsd
->nd_nam
;
1958 caddr_t dpos
= nfsd
->nd_dpos
;
1959 struct ucred
*cred
= &nfsd
->nd_cr
;
1960 struct nlookupdata nd
;
1964 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
1965 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
1967 struct mbuf
*mb
, *mreq
;
1971 struct vattr dirfor
, diraft
;
1975 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
1981 fhp
= &nfh
.fh_generic
;
1983 nfsm_srvnamesiz(len
);
1985 error
= nfs_namei(&nd
, cred
, NAMEI_DELETE
, &dvp
, &vp
,
1986 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
1987 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
1990 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
1993 if (vp
->v_type
== VDIR
) {
1994 error
= EPERM
; /* POSIX */
1998 * The root of a mounted filesystem cannot be deleted.
2000 if (vp
->v_flag
& VROOT
) {
2012 error
= VOP_NREMOVE(&nd
.nl_nch
, dvp
, nd
.nl_cred
);
2018 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2019 nfsm_reply(NFSX_WCCDATA(v3
));
2021 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2040 * nfs rename service
2043 nfsrv_rename(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2044 struct thread
*td
, struct mbuf
**mrq
)
2046 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2047 struct sockaddr
*nam
= nfsd
->nd_nam
;
2048 caddr_t dpos
= nfsd
->nd_dpos
;
2049 struct ucred
*cred
= &nfsd
->nd_cr
;
2053 int error
= 0, len
, len2
, fdirfor_ret
= 1, fdiraft_ret
= 1;
2054 int tdirfor_ret
= 1, tdiraft_ret
= 1;
2055 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2057 struct mbuf
*mb
, *mreq
;
2058 struct nlookupdata fromnd
, tond
;
2059 struct vnode
*fvp
, *fdirp
, *fdvp
;
2060 struct vnode
*tvp
, *tdirp
, *tdvp
;
2061 struct namecache
*ncp
;
2062 struct vattr fdirfor
, fdiraft
, tdirfor
, tdiraft
;
2064 fhandle_t
*ffhp
, *tfhp
;
2067 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2069 fvp
= (struct vnode
*)0;
2071 ffhp
= &fnfh
.fh_generic
;
2072 tfhp
= &tnfh
.fh_generic
;
2075 * Clear fields incase goto nfsmout occurs from macro.
2078 nlookup_zero(&fromnd
);
2079 nlookup_zero(&tond
);
2083 nfsm_srvmtofh(ffhp
);
2084 nfsm_srvnamesiz(len
);
2086 * Remember our original uid so that we can reset cr_uid before
2087 * the second nfs_namei() call, in case it is remapped.
2089 saved_uid
= cred
->cr_uid
;
2090 error
= nfs_namei(&fromnd
, cred
, NAMEI_DELETE
, NULL
, NULL
,
2091 ffhp
, len
, slp
, nam
, &md
, &dpos
, &fdirp
,
2092 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2095 fdirfor_ret
= VOP_GETATTR(fdirp
, &fdirfor
);
2098 nfsm_reply(2 * NFSX_WCCDATA(v3
));
2099 nfsm_srvwcc_data(fdirfor_ret
, &fdirfor
, fdiraft_ret
, &fdiraft
);
2100 nfsm_srvwcc_data(tdirfor_ret
, &tdirfor
, tdiraft_ret
, &tdiraft
);
2106 * We have to unlock the from ncp before we can safely lookup
2109 KKASSERT(fromnd
.nl_flags
& NLC_NCPISLOCKED
);
2110 cache_unlock(&fromnd
.nl_nch
);
2111 fromnd
.nl_flags
&= ~NLC_NCPISLOCKED
;
2112 nfsm_srvmtofh(tfhp
);
2113 nfsm_strsiz(len2
, NFS_MAXNAMLEN
);
2114 cred
->cr_uid
= saved_uid
;
2116 error
= nfs_namei(&tond
, cred
, NAMEI_RENAME
, NULL
, NULL
,
2117 tfhp
, len2
, slp
, nam
, &md
, &dpos
, &tdirp
,
2118 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2121 tdirfor_ret
= VOP_GETATTR(tdirp
, &tdirfor
);
2129 if (cache_lock_nonblock(&fromnd
.nl_nch
) == 0) {
2130 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2131 } else if (fromnd
.nl_nch
.ncp
> tond
.nl_nch
.ncp
) {
2132 cache_lock(&fromnd
.nl_nch
);
2133 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2135 cache_unlock(&tond
.nl_nch
);
2136 cache_lock(&fromnd
.nl_nch
);
2137 cache_resolve(&fromnd
.nl_nch
, fromnd
.nl_cred
);
2138 cache_lock(&tond
.nl_nch
);
2139 cache_resolve(&tond
.nl_nch
, tond
.nl_cred
);
2141 fromnd
.nl_flags
|= NLC_NCPISLOCKED
;
2143 fvp
= fromnd
.nl_nch
.ncp
->nc_vp
;
2144 tvp
= tond
.nl_nch
.ncp
->nc_vp
;
2147 * Set fdvp and tdvp. We haven't done all the topology checks
2148 * so these can wind up NULL (e.g. if either fvp or tvp is a mount
2149 * point). If we get through the checks these will be guarenteed
2152 * Holding the children ncp's should be sufficient to prevent
2153 * fdvp and tdvp ripouts.
2155 if (fromnd
.nl_nch
.ncp
->nc_parent
)
2156 fdvp
= fromnd
.nl_nch
.ncp
->nc_parent
->nc_vp
;
2159 if (tond
.nl_nch
.ncp
->nc_parent
)
2160 tdvp
= tond
.nl_nch
.ncp
->nc_parent
->nc_vp
;
2165 if (fvp
->v_type
== VDIR
&& tvp
->v_type
!= VDIR
) {
2171 } else if (fvp
->v_type
!= VDIR
&& tvp
->v_type
== VDIR
) {
2178 if (tvp
->v_type
== VDIR
&& (tond
.nl_nch
.ncp
->nc_flag
& NCF_ISMOUNTPT
)) {
2186 if (fvp
->v_type
== VDIR
&& (fromnd
.nl_nch
.ncp
->nc_flag
& NCF_ISMOUNTPT
)) {
2193 if (fromnd
.nl_nch
.mount
!= tond
.nl_nch
.mount
) {
2200 if (fromnd
.nl_nch
.ncp
== tond
.nl_nch
.ncp
->nc_parent
) {
2208 * You cannot rename a source into itself or a subdirectory of itself.
2209 * We check this by travsering the target directory upwards looking
2210 * for a match against the source.
2213 for (ncp
= tond
.nl_nch
.ncp
; ncp
; ncp
= ncp
->nc_parent
) {
2214 if (fromnd
.nl_nch
.ncp
== ncp
) {
2222 * If source is the same as the destination (that is the
2223 * same vnode with the same name in the same directory),
2224 * then there is nothing to do.
2226 if (fromnd
.nl_nch
.ncp
== tond
.nl_nch
.ncp
)
2231 * The VOP_NRENAME function releases all vnode references &
2232 * locks prior to returning so we need to clear the pointers
2233 * to bypass cleanup code later on.
2235 error
= VOP_NRENAME(&fromnd
.nl_nch
, &tond
.nl_nch
,
2236 fdvp
, tdvp
, tond
.nl_cred
);
2245 fdiraft_ret
= VOP_GETATTR(fdirp
, &fdiraft
);
2247 tdiraft_ret
= VOP_GETATTR(tdirp
, &tdiraft
);
2248 nfsm_reply(2 * NFSX_WCCDATA(v3
));
2250 nfsm_srvwcc_data(fdirfor_ret
, &fdirfor
, fdiraft_ret
, &fdiraft
);
2251 nfsm_srvwcc_data(tdirfor_ret
, &tdirfor
, tdiraft_ret
, &tdiraft
);
2259 nlookup_done(&tond
);
2262 nlookup_done(&fromnd
);
2270 nfsrv_link(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2271 struct thread
*td
, struct mbuf
**mrq
)
2273 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2274 struct sockaddr
*nam
= nfsd
->nd_nam
;
2275 caddr_t dpos
= nfsd
->nd_dpos
;
2276 struct ucred
*cred
= &nfsd
->nd_cr
;
2277 struct nlookupdata nd
;
2281 int error
= 0, rdonly
, len
, dirfor_ret
= 1, diraft_ret
= 1;
2282 int getret
= 1, v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2284 struct mbuf
*mb
, *mreq
;
2289 struct vattr dirfor
, diraft
, at
;
2291 fhandle_t
*fhp
, *dfhp
;
2293 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2295 dirp
= dvp
= vp
= xp
= NULL
;
2297 fhp
= &nfh
.fh_generic
;
2298 dfhp
= &dnfh
.fh_generic
;
2300 nfsm_srvmtofh(dfhp
);
2301 nfsm_srvnamesiz(len
);
2303 error
= nfsrv_fhtovp(fhp
, FALSE
, &xp
, cred
, slp
, nam
,
2304 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
2306 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2307 nfsm_srvpostop_attr(getret
, &at
);
2308 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2313 if (xp
->v_type
== VDIR
) {
2314 error
= EPERM
; /* POSIX */
2318 error
= nfs_namei(&nd
, cred
, NAMEI_CREATE
, &dvp
, &vp
,
2319 dfhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2320 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2323 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2332 if (xp
->v_mount
!= dvp
->v_mount
)
2337 error
= VOP_NLINK(&nd
.nl_nch
, dvp
, xp
, nd
.nl_cred
);
2345 getret
= VOP_GETATTR(xp
, &at
);
2347 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2348 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2350 nfsm_srvpostop_attr(getret
, &at
);
2351 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2374 * nfs symbolic link service
2377 nfsrv_symlink(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2378 struct thread
*td
, struct mbuf
**mrq
)
2380 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2381 struct sockaddr
*nam
= nfsd
->nd_nam
;
2382 caddr_t dpos
= nfsd
->nd_dpos
;
2383 struct ucred
*cred
= &nfsd
->nd_cr
;
2384 struct vattr va
, dirfor
, diraft
;
2385 struct nlookupdata nd
;
2386 struct vattr
*vap
= &va
;
2389 struct nfsv2_sattr
*sp
;
2390 char *bpos
, *pathcp
= (char *)0, *cp2
;
2393 int error
= 0, len
, len2
, dirfor_ret
= 1, diraft_ret
= 1;
2394 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2395 struct mbuf
*mb
, *mreq
, *mb2
;
2402 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2408 fhp
= &nfh
.fh_generic
;
2410 nfsm_srvnamesiz(len
);
2412 error
= nfs_namei(&nd
, cred
, NAMEI_CREATE
, &dvp
, &vp
,
2413 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2414 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2417 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2425 nfsm_strsiz(len2
, NFS_MAXPATHLEN
);
2426 MALLOC(pathcp
, caddr_t
, len2
+ 1, M_TEMP
, M_WAITOK
);
2427 iv
.iov_base
= pathcp
;
2429 io
.uio_resid
= len2
;
2433 io
.uio_segflg
= UIO_SYSSPACE
;
2434 io
.uio_rw
= UIO_READ
;
2436 nfsm_mtouio(&io
, len2
);
2438 nfsm_dissect(sp
, struct nfsv2_sattr
*, NFSX_V2SATTR
);
2439 vap
->va_mode
= nfstov_mode(sp
->sa_mode
);
2441 *(pathcp
+ len2
) = '\0';
2447 if (vap
->va_mode
== (mode_t
)VNOVAL
)
2451 error
= VOP_NSYMLINK(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
, pathcp
);
2455 bzero((caddr_t
)fhp
, sizeof(nfh
));
2456 fhp
->fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
2457 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
2459 error
= VOP_GETATTR(vp
, vap
);
2474 FREE(pathcp
, M_TEMP
);
2478 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2482 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2485 nfsm_srvpostop_fh(fhp
);
2486 nfsm_srvpostop_attr(0, vap
);
2488 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2500 FREE(pathcp
, M_TEMP
);
2508 nfsrv_mkdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2509 struct thread
*td
, struct mbuf
**mrq
)
2511 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2512 struct sockaddr
*nam
= nfsd
->nd_nam
;
2513 caddr_t dpos
= nfsd
->nd_dpos
;
2514 struct ucred
*cred
= &nfsd
->nd_cr
;
2515 struct vattr va
, dirfor
, diraft
;
2516 struct vattr
*vap
= &va
;
2517 struct nfs_fattr
*fp
;
2518 struct nlookupdata nd
;
2523 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
2524 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2526 struct mbuf
*mb
, *mb2
, *mreq
;
2533 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2539 fhp
= &nfh
.fh_generic
;
2541 nfsm_srvnamesiz(len
);
2543 error
= nfs_namei(&nd
, cred
, NAMEI_CREATE
, &dvp
, &vp
,
2544 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2545 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2548 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2551 nfsm_reply(NFSX_WCCDATA(v3
));
2552 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2560 nfsm_dissect(tl
, u_int32_t
*, NFSX_UNSIGNED
);
2561 vap
->va_mode
= nfstov_mode(*tl
++);
2565 * At this point nd.ni_dvp is referenced and exclusively locked and
2566 * nd.ni_vp, if it exists, is referenced but not locked.
2569 vap
->va_type
= VDIR
;
2576 * Issue mkdir op. Since SAVESTART is not set, the pathname
2577 * component is freed by the VOP call. This will fill-in
2578 * nd.ni_vp, reference, and exclusively lock it.
2580 if (vap
->va_mode
== (mode_t
)VNOVAL
)
2583 error
= VOP_NMKDIR(&nd
.nl_nch
, dvp
, &vp
, nd
.nl_cred
, vap
);
2588 bzero((caddr_t
)fhp
, sizeof(nfh
));
2589 fhp
->fh_fsid
= vp
->v_mount
->mnt_stat
.f_fsid
;
2590 error
= VFS_VPTOFH(vp
, &fhp
->fh_fid
);
2592 error
= VOP_GETATTR(vp
, vap
);
2596 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2597 nfsm_reply(NFSX_SRVFH(v3
) + NFSX_POSTOPATTR(v3
) + NFSX_WCCDATA(v3
));
2600 nfsm_srvpostop_fh(fhp
);
2601 nfsm_srvpostop_attr(0, vap
);
2603 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2605 nfsm_srvfhtom(fhp
, v3
);
2606 nfsm_build(fp
, struct nfs_fattr
*, NFSX_V2FATTR
);
2607 nfsm_srvfillattr(vap
, fp
);
2631 nfsrv_rmdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2632 struct thread
*td
, struct mbuf
**mrq
)
2634 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2635 struct sockaddr
*nam
= nfsd
->nd_nam
;
2636 caddr_t dpos
= nfsd
->nd_dpos
;
2637 struct ucred
*cred
= &nfsd
->nd_cr
;
2641 int error
= 0, len
, dirfor_ret
= 1, diraft_ret
= 1;
2642 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2644 struct mbuf
*mb
, *mreq
;
2648 struct vattr dirfor
, diraft
;
2651 struct nlookupdata nd
;
2653 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2659 fhp
= &nfh
.fh_generic
;
2661 nfsm_srvnamesiz(len
);
2663 error
= nfs_namei(&nd
, cred
, NAMEI_DELETE
, &dvp
, &vp
,
2664 fhp
, len
, slp
, nam
, &md
, &dpos
, &dirp
,
2665 td
, (nfsd
->nd_flag
& ND_KERBAUTH
), FALSE
);
2668 dirfor_ret
= VOP_GETATTR(dirp
, &dirfor
);
2671 nfsm_reply(NFSX_WCCDATA(v3
));
2672 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2676 if (vp
->v_type
!= VDIR
) {
2682 * The root of a mounted filesystem cannot be deleted.
2684 if (vp
->v_flag
& VROOT
)
2688 * Issue or abort op. Since SAVESTART is not set, path name
2689 * component is freed by the VOP after either.
2696 error
= VOP_NRMDIR(&nd
.nl_nch
, dvp
, nd
.nl_cred
);
2703 diraft_ret
= VOP_GETATTR(dirp
, &diraft
);
2704 nfsm_reply(NFSX_WCCDATA(v3
));
2706 nfsm_srvwcc_data(dirfor_ret
, &dirfor
, diraft_ret
, &diraft
);
2727 * nfs readdir service
2728 * - mallocs what it thinks is enough to read
2729 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2730 * - calls VOP_READDIR()
2731 * - loops around building the reply
2732 * if the output generated exceeds count break out of loop
2733 * The nfsm_clget macro is used here so that the reply will be packed
2734 * tightly in mbuf clusters.
2735 * - it only knows that it has encountered eof when the VOP_READDIR()
2737 * - as such one readdir rpc will return eof false although you are there
2738 * and then the next will return eof
2739 * - it trims out records with d_fileno == 0
2740 * this doesn't matter for Unix clients, but they might confuse clients
2742 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2743 * than requested, but this may not apply to all filesystems. For
2744 * example, client NFS does not { although it is never remote mounted
2746 * The alternate call nfsrv_readdirplus() does lookups as well.
2747 * PS: The NFS protocol spec. does not clarify what the "count" byte
2748 * argument is a count of.. just name strings and file id's or the
2749 * entire reply rpc or ...
2750 * I tried just file name and id sizes and it confused the Sun client,
2751 * so I am using the full rpc size now. The "paranoia.." comment refers
2752 * to including the status longwords that are not a part of the dir.
2753 * "entry" structures, but are in the rpc.
2757 u_int32_t fl_postopok
;
2758 u_int32_t fl_fattr
[NFSX_V3FATTR
/ sizeof (u_int32_t
)];
2760 u_int32_t fl_fhsize
;
2761 u_int32_t fl_nfh
[NFSX_V3FH
/ sizeof (u_int32_t
)];
2765 nfsrv_readdir(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
2766 struct thread
*td
, struct mbuf
**mrq
)
2768 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
2769 struct sockaddr
*nam
= nfsd
->nd_nam
;
2770 caddr_t dpos
= nfsd
->nd_dpos
;
2771 struct ucred
*cred
= &nfsd
->nd_cr
;
2779 struct mbuf
*mb
, *mb2
, *mreq
, *mp2
;
2780 char *cpos
, *cend
, *cp2
, *rbuf
;
2781 struct vnode
*vp
= NULL
;
2787 int len
, nlen
, rem
, xfer
, tsiz
, i
, error
= 0, getret
= 1;
2788 int siz
, cnt
, fullsiz
, eofflag
, rdonly
, ncookies
;
2789 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
2790 u_quad_t off
, toff
, verf
;
2791 off_t
*cookies
= NULL
, *cookiep
;
2793 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
2794 fhp
= &nfh
.fh_generic
;
2797 nfsm_dissect(tl
, u_int32_t
*, 5 * NFSX_UNSIGNED
);
2798 toff
= fxdr_hyper(tl
);
2800 verf
= fxdr_hyper(tl
);
2803 nfsm_dissect(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2804 toff
= fxdr_unsigned(u_quad_t
, *tl
++);
2805 verf
= 0; /* shut up gcc */
2808 cnt
= fxdr_unsigned(int, *tl
);
2809 siz
= ((cnt
+ DIRBLKSIZ
- 1) & ~(DIRBLKSIZ
- 1));
2810 xfer
= NFS_SRVMAXDATA(nfsd
);
2816 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
2817 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
2818 if (!error
&& vp
->v_type
!= VDIR
) {
2824 nfsm_reply(NFSX_UNSIGNED
);
2825 nfsm_srvpostop_attr(getret
, &at
);
2831 * Obtain lock on vnode for this section of the code
2835 error
= getret
= VOP_GETATTR(vp
, &at
);
2838 * XXX This check may be too strict for Solaris 2.5 clients.
2840 if (!error
&& toff
&& verf
&& verf
!= at
.va_filerev
)
2841 error
= NFSERR_BAD_COOKIE
;
2845 error
= nfsrv_access(vp
, VEXEC
, cred
, rdonly
, td
, 0);
2849 nfsm_reply(NFSX_POSTOPATTR(v3
));
2850 nfsm_srvpostop_attr(getret
, &at
);
2857 * end section. Allocate rbuf and continue
2859 MALLOC(rbuf
, caddr_t
, siz
, M_TEMP
, M_WAITOK
);
2862 iv
.iov_len
= fullsiz
;
2865 io
.uio_offset
= (off_t
)off
;
2866 io
.uio_resid
= fullsiz
;
2867 io
.uio_segflg
= UIO_SYSSPACE
;
2868 io
.uio_rw
= UIO_READ
;
2872 kfree((caddr_t
)cookies
, M_TEMP
);
2875 error
= VOP_READDIR(vp
, &io
, cred
, &eofflag
, &ncookies
, &cookies
);
2876 off
= (off_t
)io
.uio_offset
;
2877 if (!cookies
&& !error
)
2878 error
= NFSERR_PERM
;
2880 getret
= VOP_GETATTR(vp
, &at
);
2887 kfree((caddr_t
)rbuf
, M_TEMP
);
2889 kfree((caddr_t
)cookies
, M_TEMP
);
2890 nfsm_reply(NFSX_POSTOPATTR(v3
));
2891 nfsm_srvpostop_attr(getret
, &at
);
2896 siz
-= io
.uio_resid
;
2899 * If nothing read, return eof
2905 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_COOKIEVERF(v3
) +
2908 nfsm_srvpostop_attr(getret
, &at
);
2909 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
2910 txdr_hyper(at
.va_filerev
, tl
);
2913 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2916 FREE((caddr_t
)rbuf
, M_TEMP
);
2917 FREE((caddr_t
)cookies
, M_TEMP
);
2924 * Check for degenerate cases of nothing useful read.
2925 * If so go try again
2929 dp
= (struct dirent
*)cpos
;
2932 * For some reason FreeBSD's ufs_readdir() chooses to back the
2933 * directory offset up to a block boundary, so it is necessary to
2934 * skip over the records that preceed the requested offset. This
2935 * requires the assumption that file offset cookies monotonically
2938 while (cpos
< cend
&& ncookies
> 0 &&
2939 (dp
->d_ino
== 0 || dp
->d_type
== DT_WHT
||
2940 ((u_quad_t
)(*cookiep
)) <= toff
)) {
2941 dp
= _DIRENT_NEXT(dp
);
2946 if (cpos
>= cend
|| ncookies
== 0) {
2952 len
= 3 * NFSX_UNSIGNED
; /* paranoia, probably can be 0 */
2953 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_COOKIEVERF(v3
) + siz
);
2955 nfsm_srvpostop_attr(getret
, &at
);
2956 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
2957 txdr_hyper(at
.va_filerev
, tl
);
2961 be
= bp
+ M_TRAILINGSPACE(mp
);
2963 /* Loop through the records and build reply */
2964 while (cpos
< cend
&& ncookies
> 0) {
2965 if (dp
->d_ino
!= 0 && dp
->d_type
!= DT_WHT
) {
2966 nlen
= dp
->d_namlen
;
2967 rem
= nfsm_rndup(nlen
) - nlen
;
2968 len
+= (4 * NFSX_UNSIGNED
+ nlen
+ rem
);
2970 len
+= 2 * NFSX_UNSIGNED
;
2976 * Build the directory record xdr from
2981 bp
+= NFSX_UNSIGNED
;
2985 bp
+= NFSX_UNSIGNED
;
2988 *tl
= txdr_unsigned(dp
->d_ino
);
2989 bp
+= NFSX_UNSIGNED
;
2991 *tl
= txdr_unsigned(nlen
);
2992 bp
+= NFSX_UNSIGNED
;
2994 /* And loop around copying the name */
3003 bcopy(cp
, bp
, tsiz
);
3009 /* And null pad to a int32_t boundary */
3010 for (i
= 0; i
< rem
; i
++)
3014 /* Finish off the record */
3016 *tl
= txdr_unsigned(*cookiep
>> 32);
3017 bp
+= NFSX_UNSIGNED
;
3020 *tl
= txdr_unsigned(*cookiep
);
3021 bp
+= NFSX_UNSIGNED
;
3023 dp
= _DIRENT_NEXT(dp
);
3032 bp
+= NFSX_UNSIGNED
;
3038 bp
+= NFSX_UNSIGNED
;
3041 mp
->m_len
= bp
- mtod(mp
, caddr_t
);
3043 mp
->m_len
+= bp
- bpos
;
3044 FREE((caddr_t
)rbuf
, M_TEMP
);
3045 FREE((caddr_t
)cookies
, M_TEMP
);
3054 nfsrv_readdirplus(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3055 struct thread
*td
, struct mbuf
**mrq
)
3057 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3058 struct sockaddr
*nam
= nfsd
->nd_nam
;
3059 caddr_t dpos
= nfsd
->nd_dpos
;
3060 struct ucred
*cred
= &nfsd
->nd_cr
;
3068 struct mbuf
*mb
, *mb2
, *mreq
, *mp2
;
3069 char *cpos
, *cend
, *cp2
, *rbuf
;
3070 struct vnode
*vp
= NULL
, *nvp
;
3073 fhandle_t
*fhp
, *nfhp
= (fhandle_t
*)fl
.fl_nfh
;
3076 struct vattr va
, at
, *vap
= &va
;
3077 struct nfs_fattr
*fp
;
3078 int len
, nlen
, rem
, xfer
, tsiz
, i
, error
= 0, getret
= 1;
3079 int siz
, cnt
, fullsiz
, eofflag
, rdonly
, dirlen
, ncookies
;
3080 u_quad_t off
, toff
, verf
;
3081 off_t
*cookies
= NULL
, *cookiep
; /* needs to be int64_t or off_t */
3083 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3084 fhp
= &nfh
.fh_generic
;
3086 nfsm_dissect(tl
, u_int32_t
*, 6 * NFSX_UNSIGNED
);
3087 toff
= fxdr_hyper(tl
);
3089 verf
= fxdr_hyper(tl
);
3091 siz
= fxdr_unsigned(int, *tl
++);
3092 cnt
= fxdr_unsigned(int, *tl
);
3094 siz
= ((siz
+ DIRBLKSIZ
- 1) & ~(DIRBLKSIZ
- 1));
3095 xfer
= NFS_SRVMAXDATA(nfsd
);
3101 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
3102 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3103 if (!error
&& vp
->v_type
!= VDIR
) {
3109 nfsm_reply(NFSX_UNSIGNED
);
3110 nfsm_srvpostop_attr(getret
, &at
);
3114 error
= getret
= VOP_GETATTR(vp
, &at
);
3117 * XXX This check may be too strict for Solaris 2.5 clients.
3119 if (!error
&& toff
&& verf
&& verf
!= at
.va_filerev
)
3120 error
= NFSERR_BAD_COOKIE
;
3123 error
= nfsrv_access(vp
, VEXEC
, cred
, rdonly
, td
, 0);
3128 nfsm_reply(NFSX_V3POSTOPATTR
);
3129 nfsm_srvpostop_attr(getret
, &at
);
3134 MALLOC(rbuf
, caddr_t
, siz
, M_TEMP
, M_WAITOK
);
3137 iv
.iov_len
= fullsiz
;
3140 io
.uio_offset
= (off_t
)off
;
3141 io
.uio_resid
= fullsiz
;
3142 io
.uio_segflg
= UIO_SYSSPACE
;
3143 io
.uio_rw
= UIO_READ
;
3147 kfree((caddr_t
)cookies
, M_TEMP
);
3150 error
= VOP_READDIR(vp
, &io
, cred
, &eofflag
, &ncookies
, &cookies
);
3151 off
= (u_quad_t
)io
.uio_offset
;
3152 getret
= VOP_GETATTR(vp
, &at
);
3153 if (!cookies
&& !error
)
3154 error
= NFSERR_PERM
;
3161 kfree((caddr_t
)cookies
, M_TEMP
);
3162 kfree((caddr_t
)rbuf
, M_TEMP
);
3163 nfsm_reply(NFSX_V3POSTOPATTR
);
3164 nfsm_srvpostop_attr(getret
, &at
);
3169 siz
-= io
.uio_resid
;
3172 * If nothing read, return eof
3178 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3COOKIEVERF
+
3180 nfsm_srvpostop_attr(getret
, &at
);
3181 nfsm_build(tl
, u_int32_t
*, 4 * NFSX_UNSIGNED
);
3182 txdr_hyper(at
.va_filerev
, tl
);
3186 FREE((caddr_t
)cookies
, M_TEMP
);
3187 FREE((caddr_t
)rbuf
, M_TEMP
);
3194 * Check for degenerate cases of nothing useful read.
3195 * If so go try again
3199 dp
= (struct dirent
*)cpos
;
3202 * For some reason FreeBSD's ufs_readdir() chooses to back the
3203 * directory offset up to a block boundary, so it is necessary to
3204 * skip over the records that preceed the requested offset. This
3205 * requires the assumption that file offset cookies monotonically
3208 while (cpos
< cend
&& ncookies
> 0 &&
3209 (dp
->d_ino
== 0 || dp
->d_type
== DT_WHT
||
3210 ((u_quad_t
)(*cookiep
)) <= toff
)) {
3211 dp
= _DIRENT_NEXT(dp
);
3216 if (cpos
>= cend
|| ncookies
== 0) {
3223 * Probe one of the directory entries to see if the filesystem
3226 if (VFS_VGET(vp
->v_mount
, dp
->d_ino
, &nvp
) == EOPNOTSUPP
) {
3227 error
= NFSERR_NOTSUPP
;
3230 kfree((caddr_t
)cookies
, M_TEMP
);
3231 kfree((caddr_t
)rbuf
, M_TEMP
);
3232 nfsm_reply(NFSX_V3POSTOPATTR
);
3233 nfsm_srvpostop_attr(getret
, &at
);
3242 dirlen
= len
= NFSX_V3POSTOPATTR
+ NFSX_V3COOKIEVERF
+ 2 * NFSX_UNSIGNED
;
3244 nfsm_srvpostop_attr(getret
, &at
);
3245 nfsm_build(tl
, u_int32_t
*, 2 * NFSX_UNSIGNED
);
3246 txdr_hyper(at
.va_filerev
, tl
);
3249 be
= bp
+ M_TRAILINGSPACE(mp
);
3251 /* Loop through the records and build reply */
3252 while (cpos
< cend
&& ncookies
> 0) {
3253 if (dp
->d_ino
!= 0 && dp
->d_type
!= DT_WHT
) {
3254 nlen
= dp
->d_namlen
;
3255 rem
= nfsm_rndup(nlen
)-nlen
;
3258 * For readdir_and_lookup get the vnode using
3261 if (VFS_VGET(vp
->v_mount
, dp
->d_ino
, &nvp
))
3263 bzero((caddr_t
)nfhp
, NFSX_V3FH
);
3265 nvp
->v_mount
->mnt_stat
.f_fsid
;
3266 if (VFS_VPTOFH(nvp
, &nfhp
->fh_fid
)) {
3271 if (VOP_GETATTR(nvp
, vap
)) {
3280 * If either the dircount or maxcount will be
3281 * exceeded, get out now. Both of these lengths
3282 * are calculated conservatively, including all
3285 len
+= (8 * NFSX_UNSIGNED
+ nlen
+ rem
+ NFSX_V3FH
+
3287 dirlen
+= (6 * NFSX_UNSIGNED
+ nlen
+ rem
);
3288 if (len
> cnt
|| dirlen
> fullsiz
) {
3294 * Build the directory record xdr from
3297 fp
= (struct nfs_fattr
*)&fl
.fl_fattr
;
3298 nfsm_srvfillattr(vap
, fp
);
3299 fl
.fl_fhsize
= txdr_unsigned(NFSX_V3FH
);
3300 fl
.fl_fhok
= nfs_true
;
3301 fl
.fl_postopok
= nfs_true
;
3302 fl
.fl_off
.nfsuquad
[0] = txdr_unsigned(*cookiep
>> 32);
3303 fl
.fl_off
.nfsuquad
[1] = txdr_unsigned(*cookiep
);
3307 bp
+= NFSX_UNSIGNED
;
3310 bp
+= NFSX_UNSIGNED
;
3312 *tl
= txdr_unsigned(dp
->d_ino
);
3313 bp
+= NFSX_UNSIGNED
;
3315 *tl
= txdr_unsigned(nlen
);
3316 bp
+= NFSX_UNSIGNED
;
3318 /* And loop around copying the name */
3323 if ((bp
+ xfer
) > be
)
3327 bcopy(cp
, bp
, tsiz
);
3333 /* And null pad to a int32_t boundary */
3334 for (i
= 0; i
< rem
; i
++)
3338 * Now copy the flrep structure out.
3340 xfer
= sizeof (struct flrep
);
3344 if ((bp
+ xfer
) > be
)
3348 bcopy(cp
, bp
, tsiz
);
3356 dp
= _DIRENT_NEXT(dp
);
3365 bp
+= NFSX_UNSIGNED
;
3371 bp
+= NFSX_UNSIGNED
;
3374 mp
->m_len
= bp
- mtod(mp
, caddr_t
);
3376 mp
->m_len
+= bp
- bpos
;
3377 FREE((caddr_t
)cookies
, M_TEMP
);
3378 FREE((caddr_t
)rbuf
, M_TEMP
);
3386 * nfs commit service
3389 nfsrv_commit(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3390 struct thread
*td
, struct mbuf
**mrq
)
3392 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3393 struct sockaddr
*nam
= nfsd
->nd_nam
;
3394 caddr_t dpos
= nfsd
->nd_dpos
;
3395 struct ucred
*cred
= &nfsd
->nd_cr
;
3396 struct vattr bfor
, aft
;
3397 struct vnode
*vp
= NULL
;
3403 int error
= 0, rdonly
, for_ret
= 1, aft_ret
= 1, cnt
;
3405 struct mbuf
*mb
, *mb2
, *mreq
;
3408 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3409 fhp
= &nfh
.fh_generic
;
3411 nfsm_dissect(tl
, u_int32_t
*, 3 * NFSX_UNSIGNED
);
3414 * XXX At this time VOP_FSYNC() does not accept offset and byte
3415 * count parameters, so these arguments are useless (someday maybe).
3417 off
= fxdr_hyper(tl
);
3419 cnt
= fxdr_unsigned(int, *tl
);
3420 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
3421 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3423 nfsm_reply(2 * NFSX_UNSIGNED
);
3424 nfsm_srvwcc_data(for_ret
, &bfor
, aft_ret
, &aft
);
3428 for_ret
= VOP_GETATTR(vp
, &bfor
);
3430 if (cnt
> MAX_COMMIT_COUNT
) {
3432 * Give up and do the whole thing
3435 (vp
->v_object
->flags
& OBJ_MIGHTBEDIRTY
)) {
3436 vm_object_page_clean(vp
->v_object
, 0, 0, OBJPC_SYNC
);
3438 error
= VOP_FSYNC(vp
, MNT_WAIT
);
3441 * Locate and synchronously write any buffers that fall
3442 * into the requested range. Note: we are assuming that
3443 * f_iosize is a power of 2.
3445 int iosize
= vp
->v_mount
->mnt_stat
.f_iosize
;
3446 int iomask
= iosize
- 1;
3450 * Align to iosize boundry, super-align to page boundry.
3453 cnt
+= off
& iomask
;
3454 off
&= ~(u_quad_t
)iomask
;
3456 if (off
& PAGE_MASK
) {
3457 cnt
+= off
& PAGE_MASK
;
3458 off
&= ~(u_quad_t
)PAGE_MASK
;
3463 (vp
->v_object
->flags
& OBJ_MIGHTBEDIRTY
)) {
3464 vm_object_page_clean(vp
->v_object
, off
/ PAGE_SIZE
, (cnt
+ PAGE_MASK
) / PAGE_SIZE
, OBJPC_SYNC
);
3472 * If we have a buffer and it is marked B_DELWRI we
3473 * have to lock and write it. Otherwise the prior
3474 * write is assumed to have already been committed.
3476 if ((bp
= findblk(vp
, loffset
)) != NULL
&& (bp
->b_flags
& B_DELWRI
)) {
3477 if (BUF_LOCK(bp
, LK_EXCLUSIVE
| LK_NOWAIT
)) {
3478 if (BUF_LOCK(bp
, LK_EXCLUSIVE
| LK_SLEEPFAIL
) == 0)
3480 continue; /* retry */
3483 bp
->b_flags
&= ~B_ASYNC
;
3496 aft_ret
= VOP_GETATTR(vp
, &aft
);
3499 nfsm_reply(NFSX_V3WCCDATA
+ NFSX_V3WRITEVERF
);
3500 nfsm_srvwcc_data(for_ret
, &bfor
, aft_ret
, &aft
);
3502 nfsm_build(tl
, u_int32_t
*, NFSX_V3WRITEVERF
);
3503 if (nfsver
.tv_sec
== 0)
3505 *tl
++ = txdr_unsigned(nfsver
.tv_sec
);
3506 *tl
= txdr_unsigned(nfsver
.tv_nsec
/ 1000);
3517 * nfs statfs service
3520 nfsrv_statfs(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3521 struct thread
*td
, struct mbuf
**mrq
)
3523 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3524 struct sockaddr
*nam
= nfsd
->nd_nam
;
3525 caddr_t dpos
= nfsd
->nd_dpos
;
3526 struct ucred
*cred
= &nfsd
->nd_cr
;
3528 struct nfs_statfs
*sfp
;
3532 int error
= 0, rdonly
, getret
= 1;
3533 int v3
= (nfsd
->nd_flag
& ND_NFSV3
);
3535 struct mbuf
*mb
, *mb2
, *mreq
;
3536 struct vnode
*vp
= NULL
;
3540 struct statfs statfs
;
3543 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3544 fhp
= &nfh
.fh_generic
;
3546 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
3547 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3549 nfsm_reply(NFSX_UNSIGNED
);
3550 nfsm_srvpostop_attr(getret
, &at
);
3555 error
= VFS_STATFS(vp
->v_mount
, sf
, proc0
.p_ucred
);
3556 getret
= VOP_GETATTR(vp
, &at
);
3559 nfsm_reply(NFSX_POSTOPATTR(v3
) + NFSX_STATFS(v3
));
3561 nfsm_srvpostop_attr(getret
, &at
);
3566 nfsm_build(sfp
, struct nfs_statfs
*, NFSX_STATFS(v3
));
3568 tval
= (u_quad_t
)sf
->f_blocks
;
3569 tval
*= (u_quad_t
)sf
->f_bsize
;
3570 txdr_hyper(tval
, &sfp
->sf_tbytes
);
3571 tval
= (u_quad_t
)sf
->f_bfree
;
3572 tval
*= (u_quad_t
)sf
->f_bsize
;
3573 txdr_hyper(tval
, &sfp
->sf_fbytes
);
3574 tval
= (u_quad_t
)sf
->f_bavail
;
3575 tval
*= (u_quad_t
)sf
->f_bsize
;
3576 txdr_hyper(tval
, &sfp
->sf_abytes
);
3577 sfp
->sf_tfiles
.nfsuquad
[0] = 0;
3578 sfp
->sf_tfiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_files
);
3579 sfp
->sf_ffiles
.nfsuquad
[0] = 0;
3580 sfp
->sf_ffiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_ffree
);
3581 sfp
->sf_afiles
.nfsuquad
[0] = 0;
3582 sfp
->sf_afiles
.nfsuquad
[1] = txdr_unsigned(sf
->f_ffree
);
3583 sfp
->sf_invarsec
= 0;
3585 sfp
->sf_tsize
= txdr_unsigned(NFS_MAXDGRAMDATA
);
3586 sfp
->sf_bsize
= txdr_unsigned(sf
->f_bsize
);
3587 sfp
->sf_blocks
= txdr_unsigned(sf
->f_blocks
);
3588 sfp
->sf_bfree
= txdr_unsigned(sf
->f_bfree
);
3589 sfp
->sf_bavail
= txdr_unsigned(sf
->f_bavail
);
3598 * nfs fsinfo service
3601 nfsrv_fsinfo(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3602 struct thread
*td
, struct mbuf
**mrq
)
3604 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3605 struct sockaddr
*nam
= nfsd
->nd_nam
;
3606 caddr_t dpos
= nfsd
->nd_dpos
;
3607 struct ucred
*cred
= &nfsd
->nd_cr
;
3609 struct nfsv3_fsinfo
*sip
;
3612 int error
= 0, rdonly
, getret
= 1, pref
;
3614 struct mbuf
*mb
, *mb2
, *mreq
;
3615 struct vnode
*vp
= NULL
;
3622 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3623 fhp
= &nfh
.fh_generic
;
3625 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
3626 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3628 nfsm_reply(NFSX_UNSIGNED
);
3629 nfsm_srvpostop_attr(getret
, &at
);
3634 /* XXX Try to make a guess on the max file size. */
3635 VFS_STATFS(vp
->v_mount
, &sb
, proc0
.p_ucred
);
3636 maxfsize
= (u_quad_t
)0x80000000 * sb
.f_bsize
- 1;
3638 getret
= VOP_GETATTR(vp
, &at
);
3641 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3FSINFO
);
3642 nfsm_srvpostop_attr(getret
, &at
);
3643 nfsm_build(sip
, struct nfsv3_fsinfo
*, NFSX_V3FSINFO
);
3647 * There should be file system VFS OP(s) to get this information.
3648 * For now, assume ufs.
3650 if (slp
->ns_so
->so_type
== SOCK_DGRAM
)
3651 pref
= NFS_MAXDGRAMDATA
;
3654 sip
->fs_rtmax
= txdr_unsigned(NFS_MAXDATA
);
3655 sip
->fs_rtpref
= txdr_unsigned(pref
);
3656 sip
->fs_rtmult
= txdr_unsigned(NFS_FABLKSIZE
);
3657 sip
->fs_wtmax
= txdr_unsigned(NFS_MAXDATA
);
3658 sip
->fs_wtpref
= txdr_unsigned(pref
);
3659 sip
->fs_wtmult
= txdr_unsigned(NFS_FABLKSIZE
);
3660 sip
->fs_dtpref
= txdr_unsigned(pref
);
3661 txdr_hyper(maxfsize
, &sip
->fs_maxfilesize
);
3662 sip
->fs_timedelta
.nfsv3_sec
= 0;
3663 sip
->fs_timedelta
.nfsv3_nsec
= txdr_unsigned(1);
3664 sip
->fs_properties
= txdr_unsigned(NFSV3FSINFO_LINK
|
3665 NFSV3FSINFO_SYMLINK
| NFSV3FSINFO_HOMOGENEOUS
|
3666 NFSV3FSINFO_CANSETTIME
);
3674 * nfs pathconf service
3677 nfsrv_pathconf(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3678 struct thread
*td
, struct mbuf
**mrq
)
3680 struct mbuf
*mrep
= nfsd
->nd_mrep
, *md
= nfsd
->nd_md
;
3681 struct sockaddr
*nam
= nfsd
->nd_nam
;
3682 caddr_t dpos
= nfsd
->nd_dpos
;
3683 struct ucred
*cred
= &nfsd
->nd_cr
;
3685 struct nfsv3_pathconf
*pc
;
3688 int error
= 0, rdonly
, getret
= 1;
3689 register_t linkmax
, namemax
, chownres
, notrunc
;
3691 struct mbuf
*mb
, *mb2
, *mreq
;
3692 struct vnode
*vp
= NULL
;
3697 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3698 fhp
= &nfh
.fh_generic
;
3700 error
= nfsrv_fhtovp(fhp
, 1, &vp
, cred
, slp
, nam
,
3701 &rdonly
, (nfsd
->nd_flag
& ND_KERBAUTH
), TRUE
);
3703 nfsm_reply(NFSX_UNSIGNED
);
3704 nfsm_srvpostop_attr(getret
, &at
);
3708 error
= VOP_PATHCONF(vp
, _PC_LINK_MAX
, &linkmax
);
3710 error
= VOP_PATHCONF(vp
, _PC_NAME_MAX
, &namemax
);
3712 error
= VOP_PATHCONF(vp
, _PC_CHOWN_RESTRICTED
, &chownres
);
3714 error
= VOP_PATHCONF(vp
, _PC_NO_TRUNC
, ¬runc
);
3715 getret
= VOP_GETATTR(vp
, &at
);
3718 nfsm_reply(NFSX_V3POSTOPATTR
+ NFSX_V3PATHCONF
);
3719 nfsm_srvpostop_attr(getret
, &at
);
3724 nfsm_build(pc
, struct nfsv3_pathconf
*, NFSX_V3PATHCONF
);
3726 pc
->pc_linkmax
= txdr_unsigned(linkmax
);
3727 pc
->pc_namemax
= txdr_unsigned(namemax
);
3728 pc
->pc_notrunc
= txdr_unsigned(notrunc
);
3729 pc
->pc_chownrestricted
= txdr_unsigned(chownres
);
3732 * These should probably be supported by VOP_PATHCONF(), but
3733 * until msdosfs is exportable (why would you want to?), the
3734 * Unix defaults should be ok.
3736 pc
->pc_caseinsensitive
= nfs_false
;
3737 pc
->pc_casepreserving
= nfs_true
;
3745 * Null operation, used by clients to ping server
3749 nfsrv_null(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3750 struct thread
*td
, struct mbuf
**mrq
)
3752 struct mbuf
*mrep
= nfsd
->nd_mrep
;
3754 int error
= NFSERR_RETVOID
;
3755 struct mbuf
*mb
, *mreq
;
3757 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3763 * No operation, used for obsolete procedures
3767 nfsrv_noop(struct nfsrv_descript
*nfsd
, struct nfssvc_sock
*slp
,
3768 struct thread
*td
, struct mbuf
**mrq
)
3770 struct mbuf
*mrep
= nfsd
->nd_mrep
;
3773 struct mbuf
*mb
, *mreq
;
3775 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3776 if (nfsd
->nd_repstat
)
3777 error
= nfsd
->nd_repstat
;
3779 error
= EPROCUNAVAIL
;
3786 * Perform access checking for vnodes obtained from file handles that would
3787 * refer to files already opened by a Unix client. You cannot just use
3788 * vn_writechk() and VOP_ACCESS() for two reasons.
3789 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3790 * 2 - The owner is to be given access irrespective of mode bits for some
3791 * operations, so that processes that chmod after opening a file don't
3792 * break. I don't like this because it opens a security hole, but since
3793 * the nfs server opens a security hole the size of a barn door anyhow,
3796 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3797 * will return EPERM instead of EACCESS. EPERM is always an error.
3800 nfsrv_access(struct vnode
*vp
, int flags
, struct ucred
*cred
,
3801 int rdonly
, struct thread
*td
, int override
)
3806 nfsdbprintf(("%s %d\n", __FILE__
, __LINE__
));
3807 if (flags
& VWRITE
) {
3808 /* Just vn_writechk() changed to check rdonly */
3810 * Disallow write attempts on read-only file systems;
3811 * unless the file is a socket or a block or character
3812 * device resident on the file system.
3814 if (rdonly
|| (vp
->v_mount
->mnt_flag
& MNT_RDONLY
)) {
3815 switch (vp
->v_type
) {
3825 * If there's shared text associated with
3826 * the inode, we can't allow writing.
3828 if (vp
->v_flag
& VTEXT
)
3831 error
= VOP_GETATTR(vp
, &vattr
);
3834 error
= VOP_ACCESS(vp
, flags
, cred
);
3836 * Allow certain operations for the owner (reads and writes
3837 * on files that are already open).
3839 if (override
&& error
== EACCES
&& cred
->cr_uid
== vattr
.va_uid
)
3843 #endif /* NFS_NOSERVER */