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