nfs_serv.c revision 1.78 1 /* $NetBSD: nfs_serv.c,v 1.78 2003/06/29 18:43:36 thorpej Exp $ */
2
3 /*
4 * Copyright (c) 1989, 1993
5 * The Regents of the University of California. All rights reserved.
6 *
7 * This code is derived from software contributed to Berkeley by
8 * Rick Macklem at The University of Guelph.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the University of
21 * California, Berkeley and its contributors.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
39 */
40
41 /*
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
48 * nb:
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
51 *
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
56 * a reply.
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.
59 */
60
61 #include <sys/cdefs.h>
62 __KERNEL_RCSID(0, "$NetBSD: nfs_serv.c,v 1.78 2003/06/29 18:43:36 thorpej Exp $");
63
64 #include <sys/param.h>
65 #include <sys/systm.h>
66 #include <sys/proc.h>
67 #include <sys/file.h>
68 #include <sys/namei.h>
69 #include <sys/vnode.h>
70 #include <sys/mount.h>
71 #include <sys/socket.h>
72 #include <sys/socketvar.h>
73 #include <sys/mbuf.h>
74 #include <sys/dirent.h>
75 #include <sys/stat.h>
76 #include <sys/kernel.h>
77 #include <ufs/ufs/dir.h>
78
79 #include <uvm/uvm.h>
80
81 #include <nfs/nfsproto.h>
82 #include <nfs/rpcv2.h>
83 #include <nfs/nfs.h>
84 #include <nfs/xdr_subs.h>
85 #include <nfs/nfsm_subs.h>
86 #include <nfs/nqnfs.h>
87 #include <nfs/nfs_var.h>
88
89 /* Global vars */
90 extern u_int32_t nfs_xdrneg1;
91 extern u_int32_t nfs_false, nfs_true;
92 extern enum vtype nv3tov_type[8];
93 extern struct nfsstats nfsstats;
94 extern const nfstype nfsv2_type[9];
95 extern const nfstype nfsv3_type[9];
96 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
97 int nfsd_use_loan = 1; /* use page-loan for READ OP */
98
99 /*
100 * nfs v3 access service
101 */
102 int
103 nfsrv3_access(nfsd, slp, lwp, mrq)
104 struct nfsrv_descript *nfsd;
105 struct nfssvc_sock *slp;
106 struct lwp *lwp;
107 struct mbuf **mrq;
108 {
109 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
110 struct mbuf *nam = nfsd->nd_nam;
111 caddr_t dpos = nfsd->nd_dpos;
112 struct ucred *cred = &nfsd->nd_cr;
113 struct vnode *vp;
114 nfsfh_t nfh;
115 fhandle_t *fhp;
116 u_int32_t *tl;
117 int32_t t1;
118 caddr_t bpos;
119 int error = 0, rdonly, cache = 0, getret;
120 char *cp2;
121 struct mbuf *mb, *mreq;
122 struct vattr va;
123 u_long inmode, testmode, outmode;
124 u_quad_t frev;
125
126 fhp = &nfh.fh_generic;
127 nfsm_srvmtofh(fhp);
128 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
129 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
130 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
131 if (error) {
132 nfsm_reply(NFSX_UNSIGNED);
133 nfsm_srvpostop_attr(1, (struct vattr *)0);
134 return (0);
135 }
136 inmode = fxdr_unsigned(u_int32_t, *tl);
137 outmode = 0;
138 if ((inmode & NFSV3ACCESS_READ) &&
139 nfsrv_access(vp, VREAD, cred, rdonly, lwp, 0) == 0)
140 outmode |= NFSV3ACCESS_READ;
141 if (vp->v_type != VDIR) {
142 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
143 if (testmode &&
144 nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 0) == 0)
145 outmode |= testmode;
146 if ((inmode & NFSV3ACCESS_EXECUTE) &&
147 nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0) == 0)
148 outmode |= NFSV3ACCESS_EXECUTE;
149 } else {
150 testmode = inmode & (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
151 NFSV3ACCESS_DELETE);
152 if (testmode &&
153 nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 0) == 0)
154 outmode |= testmode;
155 if ((inmode & NFSV3ACCESS_LOOKUP) &&
156 nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0) == 0)
157 outmode |= NFSV3ACCESS_LOOKUP;
158 }
159 getret = VOP_GETATTR(vp, &va, cred, lwp);
160 vput(vp);
161 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
162 nfsm_srvpostop_attr(getret, &va);
163 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
164 *tl = txdr_unsigned(outmode);
165 nfsm_srvdone;
166 }
167
168 /*
169 * nfs getattr service
170 */
171 int
172 nfsrv_getattr(nfsd, slp, lwp, mrq)
173 struct nfsrv_descript *nfsd;
174 struct nfssvc_sock *slp;
175 struct lwp *lwp;
176 struct mbuf **mrq;
177 {
178 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
179 struct mbuf *nam = nfsd->nd_nam;
180 caddr_t dpos = nfsd->nd_dpos;
181 struct ucred *cred = &nfsd->nd_cr;
182 struct nfs_fattr *fp;
183 struct vattr va;
184 struct vnode *vp;
185 nfsfh_t nfh;
186 fhandle_t *fhp;
187 u_int32_t *tl;
188 int32_t t1;
189 caddr_t bpos;
190 int error = 0, rdonly, cache;
191 char *cp2;
192 struct mbuf *mb, *mreq;
193 u_quad_t frev;
194
195 fhp = &nfh.fh_generic;
196 nfsm_srvmtofh(fhp);
197 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
198 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
199 if (error) {
200 nfsm_reply(0);
201 return (0);
202 }
203 nqsrv_getl(vp, ND_READ);
204 error = VOP_GETATTR(vp, &va, cred, lwp);
205 vput(vp);
206 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
207 if (error)
208 return (0);
209 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
210 nfsm_srvfillattr(&va, fp);
211 nfsm_srvdone;
212 }
213
214 /*
215 * nfs setattr service
216 */
217 int
218 nfsrv_setattr(nfsd, slp, lwp, mrq)
219 struct nfsrv_descript *nfsd;
220 struct nfssvc_sock *slp;
221 struct lwp *lwp;
222 struct mbuf **mrq;
223 {
224 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
225 struct mbuf *nam = nfsd->nd_nam;
226 caddr_t dpos = nfsd->nd_dpos;
227 struct ucred *cred = &nfsd->nd_cr;
228 struct vattr va, preat;
229 struct nfsv2_sattr *sp;
230 struct nfs_fattr *fp;
231 struct vnode *vp;
232 nfsfh_t nfh;
233 fhandle_t *fhp;
234 u_int32_t *tl;
235 int32_t t1;
236 caddr_t bpos;
237 int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1;
238 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
239 char *cp2;
240 struct mbuf *mb, *mreq;
241 u_quad_t frev;
242 struct timespec guard;
243
244 fhp = &nfh.fh_generic;
245 nfsm_srvmtofh(fhp);
246 VATTR_NULL(&va);
247 if (v3) {
248 nfsm_srvsattr(&va);
249 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
250 gcheck = fxdr_unsigned(int, *tl);
251 if (gcheck) {
252 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
253 fxdr_nfsv3time(tl, &guard);
254 }
255 } else {
256 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
257 /*
258 * Nah nah nah nah na nah
259 * There is a bug in the Sun client that puts 0xffff in the mode
260 * field of sattr when it should put in 0xffffffff. The u_short
261 * doesn't sign extend.
262 * --> check the low order 2 bytes for 0xffff
263 */
264 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
265 va.va_mode = nfstov_mode(sp->sa_mode);
266 if (sp->sa_uid != nfs_xdrneg1)
267 va.va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
268 if (sp->sa_gid != nfs_xdrneg1)
269 va.va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
270 if (sp->sa_size != nfs_xdrneg1)
271 va.va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
272 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) {
273 #ifdef notyet
274 fxdr_nfsv2time(&sp->sa_atime, &va.va_atime);
275 #else
276 va.va_atime.tv_sec =
277 fxdr_unsigned(u_int32_t,sp->sa_atime.nfsv2_sec);
278 va.va_atime.tv_nsec = 0;
279 #endif
280 }
281 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1)
282 fxdr_nfsv2time(&sp->sa_mtime, &va.va_mtime);
283
284 }
285
286 /*
287 * Now that we have all the fields, lets do it.
288 */
289 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly,
290 (nfsd->nd_flag & ND_KERBAUTH), FALSE);
291 if (error) {
292 nfsm_reply(2 * NFSX_UNSIGNED);
293 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
294 return (0);
295 }
296 nqsrv_getl(vp, ND_WRITE);
297 if (v3) {
298 error = preat_ret = VOP_GETATTR(vp, &preat, cred, lwp);
299 if (!error && gcheck &&
300 (preat.va_ctime.tv_sec != guard.tv_sec ||
301 preat.va_ctime.tv_nsec != guard.tv_nsec))
302 error = NFSERR_NOT_SYNC;
303 if (error) {
304 vput(vp);
305 nfsm_reply(NFSX_WCCDATA(v3));
306 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
307 return (0);
308 }
309 }
310
311 /*
312 * If the size is being changed write acces is required, otherwise
313 * just check for a read only file system.
314 */
315 if (va.va_size == ((u_quad_t)((quad_t) -1))) {
316 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
317 error = EROFS;
318 goto out;
319 }
320 } else {
321 if (vp->v_type == VDIR) {
322 error = EISDIR;
323 goto out;
324 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
325 lwp, 0)) != 0)
326 goto out;
327 }
328 error = VOP_SETATTR(vp, &va, cred, lwp);
329 postat_ret = VOP_GETATTR(vp, &va, cred, lwp);
330 if (!error)
331 error = postat_ret;
332 out:
333 vput(vp);
334 nfsm_reply(NFSX_WCCORFATTR(v3));
335 if (v3) {
336 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, &va);
337 return (0);
338 } else {
339 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
340 nfsm_srvfillattr(&va, fp);
341 }
342 nfsm_srvdone;
343 }
344
345 /*
346 * nfs lookup rpc
347 */
348 int
349 nfsrv_lookup(nfsd, slp, lwp, mrq)
350 struct nfsrv_descript *nfsd;
351 struct nfssvc_sock *slp;
352 struct lwp *lwp;
353 struct mbuf **mrq;
354 {
355 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
356 struct mbuf *nam = nfsd->nd_nam;
357 caddr_t dpos = nfsd->nd_dpos;
358 struct ucred *cred = &nfsd->nd_cr;
359 struct nfs_fattr *fp;
360 struct nameidata nd, ind, *ndp = &nd;
361 struct vnode *vp, *dirp;
362 nfsfh_t nfh;
363 fhandle_t *fhp;
364 caddr_t cp;
365 u_int32_t *tl;
366 int32_t t1;
367 caddr_t bpos;
368 int error = 0, cache, dirattr_ret = 1;
369 uint32_t len;
370 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
371 char *cp2;
372 struct mbuf *mb, *mreq;
373 struct vattr va, dirattr;
374 u_quad_t frev;
375
376 fhp = &nfh.fh_generic;
377 nfsm_srvmtofh(fhp);
378 nfsm_srvnamesiz(len);
379
380 pubflag = nfs_ispublicfh(fhp);
381
382 nd.ni_cnd.cn_cred = cred;
383 nd.ni_cnd.cn_nameiop = LOOKUP;
384 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
385 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
386 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), pubflag);
387
388 if (!error && pubflag) {
389 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
390 /*
391 * Setup call to lookup() to see if we can find
392 * the index file. Arguably, this doesn't belong
393 * in a kernel.. Ugh.
394 */
395 ind = nd;
396 VOP_UNLOCK(nd.ni_vp, 0);
397 ind.ni_pathlen = strlen(nfs_pub.np_index);
398 ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
399 nfs_pub.np_index;
400 ind.ni_startdir = nd.ni_vp;
401 VREF(ind.ni_startdir);
402 error = lookup(&ind);
403 if (!error) {
404 /*
405 * Found an index file. Get rid of
406 * the old references.
407 */
408 if (dirp)
409 vrele(dirp);
410 dirp = nd.ni_vp;
411 vrele(nd.ni_startdir);
412 ndp = &ind;
413 } else
414 error = 0;
415 }
416 /*
417 * If the public filehandle was used, check that this lookup
418 * didn't result in a filehandle outside the publicly exported
419 * filesystem.
420 */
421
422 if (!error && ndp->ni_vp->v_mount != nfs_pub.np_mount) {
423 vput(nd.ni_vp);
424 error = EPERM;
425 }
426 }
427
428 if (dirp) {
429 if (v3)
430 dirattr_ret = VOP_GETATTR(dirp, &dirattr, cred, lwp);
431 vrele(dirp);
432 }
433
434 if (error) {
435 nfsm_reply(NFSX_POSTOPATTR(v3));
436 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
437 return (0);
438 }
439
440 nqsrv_getl(ndp->ni_startdir, ND_READ);
441 vrele(ndp->ni_startdir);
442 PNBUF_PUT(nd.ni_cnd.cn_pnbuf);
443 vp = ndp->ni_vp;
444 memset((caddr_t)fhp, 0, sizeof(nfh));
445 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
446 error = VFS_VPTOFH(vp, &fhp->fh_fid);
447 if (!error)
448 error = VOP_GETATTR(vp, &va, cred, lwp);
449 vput(vp);
450 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
451 if (error) {
452 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
453 return (0);
454 }
455 nfsm_srvfhtom(fhp, v3);
456 if (v3) {
457 nfsm_srvpostop_attr(0, &va);
458 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
459 } else {
460 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
461 nfsm_srvfillattr(&va, fp);
462 }
463 nfsm_srvdone;
464 }
465
466 /*
467 * nfs readlink service
468 */
469 int
470 nfsrv_readlink(nfsd, slp, lwp, mrq)
471 struct nfsrv_descript *nfsd;
472 struct nfssvc_sock *slp;
473 struct lwp *lwp;
474 struct mbuf **mrq;
475 {
476 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
477 struct mbuf *nam = nfsd->nd_nam;
478 caddr_t dpos = nfsd->nd_dpos;
479 struct ucred *cred = &nfsd->nd_cr;
480 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
481 struct iovec *ivp = iv;
482 struct mbuf *mp;
483 u_int32_t *tl;
484 int32_t t1;
485 caddr_t bpos;
486 int error = 0, rdonly, cache, i, padlen, getret;
487 uint32_t len;
488 int v3 = (nfsd->nd_flag & ND_NFSV3);
489 char *cp2;
490 struct mbuf *mb, *mp2 = NULL, *mp3 = NULL, *mreq;
491 struct vnode *vp;
492 struct vattr attr;
493 nfsfh_t nfh;
494 fhandle_t *fhp;
495 struct uio io, *uiop = &io;
496 u_quad_t frev;
497
498 fhp = &nfh.fh_generic;
499 nfsm_srvmtofh(fhp);
500 len = 0;
501 i = 0;
502 while (len < NFS_MAXPATHLEN) {
503 mp = m_get(M_WAIT, MT_DATA);
504 MCLAIM(mp, &nfs_mowner);
505 m_clget(mp, M_WAIT);
506 mp->m_len = NFSMSIZ(mp);
507 if (len == 0)
508 mp3 = mp2 = mp;
509 else {
510 mp2->m_next = mp;
511 mp2 = mp;
512 }
513 if ((len+mp->m_len) > NFS_MAXPATHLEN) {
514 mp->m_len = NFS_MAXPATHLEN-len;
515 len = NFS_MAXPATHLEN;
516 } else
517 len += mp->m_len;
518 ivp->iov_base = mtod(mp, caddr_t);
519 ivp->iov_len = mp->m_len;
520 i++;
521 ivp++;
522 }
523 uiop->uio_iov = iv;
524 uiop->uio_iovcnt = i;
525 uiop->uio_offset = 0;
526 uiop->uio_resid = len;
527 uiop->uio_rw = UIO_READ;
528 uiop->uio_segflg = UIO_SYSSPACE;
529 uiop->uio_lwp = (struct lwp *)0;
530 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
531 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
532 if (error) {
533 m_freem(mp3);
534 nfsm_reply(2 * NFSX_UNSIGNED);
535 nfsm_srvpostop_attr(1, (struct vattr *)0);
536 return (0);
537 }
538 if (vp->v_type != VLNK) {
539 if (v3)
540 error = EINVAL;
541 else
542 error = ENXIO;
543 goto out;
544 }
545 nqsrv_getl(vp, ND_READ);
546 error = VOP_READLINK(vp, uiop, cred);
547 out:
548 getret = VOP_GETATTR(vp, &attr, cred, lwp);
549 vput(vp);
550 if (error)
551 m_freem(mp3);
552 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
553 if (v3) {
554 nfsm_srvpostop_attr(getret, &attr);
555 if (error)
556 return (0);
557 }
558 len -= uiop->uio_resid;
559 padlen = nfsm_padlen(len);
560 if (uiop->uio_resid || padlen)
561 nfs_zeropad(mp3, uiop->uio_resid, padlen);
562 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED);
563 *tl = txdr_unsigned(len);
564 mb->m_next = mp3;
565 nfsm_srvdone;
566 }
567
568 /*
569 * XXX UBC temp limit
570 * maximum number of pages we can do VOP_GETPAGES and loan-out at once.
571 * should be <= MAX_READ_AHEAD in genfs_vnops.c
572 */
573 #define NFSD_READ_GETPAGES_CHUNK 16
574
575 /*
576 * nfs read service
577 */
578 int
579 nfsrv_read(nfsd, slp, lwp, mrq)
580 struct nfsrv_descript *nfsd;
581 struct nfssvc_sock *slp;
582 struct lwp *lwp;
583 struct mbuf **mrq;
584 {
585 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
586 struct mbuf *nam = nfsd->nd_nam;
587 caddr_t dpos = nfsd->nd_dpos;
588 struct ucred *cred = &nfsd->nd_cr;
589 struct mbuf *m;
590 struct nfs_fattr *fp;
591 u_int32_t *tl;
592 int32_t t1;
593 int i;
594 caddr_t bpos;
595 int error = 0, rdonly, cache, getret;
596 int v3 = (nfsd->nd_flag & ND_NFSV3);
597 uint32_t reqlen, len, cnt, left;
598 int padlen;
599 char *cp2;
600 struct mbuf *mb, *mreq;
601 struct vnode *vp;
602 nfsfh_t nfh;
603 fhandle_t *fhp;
604 struct uio io, *uiop = &io;
605 struct vattr va;
606 off_t off;
607 u_quad_t frev;
608
609 fhp = &nfh.fh_generic;
610 nfsm_srvmtofh(fhp);
611 if (v3) {
612 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
613 off = fxdr_hyper(tl);
614 } else {
615 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
616 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
617 }
618 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
619 reqlen = fxdr_unsigned(uint32_t, *tl);
620 reqlen = MIN(reqlen, NFS_SRVMAXDATA(nfsd));
621 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
622 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
623 if (error) {
624 nfsm_reply(2 * NFSX_UNSIGNED);
625 nfsm_srvpostop_attr(1, (struct vattr *)0);
626 return (0);
627 }
628 if (vp->v_type != VREG) {
629 if (v3)
630 error = EINVAL;
631 else
632 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
633 }
634 if (!error) {
635 nqsrv_getl(vp, ND_READ);
636 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, lwp, 1)) != 0)
637 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 1);
638 }
639 getret = VOP_GETATTR(vp, &va, cred, lwp);
640 if (!error)
641 error = getret;
642 if (error) {
643 vput(vp);
644 nfsm_reply(NFSX_POSTOPATTR(v3));
645 nfsm_srvpostop_attr(getret, &va);
646 return (0);
647 }
648 if (off >= va.va_size)
649 cnt = 0;
650 else if ((off + reqlen) > va.va_size)
651 cnt = va.va_size - off;
652 else
653 cnt = reqlen;
654 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
655 if (v3) {
656 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
657 *tl++ = nfs_true;
658 fp = (struct nfs_fattr *)tl;
659 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
660 } else {
661 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
662 fp = (struct nfs_fattr *)tl;
663 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
664 }
665 len = left = cnt;
666 if (cnt > 0) {
667 if (nfsd_use_loan) {
668 struct vm_page **pgpp;
669 voff_t pgoff = trunc_page(off);
670 int orignpages, nleftpages;
671 vaddr_t lva, curlva;
672
673 orignpages = (round_page(off + cnt) - pgoff)
674 >> PAGE_SHIFT;
675 KASSERT(orignpages <= M_EXT_MAXPAGES); /* XXX */
676
677 lva = sokvaalloc(orignpages << PAGE_SHIFT, slp->ns_so);
678 if (lva == 0) {
679 /* fall back to VOP_READ */
680 goto loan_fail;
681 }
682
683 m = m_get(M_WAIT, MT_DATA);
684 pgpp = m->m_ext.ext_pgs;
685
686 curlva = lva;
687 nleftpages = orignpages;
688 while (nleftpages > 0) {
689 int npages = nleftpages;
690 if (npages > NFSD_READ_GETPAGES_CHUNK)
691 npages = NFSD_READ_GETPAGES_CHUNK;
692 again:
693 simple_lock(&vp->v_interlock);
694 error = VOP_GETPAGES(vp, pgoff, pgpp, &npages,
695 0, VM_PROT_READ, 0, PGO_SYNCIO);
696 if (error == EAGAIN) {
697 tsleep(&lbolt, PVM, "nfsread", 0);
698 goto again;
699 }
700 if (error) {
701 uvm_unloan(m->m_ext.ext_pgs,
702 orignpages - nleftpages,
703 UVM_LOAN_TOPAGE);
704 sokvafree(lva,
705 orignpages << PAGE_SHIFT);
706 m_free(m);
707 goto read_error;
708 }
709
710 /* loan and unbusy pages */
711 simple_lock(&vp->v_interlock);
712 for (i = 0; i < npages; i++) {
713 if (pgpp[i]->flags & PG_RELEASED) {
714 uvm_lock_pageq();
715 uvm_page_unbusy(pgpp, npages);
716 uvm_unlock_pageq();
717 simple_unlock(&vp->v_interlock);
718 continue;
719 }
720 }
721 uvm_loanuobjpages(pgpp, npages);
722 simple_unlock(&vp->v_interlock);
723
724 /* map pages */
725 for (i = 0; i < npages; i++) {
726 pmap_kenter_pa(curlva,
727 VM_PAGE_TO_PHYS(pgpp[i]),
728 VM_PROT_READ);
729 curlva += PAGE_SIZE;
730 }
731 nleftpages -= npages;
732 pgpp += npages;
733 pgoff += npages << PAGE_SHIFT;
734 }
735
736 lva += off & PAGE_MASK;
737
738 MCLAIM(m, &nfs_mowner);
739 MEXTADD(m, (void *)lva, cnt, M_MBUF, soloanfree,
740 slp->ns_so);
741 m->m_flags |= M_EXT_PAGES | M_EXT_ROMAP;
742 m->m_len = cnt;
743
744 pmap_update(pmap_kernel());
745 mb->m_next = m;
746 mb = m;
747 error = 0;
748 uiop->uio_resid = 0;
749 } else {
750 struct iovec *iv;
751 struct iovec *iv2;
752 struct mbuf *m2;
753 int siz;
754 loan_fail:
755 /*
756 * Generate the mbuf list with the uio_iov ref. to it.
757 */
758 i = 0;
759 m = m2 = mb;
760 while (left > 0) {
761 siz = min(M_TRAILINGSPACE(m), left);
762 if (siz > 0) {
763 left -= siz;
764 i++;
765 }
766 if (left > 0) {
767 m = m_get(M_WAIT, MT_DATA);
768 MCLAIM(m, &nfs_mowner);
769 m_clget(m, M_WAIT);
770 m->m_len = 0;
771 m2->m_next = m;
772 m2 = m;
773 }
774 }
775 iv = malloc(i * sizeof(struct iovec), M_TEMP, M_WAITOK);
776 uiop->uio_iov = iv2 = iv;
777 m = mb;
778 left = cnt;
779 i = 0;
780 while (left > 0) {
781 if (m == NULL)
782 panic("nfsrv_read iov");
783 siz = min(M_TRAILINGSPACE(m), left);
784 if (siz > 0) {
785 iv->iov_base = mtod(m, caddr_t) +
786 m->m_len;
787 iv->iov_len = siz;
788 m->m_len += siz;
789 left -= siz;
790 iv++;
791 i++;
792 }
793 m = m->m_next;
794 }
795 uiop->uio_iovcnt = i;
796 uiop->uio_offset = off;
797 uiop->uio_resid = cnt;
798 uiop->uio_rw = UIO_READ;
799 uiop->uio_segflg = UIO_SYSSPACE;
800 error = VOP_READ(vp, uiop, IO_NODELOCKED, cred);
801 off = uiop->uio_offset;
802 free((caddr_t)iv2, M_TEMP);
803 }
804 read_error:
805 if (error || (getret = VOP_GETATTR(vp, &va, cred, lwp)) != 0){
806 if (!error)
807 error = getret;
808 m_freem(mreq);
809 vput(vp);
810 nfsm_reply(NFSX_POSTOPATTR(v3));
811 nfsm_srvpostop_attr(getret, &va);
812 return (0);
813 }
814 } else {
815 uiop->uio_resid = 0;
816 }
817 vput(vp);
818 nfsm_srvfillattr(&va, fp);
819 len -= uiop->uio_resid;
820 padlen = nfsm_padlen(len);
821 if (uiop->uio_resid || padlen)
822 nfs_zeropad(mb, uiop->uio_resid, padlen);
823 if (v3) {
824 *tl++ = txdr_unsigned(len);
825 if (len < reqlen)
826 *tl++ = nfs_true;
827 else
828 *tl++ = nfs_false;
829 }
830 *tl = txdr_unsigned(len);
831 nfsm_srvdone;
832 }
833
834 /*
835 * nfs write service
836 */
837 int
838 nfsrv_write(nfsd, slp, lwp, mrq)
839 struct nfsrv_descript *nfsd;
840 struct nfssvc_sock *slp;
841 struct lwp *lwp;
842 struct mbuf **mrq;
843 {
844 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
845 struct mbuf *nam = nfsd->nd_nam;
846 caddr_t dpos = nfsd->nd_dpos;
847 struct ucred *cred = &nfsd->nd_cr;
848 struct iovec *ivp;
849 int i, cnt;
850 struct mbuf *mp;
851 struct nfs_fattr *fp;
852 struct iovec *iv;
853 struct vattr va, forat;
854 u_int32_t *tl;
855 int32_t t1;
856 caddr_t bpos;
857 int error = 0, rdonly, cache, len, forat_ret = 1;
858 int ioflags, aftat_ret = 1, retlen, zeroing, adjust;
859 int stable = NFSV3WRITE_FILESYNC;
860 int v3 = (nfsd->nd_flag & ND_NFSV3);
861 char *cp2;
862 struct mbuf *mb, *mreq;
863 struct vnode *vp;
864 nfsfh_t nfh;
865 fhandle_t *fhp;
866 struct uio io, *uiop = &io;
867 off_t off;
868 u_quad_t frev;
869
870 if (mrep == NULL) {
871 *mrq = NULL;
872 return (0);
873 }
874 fhp = &nfh.fh_generic;
875 nfsm_srvmtofh(fhp);
876 if (v3) {
877 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
878 off = fxdr_hyper(tl);
879 tl += 3;
880 stable = fxdr_unsigned(int, *tl++);
881 } else {
882 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
883 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
884 tl += 2;
885 }
886 retlen = len = fxdr_unsigned(int32_t, *tl);
887 cnt = i = 0;
888
889 /*
890 * For NFS Version 2, it is not obvious what a write of zero length
891 * should do, but I might as well be consistent with Version 3,
892 * which is to return ok so long as there are no permission problems.
893 */
894 if (len > 0) {
895 zeroing = 1;
896 mp = mrep;
897 while (mp) {
898 if (mp == md) {
899 zeroing = 0;
900 adjust = dpos - mtod(mp, caddr_t);
901 mp->m_len -= adjust;
902 if (mp->m_len > 0 && adjust > 0)
903 NFSMADV(mp, adjust);
904 }
905 if (zeroing)
906 mp->m_len = 0;
907 else if (mp->m_len > 0) {
908 i += mp->m_len;
909 if (i > len) {
910 mp->m_len -= (i - len);
911 zeroing = 1;
912 }
913 if (mp->m_len > 0)
914 cnt++;
915 }
916 mp = mp->m_next;
917 }
918 }
919 if (len > NFS_MAXDATA || len < 0 || i < len) {
920 error = EIO;
921 nfsm_reply(2 * NFSX_UNSIGNED);
922 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
923 return (0);
924 }
925 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
926 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
927 if (error) {
928 nfsm_reply(2 * NFSX_UNSIGNED);
929 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
930 return (0);
931 }
932 if (v3)
933 forat_ret = VOP_GETATTR(vp, &forat, cred, lwp);
934 if (vp->v_type != VREG) {
935 if (v3)
936 error = EINVAL;
937 else
938 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
939 }
940 if (!error) {
941 nqsrv_getl(vp, ND_WRITE);
942 error = nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 1);
943 }
944 if (error) {
945 vput(vp);
946 nfsm_reply(NFSX_WCCDATA(v3));
947 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
948 return (0);
949 }
950
951 if (len > 0) {
952 ivp = malloc(cnt * sizeof (struct iovec), M_TEMP, M_WAITOK);
953 uiop->uio_iov = iv = ivp;
954 uiop->uio_iovcnt = cnt;
955 mp = mrep;
956 while (mp) {
957 if (mp->m_len > 0) {
958 ivp->iov_base = mtod(mp, caddr_t);
959 ivp->iov_len = mp->m_len;
960 ivp++;
961 }
962 mp = mp->m_next;
963 }
964
965 /*
966 * XXX
967 * The IO_METASYNC flag indicates that all metadata (and not
968 * just enough to ensure data integrity) must be written to
969 * stable storage synchronously.
970 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
971 */
972 if (stable == NFSV3WRITE_UNSTABLE)
973 ioflags = IO_NODELOCKED;
974 else if (stable == NFSV3WRITE_DATASYNC)
975 ioflags = (IO_SYNC | IO_NODELOCKED);
976 else
977 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
978 uiop->uio_resid = len;
979 uiop->uio_rw = UIO_WRITE;
980 uiop->uio_segflg = UIO_SYSSPACE;
981 uiop->uio_lwp = (struct lwp *)0;
982 uiop->uio_offset = off;
983 error = VOP_WRITE(vp, uiop, ioflags, cred);
984 nfsstats.srvvop_writes++;
985 free(iv, M_TEMP);
986 }
987 aftat_ret = VOP_GETATTR(vp, &va, cred, lwp);
988 vput(vp);
989 if (!error)
990 error = aftat_ret;
991 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
992 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
993 if (v3) {
994 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
995 if (error)
996 return (0);
997 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
998 *tl++ = txdr_unsigned(retlen);
999 if (stable == NFSV3WRITE_UNSTABLE)
1000 *tl++ = txdr_unsigned(stable);
1001 else
1002 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1003 /*
1004 * Actually, there is no need to txdr these fields,
1005 * but it may make the values more human readable,
1006 * for debugging purposes.
1007 */
1008 *tl++ = txdr_unsigned(boottime.tv_sec);
1009 *tl = txdr_unsigned(boottime.tv_usec);
1010 } else {
1011 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1012 nfsm_srvfillattr(&va, fp);
1013 }
1014 nfsm_srvdone;
1015 }
1016
1017 /*
1018 * NFS write service with write gathering support. Called when
1019 * nfsrvw_procrastinate > 0.
1020 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1021 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1022 * Jan. 1994.
1023 */
1024 int
1025 nfsrv_writegather(ndp, slp, lwp, mrq)
1026 struct nfsrv_descript **ndp;
1027 struct nfssvc_sock *slp;
1028 struct lwp *lwp;
1029 struct mbuf **mrq;
1030 {
1031 struct iovec *ivp;
1032 struct mbuf *mp;
1033 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1034 struct nfs_fattr *fp;
1035 int i = 0;
1036 struct iovec *iov;
1037 struct nfsrvw_delayhash *wpp;
1038 struct ucred *cred;
1039 struct vattr va, forat;
1040 u_int32_t *tl;
1041 int32_t t1;
1042 caddr_t bpos, dpos;
1043 int error = 0, rdonly, cache, len = 0, forat_ret = 1;
1044 int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
1045 char *cp2;
1046 struct mbuf *mb, *mreq, *mrep, *md;
1047 struct vnode *vp;
1048 struct uio io, *uiop = &io;
1049 u_quad_t frev, cur_usec;
1050
1051 *mrq = NULL;
1052 if (*ndp) {
1053 nfsd = *ndp;
1054 *ndp = NULL;
1055 mrep = nfsd->nd_mrep;
1056 md = nfsd->nd_md;
1057 dpos = nfsd->nd_dpos;
1058 cred = &nfsd->nd_cr;
1059 v3 = (nfsd->nd_flag & ND_NFSV3);
1060 LIST_INIT(&nfsd->nd_coalesce);
1061 nfsd->nd_mreq = NULL;
1062 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1063 cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
1064 nfsd->nd_time = cur_usec + nfsrvw_procrastinate;
1065
1066 /*
1067 * Now, get the write header..
1068 */
1069 nfsm_srvmtofh(&nfsd->nd_fh);
1070 if (v3) {
1071 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
1072 nfsd->nd_off = fxdr_hyper(tl);
1073 tl += 3;
1074 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1075 } else {
1076 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1077 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1078 tl += 2;
1079 }
1080 len = fxdr_unsigned(int32_t, *tl);
1081 nfsd->nd_len = len;
1082 nfsd->nd_eoff = nfsd->nd_off + len;
1083
1084 /*
1085 * Trim the header out of the mbuf list and trim off any trailing
1086 * junk so that the mbuf list has only the write data.
1087 */
1088 zeroing = 1;
1089 i = 0;
1090 mp = mrep;
1091 while (mp) {
1092 if (mp == md) {
1093 zeroing = 0;
1094 adjust = dpos - mtod(mp, caddr_t);
1095 mp->m_len -= adjust;
1096 if (mp->m_len > 0 && adjust > 0)
1097 NFSMADV(mp, adjust);
1098 }
1099 if (zeroing)
1100 mp->m_len = 0;
1101 else {
1102 i += mp->m_len;
1103 if (i > len) {
1104 mp->m_len -= (i - len);
1105 zeroing = 1;
1106 }
1107 }
1108 mp = mp->m_next;
1109 }
1110 if (len > NFS_MAXDATA || len < 0 || i < len) {
1111 nfsmout:
1112 m_freem(mrep);
1113 error = EIO;
1114 nfsm_writereply(2 * NFSX_UNSIGNED, v3);
1115 if (v3)
1116 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1117 nfsd->nd_mreq = mreq;
1118 nfsd->nd_mrep = NULL;
1119 nfsd->nd_time = 0;
1120 }
1121
1122 /*
1123 * Add this entry to the hash and time queues.
1124 */
1125 s = splsoftclock();
1126 owp = NULL;
1127 wp = LIST_FIRST(&slp->ns_tq);
1128 while (wp && wp->nd_time < nfsd->nd_time) {
1129 owp = wp;
1130 wp = LIST_NEXT(wp, nd_tq);
1131 }
1132 if (owp) {
1133 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1134 } else {
1135 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1136 }
1137 if (nfsd->nd_mrep) {
1138 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1139 owp = NULL;
1140 wp = LIST_FIRST(wpp);
1141 while (wp &&
1142 memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1143 owp = wp;
1144 wp = LIST_NEXT(wp, nd_hash);
1145 }
1146 while (wp && wp->nd_off < nfsd->nd_off &&
1147 !memcmp((caddr_t)&nfsd->nd_fh, (caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1148 owp = wp;
1149 wp = LIST_NEXT(wp, nd_hash);
1150 }
1151 if (owp) {
1152 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1153
1154 /*
1155 * Search the hash list for overlapping entries and
1156 * coalesce.
1157 */
1158 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1159 wp = LIST_NEXT(nfsd, nd_hash);
1160 if (NFSW_SAMECRED(owp, nfsd))
1161 nfsrvw_coalesce(owp, nfsd);
1162 }
1163 } else {
1164 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1165 }
1166 }
1167 splx(s);
1168 }
1169
1170 /*
1171 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1172 * and generate the associated reply mbuf list(s).
1173 */
1174 loop1:
1175 cur_usec = (u_quad_t)time.tv_sec * 1000000 + (u_quad_t)time.tv_usec;
1176 s = splsoftclock();
1177 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
1178 owp = LIST_NEXT(nfsd, nd_tq);
1179 if (nfsd->nd_time > cur_usec)
1180 break;
1181 if (nfsd->nd_mreq)
1182 continue;
1183 LIST_REMOVE(nfsd, nd_tq);
1184 LIST_REMOVE(nfsd, nd_hash);
1185 splx(s);
1186 mrep = nfsd->nd_mrep;
1187 nfsd->nd_mrep = NULL;
1188 cred = &nfsd->nd_cr;
1189 v3 = (nfsd->nd_flag & ND_NFSV3);
1190 forat_ret = aftat_ret = 1;
1191 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1192 nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH),
1193 FALSE);
1194 if (!error) {
1195 if (v3)
1196 forat_ret = VOP_GETATTR(vp, &forat, cred, lwp);
1197 if (vp->v_type != VREG) {
1198 if (v3)
1199 error = EINVAL;
1200 else
1201 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1202 }
1203 } else
1204 vp = NULL;
1205 if (!error) {
1206 nqsrv_getl(vp, ND_WRITE);
1207 error = nfsrv_access(vp, VWRITE, cred, rdonly, lwp, 1);
1208 }
1209
1210 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1211 ioflags = IO_NODELOCKED;
1212 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1213 ioflags = (IO_SYNC | IO_NODELOCKED);
1214 else
1215 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1216 uiop->uio_rw = UIO_WRITE;
1217 uiop->uio_segflg = UIO_SYSSPACE;
1218 uiop->uio_lwp = (struct lwp *)0;
1219 uiop->uio_offset = nfsd->nd_off;
1220 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1221 if (uiop->uio_resid > 0) {
1222 mp = mrep;
1223 i = 0;
1224 while (mp) {
1225 if (mp->m_len > 0)
1226 i++;
1227 mp = mp->m_next;
1228 }
1229 uiop->uio_iovcnt = i;
1230 iov = malloc(i * sizeof (struct iovec), M_TEMP, M_WAITOK);
1231 uiop->uio_iov = ivp = iov;
1232 mp = mrep;
1233 while (mp) {
1234 if (mp->m_len > 0) {
1235 ivp->iov_base = mtod(mp, caddr_t);
1236 ivp->iov_len = mp->m_len;
1237 ivp++;
1238 }
1239 mp = mp->m_next;
1240 }
1241 if (!error) {
1242 error = VOP_WRITE(vp, uiop, ioflags, cred);
1243 nfsstats.srvvop_writes++;
1244 }
1245 free((caddr_t)iov, M_TEMP);
1246 }
1247 m_freem(mrep);
1248 if (vp) {
1249 aftat_ret = VOP_GETATTR(vp, &va, cred, lwp);
1250 vput(vp);
1251 }
1252
1253 /*
1254 * Loop around generating replies for all write rpcs that have
1255 * now been completed.
1256 */
1257 swp = nfsd;
1258 do {
1259 if (error) {
1260 nfsm_writereply(NFSX_WCCDATA(v3), v3);
1261 if (v3) {
1262 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1263 }
1264 } else {
1265 nfsm_writereply(NFSX_PREOPATTR(v3) +
1266 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1267 NFSX_WRITEVERF(v3), v3);
1268 if (v3) {
1269 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1270 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
1271 *tl++ = txdr_unsigned(nfsd->nd_len);
1272 *tl++ = txdr_unsigned(swp->nd_stable);
1273 /*
1274 * Actually, there is no need to txdr these fields,
1275 * but it may make the values more human readable,
1276 * for debugging purposes.
1277 */
1278 *tl++ = txdr_unsigned(boottime.tv_sec);
1279 *tl = txdr_unsigned(boottime.tv_usec);
1280 } else {
1281 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1282 nfsm_srvfillattr(&va, fp);
1283 }
1284 }
1285 nfsd->nd_mreq = mreq;
1286 if (nfsd->nd_mrep)
1287 panic("nfsrv_write: nd_mrep not free");
1288
1289 /*
1290 * Done. Put it at the head of the timer queue so that
1291 * the final phase can return the reply.
1292 */
1293 s = splsoftclock();
1294 if (nfsd != swp) {
1295 nfsd->nd_time = 0;
1296 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1297 }
1298 nfsd = LIST_FIRST(&swp->nd_coalesce);
1299 if (nfsd) {
1300 LIST_REMOVE(nfsd, nd_tq);
1301 }
1302 splx(s);
1303 } while (nfsd);
1304 s = splsoftclock();
1305 swp->nd_time = 0;
1306 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1307 splx(s);
1308 goto loop1;
1309 }
1310 splx(s);
1311
1312 /*
1313 * Search for a reply to return.
1314 */
1315 s = splsoftclock();
1316 LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq) {
1317 if (nfsd->nd_mreq) {
1318 LIST_REMOVE(nfsd, nd_tq);
1319 *mrq = nfsd->nd_mreq;
1320 *ndp = nfsd;
1321 break;
1322 }
1323 }
1324 splx(s);
1325 return (0);
1326 }
1327
1328 /*
1329 * Coalesce the write request nfsd into owp. To do this we must:
1330 * - remove nfsd from the queues
1331 * - merge nfsd->nd_mrep into owp->nd_mrep
1332 * - update the nd_eoff and nd_stable for owp
1333 * - put nfsd on owp's nd_coalesce list
1334 * NB: Must be called at splsoftclock().
1335 */
1336 void
1337 nfsrvw_coalesce(owp, nfsd)
1338 struct nfsrv_descript *owp;
1339 struct nfsrv_descript *nfsd;
1340 {
1341 int overlap;
1342 struct mbuf *mp;
1343 struct nfsrv_descript *m;
1344
1345 LIST_REMOVE(nfsd, nd_hash);
1346 LIST_REMOVE(nfsd, nd_tq);
1347 if (owp->nd_eoff < nfsd->nd_eoff) {
1348 overlap = owp->nd_eoff - nfsd->nd_off;
1349 if (overlap < 0)
1350 panic("nfsrv_coalesce: bad off");
1351 if (overlap > 0)
1352 m_adj(nfsd->nd_mrep, overlap);
1353 mp = owp->nd_mrep;
1354 while (mp->m_next)
1355 mp = mp->m_next;
1356 mp->m_next = nfsd->nd_mrep;
1357 owp->nd_eoff = nfsd->nd_eoff;
1358 } else
1359 m_freem(nfsd->nd_mrep);
1360 nfsd->nd_mrep = NULL;
1361 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1362 owp->nd_stable = NFSV3WRITE_FILESYNC;
1363 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1364 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1365 owp->nd_stable = NFSV3WRITE_DATASYNC;
1366 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1367 /*
1368 * nfsd might hold coalesce elements! Move them to owp.
1369 * Otherwise, requests may be lost and clients will be stuck.
1370 */
1371 while ((m = LIST_FIRST(&nfsd->nd_coalesce)) != NULL) {
1372 LIST_REMOVE(m, nd_tq);
1373 LIST_INSERT_HEAD(&owp->nd_coalesce, m, nd_tq);
1374 }
1375 }
1376
1377 /*
1378 * nfs create service
1379 * now does a truncate to 0 length via. setattr if it already exists
1380 */
1381 int
1382 nfsrv_create(nfsd, slp, lwp, mrq)
1383 struct nfsrv_descript *nfsd;
1384 struct nfssvc_sock *slp;
1385 struct lwp *lwp;
1386 struct mbuf **mrq;
1387 {
1388 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1389 struct mbuf *nam = nfsd->nd_nam;
1390 caddr_t dpos = nfsd->nd_dpos;
1391 struct ucred *cred = &nfsd->nd_cr;
1392 struct nfs_fattr *fp;
1393 struct vattr va, dirfor, diraft;
1394 struct nfsv2_sattr *sp;
1395 u_int32_t *tl;
1396 struct nameidata nd;
1397 caddr_t cp;
1398 int32_t t1;
1399 caddr_t bpos;
1400 int error = 0, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1401 int rdev = 0;
1402 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1403 char *cp2;
1404 struct mbuf *mb, *mreq;
1405 struct vnode *vp = NULL, *dirp = NULL;
1406 nfsfh_t nfh;
1407 fhandle_t *fhp;
1408 u_quad_t frev, tempsize;
1409 u_char cverf[NFSX_V3CREATEVERF];
1410
1411 nd.ni_cnd.cn_nameiop = 0;
1412 fhp = &nfh.fh_generic;
1413 nfsm_srvmtofh(fhp);
1414 nfsm_srvnamesiz(len);
1415 nd.ni_cnd.cn_cred = cred;
1416 nd.ni_cnd.cn_nameiop = CREATE;
1417 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1418 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1419 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1420 if (dirp) {
1421 if (v3)
1422 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
1423 else {
1424 vrele(dirp);
1425 dirp = (struct vnode *)0;
1426 }
1427 }
1428 if (error) {
1429 nfsm_reply(NFSX_WCCDATA(v3));
1430 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1431 if (dirp)
1432 vrele(dirp);
1433 return (0);
1434 }
1435 VATTR_NULL(&va);
1436 if (v3) {
1437 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1438 how = fxdr_unsigned(int, *tl);
1439 switch (how) {
1440 case NFSV3CREATE_GUARDED:
1441 if (nd.ni_vp) {
1442 error = EEXIST;
1443 break;
1444 }
1445 case NFSV3CREATE_UNCHECKED:
1446 nfsm_srvsattr(&va);
1447 break;
1448 case NFSV3CREATE_EXCLUSIVE:
1449 nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF);
1450 memcpy(cverf, cp, NFSX_V3CREATEVERF);
1451 exclusive_flag = 1;
1452 if (nd.ni_vp == NULL)
1453 va.va_mode = 0;
1454 break;
1455 };
1456 va.va_type = VREG;
1457 } else {
1458 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
1459 va.va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1460 if (va.va_type == VNON)
1461 va.va_type = VREG;
1462 va.va_mode = nfstov_mode(sp->sa_mode);
1463 switch (va.va_type) {
1464 case VREG:
1465 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1466 if (tsize != -1)
1467 va.va_size = (u_quad_t)tsize;
1468 break;
1469 case VCHR:
1470 case VBLK:
1471 case VFIFO:
1472 rdev = fxdr_unsigned(int32_t, sp->sa_size);
1473 break;
1474 default:
1475 break;
1476 };
1477 }
1478
1479 /*
1480 * Iff doesn't exist, create it
1481 * otherwise just truncate to 0 length
1482 * should I set the mode too ??
1483 */
1484 if (nd.ni_vp == NULL) {
1485 if (va.va_type == VREG || va.va_type == VSOCK) {
1486 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1487 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1488 if (!error) {
1489 if (exclusive_flag) {
1490 exclusive_flag = 0;
1491 VATTR_NULL(&va);
1492 memcpy((caddr_t)&va.va_atime, cverf,
1493 NFSX_V3CREATEVERF);
1494 error = VOP_SETATTR(nd.ni_vp, &va, cred,
1495 lwp);
1496 }
1497 }
1498 } else if (va.va_type == VCHR || va.va_type == VBLK ||
1499 va.va_type == VFIFO) {
1500 if (va.va_type == VCHR && rdev == 0xffffffff)
1501 va.va_type = VFIFO;
1502 if (va.va_type != VFIFO &&
1503 (error = suser(cred, (u_short *)0))) {
1504 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1505 vput(nd.ni_dvp);
1506 nfsm_reply(0);
1507 return (error);
1508 } else
1509 va.va_rdev = (dev_t)rdev;
1510 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1511 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd,
1512 &va);
1513 if (error) {
1514 nfsm_reply(0);
1515 }
1516 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1517 vrele(nd.ni_dvp);
1518 vput(nd.ni_vp);
1519 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1520 error = EINVAL;
1521 nfsm_reply(0);
1522 }
1523 } else {
1524 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1525 vput(nd.ni_dvp);
1526 error = ENXIO;
1527 }
1528 vp = nd.ni_vp;
1529 } else {
1530 vp = nd.ni_vp;
1531 if (nd.ni_dvp == vp)
1532 vrele(nd.ni_dvp);
1533 else
1534 vput(nd.ni_dvp);
1535 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1536 if (!error && va.va_size != -1) {
1537 error = nfsrv_access(vp, VWRITE, cred,
1538 (nd.ni_cnd.cn_flags & RDONLY), lwp, 0);
1539 if (!error) {
1540 nqsrv_getl(vp, ND_WRITE);
1541 tempsize = va.va_size;
1542 VATTR_NULL(&va);
1543 va.va_size = tempsize;
1544 error = VOP_SETATTR(vp, &va, cred, lwp);
1545 }
1546 }
1547 if (error)
1548 vput(vp);
1549 }
1550 if (!error) {
1551 memset((caddr_t)fhp, 0, sizeof(nfh));
1552 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1553 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1554 if (!error)
1555 error = VOP_GETATTR(vp, &va, cred, lwp);
1556 vput(vp);
1557 }
1558 if (v3) {
1559 if (exclusive_flag && !error &&
1560 memcmp(cverf, (caddr_t)&va.va_atime, NFSX_V3CREATEVERF))
1561 error = EEXIST;
1562 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
1563 vrele(dirp);
1564 }
1565 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1566 if (v3) {
1567 if (!error) {
1568 nfsm_srvpostop_fh(fhp);
1569 nfsm_srvpostop_attr(0, &va);
1570 }
1571 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1572 } else {
1573 nfsm_srvfhtom(fhp, v3);
1574 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
1575 nfsm_srvfillattr(&va, fp);
1576 }
1577 return (0);
1578 nfsmout:
1579 if (dirp)
1580 vrele(dirp);
1581 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1582 if (nd.ni_dvp == nd.ni_vp)
1583 vrele(nd.ni_dvp);
1584 else
1585 vput(nd.ni_dvp);
1586 if (nd.ni_vp)
1587 vput(nd.ni_vp);
1588 return (error);
1589 }
1590
1591 /*
1592 * nfs v3 mknod service
1593 */
1594 int
1595 nfsrv_mknod(nfsd, slp, lwp, mrq)
1596 struct nfsrv_descript *nfsd;
1597 struct nfssvc_sock *slp;
1598 struct lwp *lwp;
1599 struct mbuf **mrq;
1600 {
1601 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1602 struct mbuf *nam = nfsd->nd_nam;
1603 caddr_t dpos = nfsd->nd_dpos;
1604 struct ucred *cred = &nfsd->nd_cr;
1605 struct vattr va, dirfor, diraft;
1606 u_int32_t *tl;
1607 struct nameidata nd;
1608 int32_t t1;
1609 caddr_t bpos;
1610 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
1611 u_int32_t major, minor;
1612 enum vtype vtyp;
1613 char *cp2;
1614 struct mbuf *mb, *mreq;
1615 struct vnode *vp, *dirp = (struct vnode *)0;
1616 nfsfh_t nfh;
1617 fhandle_t *fhp;
1618 u_quad_t frev;
1619
1620 nd.ni_cnd.cn_nameiop = 0;
1621 fhp = &nfh.fh_generic;
1622 nfsm_srvmtofh(fhp);
1623 nfsm_srvnamesiz(len);
1624 nd.ni_cnd.cn_cred = cred;
1625 nd.ni_cnd.cn_nameiop = CREATE;
1626 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1627 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1628 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1629 if (dirp)
1630 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
1631 if (error) {
1632 nfsm_reply(NFSX_WCCDATA(1));
1633 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1634 if (dirp)
1635 vrele(dirp);
1636 return (0);
1637 }
1638 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
1639 vtyp = nfsv3tov_type(*tl);
1640 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
1641 error = NFSERR_BADTYPE;
1642 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1643 if (nd.ni_dvp == nd.ni_vp)
1644 vrele(nd.ni_dvp);
1645 else
1646 vput(nd.ni_dvp);
1647 if (nd.ni_vp)
1648 vput(nd.ni_vp);
1649 goto out;
1650 }
1651 VATTR_NULL(&va);
1652 nfsm_srvsattr(&va);
1653 if (vtyp == VCHR || vtyp == VBLK) {
1654 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
1655 major = fxdr_unsigned(u_int32_t, *tl++);
1656 minor = fxdr_unsigned(u_int32_t, *tl);
1657 va.va_rdev = makedev(major, minor);
1658 }
1659
1660 /*
1661 * Iff doesn't exist, create it.
1662 */
1663 if (nd.ni_vp) {
1664 error = EEXIST;
1665 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1666 if (nd.ni_dvp == nd.ni_vp)
1667 vrele(nd.ni_dvp);
1668 else
1669 vput(nd.ni_dvp);
1670 vput(nd.ni_vp);
1671 goto out;
1672 }
1673 va.va_type = vtyp;
1674 if (vtyp == VSOCK) {
1675 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1676 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1677 } else {
1678 if (va.va_type != VFIFO &&
1679 (error = suser(cred, (u_short *)0))) {
1680 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1681 vput(nd.ni_dvp);
1682 goto out;
1683 }
1684 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1685 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
1686 if (error) {
1687 goto out;
1688 }
1689 if (error)
1690 goto out;
1691 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1692 vput(nd.ni_vp);
1693 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1694 error = EINVAL;
1695 }
1696 }
1697 out:
1698 vp = nd.ni_vp;
1699 if (!error) {
1700 memset((caddr_t)fhp, 0, sizeof(nfh));
1701 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
1702 error = VFS_VPTOFH(vp, &fhp->fh_fid);
1703 if (!error)
1704 error = VOP_GETATTR(vp, &va, cred, lwp);
1705 vput(vp);
1706 }
1707 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
1708 vrele(dirp);
1709 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
1710 if (!error) {
1711 nfsm_srvpostop_fh(fhp);
1712 nfsm_srvpostop_attr(0, &va);
1713 }
1714 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1715 return (0);
1716 nfsmout:
1717 if (dirp)
1718 vrele(dirp);
1719 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1720 if (nd.ni_dvp == nd.ni_vp)
1721 vrele(nd.ni_dvp);
1722 else
1723 vput(nd.ni_dvp);
1724 if (nd.ni_vp)
1725 vput(nd.ni_vp);
1726 return (error);
1727 }
1728
1729 /*
1730 * nfs remove service
1731 */
1732 int
1733 nfsrv_remove(nfsd, slp, lwp, mrq)
1734 struct nfsrv_descript *nfsd;
1735 struct nfssvc_sock *slp;
1736 struct lwp *lwp;
1737 struct mbuf **mrq;
1738 {
1739 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1740 struct mbuf *nam = nfsd->nd_nam;
1741 caddr_t dpos = nfsd->nd_dpos;
1742 struct ucred *cred = &nfsd->nd_cr;
1743 struct nameidata nd;
1744 u_int32_t *tl;
1745 int32_t t1;
1746 caddr_t bpos;
1747 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
1748 int v3 = (nfsd->nd_flag & ND_NFSV3);
1749 char *cp2;
1750 struct mbuf *mb, *mreq;
1751 struct vnode *vp, *dirp;
1752 struct vattr dirfor, diraft;
1753 nfsfh_t nfh;
1754 fhandle_t *fhp;
1755 u_quad_t frev;
1756
1757 #ifndef nolint
1758 vp = (struct vnode *)0;
1759 #endif
1760 fhp = &nfh.fh_generic;
1761 nfsm_srvmtofh(fhp);
1762 nfsm_srvnamesiz(len);
1763 nd.ni_cnd.cn_cred = cred;
1764 nd.ni_cnd.cn_nameiop = DELETE;
1765 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
1766 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1767 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1768 if (dirp) {
1769 if (v3)
1770 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
1771 else
1772 vrele(dirp);
1773 }
1774 if (!error) {
1775 vp = nd.ni_vp;
1776 if (vp->v_type == VDIR &&
1777 (error = suser(cred, (u_short *)0)) != 0)
1778 goto out;
1779 /*
1780 * The root of a mounted filesystem cannot be deleted.
1781 */
1782 if (vp->v_flag & VROOT) {
1783 error = EBUSY;
1784 goto out;
1785 }
1786 out:
1787 if (!error) {
1788 nqsrv_getl(nd.ni_dvp, ND_WRITE);
1789 nqsrv_getl(vp, ND_WRITE);
1790 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
1791 } else {
1792 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
1793 if (nd.ni_dvp == vp)
1794 vrele(nd.ni_dvp);
1795 else
1796 vput(nd.ni_dvp);
1797 vput(vp);
1798 }
1799 }
1800 if (dirp && v3) {
1801 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
1802 vrele(dirp);
1803 }
1804 nfsm_reply(NFSX_WCCDATA(v3));
1805 if (v3) {
1806 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1807 return (0);
1808 }
1809 nfsm_srvdone;
1810 }
1811
1812 /*
1813 * nfs rename service
1814 */
1815 int
1816 nfsrv_rename(nfsd, slp, lwp, mrq)
1817 struct nfsrv_descript *nfsd;
1818 struct nfssvc_sock *slp;
1819 struct lwp *lwp;
1820 struct mbuf **mrq;
1821 {
1822 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1823 struct mbuf *nam = nfsd->nd_nam;
1824 caddr_t dpos = nfsd->nd_dpos;
1825 struct ucred *cred = &nfsd->nd_cr;
1826 u_int32_t *tl;
1827 int32_t t1;
1828 caddr_t bpos;
1829 int error = 0, cache, fdirfor_ret = 1, fdiraft_ret = 1;
1830 uint32_t len, len2;
1831 int tdirfor_ret = 1, tdiraft_ret = 1;
1832 int v3 = (nfsd->nd_flag & ND_NFSV3);
1833 char *cp2;
1834 struct mbuf *mb, *mreq;
1835 struct nameidata fromnd, tond;
1836 struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0;
1837 struct vnode *tdirp = (struct vnode *)0;
1838 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
1839 nfsfh_t fnfh, tnfh;
1840 fhandle_t *ffhp, *tfhp;
1841 u_quad_t frev;
1842 uid_t saved_uid;
1843
1844 #ifndef nolint
1845 fvp = (struct vnode *)0;
1846 #endif
1847 ffhp = &fnfh.fh_generic;
1848 tfhp = &tnfh.fh_generic;
1849 fromnd.ni_cnd.cn_nameiop = 0;
1850 tond.ni_cnd.cn_nameiop = 0;
1851 nfsm_srvmtofh(ffhp);
1852 nfsm_srvnamesiz(len);
1853 /*
1854 * Remember our original uid so that we can reset cr_uid before
1855 * the second nfs_namei() call, in case it is remapped.
1856 */
1857 saved_uid = cred->cr_uid;
1858 fromnd.ni_cnd.cn_cred = cred;
1859 fromnd.ni_cnd.cn_nameiop = DELETE;
1860 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
1861 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
1862 &dpos, &fdirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1863 if (fdirp) {
1864 if (v3)
1865 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, cred, lwp);
1866 else {
1867 vrele(fdirp);
1868 fdirp = (struct vnode *)0;
1869 }
1870 }
1871 if (error) {
1872 nfsm_reply(2 * NFSX_WCCDATA(v3));
1873 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
1874 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
1875 if (fdirp)
1876 vrele(fdirp);
1877 return (0);
1878 }
1879 fvp = fromnd.ni_vp;
1880 nfsm_srvmtofh(tfhp);
1881 if (v3) {
1882 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
1883 len2 = fxdr_unsigned(uint32_t, *tl);
1884 /* len2 will be checked by nfs_namei */
1885 }
1886 else {
1887 /* NFSv2 */
1888 nfsm_strsiz(len2, NFS_MAXNAMLEN);
1889 }
1890 cred->cr_uid = saved_uid;
1891 tond.ni_cnd.cn_cred = cred;
1892 tond.ni_cnd.cn_nameiop = RENAME;
1893 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
1894 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
1895 &dpos, &tdirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
1896 if (tdirp) {
1897 if (v3)
1898 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, cred, lwp);
1899 else {
1900 vrele(tdirp);
1901 tdirp = (struct vnode *)0;
1902 }
1903 }
1904 if (error) {
1905 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1906 vrele(fromnd.ni_dvp);
1907 vrele(fvp);
1908 goto out1;
1909 }
1910 tdvp = tond.ni_dvp;
1911 tvp = tond.ni_vp;
1912 if (tvp != NULL) {
1913 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
1914 if (v3)
1915 error = EEXIST;
1916 else
1917 error = EISDIR;
1918 goto out;
1919 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
1920 if (v3)
1921 error = EEXIST;
1922 else
1923 error = ENOTDIR;
1924 goto out;
1925 }
1926 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
1927 if (v3)
1928 error = EXDEV;
1929 else
1930 error = ENOTEMPTY;
1931 goto out;
1932 }
1933 }
1934 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
1935 if (v3)
1936 error = EXDEV;
1937 else
1938 error = ENOTEMPTY;
1939 goto out;
1940 }
1941 if (fvp->v_mount != tdvp->v_mount) {
1942 if (v3)
1943 error = EXDEV;
1944 else
1945 error = ENOTEMPTY;
1946 goto out;
1947 }
1948 if (fvp == tdvp) {
1949 if (v3)
1950 error = EINVAL;
1951 else
1952 error = ENOTEMPTY;
1953 }
1954 /*
1955 * If source is the same as the destination (that is the
1956 * same vnode with the same name in the same directory),
1957 * then there is nothing to do.
1958 */
1959 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
1960 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1961 !memcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
1962 fromnd.ni_cnd.cn_namelen))
1963 error = -1;
1964 out:
1965 if (!error) {
1966 nqsrv_getl(fromnd.ni_dvp, ND_WRITE);
1967 nqsrv_getl(tdvp, ND_WRITE);
1968 if (tvp) {
1969 nqsrv_getl(tvp, ND_WRITE);
1970 }
1971 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
1972 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
1973 } else {
1974 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
1975 if (tdvp == tvp)
1976 vrele(tdvp);
1977 else
1978 vput(tdvp);
1979 if (tvp)
1980 vput(tvp);
1981 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
1982 vrele(fromnd.ni_dvp);
1983 vrele(fvp);
1984 if (error == -1)
1985 error = 0;
1986 }
1987 vrele(tond.ni_startdir);
1988 PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
1989 out1:
1990 if (fdirp) {
1991 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, lwp);
1992 vrele(fdirp);
1993 }
1994 if (tdirp) {
1995 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, lwp);
1996 vrele(tdirp);
1997 }
1998 vrele(fromnd.ni_startdir);
1999 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
2000 nfsm_reply(2 * NFSX_WCCDATA(v3));
2001 if (v3) {
2002 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2003 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2004 }
2005 return (0);
2006
2007 nfsmout:
2008 if (fdirp)
2009 vrele(fdirp);
2010 if (tdirp)
2011 vrele(tdirp);
2012 if (tond.ni_cnd.cn_nameiop) {
2013 vrele(tond.ni_startdir);
2014 PNBUF_PUT(tond.ni_cnd.cn_pnbuf);
2015 }
2016 if (fromnd.ni_cnd.cn_nameiop) {
2017 vrele(fromnd.ni_startdir);
2018 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf);
2019 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
2020 vrele(fromnd.ni_dvp);
2021 vrele(fvp);
2022 }
2023 return (error);
2024 }
2025
2026 /*
2027 * nfs link service
2028 */
2029 int
2030 nfsrv_link(nfsd, slp, lwp, mrq)
2031 struct nfsrv_descript *nfsd;
2032 struct nfssvc_sock *slp;
2033 struct lwp *lwp;
2034 struct mbuf **mrq;
2035 {
2036 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2037 struct mbuf *nam = nfsd->nd_nam;
2038 caddr_t dpos = nfsd->nd_dpos;
2039 struct ucred *cred = &nfsd->nd_cr;
2040 struct nameidata nd;
2041 u_int32_t *tl;
2042 int32_t t1;
2043 caddr_t bpos;
2044 int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1;
2045 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2046 char *cp2;
2047 struct mbuf *mb, *mreq;
2048 struct vnode *vp, *xp, *dirp = (struct vnode *)0;
2049 struct vattr dirfor, diraft, at;
2050 nfsfh_t nfh, dnfh;
2051 fhandle_t *fhp, *dfhp;
2052 u_quad_t frev;
2053
2054 fhp = &nfh.fh_generic;
2055 dfhp = &dnfh.fh_generic;
2056 nfsm_srvmtofh(fhp);
2057 nfsm_srvmtofh(dfhp);
2058 nfsm_srvnamesiz(len);
2059 error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam,
2060 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2061 if (error) {
2062 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2063 nfsm_srvpostop_attr(getret, &at);
2064 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2065 return (0);
2066 }
2067 if (vp->v_type == VDIR && (error = suser(cred, (u_short *)0)) != 0)
2068 goto out1;
2069 nd.ni_cnd.cn_cred = cred;
2070 nd.ni_cnd.cn_nameiop = CREATE;
2071 nd.ni_cnd.cn_flags = LOCKPARENT;
2072 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2073 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2074 if (dirp) {
2075 if (v3)
2076 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
2077 else {
2078 vrele(dirp);
2079 dirp = (struct vnode *)0;
2080 }
2081 }
2082 if (error)
2083 goto out1;
2084 xp = nd.ni_vp;
2085 if (xp != NULL) {
2086 error = EEXIST;
2087 goto out;
2088 }
2089 xp = nd.ni_dvp;
2090 if (vp->v_mount != xp->v_mount)
2091 error = EXDEV;
2092 out:
2093 if (!error) {
2094 nqsrv_getl(vp, ND_WRITE);
2095 nqsrv_getl(xp, ND_WRITE);
2096 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2097 } else {
2098 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2099 if (nd.ni_dvp == nd.ni_vp)
2100 vrele(nd.ni_dvp);
2101 else
2102 vput(nd.ni_dvp);
2103 if (nd.ni_vp)
2104 vrele(nd.ni_vp);
2105 }
2106 out1:
2107 if (v3)
2108 getret = VOP_GETATTR(vp, &at, cred, lwp);
2109 if (dirp) {
2110 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
2111 vrele(dirp);
2112 }
2113 vrele(vp);
2114 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2115 if (v3) {
2116 nfsm_srvpostop_attr(getret, &at);
2117 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2118 return (0);
2119 }
2120 nfsm_srvdone;
2121 }
2122
2123 /*
2124 * nfs symbolic link service
2125 */
2126 int
2127 nfsrv_symlink(nfsd, slp, lwp, mrq)
2128 struct nfsrv_descript *nfsd;
2129 struct nfssvc_sock *slp;
2130 struct lwp *lwp;
2131 struct mbuf **mrq;
2132 {
2133 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2134 struct mbuf *nam = nfsd->nd_nam;
2135 caddr_t dpos = nfsd->nd_dpos;
2136 struct ucred *cred = &nfsd->nd_cr;
2137 struct vattr va, dirfor, diraft;
2138 struct nameidata nd;
2139 u_int32_t *tl;
2140 int32_t t1;
2141 struct nfsv2_sattr *sp;
2142 char *bpos, *pathcp = NULL, *cp2;
2143 struct uio io;
2144 struct iovec iv;
2145 int error = 0, cache, dirfor_ret = 1, diraft_ret = 1;
2146 uint32_t len, len2;
2147 int v3 = (nfsd->nd_flag & ND_NFSV3);
2148 struct mbuf *mb, *mreq;
2149 struct vnode *dirp = (struct vnode *)0;
2150 nfsfh_t nfh;
2151 fhandle_t *fhp;
2152 u_quad_t frev;
2153
2154 nd.ni_cnd.cn_nameiop = 0;
2155 fhp = &nfh.fh_generic;
2156 nfsm_srvmtofh(fhp);
2157 nfsm_srvnamesiz(len);
2158 nd.ni_cnd.cn_cred = cred;
2159 nd.ni_cnd.cn_nameiop = CREATE;
2160 nd.ni_cnd.cn_flags = LOCKPARENT;
2161 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2162 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2163 if (dirp) {
2164 if (v3)
2165 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
2166 else {
2167 vrele(dirp);
2168 dirp = (struct vnode *)0;
2169 }
2170 }
2171 if (error)
2172 goto out;
2173 VATTR_NULL(&va);
2174 if (v3) {
2175 nfsm_srvsattr(&va);
2176 nfsm_dissect(tl, uint32_t *, NFSX_UNSIGNED);
2177 len2 = fxdr_unsigned(uint32_t, *tl);
2178 if (len2 > PATH_MAX) {
2179 /* XXX should check _PC_NO_TRUNC */
2180 error = ENAMETOOLONG;
2181 goto abortop;
2182 }
2183 }
2184 else {
2185 /* NFSv2 */
2186 nfsm_strsiz(len2, NFS_MAXPATHLEN);
2187 }
2188 pathcp = malloc(len2 + 1, M_TEMP, M_WAITOK);
2189 iv.iov_base = pathcp;
2190 iv.iov_len = len2;
2191 io.uio_resid = len2;
2192 io.uio_offset = 0;
2193 io.uio_iov = &iv;
2194 io.uio_iovcnt = 1;
2195 io.uio_segflg = UIO_SYSSPACE;
2196 io.uio_rw = UIO_READ;
2197 io.uio_lwp = (struct lwp *)0;
2198 nfsm_mtouio(&io, len2);
2199 if (!v3) {
2200 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR);
2201 va.va_mode = fxdr_unsigned(u_int16_t, sp->sa_mode);
2202 }
2203 *(pathcp + len2) = '\0';
2204 if (nd.ni_vp) {
2205 error = EEXIST;
2206 abortop:
2207 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2208 if (nd.ni_dvp == nd.ni_vp)
2209 vrele(nd.ni_dvp);
2210 else
2211 vput(nd.ni_dvp);
2212 if (nd.ni_vp)
2213 vrele(nd.ni_vp);
2214 goto out;
2215 }
2216 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2217 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va, pathcp);
2218 if (!error) {
2219 if (v3) {
2220 memset((caddr_t)fhp, 0, sizeof(nfh));
2221 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2222 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2223 if (!error)
2224 error = VOP_GETATTR(nd.ni_vp, &va, cred, lwp);
2225 vput(nd.ni_vp);
2226 } else {
2227 vput(nd.ni_vp);
2228 }
2229 }
2230 out:
2231 if (pathcp)
2232 free(pathcp, M_TEMP);
2233 if (dirp) {
2234 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
2235 vrele(dirp);
2236 }
2237 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2238 if (v3) {
2239 if (!error) {
2240 nfsm_srvpostop_fh(fhp);
2241 nfsm_srvpostop_attr(0, &va);
2242 }
2243 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2244 }
2245 return (0);
2246 nfsmout:
2247 if (dirp)
2248 vrele(dirp);
2249 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2250 if (nd.ni_dvp == nd.ni_vp)
2251 vrele(nd.ni_dvp);
2252 else
2253 vput(nd.ni_dvp);
2254 if (nd.ni_vp)
2255 vrele(nd.ni_vp);
2256 if (pathcp)
2257 free(pathcp, M_TEMP);
2258 return (error);
2259 }
2260
2261 /*
2262 * nfs mkdir service
2263 */
2264 int
2265 nfsrv_mkdir(nfsd, slp, lwp, mrq)
2266 struct nfsrv_descript *nfsd;
2267 struct nfssvc_sock *slp;
2268 struct lwp *lwp;
2269 struct mbuf **mrq;
2270 {
2271 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2272 struct mbuf *nam = nfsd->nd_nam;
2273 caddr_t dpos = nfsd->nd_dpos;
2274 struct ucred *cred = &nfsd->nd_cr;
2275 struct vattr va, dirfor, diraft;
2276 struct nfs_fattr *fp;
2277 struct nameidata nd;
2278 caddr_t cp;
2279 u_int32_t *tl;
2280 int32_t t1;
2281 caddr_t bpos;
2282 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2283 int v3 = (nfsd->nd_flag & ND_NFSV3);
2284 char *cp2;
2285 struct mbuf *mb, *mreq;
2286 struct vnode *vp, *dirp = (struct vnode *)0;
2287 nfsfh_t nfh;
2288 fhandle_t *fhp;
2289 u_quad_t frev;
2290
2291 fhp = &nfh.fh_generic;
2292 nfsm_srvmtofh(fhp);
2293 nfsm_srvnamesiz(len);
2294 nd.ni_cnd.cn_cred = cred;
2295 nd.ni_cnd.cn_nameiop = CREATE;
2296 nd.ni_cnd.cn_flags = LOCKPARENT;
2297 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2298 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2299 if (dirp) {
2300 if (v3)
2301 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
2302 else {
2303 vrele(dirp);
2304 dirp = (struct vnode *)0;
2305 }
2306 }
2307 if (error) {
2308 nfsm_reply(NFSX_WCCDATA(v3));
2309 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2310 if (dirp)
2311 vrele(dirp);
2312 return (0);
2313 }
2314 VATTR_NULL(&va);
2315 if (v3) {
2316 nfsm_srvsattr(&va);
2317 } else {
2318 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED);
2319 va.va_mode = nfstov_mode(*tl++);
2320 }
2321 va.va_type = VDIR;
2322 vp = nd.ni_vp;
2323 if (vp != NULL) {
2324 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2325 if (nd.ni_dvp == vp)
2326 vrele(nd.ni_dvp);
2327 else
2328 vput(nd.ni_dvp);
2329 vrele(vp);
2330 error = EEXIST;
2331 goto out;
2332 }
2333 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2334 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &va);
2335 if (!error) {
2336 vp = nd.ni_vp;
2337 memset((caddr_t)fhp, 0, sizeof(nfh));
2338 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2339 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2340 if (!error)
2341 error = VOP_GETATTR(vp, &va, cred, lwp);
2342 vput(vp);
2343 }
2344 out:
2345 if (dirp) {
2346 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
2347 vrele(dirp);
2348 }
2349 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2350 if (v3) {
2351 if (!error) {
2352 nfsm_srvpostop_fh(fhp);
2353 nfsm_srvpostop_attr(0, &va);
2354 }
2355 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2356 } else {
2357 nfsm_srvfhtom(fhp, v3);
2358 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR);
2359 nfsm_srvfillattr(&va, fp);
2360 }
2361 return (0);
2362 nfsmout:
2363 if (dirp)
2364 vrele(dirp);
2365 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2366 if (nd.ni_dvp == nd.ni_vp)
2367 vrele(nd.ni_dvp);
2368 else
2369 vput(nd.ni_dvp);
2370 if (nd.ni_vp)
2371 vrele(nd.ni_vp);
2372 return (error);
2373 }
2374
2375 /*
2376 * nfs rmdir service
2377 */
2378 int
2379 nfsrv_rmdir(nfsd, slp, lwp, mrq)
2380 struct nfsrv_descript *nfsd;
2381 struct nfssvc_sock *slp;
2382 struct lwp *lwp;
2383 struct mbuf **mrq;
2384 {
2385 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2386 struct mbuf *nam = nfsd->nd_nam;
2387 caddr_t dpos = nfsd->nd_dpos;
2388 struct ucred *cred = &nfsd->nd_cr;
2389 u_int32_t *tl;
2390 int32_t t1;
2391 caddr_t bpos;
2392 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1;
2393 int v3 = (nfsd->nd_flag & ND_NFSV3);
2394 char *cp2;
2395 struct mbuf *mb, *mreq;
2396 struct vnode *vp, *dirp = (struct vnode *)0;
2397 struct vattr dirfor, diraft;
2398 nfsfh_t nfh;
2399 fhandle_t *fhp;
2400 struct nameidata nd;
2401 u_quad_t frev;
2402
2403 fhp = &nfh.fh_generic;
2404 nfsm_srvmtofh(fhp);
2405 nfsm_srvnamesiz(len);
2406 nd.ni_cnd.cn_cred = cred;
2407 nd.ni_cnd.cn_nameiop = DELETE;
2408 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2409 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2410 &dirp, lwp, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2411 if (dirp) {
2412 if (v3)
2413 dirfor_ret = VOP_GETATTR(dirp, &dirfor, cred, lwp);
2414 else {
2415 vrele(dirp);
2416 dirp = (struct vnode *)0;
2417 }
2418 }
2419 if (error) {
2420 nfsm_reply(NFSX_WCCDATA(v3));
2421 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2422 if (dirp)
2423 vrele(dirp);
2424 return (0);
2425 }
2426 vp = nd.ni_vp;
2427 if (vp->v_type != VDIR) {
2428 error = ENOTDIR;
2429 goto out;
2430 }
2431 /*
2432 * No rmdir "." please.
2433 */
2434 if (nd.ni_dvp == vp) {
2435 error = EINVAL;
2436 goto out;
2437 }
2438 /*
2439 * The root of a mounted filesystem cannot be deleted.
2440 */
2441 if (vp->v_flag & VROOT)
2442 error = EBUSY;
2443 out:
2444 if (!error) {
2445 nqsrv_getl(nd.ni_dvp, ND_WRITE);
2446 nqsrv_getl(vp, ND_WRITE);
2447 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2448 } else {
2449 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
2450 if (nd.ni_dvp == nd.ni_vp)
2451 vrele(nd.ni_dvp);
2452 else
2453 vput(nd.ni_dvp);
2454 vput(vp);
2455 }
2456 if (dirp) {
2457 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, lwp);
2458 vrele(dirp);
2459 }
2460 nfsm_reply(NFSX_WCCDATA(v3));
2461 if (v3) {
2462 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2463 return (0);
2464 }
2465 nfsm_srvdone;
2466 }
2467
2468 /*
2469 * nfs readdir service
2470 * - mallocs what it thinks is enough to read
2471 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
2472 * - calls VOP_READDIR()
2473 * - loops around building the reply
2474 * if the output generated exceeds count break out of loop
2475 * The nfsm_clget macro is used here so that the reply will be packed
2476 * tightly in mbuf clusters.
2477 * - it only knows that it has encountered eof when the VOP_READDIR()
2478 * reads nothing
2479 * - as such one readdir rpc will return eof false although you are there
2480 * and then the next will return eof
2481 * - it trims out records with d_fileno == 0
2482 * this doesn't matter for Unix clients, but they might confuse clients
2483 * for other os'.
2484 * - it trims out records with d_type == DT_WHT
2485 * these cannot be seen through NFS (unless we extend the protocol)
2486 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
2487 * than requested, but this may not apply to all filesystems. For
2488 * example, client NFS does not { although it is never remote mounted
2489 * anyhow }
2490 * The alternate call nfsrv_readdirplus() does lookups as well.
2491 * PS: The NFS protocol spec. does not clarify what the "count" byte
2492 * argument is a count of.. just name strings and file id's or the
2493 * entire reply rpc or ...
2494 * I tried just file name and id sizes and it confused the Sun client,
2495 * so I am using the full rpc size now. The "paranoia.." comment refers
2496 * to including the status longwords that are not a part of the dir.
2497 * "entry" structures, but are in the rpc.
2498 */
2499 struct flrep {
2500 nfsuint64 fl_off;
2501 u_int32_t fl_postopok;
2502 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
2503 u_int32_t fl_fhok;
2504 u_int32_t fl_fhsize;
2505 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
2506 };
2507
2508 int
2509 nfsrv_readdir(nfsd, slp, lwp, mrq)
2510 struct nfsrv_descript *nfsd;
2511 struct nfssvc_sock *slp;
2512 struct lwp *lwp;
2513 struct mbuf **mrq;
2514 {
2515 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2516 struct mbuf *nam = nfsd->nd_nam;
2517 caddr_t dpos = nfsd->nd_dpos;
2518 struct ucred *cred = &nfsd->nd_cr;
2519 char *bp, *be;
2520 struct mbuf *mp;
2521 struct dirent *dp;
2522 caddr_t cp;
2523 u_int32_t *tl;
2524 int32_t t1;
2525 caddr_t bpos;
2526 struct mbuf *mb, *mreq, *mp2;
2527 char *cpos, *cend, *cp2, *rbuf;
2528 struct vnode *vp;
2529 struct vattr at;
2530 nfsfh_t nfh;
2531 fhandle_t *fhp;
2532 struct uio io;
2533 struct iovec iv;
2534 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2535 int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies;
2536 int v3 = (nfsd->nd_flag & ND_NFSV3);
2537 u_quad_t frev, off, toff, verf;
2538 off_t *cookies = NULL, *cookiep;
2539 nfsuint64 jar;
2540
2541 fhp = &nfh.fh_generic;
2542 nfsm_srvmtofh(fhp);
2543 if (v3) {
2544 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED);
2545 toff = fxdr_hyper(tl);
2546 tl += 2;
2547 verf = fxdr_hyper(tl);
2548 tl += 2;
2549 } else {
2550 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2551 toff = fxdr_unsigned(u_quad_t, *tl++);
2552 }
2553 off = toff;
2554 cnt = fxdr_unsigned(int, *tl);
2555 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2556 xfer = NFS_SRVMAXDATA(nfsd);
2557 if (siz > xfer)
2558 siz = xfer;
2559 fullsiz = siz;
2560 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2561 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2562 if (!error && vp->v_type != VDIR) {
2563 error = ENOTDIR;
2564 vput(vp);
2565 }
2566 if (error) {
2567 nfsm_reply(NFSX_UNSIGNED);
2568 nfsm_srvpostop_attr(getret, &at);
2569 return (0);
2570 }
2571 nqsrv_getl(vp, ND_READ);
2572 if (v3) {
2573 error = getret = VOP_GETATTR(vp, &at, cred, lwp);
2574 #ifdef NFS3_STRICTVERF
2575 /*
2576 * XXX This check is too strict for Solaris 2.5 clients.
2577 */
2578 if (!error && toff && verf != at.va_filerev)
2579 error = NFSERR_BAD_COOKIE;
2580 #endif
2581 }
2582 if (!error)
2583 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0);
2584 if (error) {
2585 vput(vp);
2586 nfsm_reply(NFSX_POSTOPATTR(v3));
2587 nfsm_srvpostop_attr(getret, &at);
2588 return (0);
2589 }
2590 VOP_UNLOCK(vp, 0);
2591 rbuf = malloc(siz, M_TEMP, M_WAITOK);
2592 again:
2593 iv.iov_base = rbuf;
2594 iv.iov_len = fullsiz;
2595 io.uio_iov = &iv;
2596 io.uio_iovcnt = 1;
2597 io.uio_offset = (off_t)off;
2598 io.uio_resid = fullsiz;
2599 io.uio_segflg = UIO_SYSSPACE;
2600 io.uio_rw = UIO_READ;
2601 io.uio_lwp = (struct lwp *)0;
2602 eofflag = 0;
2603 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2604
2605 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
2606
2607 off = (off_t)io.uio_offset;
2608 if (!cookies && !error)
2609 error = NFSERR_PERM;
2610 if (v3) {
2611 getret = VOP_GETATTR(vp, &at, cred, lwp);
2612 if (!error)
2613 error = getret;
2614 }
2615
2616 VOP_UNLOCK(vp, 0);
2617 if (error) {
2618 vrele(vp);
2619 free((caddr_t)rbuf, M_TEMP);
2620 if (cookies)
2621 free((caddr_t)cookies, M_TEMP);
2622 nfsm_reply(NFSX_POSTOPATTR(v3));
2623 nfsm_srvpostop_attr(getret, &at);
2624 return (0);
2625 }
2626 if (io.uio_resid) {
2627 siz -= io.uio_resid;
2628
2629 /*
2630 * If nothing read, return eof
2631 * rpc reply
2632 */
2633 if (siz == 0) {
2634 vrele(vp);
2635 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
2636 2 * NFSX_UNSIGNED);
2637 if (v3) {
2638 nfsm_srvpostop_attr(getret, &at);
2639 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2640 txdr_hyper(at.va_filerev, tl);
2641 tl += 2;
2642 } else
2643 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2644 *tl++ = nfs_false;
2645 *tl = nfs_true;
2646 free((caddr_t)rbuf, M_TEMP);
2647 free((caddr_t)cookies, M_TEMP);
2648 return (0);
2649 }
2650 }
2651
2652 /*
2653 * Check for degenerate cases of nothing useful read.
2654 * If so go try again
2655 */
2656 cpos = rbuf;
2657 cend = rbuf + siz;
2658 dp = (struct dirent *)cpos;
2659 cookiep = cookies;
2660
2661 while (cpos < cend && ncookies > 0 &&
2662 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
2663 cpos += dp->d_reclen;
2664 dp = (struct dirent *)cpos;
2665 cookiep++;
2666 ncookies--;
2667 }
2668 if (cpos >= cend || ncookies == 0) {
2669 toff = off;
2670 siz = fullsiz;
2671 goto again;
2672 }
2673
2674 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
2675 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
2676 if (v3) {
2677 nfsm_srvpostop_attr(getret, &at);
2678 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2679 txdr_hyper(at.va_filerev, tl);
2680 }
2681 mp = mp2 = mb;
2682 bp = bpos;
2683 be = bp + M_TRAILINGSPACE(mp);
2684
2685 /* Loop through the records and build reply */
2686 while (cpos < cend && ncookies > 0) {
2687 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2688 nlen = dp->d_namlen;
2689 rem = nfsm_rndup(nlen)-nlen;
2690 len += (4 * NFSX_UNSIGNED + nlen + rem);
2691 if (v3)
2692 len += 2 * NFSX_UNSIGNED;
2693 if (len > cnt) {
2694 eofflag = 0;
2695 break;
2696 }
2697 /*
2698 * Build the directory record xdr from
2699 * the dirent entry.
2700 */
2701 nfsm_clget;
2702 *tl = nfs_true;
2703 bp += NFSX_UNSIGNED;
2704 if (v3) {
2705 nfsm_clget;
2706 *tl = 0;
2707 bp += NFSX_UNSIGNED;
2708 }
2709 nfsm_clget;
2710 *tl = txdr_unsigned(dp->d_fileno);
2711 bp += NFSX_UNSIGNED;
2712 nfsm_clget;
2713 *tl = txdr_unsigned(nlen);
2714 bp += NFSX_UNSIGNED;
2715
2716 /* And loop around copying the name */
2717 xfer = nlen;
2718 cp = dp->d_name;
2719 while (xfer > 0) {
2720 nfsm_clget;
2721 if ((bp+xfer) > be)
2722 tsiz = be-bp;
2723 else
2724 tsiz = xfer;
2725 memcpy(bp, cp, tsiz);
2726 bp += tsiz;
2727 xfer -= tsiz;
2728 if (xfer > 0)
2729 cp += tsiz;
2730 }
2731 /* And null pad to an int32_t boundary */
2732 for (i = 0; i < rem; i++)
2733 *bp++ = '\0';
2734 nfsm_clget;
2735
2736 /* Finish off the record */
2737 txdr_hyper(*cookiep, &jar);
2738 if (v3) {
2739 *tl = jar.nfsuquad[0];
2740 bp += NFSX_UNSIGNED;
2741 nfsm_clget;
2742 }
2743 *tl = jar.nfsuquad[1];
2744 bp += NFSX_UNSIGNED;
2745 }
2746 cpos += dp->d_reclen;
2747 dp = (struct dirent *)cpos;
2748 cookiep++;
2749 ncookies--;
2750 }
2751 vrele(vp);
2752 nfsm_clget;
2753 *tl = nfs_false;
2754 bp += NFSX_UNSIGNED;
2755 nfsm_clget;
2756 if (eofflag)
2757 *tl = nfs_true;
2758 else
2759 *tl = nfs_false;
2760 bp += NFSX_UNSIGNED;
2761 if (mp != mb) {
2762 if (bp < be)
2763 mp->m_len = bp - mtod(mp, caddr_t);
2764 } else
2765 mp->m_len += bp - bpos;
2766 free((caddr_t)rbuf, M_TEMP);
2767 free((caddr_t)cookies, M_TEMP);
2768 nfsm_srvdone;
2769 }
2770
2771 int
2772 nfsrv_readdirplus(nfsd, slp, lwp, mrq)
2773 struct nfsrv_descript *nfsd;
2774 struct nfssvc_sock *slp;
2775 struct lwp *lwp;
2776 struct mbuf **mrq;
2777 {
2778 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2779 struct mbuf *nam = nfsd->nd_nam;
2780 caddr_t dpos = nfsd->nd_dpos;
2781 struct ucred *cred = &nfsd->nd_cr;
2782 char *bp, *be;
2783 struct mbuf *mp;
2784 struct dirent *dp;
2785 caddr_t cp;
2786 u_int32_t *tl;
2787 int32_t t1;
2788 caddr_t bpos;
2789 struct mbuf *mb, *mreq, *mp2;
2790 char *cpos, *cend, *cp2, *rbuf;
2791 struct vnode *vp, *nvp;
2792 struct flrep fl;
2793 nfsfh_t nfh;
2794 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
2795 struct uio io;
2796 struct iovec iv;
2797 struct vattr va, at, *vap = &va;
2798 struct nfs_fattr *fp;
2799 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
2800 int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies;
2801 u_quad_t frev, off, toff, verf;
2802 off_t *cookies = NULL, *cookiep;
2803
2804 fhp = &nfh.fh_generic;
2805 nfsm_srvmtofh(fhp);
2806 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED);
2807 toff = fxdr_hyper(tl);
2808 tl += 2;
2809 verf = fxdr_hyper(tl);
2810 tl += 2;
2811 siz = fxdr_unsigned(int, *tl++);
2812 cnt = fxdr_unsigned(int, *tl);
2813 off = toff;
2814 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
2815 xfer = NFS_SRVMAXDATA(nfsd);
2816 if (siz > xfer)
2817 siz = xfer;
2818 fullsiz = siz;
2819 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
2820 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
2821 if (!error && vp->v_type != VDIR) {
2822 error = ENOTDIR;
2823 vput(vp);
2824 }
2825 if (error) {
2826 nfsm_reply(NFSX_UNSIGNED);
2827 nfsm_srvpostop_attr(getret, &at);
2828 return (0);
2829 }
2830 error = getret = VOP_GETATTR(vp, &at, cred, lwp);
2831 #ifdef NFS3_STRICTVERF
2832 /*
2833 * XXX This check is too strict for Solaris 2.5 clients.
2834 */
2835 if (!error && toff && verf != at.va_filerev)
2836 error = NFSERR_BAD_COOKIE;
2837 #endif
2838 if (!error) {
2839 nqsrv_getl(vp, ND_READ);
2840 error = nfsrv_access(vp, VEXEC, cred, rdonly, lwp, 0);
2841 }
2842 if (error) {
2843 vput(vp);
2844 nfsm_reply(NFSX_V3POSTOPATTR);
2845 nfsm_srvpostop_attr(getret, &at);
2846 return (0);
2847 }
2848 VOP_UNLOCK(vp, 0);
2849
2850 rbuf = malloc(siz, M_TEMP, M_WAITOK);
2851 again:
2852 iv.iov_base = rbuf;
2853 iv.iov_len = fullsiz;
2854 io.uio_iov = &iv;
2855 io.uio_iovcnt = 1;
2856 io.uio_offset = (off_t)off;
2857 io.uio_resid = fullsiz;
2858 io.uio_segflg = UIO_SYSSPACE;
2859 io.uio_rw = UIO_READ;
2860 io.uio_lwp = (struct lwp *)0;
2861 eofflag = 0;
2862
2863 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
2864
2865 error = VOP_READDIR(vp, &io, cred, &eofflag, &cookies, &ncookies);
2866
2867 off = (u_quad_t)io.uio_offset;
2868 getret = VOP_GETATTR(vp, &at, cred, lwp);
2869
2870 VOP_UNLOCK(vp, 0);
2871
2872 /*
2873 * If the VGET operation doesn't work for this filesystem,
2874 * we can't support readdirplus. Returning NOTSUPP should
2875 * make clients fall back to plain readdir.
2876 * There's no need to check for VPTOFH as well, we wouldn't
2877 * even be here otherwise.
2878 */
2879 if (!getret) {
2880 if ((getret = VFS_VGET(vp->v_mount, at.va_fileid, &nvp)))
2881 getret = (getret == EOPNOTSUPP) ?
2882 NFSERR_NOTSUPP : NFSERR_IO;
2883 else
2884 vput(nvp);
2885 }
2886
2887 if (!cookies && !error)
2888 error = NFSERR_PERM;
2889 if (!error)
2890 error = getret;
2891 if (error) {
2892 vrele(vp);
2893 if (cookies)
2894 free((caddr_t)cookies, M_TEMP);
2895 free((caddr_t)rbuf, M_TEMP);
2896 nfsm_reply(NFSX_V3POSTOPATTR);
2897 nfsm_srvpostop_attr(getret, &at);
2898 return (0);
2899 }
2900 if (io.uio_resid) {
2901 siz -= io.uio_resid;
2902
2903 /*
2904 * If nothing read, return eof
2905 * rpc reply
2906 */
2907 if (siz == 0) {
2908 vrele(vp);
2909 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
2910 2 * NFSX_UNSIGNED);
2911 nfsm_srvpostop_attr(getret, &at);
2912 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED);
2913 txdr_hyper(at.va_filerev, tl);
2914 tl += 2;
2915 *tl++ = nfs_false;
2916 *tl = nfs_true;
2917 free((caddr_t)cookies, M_TEMP);
2918 free((caddr_t)rbuf, M_TEMP);
2919 return (0);
2920 }
2921 }
2922
2923 /*
2924 * Check for degenerate cases of nothing useful read.
2925 * If so go try again
2926 */
2927 cpos = rbuf;
2928 cend = rbuf + siz;
2929 dp = (struct dirent *)cpos;
2930 cookiep = cookies;
2931
2932 while (cpos < cend && ncookies > 0 &&
2933 (dp->d_fileno == 0 || dp->d_type == DT_WHT)) {
2934 cpos += dp->d_reclen;
2935 dp = (struct dirent *)cpos;
2936 cookiep++;
2937 ncookies--;
2938 }
2939 if (cpos >= cend || ncookies == 0) {
2940 toff = off;
2941 siz = fullsiz;
2942 goto again;
2943 }
2944
2945 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED;
2946 nfsm_reply(cnt);
2947 nfsm_srvpostop_attr(getret, &at);
2948 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED);
2949 txdr_hyper(at.va_filerev, tl);
2950 mp = mp2 = mb;
2951 bp = bpos;
2952 be = bp + M_TRAILINGSPACE(mp);
2953
2954 /* Loop through the records and build reply */
2955 while (cpos < cend && ncookies > 0) {
2956 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
2957 nlen = dp->d_namlen;
2958 rem = nfsm_rndup(nlen)-nlen;
2959
2960 /*
2961 * For readdir_and_lookup get the vnode using
2962 * the file number.
2963 */
2964 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp))
2965 goto invalid;
2966 memset((caddr_t)nfhp, 0, NFSX_V3FH);
2967 nfhp->fh_fsid =
2968 nvp->v_mount->mnt_stat.f_fsid;
2969 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
2970 vput(nvp);
2971 goto invalid;
2972 }
2973 if (VOP_GETATTR(nvp, vap, cred, lwp)) {
2974 vput(nvp);
2975 goto invalid;
2976 }
2977 vput(nvp);
2978
2979 /*
2980 * If either the dircount or maxcount will be
2981 * exceeded, get out now. Both of these lengths
2982 * are calculated conservatively, including all
2983 * XDR overheads.
2984 */
2985 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
2986 NFSX_V3POSTOPATTR);
2987 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
2988 if (len > cnt || dirlen > fullsiz) {
2989 eofflag = 0;
2990 break;
2991 }
2992
2993 /*
2994 * Build the directory record xdr from
2995 * the dirent entry.
2996 */
2997 fp = (struct nfs_fattr *)&fl.fl_fattr;
2998 nfsm_srvfillattr(vap, fp);
2999 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3000 fl.fl_fhok = nfs_true;
3001 fl.fl_postopok = nfs_true;
3002 txdr_hyper(*cookiep, fl.fl_off.nfsuquad);
3003
3004 nfsm_clget;
3005 *tl = nfs_true;
3006 bp += NFSX_UNSIGNED;
3007 nfsm_clget;
3008 *tl = 0;
3009 bp += NFSX_UNSIGNED;
3010 nfsm_clget;
3011 *tl = txdr_unsigned(dp->d_fileno);
3012 bp += NFSX_UNSIGNED;
3013 nfsm_clget;
3014 *tl = txdr_unsigned(nlen);
3015 bp += NFSX_UNSIGNED;
3016
3017 /* And loop around copying the name */
3018 xfer = nlen;
3019 cp = dp->d_name;
3020 while (xfer > 0) {
3021 nfsm_clget;
3022 if ((bp + xfer) > be)
3023 tsiz = be - bp;
3024 else
3025 tsiz = xfer;
3026 memcpy(bp, cp, tsiz);
3027 bp += tsiz;
3028 xfer -= tsiz;
3029 if (xfer > 0)
3030 cp += tsiz;
3031 }
3032 /* And null pad to an int32_t boundary */
3033 for (i = 0; i < rem; i++)
3034 *bp++ = '\0';
3035
3036 /*
3037 * Now copy the flrep structure out.
3038 */
3039 xfer = sizeof (struct flrep);
3040 cp = (caddr_t)&fl;
3041 while (xfer > 0) {
3042 nfsm_clget;
3043 if ((bp + xfer) > be)
3044 tsiz = be - bp;
3045 else
3046 tsiz = xfer;
3047 memcpy(bp, cp, tsiz);
3048 bp += tsiz;
3049 xfer -= tsiz;
3050 if (xfer > 0)
3051 cp += tsiz;
3052 }
3053 }
3054 invalid:
3055 cpos += dp->d_reclen;
3056 dp = (struct dirent *)cpos;
3057 cookiep++;
3058 ncookies--;
3059 }
3060 vrele(vp);
3061 nfsm_clget;
3062 *tl = nfs_false;
3063 bp += NFSX_UNSIGNED;
3064 nfsm_clget;
3065 if (eofflag)
3066 *tl = nfs_true;
3067 else
3068 *tl = nfs_false;
3069 bp += NFSX_UNSIGNED;
3070 if (mp != mb) {
3071 if (bp < be)
3072 mp->m_len = bp - mtod(mp, caddr_t);
3073 } else
3074 mp->m_len += bp - bpos;
3075 free((caddr_t)cookies, M_TEMP);
3076 free((caddr_t)rbuf, M_TEMP);
3077 nfsm_srvdone;
3078 }
3079
3080 /*
3081 * nfs commit service
3082 */
3083 int
3084 nfsrv_commit(nfsd, slp, lwp, mrq)
3085 struct nfsrv_descript *nfsd;
3086 struct nfssvc_sock *slp;
3087 struct lwp *lwp;
3088 struct mbuf **mrq;
3089 {
3090 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3091 struct mbuf *nam = nfsd->nd_nam;
3092 caddr_t dpos = nfsd->nd_dpos;
3093 struct ucred *cred = &nfsd->nd_cr;
3094 struct vattr bfor, aft;
3095 struct vnode *vp;
3096 nfsfh_t nfh;
3097 fhandle_t *fhp;
3098 u_int32_t *tl;
3099 int32_t t1;
3100 caddr_t bpos;
3101 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache;
3102 char *cp2;
3103 struct mbuf *mb, *mreq;
3104 u_quad_t frev, off, end;
3105
3106 #ifndef nolint
3107 cache = 0;
3108 #endif
3109 fhp = &nfh.fh_generic;
3110 nfsm_srvmtofh(fhp);
3111 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED);
3112
3113 off = fxdr_hyper(tl);
3114 tl += 2;
3115 cnt = fxdr_unsigned(int, *tl);
3116 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3117 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3118 if (error) {
3119 nfsm_reply(2 * NFSX_UNSIGNED);
3120 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3121 return (0);
3122 }
3123 for_ret = VOP_GETATTR(vp, &bfor, cred, lwp);
3124 end = (cnt > 0) ? off + cnt : vp->v_size;
3125 if (end < off || end > vp->v_size)
3126 end = vp->v_size;
3127 error = VOP_FSYNC(vp, cred, FSYNC_WAIT, off, end, lwp);
3128 aft_ret = VOP_GETATTR(vp, &aft, cred, lwp);
3129 vput(vp);
3130 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
3131 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
3132 if (!error) {
3133 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF);
3134 *tl++ = txdr_unsigned(boottime.tv_sec);
3135 *tl = txdr_unsigned(boottime.tv_usec);
3136 } else
3137 return (0);
3138 nfsm_srvdone;
3139 }
3140
3141 /*
3142 * nfs statfs service
3143 */
3144 int
3145 nfsrv_statfs(nfsd, slp, lwp, mrq)
3146 struct nfsrv_descript *nfsd;
3147 struct nfssvc_sock *slp;
3148 struct lwp *lwp;
3149 struct mbuf **mrq;
3150 {
3151 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3152 struct mbuf *nam = nfsd->nd_nam;
3153 caddr_t dpos = nfsd->nd_dpos;
3154 struct ucred *cred = &nfsd->nd_cr;
3155 struct statfs *sf;
3156 struct nfs_statfs *sfp;
3157 u_int32_t *tl;
3158 int32_t t1;
3159 caddr_t bpos;
3160 int error = 0, rdonly, cache, getret = 1;
3161 int v3 = (nfsd->nd_flag & ND_NFSV3);
3162 char *cp2;
3163 struct mbuf *mb, *mreq;
3164 struct vnode *vp;
3165 struct vattr at;
3166 nfsfh_t nfh;
3167 fhandle_t *fhp;
3168 struct statfs statfs;
3169 u_quad_t frev, tval;
3170
3171 #ifndef nolint
3172 cache = 0;
3173 #endif
3174 fhp = &nfh.fh_generic;
3175 nfsm_srvmtofh(fhp);
3176 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3177 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3178 if (error) {
3179 nfsm_reply(NFSX_UNSIGNED);
3180 nfsm_srvpostop_attr(getret, &at);
3181 return (0);
3182 }
3183 sf = &statfs;
3184 error = VFS_STATFS(vp->v_mount, sf, lwp);
3185 getret = VOP_GETATTR(vp, &at, cred, lwp);
3186 vput(vp);
3187 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
3188 if (v3)
3189 nfsm_srvpostop_attr(getret, &at);
3190 if (error)
3191 return (0);
3192 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3));
3193 if (v3) {
3194 tval = (u_quad_t)((quad_t)sf->f_blocks * (quad_t)sf->f_bsize);
3195 txdr_hyper(tval, &sfp->sf_tbytes);
3196 tval = (u_quad_t)((quad_t)sf->f_bfree * (quad_t)sf->f_bsize);
3197 txdr_hyper(tval, &sfp->sf_fbytes);
3198 tval = (u_quad_t)((quad_t)sf->f_bavail * (quad_t)sf->f_bsize);
3199 txdr_hyper(tval, &sfp->sf_abytes);
3200 tval = (u_quad_t)sf->f_files;
3201 txdr_hyper(tval, &sfp->sf_tfiles);
3202 tval = (u_quad_t)sf->f_ffree;
3203 txdr_hyper(tval, &sfp->sf_ffiles);
3204 txdr_hyper(tval, &sfp->sf_afiles);
3205 sfp->sf_invarsec = 0;
3206 } else {
3207 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
3208 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
3209 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
3210 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
3211 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
3212 }
3213 nfsm_srvdone;
3214 }
3215
3216 /*
3217 * nfs fsinfo service
3218 */
3219 int
3220 nfsrv_fsinfo(nfsd, slp, lwp, mrq)
3221 struct nfsrv_descript *nfsd;
3222 struct nfssvc_sock *slp;
3223 struct lwp *lwp;
3224 struct mbuf **mrq;
3225 {
3226 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3227 struct mbuf *nam = nfsd->nd_nam;
3228 caddr_t dpos = nfsd->nd_dpos;
3229 struct ucred *cred = &nfsd->nd_cr;
3230 u_int32_t *tl;
3231 struct nfsv3_fsinfo *sip;
3232 int32_t t1;
3233 caddr_t bpos;
3234 int error = 0, rdonly, cache, getret = 1;
3235 uint32_t maxdata;
3236 char *cp2;
3237 struct mbuf *mb, *mreq;
3238 struct vnode *vp;
3239 struct vattr at;
3240 nfsfh_t nfh;
3241 fhandle_t *fhp;
3242 u_quad_t frev, maxfsize;
3243 struct statfs sb;
3244
3245 #ifndef nolint
3246 cache = 0;
3247 #endif
3248 fhp = &nfh.fh_generic;
3249 nfsm_srvmtofh(fhp);
3250 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3251 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3252 if (error) {
3253 nfsm_reply(NFSX_UNSIGNED);
3254 nfsm_srvpostop_attr(getret, &at);
3255 return (0);
3256 }
3257
3258 /* XXX Try to make a guess on the max file size. */
3259 VFS_STATFS(vp->v_mount, &sb, (struct lwp *)0);
3260 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
3261
3262 getret = VOP_GETATTR(vp, &at, cred, lwp);
3263 vput(vp);
3264 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
3265 nfsm_srvpostop_attr(getret, &at);
3266 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO);
3267
3268 /*
3269 * XXX
3270 * There should be file system VFS OP(s) to get this information.
3271 * For now, assume ufs.
3272 */
3273 if (slp->ns_so->so_type == SOCK_DGRAM)
3274 maxdata = NFS_MAXDGRAMDATA;
3275 else
3276 maxdata = NFS_MAXDATA;
3277 sip->fs_rtmax = txdr_unsigned(maxdata);
3278 sip->fs_rtpref = txdr_unsigned(maxdata);
3279 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
3280 sip->fs_wtmax = txdr_unsigned(maxdata);
3281 sip->fs_wtpref = txdr_unsigned(maxdata);
3282 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
3283 sip->fs_dtpref = txdr_unsigned(maxdata);
3284 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
3285 sip->fs_timedelta.nfsv3_sec = 0;
3286 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
3287 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
3288 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
3289 NFSV3FSINFO_CANSETTIME);
3290 nfsm_srvdone;
3291 }
3292
3293 /*
3294 * nfs pathconf service
3295 */
3296 int
3297 nfsrv_pathconf(nfsd, slp, lwp, mrq)
3298 struct nfsrv_descript *nfsd;
3299 struct nfssvc_sock *slp;
3300 struct lwp *lwp;
3301 struct mbuf **mrq;
3302 {
3303 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3304 struct mbuf *nam = nfsd->nd_nam;
3305 caddr_t dpos = nfsd->nd_dpos;
3306 struct ucred *cred = &nfsd->nd_cr;
3307 u_int32_t *tl;
3308 struct nfsv3_pathconf *pc;
3309 int32_t t1;
3310 caddr_t bpos;
3311 int error = 0, rdonly, cache, getret = 1;
3312 register_t linkmax, namemax, chownres, notrunc;
3313 char *cp2;
3314 struct mbuf *mb, *mreq;
3315 struct vnode *vp;
3316 struct vattr at;
3317 nfsfh_t nfh;
3318 fhandle_t *fhp;
3319 u_quad_t frev;
3320
3321 #ifndef nolint
3322 cache = 0;
3323 #endif
3324 fhp = &nfh.fh_generic;
3325 nfsm_srvmtofh(fhp);
3326 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam,
3327 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), FALSE);
3328 if (error) {
3329 nfsm_reply(NFSX_UNSIGNED);
3330 nfsm_srvpostop_attr(getret, &at);
3331 return (0);
3332 }
3333 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
3334 if (!error)
3335 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
3336 if (!error)
3337 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
3338 if (!error)
3339 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
3340 getret = VOP_GETATTR(vp, &at, cred, lwp);
3341 vput(vp);
3342 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
3343 nfsm_srvpostop_attr(getret, &at);
3344 if (error)
3345 return (0);
3346 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF);
3347
3348 pc->pc_linkmax = txdr_unsigned(linkmax);
3349 pc->pc_namemax = txdr_unsigned(namemax);
3350 pc->pc_notrunc = txdr_unsigned(notrunc);
3351 pc->pc_chownrestricted = txdr_unsigned(chownres);
3352
3353 /*
3354 * These should probably be supported by VOP_PATHCONF(), but
3355 * until msdosfs is exportable (why would you want to?), the
3356 * Unix defaults should be ok.
3357 */
3358 pc->pc_caseinsensitive = nfs_false;
3359 pc->pc_casepreserving = nfs_true;
3360 nfsm_srvdone;
3361 }
3362
3363 /*
3364 * Null operation, used by clients to ping server
3365 */
3366 /* ARGSUSED */
3367 int
3368 nfsrv_null(nfsd, slp, lwp, mrq)
3369 struct nfsrv_descript *nfsd;
3370 struct nfssvc_sock *slp;
3371 struct lwp *lwp;
3372 struct mbuf **mrq;
3373 {
3374 struct mbuf *mrep = nfsd->nd_mrep;
3375 caddr_t bpos;
3376 int error = NFSERR_RETVOID, cache = 0;
3377 struct mbuf *mb, *mreq;
3378 u_quad_t frev;
3379
3380 nfsm_reply(0);
3381 return (0);
3382 }
3383
3384 /*
3385 * No operation, used for obsolete procedures
3386 */
3387 /* ARGSUSED */
3388 int
3389 nfsrv_noop(nfsd, slp, lwp, mrq)
3390 struct nfsrv_descript *nfsd;
3391 struct nfssvc_sock *slp;
3392 struct lwp *lwp;
3393 struct mbuf **mrq;
3394 {
3395 struct mbuf *mrep = nfsd->nd_mrep;
3396 caddr_t bpos;
3397 int error, cache = 0;
3398 struct mbuf *mb, *mreq;
3399 u_quad_t frev;
3400
3401 if (nfsd->nd_repstat)
3402 error = nfsd->nd_repstat;
3403 else
3404 error = EPROCUNAVAIL;
3405 nfsm_reply(0);
3406 return (0);
3407 }
3408
3409 /*
3410 * Perform access checking for vnodes obtained from file handles that would
3411 * refer to files already opened by a Unix client. You cannot just use
3412 * vn_writechk() and VOP_ACCESS() for two reasons.
3413 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case
3414 * 2 - The owner is to be given access irrespective of mode bits for some
3415 * operations, so that processes that chmod after opening a file don't
3416 * break. I don't like this because it opens a security hole, but since
3417 * the nfs server opens a security hole the size of a barn door anyhow,
3418 * what the heck.
3419 *
3420 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
3421 * will return EPERM instead of EACCESS. EPERM is always an error.
3422 */
3423 int
3424 nfsrv_access(vp, flags, cred, rdonly, lwp, override)
3425 struct vnode *vp;
3426 int flags;
3427 struct ucred *cred;
3428 int rdonly;
3429 struct lwp *lwp;
3430 {
3431 struct vattr vattr;
3432 int error;
3433 if (flags & VWRITE) {
3434 /* Just vn_writechk() changed to check rdonly */
3435 /*
3436 * Disallow write attempts on read-only file systems;
3437 * unless the file is a socket or a block or character
3438 * device resident on the file system.
3439 */
3440 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
3441 switch (vp->v_type) {
3442 case VREG:
3443 case VDIR:
3444 case VLNK:
3445 return (EROFS);
3446 default:
3447 break;
3448 }
3449 }
3450
3451 /*
3452 * If the vnode is in use as a process's text,
3453 * we can't allow writing.
3454 */
3455 if (vp->v_flag & VTEXT)
3456 return (ETXTBSY);
3457 }
3458 error = VOP_GETATTR(vp, &vattr, cred, lwp);
3459 if (error)
3460 return (error);
3461 error = VOP_ACCESS(vp, flags, cred, lwp);
3462 /*
3463 * Allow certain operations for the owner (reads and writes
3464 * on files that are already open).
3465 */
3466 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
3467 error = 0;
3468 return error;
3469 }
3470