1 /*-
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Rick Macklem at The University of Guelph.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 4. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)nfs_serv.c 8.8 (Berkeley) 7/31/95
33 */
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 /*
39 * nfs version 2 and 3 server calls to vnode ops
40 * - these routines generally have 3 phases
41 * 1 - break down and validate rpc request in mbuf list
42 * 2 - do the vnode ops for the request
43 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c)
44 * 3 - build the rpc reply in an mbuf list
45 * nb:
46 * - do not mix the phases, since the nfsm_?? macros can return failures
47 * on a bad rpc or similar and do not do any vrele() or vput()'s
48 *
49 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs
50 * error number iff error != 0 whereas
51 * returning an error from the server function implies a fatal error
52 * such as a badly constructed rpc request that should be dropped without
53 * a reply.
54 * For nfsm_reply(), the case where error == EBADRPC is treated
55 * specially; after constructing a reply, it does an immediate
56 * `goto nfsmout' to avoid getting any V3 post-op status appended.
57 *
58 * Other notes:
59 * Warning: always pay careful attention to resource cleanup on return
60 * and note that nfsm_*() macros can terminate a procedure on certain
61 * errors.
62 *
63 * lookup() and namei()
64 * may return garbage in various structural fields/return elements
65 * if an error is returned, and may garbage up nd.ni_dvp even if no
66 * error is returned and you did not request LOCKPARENT or WANTPARENT.
67 *
68 * We use the ni_cnd.cn_flags 'HASBUF' flag to track whether the name
69 * buffer has been freed or not.
70 */
71
72 #include <sys/param.h>
73 #include <sys/systm.h>
74 #include <sys/proc.h>
75 #include <sys/namei.h>
76 #include <sys/unistd.h>
77 #include <sys/vnode.h>
78 #include <sys/mount.h>
79 #include <sys/socket.h>
80 #include <sys/socketvar.h>
81 #include <sys/malloc.h>
82 #include <sys/mbuf.h>
83 #include <sys/dirent.h>
84 #include <sys/stat.h>
85 #include <sys/kernel.h>
86 #include <sys/sysctl.h>
87 #include <sys/bio.h>
88 #include <sys/buf.h>
89
90 #include <vm/vm.h>
91 #include <vm/vm_extern.h>
92 #include <vm/vm_object.h>
93
94 #include <nfs/nfsproto.h>
95 #include <nfs/rpcv2.h>
96 #include <nfsserver/nfs.h>
97 #include <nfs/xdr_subs.h>
98 #include <nfsserver/nfsm_subs.h>
99
100 #ifdef NFSRV_DEBUG
101 #define nfsdbprintf(info) printf info
102 #else
103 #define nfsdbprintf(info)
104 #endif
105
106 #define MAX_COMMIT_COUNT (1024 * 1024)
107
108 #define NUM_HEURISTIC 1017
109 #define NHUSE_INIT 64
110 #define NHUSE_INC 16
111 #define NHUSE_MAX 2048
112
113 static struct nfsheur {
114 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */
115 off_t nh_nextr; /* next offset for sequential detection */
116 int nh_use; /* use count for selection */
117 int nh_seqcount; /* heuristic */
118 } nfsheur[NUM_HEURISTIC];
119
120 /* Global vars */
121
122 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000;
123 int nfsrvw_procrastinate_v3 = 0;
124
125 static struct timeval nfsver = { 0 };
126
127 SYSCTL_NODE(_vfs, OID_AUTO, nfsrv, CTLFLAG_RW, 0, "NFS server");
128
129 static int nfs_async;
130 static int nfs_commit_blks;
131 static int nfs_commit_miss;
132 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, "");
133 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, "");
134 SYSCTL_INT(_vfs_nfsrv, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, "");
135
136 struct nfsrvstats nfsrvstats;
137 SYSCTL_STRUCT(_vfs_nfsrv, NFS_NFSRVSTATS, nfsrvstats, CTLFLAG_RW,
138 &nfsrvstats, nfsrvstats, "S,nfsrvstats");
139
140 static int nfsrv_access_withgiant(struct vnode *vp, int flags,
141 struct ucred *cred, int rdonly, struct thread *td,
142 int override);
143 static int nfsrv_access(struct vnode *, int, struct ucred *, int,
144 struct thread *, int);
145 static void nfsrvw_coalesce(struct nfsrv_descript *,
146 struct nfsrv_descript *);
147
148 /*
149 * Clear nameidata fields that are tested in nsfmout cleanup code prior
150 * to using first nfsm macro (that might jump to the cleanup code).
151 */
152
153 static __inline void
154 ndclear(struct nameidata *nd)
155 {
156
157 nd->ni_cnd.cn_flags = 0;
158 nd->ni_vp = NULL;
159 nd->ni_dvp = NULL;
160 nd->ni_startdir = NULL;
161 }
162
163 /*
164 * nfs v3 access service
165 */
166 int
167 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
168 struct thread *td, struct mbuf **mrq)
169 {
170 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
171 struct sockaddr *nam = nfsd->nd_nam;
172 caddr_t dpos = nfsd->nd_dpos;
173 struct ucred *cred = nfsd->nd_cr;
174 struct vnode *vp = NULL;
175 nfsfh_t nfh;
176 fhandle_t *fhp;
177 u_int32_t *tl;
178 caddr_t bpos;
179 int error = 0, rdonly, getret;
180 struct mbuf *mb, *mreq;
181 struct vattr vattr, *vap = &vattr;
182 u_long testmode, nfsmode;
183 int v3 = (nfsd->nd_flag & ND_NFSV3);
184
185 NFSD_LOCK_ASSERT();
186
187 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
188 if (!v3)
189 panic("nfsrv3_access: v3 proc called on a v2 connection");
190 fhp = &nfh.fh_generic;
191 nfsm_srvmtofh(fhp);
192 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
193 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
194 if (error) {
195 nfsm_reply(NFSX_UNSIGNED);
196 nfsm_srvpostop_attr(1, NULL);
197 error = 0;
198 goto nfsmout;
199 }
200 nfsmode = fxdr_unsigned(u_int32_t, *tl);
201 NFSD_UNLOCK();
202 mtx_lock(&Giant); /* VFS */
203 if ((nfsmode & NFSV3ACCESS_READ) &&
204 nfsrv_access_withgiant(vp, VREAD, cred, rdonly, td, 0))
205 nfsmode &= ~NFSV3ACCESS_READ;
206 if (vp->v_type == VDIR)
207 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND |
208 NFSV3ACCESS_DELETE);
209 else
210 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND);
211 if ((nfsmode & testmode) &&
212 nfsrv_access_withgiant(vp, VWRITE, cred, rdonly, td, 0))
213 nfsmode &= ~testmode;
214 if (vp->v_type == VDIR)
215 testmode = NFSV3ACCESS_LOOKUP;
216 else
217 testmode = NFSV3ACCESS_EXECUTE;
218 if ((nfsmode & testmode) &&
219 nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0))
220 nfsmode &= ~testmode;
221 getret = VOP_GETATTR(vp, vap, cred, td);
222 vput(vp);
223 mtx_unlock(&Giant); /* VFS */
224 vp = NULL;
225 NFSD_LOCK();
226 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED);
227 nfsm_srvpostop_attr(getret, vap);
228 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
229 *tl = txdr_unsigned(nfsmode);
230 nfsmout:
231 NFSD_LOCK_ASSERT();
232 if (vp) {
233 NFSD_UNLOCK();
234 mtx_lock(&Giant); /* VFS */
235 vput(vp);
236 mtx_unlock(&Giant); /* VFS */
237 NFSD_LOCK();
238 }
239 return(error);
240 }
241
242 /*
243 * nfs getattr service
244 */
245 int
246 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
247 struct thread *td, struct mbuf **mrq)
248 {
249 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
250 struct sockaddr *nam = nfsd->nd_nam;
251 caddr_t dpos = nfsd->nd_dpos;
252 struct ucred *cred = nfsd->nd_cr;
253 struct nfs_fattr *fp;
254 struct vattr va;
255 struct vattr *vap = &va;
256 struct vnode *vp = NULL;
257 nfsfh_t nfh;
258 fhandle_t *fhp;
259 caddr_t bpos;
260 int error = 0, rdonly;
261 struct mbuf *mb, *mreq;
262
263 NFSD_LOCK_ASSERT();
264
265 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
266 fhp = &nfh.fh_generic;
267 nfsm_srvmtofh(fhp);
268 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
269 if (error) {
270 nfsm_reply(0);
271 error = 0;
272 goto nfsmout;
273 }
274 NFSD_UNLOCK();
275 mtx_lock(&Giant); /* VFS */
276 error = VOP_GETATTR(vp, vap, cred, td);
277 vput(vp);
278 mtx_unlock(&Giant); /* VFS */
279 vp = NULL;
280 NFSD_LOCK();
281 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
282 if (error) {
283 error = 0;
284 goto nfsmout;
285 }
286 fp = nfsm_build(struct nfs_fattr *,
287 NFSX_FATTR(nfsd->nd_flag & ND_NFSV3));
288 nfsm_srvfillattr(vap, fp);
289 /* fall through */
290
291 nfsmout:
292 NFSD_LOCK_ASSERT();
293 if (vp) {
294 NFSD_UNLOCK();
295 mtx_lock(&Giant); /* VFS */
296 vput(vp);
297 mtx_unlock(&Giant); /* VFS */
298 NFSD_LOCK();
299 }
300 return(error);
301 }
302
303 /*
304 * nfs setattr service
305 */
306 int
307 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
308 struct thread *td, struct mbuf **mrq)
309 {
310 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
311 struct sockaddr *nam = nfsd->nd_nam;
312 caddr_t dpos = nfsd->nd_dpos;
313 struct ucred *cred = nfsd->nd_cr;
314 struct vattr va, preat;
315 struct vattr *vap = &va;
316 struct nfsv2_sattr *sp;
317 struct nfs_fattr *fp;
318 struct vnode *vp = NULL;
319 nfsfh_t nfh;
320 fhandle_t *fhp;
321 u_int32_t *tl;
322 caddr_t bpos;
323 int error = 0, rdonly, preat_ret = 1, postat_ret = 1;
324 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0;
325 struct mbuf *mb, *mreq;
326 struct timespec guard;
327 struct mount *mp = NULL;
328
329 NFSD_LOCK_ASSERT();
330
331 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
332 fhp = &nfh.fh_generic;
333 nfsm_srvmtofh(fhp);
334 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
335 error = ESTALE;
336 goto out;
337 }
338 NFSD_UNLOCK();
339 mtx_lock(&Giant); /* VFS */
340 (void) vn_start_write(NULL, &mp, V_WAIT);
341 vfs_rel(mp); /* The write holds a ref. */
342 mtx_unlock(&Giant); /* VFS */
343 NFSD_LOCK();
344 VATTR_NULL(vap);
345 if (v3) {
346 nfsm_srvsattr(vap);
347 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
348 gcheck = fxdr_unsigned(int, *tl);
349 if (gcheck) {
350 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
351 fxdr_nfsv3time(tl, &guard);
352 }
353 } else {
354 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
355 /*
356 * Nah nah nah nah na nah
357 * There is a bug in the Sun client that puts 0xffff in the mode
358 * field of sattr when it should put in 0xffffffff. The u_short
359 * doesn't sign extend.
360 * --> check the low order 2 bytes for 0xffff
361 */
362 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff)
363 vap->va_mode = nfstov_mode(sp->sa_mode);
364 if (sp->sa_uid != nfsrv_nfs_xdrneg1)
365 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid);
366 if (sp->sa_gid != nfsrv_nfs_xdrneg1)
367 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid);
368 if (sp->sa_size != nfsrv_nfs_xdrneg1)
369 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size);
370 if (sp->sa_atime.nfsv2_sec != nfsrv_nfs_xdrneg1) {
371 #ifdef notyet
372 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime);
373 #else
374 vap->va_atime.tv_sec =
375 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec);
376 vap->va_atime.tv_nsec = 0;
377 #endif
378 }
379 if (sp->sa_mtime.nfsv2_sec != nfsrv_nfs_xdrneg1)
380 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime);
381
382 }
383
384 /*
385 * Now that we have all the fields, lets do it.
386 */
387 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
388 if (error) {
389 nfsm_reply(2 * NFSX_UNSIGNED);
390 if (v3)
391 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
392 error = 0;
393 goto nfsmout;
394 }
395
396 /*
397 * vp now an active resource, pay careful attention to cleanup
398 */
399 if (v3) {
400 NFSD_UNLOCK();
401 mtx_lock(&Giant); /* VFS */
402 error = preat_ret = VOP_GETATTR(vp, &preat, cred, td);
403 if (!error && gcheck &&
404 (preat.va_ctime.tv_sec != guard.tv_sec ||
405 preat.va_ctime.tv_nsec != guard.tv_nsec))
406 error = NFSERR_NOT_SYNC;
407 if (error) {
408 vput(vp);
409 mtx_unlock(&Giant); /* VFS */
410 vp = NULL;
411 NFSD_LOCK();
412 nfsm_reply(NFSX_WCCDATA(v3));
413 if (v3)
414 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
415 error = 0;
416 goto nfsmout;
417 }
418 mtx_unlock(&Giant); /* VFS */
419 NFSD_LOCK();
420 }
421 NFSD_LOCK_ASSERT();
422
423 /*
424 * If the size is being changed write acces is required, otherwise
425 * just check for a read only filesystem.
426 */
427 if (vap->va_size == ((u_quad_t)((quad_t) -1))) {
428 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
429 error = EROFS;
430 goto out;
431 }
432 } else {
433 if (vp->v_type == VDIR) {
434 error = EISDIR;
435 goto out;
436 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly,
437 td, 0)) != 0)
438 goto out;
439 }
440 NFSD_UNLOCK();
441 mtx_lock(&Giant); /* VFS */
442 error = VOP_SETATTR(vp, vap, cred, td);
443 postat_ret = VOP_GETATTR(vp, vap, cred, td);
444 mtx_unlock(&Giant); /* VFS */
445 NFSD_LOCK();
446 if (!error)
447 error = postat_ret;
448 out:
449 NFSD_LOCK_ASSERT();
450 if (vp != NULL) {
451 NFSD_UNLOCK();
452 mtx_lock(&Giant); /* VFS */
453 vput(vp);
454 mtx_unlock(&Giant); /* VFS */
455 NFSD_LOCK();
456 }
457
458 vp = NULL;
459 nfsm_reply(NFSX_WCCORFATTR(v3));
460 if (v3) {
461 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap);
462 } else if (!error) {
463 /* v2 non-error case. */
464 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
465 nfsm_srvfillattr(vap, fp);
466 }
467 error = 0;
468 /* fall through */
469
470 nfsmout:
471 NFSD_LOCK_ASSERT();
472 NFSD_UNLOCK();
473 mtx_lock(&Giant); /* VFS */
474 if (vp)
475 vput(vp);
476 vn_finished_write(mp);
477 mtx_unlock(&Giant); /* VFS */
478 NFSD_LOCK();
479 return(error);
480 }
481
482 /*
483 * nfs lookup rpc
484 */
485 int
486 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
487 struct thread *td, struct mbuf **mrq)
488 {
489 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
490 struct sockaddr *nam = nfsd->nd_nam;
491 caddr_t dpos = nfsd->nd_dpos;
492 struct ucred *cred = nfsd->nd_cr;
493 struct nfs_fattr *fp;
494 struct nameidata nd, ind, *ndp = &nd;
495 struct vnode *vp, *dirp = NULL;
496 nfsfh_t nfh;
497 fhandle_t *fhp;
498 caddr_t bpos;
499 int error = 0, len, dirattr_ret = 1;
500 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag;
501 struct mbuf *mb, *mreq;
502 struct vattr va, dirattr, *vap = &va;
503
504 NFSD_LOCK_ASSERT();
505
506 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
507 ndclear(&nd);
508
509 fhp = &nfh.fh_generic;
510 nfsm_srvmtofh(fhp);
511 nfsm_srvnamesiz(len);
512
513 pubflag = nfs_ispublicfh(fhp);
514
515 nd.ni_cnd.cn_cred = cred;
516 nd.ni_cnd.cn_nameiop = LOOKUP;
517 nd.ni_cnd.cn_flags = LOCKLEAF | SAVESTART;
518 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
519 &dirp, v3, &dirattr, &dirattr_ret, td, pubflag);
520
521 /*
522 * namei failure, only dirp to cleanup. Clear out garbarge from
523 * structure in case macros jump to nfsmout.
524 */
525
526 NFSD_UNLOCK();
527 mtx_lock(&Giant); /* VFS */
528 if (error) {
529 if (dirp) {
530 vrele(dirp);
531 dirp = NULL;
532 }
533 mtx_unlock(&Giant); /* VFS */
534 NFSD_LOCK();
535 nfsm_reply(NFSX_POSTOPATTR(v3));
536 if (v3)
537 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
538 error = 0;
539 goto nfsmout;
540 }
541
542 /*
543 * Locate index file for public filehandle
544 *
545 * error is 0 on entry and 0 on exit from this block.
546 */
547
548 if (pubflag) {
549 if (nd.ni_vp->v_type == VDIR && nfs_pub.np_index != NULL) {
550 /*
551 * Setup call to lookup() to see if we can find
552 * the index file. Arguably, this doesn't belong
553 * in a kernel.. Ugh. If an error occurs, do not
554 * try to install an index file and then clear the
555 * error.
556 *
557 * When we replace nd with ind and redirect ndp,
558 * maintenance of ni_startdir and ni_vp shift to
559 * ind and we have to clean them up in the old nd.
560 * However, the cnd resource continues to be maintained
561 * via the original nd. Confused? You aren't alone!
562 */
563 ind = nd;
564 VOP_UNLOCK(nd.ni_vp, 0, td);
565 ind.ni_pathlen = strlen(nfs_pub.np_index);
566 ind.ni_cnd.cn_nameptr = ind.ni_cnd.cn_pnbuf =
567 nfs_pub.np_index;
568 ind.ni_startdir = nd.ni_vp;
569 VREF(ind.ni_startdir);
570
571 error = lookup(&ind);
572 ind.ni_dvp = NULL;
573 if (ind.ni_cnd.cn_flags & GIANTHELD) {
574 mtx_unlock(&Giant);
575 ind.ni_cnd.cn_flags &= ~GIANTHELD;
576 }
577
578 if (error == 0) {
579 /*
580 * Found an index file. Get rid of
581 * the old references. transfer nd.ni_vp'
582 */
583 if (dirp)
584 vrele(dirp);
585 dirp = nd.ni_vp;
586 nd.ni_vp = NULL;
587 vrele(nd.ni_startdir);
588 nd.ni_startdir = NULL;
589 ndp = &ind;
590 }
591 error = 0;
592 }
593 /*
594 * If the public filehandle was used, check that this lookup
595 * didn't result in a filehandle outside the publicly exported
596 * filesystem. We clear the poor vp here to avoid lockups due
597 * to NFS I/O.
598 */
599
600 if (ndp->ni_vp->v_mount != nfs_pub.np_mount) {
601 vput(nd.ni_vp);
602 nd.ni_vp = NULL;
603 error = EPERM;
604 }
605 }
606
607 /*
608 * Resources at this point:
609 * ndp->ni_vp may not be NULL
610 */
611
612 if (error) {
613 mtx_unlock(&Giant); /* VFS */
614 NFSD_LOCK();
615 nfsm_reply(NFSX_POSTOPATTR(v3));
616 if (v3)
617 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
618 error = 0;
619 goto nfsmout;
620 }
621
622 /*
623 * Get underlying attribute, then release remaining resources ( for
624 * the same potential blocking reason ) and reply.
625 */
626 vp = ndp->ni_vp;
627 bzero((caddr_t)fhp, sizeof(nfh));
628 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
629 error = VFS_VPTOFH(vp, &fhp->fh_fid);
630 if (!error)
631 error = VOP_GETATTR(vp, vap, cred, td);
632
633 vput(vp);
634 vrele(ndp->ni_startdir);
635 vrele(dirp);
636 ndp->ni_vp = NULL;
637 ndp->ni_startdir = NULL;
638 dirp = NULL;
639 mtx_unlock(&Giant); /* VFS */
640 NFSD_LOCK();
641 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3));
642 if (error) {
643 if (v3)
644 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
645 error = 0;
646 goto nfsmout;
647 }
648 nfsm_srvfhtom(fhp, v3);
649 if (v3) {
650 nfsm_srvpostop_attr(0, vap);
651 nfsm_srvpostop_attr(dirattr_ret, &dirattr);
652 } else {
653 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
654 nfsm_srvfillattr(vap, fp);
655 }
656
657 nfsmout:
658 NFSD_LOCK_ASSERT();
659 if (ndp->ni_vp || dirp || ndp->ni_startdir) {
660 NFSD_UNLOCK();
661 mtx_lock(&Giant); /* VFS */
662 if (ndp->ni_vp)
663 vput(ndp->ni_vp);
664 if (dirp)
665 vrele(dirp);
666 if (ndp->ni_startdir)
667 vrele(ndp->ni_startdir);
668 mtx_unlock(&Giant); /* VFS */
669 NFSD_LOCK();
670 }
671 NDFREE(&nd, NDF_ONLY_PNBUF);
672 return (error);
673 }
674
675 /*
676 * nfs readlink service
677 */
678 int
679 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
680 struct thread *td, struct mbuf **mrq)
681 {
682 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
683 struct sockaddr *nam = nfsd->nd_nam;
684 caddr_t dpos = nfsd->nd_dpos;
685 struct ucred *cred = nfsd->nd_cr;
686 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN];
687 struct iovec *ivp = iv;
688 struct mbuf *mp;
689 u_int32_t *tl;
690 caddr_t bpos;
691 int error = 0, rdonly, i, tlen, len, getret;
692 int v3 = (nfsd->nd_flag & ND_NFSV3);
693 struct mbuf *mb, *mp3, *nmp, *mreq;
694 struct vnode *vp = NULL;
695 struct vattr attr;
696 nfsfh_t nfh;
697 fhandle_t *fhp;
698 struct uio io, *uiop = &io;
699
700 NFSD_LOCK_ASSERT();
701
702 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
703 #ifndef nolint
704 mp = NULL;
705 #endif
706 mp3 = NULL;
707 fhp = &nfh.fh_generic;
708 nfsm_srvmtofh(fhp);
709 len = 0;
710 i = 0;
711 NFSD_UNLOCK();
712 while (len < NFS_MAXPATHLEN) {
713 MGET(nmp, M_TRYWAIT, MT_DATA);
714 MCLGET(nmp, M_TRYWAIT);
715 nmp->m_len = NFSMSIZ(nmp);
716 if (len == 0)
717 mp3 = mp = nmp;
718 else {
719 mp->m_next = nmp;
720 mp = nmp;
721 }
722 if ((len + mp->m_len) > NFS_MAXPATHLEN) {
723 mp->m_len = NFS_MAXPATHLEN - len;
724 len = NFS_MAXPATHLEN;
725 } else
726 len += mp->m_len;
727 ivp->iov_base = mtod(mp, caddr_t);
728 ivp->iov_len = mp->m_len;
729 i++;
730 ivp++;
731 }
732 uiop->uio_iov = iv;
733 uiop->uio_iovcnt = i;
734 uiop->uio_offset = 0;
735 uiop->uio_resid = len;
736 uiop->uio_rw = UIO_READ;
737 uiop->uio_segflg = UIO_SYSSPACE;
738 uiop->uio_td = NULL;
739 NFSD_LOCK();
740 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
741 if (error) {
742 nfsm_reply(2 * NFSX_UNSIGNED);
743 if (v3)
744 nfsm_srvpostop_attr(1, NULL);
745 error = 0;
746 goto nfsmout;
747 }
748 NFSD_UNLOCK();
749 mtx_lock(&Giant); /* VFS */
750 if (vp->v_type != VLNK) {
751 if (v3)
752 error = EINVAL;
753 else
754 error = ENXIO;
755 } else
756 error = VOP_READLINK(vp, uiop, cred);
757 getret = VOP_GETATTR(vp, &attr, cred, td);
758 vput(vp);
759 mtx_unlock(&Giant); /* VFS */
760 vp = NULL;
761 NFSD_LOCK();
762 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED);
763 if (v3)
764 nfsm_srvpostop_attr(getret, &attr);
765 if (error) {
766 error = 0;
767 goto nfsmout;
768 }
769 if (uiop->uio_resid > 0) {
770 len -= uiop->uio_resid;
771 tlen = nfsm_rndup(len);
772 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len);
773 }
774 tl = nfsm_build(u_int32_t *, NFSX_UNSIGNED);
775 *tl = txdr_unsigned(len);
776 mb->m_next = mp3;
777 mp3 = NULL;
778 nfsmout:
779 NFSD_LOCK_ASSERT();
780 if (mp3)
781 m_freem(mp3);
782 if (vp) {
783 NFSD_UNLOCK();
784 mtx_lock(&Giant); /* VFS */
785 vput(vp);
786 mtx_unlock(&Giant); /* VFS */
787 NFSD_LOCK();
788 }
789 return(error);
790 }
791
792 /*
793 * nfs read service
794 */
795 int
796 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
797 struct thread *td, struct mbuf **mrq)
798 {
799 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
800 struct sockaddr *nam = nfsd->nd_nam;
801 caddr_t dpos = nfsd->nd_dpos;
802 struct ucred *cred = nfsd->nd_cr;
803 struct iovec *iv;
804 struct iovec *iv2;
805 struct mbuf *m;
806 struct nfs_fattr *fp;
807 u_int32_t *tl;
808 int i;
809 caddr_t bpos;
810 int error = 0, rdonly, cnt, len, left, siz, tlen, getret;
811 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen;
812 struct mbuf *mb, *mreq;
813 struct mbuf *m2;
814 struct vnode *vp = NULL;
815 nfsfh_t nfh;
816 fhandle_t *fhp;
817 struct uio io, *uiop = &io;
818 struct vattr va, *vap = &va;
819 struct nfsheur *nh;
820 off_t off;
821 int ioflag = 0;
822
823 NFSD_LOCK_ASSERT();
824
825 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
826 fhp = &nfh.fh_generic;
827 nfsm_srvmtofh(fhp);
828 if (v3) {
829 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
830 off = fxdr_hyper(tl);
831 } else {
832 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
833 off = (off_t)fxdr_unsigned(u_int32_t, *tl);
834 }
835 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd));
836
837 /*
838 * Reference vp. If an error occurs, vp will be invalid, but we
839 * have to NULL it just in case. The macros might goto nfsmout
840 * as well.
841 */
842
843 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
844 if (error) {
845 vp = NULL;
846 nfsm_reply(2 * NFSX_UNSIGNED);
847 if (v3)
848 nfsm_srvpostop_attr(1, NULL);
849 error = 0;
850 goto nfsmout;
851 }
852
853 if (vp->v_type != VREG) {
854 if (v3)
855 error = EINVAL;
856 else
857 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
858 }
859 NFSD_UNLOCK();
860 mtx_lock(&Giant); /* VFS */
861 if (!error) {
862 if ((error = nfsrv_access_withgiant(vp, VREAD, cred, rdonly,
863 td, 1)) != 0)
864 error = nfsrv_access_withgiant(vp, VEXEC, cred,
865 rdonly, td, 1);
866 }
867 getret = VOP_GETATTR(vp, vap, cred, td);
868 if (!error)
869 error = getret;
870 if (error) {
871 vput(vp);
872 mtx_unlock(&Giant); /* VFS */
873 vp = NULL;
874 NFSD_LOCK();
875 nfsm_reply(NFSX_POSTOPATTR(v3));
876 if (v3)
877 nfsm_srvpostop_attr(getret, vap);
878 error = 0;
879 goto nfsmout;
880 }
881 mtx_unlock(&Giant); /* VFS */
882 NFSD_LOCK();
883
884 /*
885 * Calculate byte count to read
886 */
887
888 if (off >= vap->va_size)
889 cnt = 0;
890 else if ((off + reqlen) > vap->va_size)
891 cnt = vap->va_size - off;
892 else
893 cnt = reqlen;
894
895 /*
896 * Calculate seqcount for heuristic
897 */
898
899 {
900 int hi;
901 int try = 32;
902
903 /*
904 * Locate best candidate
905 */
906
907 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC;
908 nh = &nfsheur[hi];
909
910 while (try--) {
911 if (nfsheur[hi].nh_vp == vp) {
912 nh = &nfsheur[hi];
913 break;
914 }
915 if (nfsheur[hi].nh_use > 0)
916 --nfsheur[hi].nh_use;
917 hi = (hi + 1) % NUM_HEURISTIC;
918 if (nfsheur[hi].nh_use < nh->nh_use)
919 nh = &nfsheur[hi];
920 }
921
922 if (nh->nh_vp != vp) {
923 nh->nh_vp = vp;
924 nh->nh_nextr = off;
925 nh->nh_use = NHUSE_INIT;
926 if (off == 0)
927 nh->nh_seqcount = 4;
928 else
929 nh->nh_seqcount = 1;
930 }
931
932 /*
933 * Calculate heuristic
934 */
935
936 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) {
937 if (++nh->nh_seqcount > IO_SEQMAX)
938 nh->nh_seqcount = IO_SEQMAX;
939 } else if (nh->nh_seqcount > 1) {
940 nh->nh_seqcount = 1;
941 } else {
942 nh->nh_seqcount = 0;
943 }
944 nh->nh_use += NHUSE_INC;
945 if (nh->nh_use > NHUSE_MAX)
946 nh->nh_use = NHUSE_MAX;
947 ioflag |= nh->nh_seqcount << IO_SEQSHIFT;
948 }
949
950 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt));
951 if (v3) {
952 tl = nfsm_build(u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED);
953 *tl++ = nfsrv_nfs_true;
954 fp = (struct nfs_fattr *)tl;
955 tl += (NFSX_V3FATTR / sizeof (u_int32_t));
956 } else {
957 tl = nfsm_build(u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED);
958 fp = (struct nfs_fattr *)tl;
959 tl += (NFSX_V2FATTR / sizeof (u_int32_t));
960 }
961 len = left = nfsm_rndup(cnt);
962 NFSD_UNLOCK();
963 if (cnt > 0) {
964 /*
965 * Generate the mbuf list with the uio_iov ref. to it.
966 */
967 i = 0;
968 m = m2 = mb;
969 while (left > 0) {
970 siz = min(M_TRAILINGSPACE(m), left);
971 if (siz > 0) {
972 left -= siz;
973 i++;
974 }
975 if (left > 0) {
976 MGET(m, M_TRYWAIT, MT_DATA);
977 MCLGET(m, M_TRYWAIT);
978 m->m_len = 0;
979 m2->m_next = m;
980 m2 = m;
981 }
982 }
983 MALLOC(iv, struct iovec *, i * sizeof (struct iovec),
984 M_TEMP, M_WAITOK);
985 uiop->uio_iov = iv2 = iv;
986 m = mb;
987 left = len;
988 i = 0;
989 while (left > 0) {
990 if (m == NULL)
991 panic("nfsrv_read iov");
992 siz = min(M_TRAILINGSPACE(m), left);
993 if (siz > 0) {
994 iv->iov_base = mtod(m, caddr_t) + m->m_len;
995 iv->iov_len = siz;
996 m->m_len += siz;
997 left -= siz;
998 iv++;
999 i++;
1000 }
1001 m = m->m_next;
1002 }
1003 uiop->uio_iovcnt = i;
1004 uiop->uio_offset = off;
1005 uiop->uio_resid = len;
1006 uiop->uio_rw = UIO_READ;
1007 uiop->uio_segflg = UIO_SYSSPACE;
1008 mtx_lock(&Giant); /* VFS */
1009 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred);
1010 off = uiop->uio_offset;
1011 nh->nh_nextr = off;
1012 FREE((caddr_t)iv2, M_TEMP);
1013 if (error || (getret = VOP_GETATTR(vp, vap, cred, td))) {
1014 if (!error)
1015 error = getret;
1016 m_freem(mreq);
1017 vput(vp);
1018 mtx_unlock(&Giant); /* VFS */
1019 NFSD_LOCK();
1020 vp = NULL;
1021 nfsm_reply(NFSX_POSTOPATTR(v3));
1022 if (v3)
1023 nfsm_srvpostop_attr(getret, vap);
1024 error = 0;
1025 goto nfsmout;
1026 }
1027 } else {
1028 uiop->uio_resid = 0;
1029 mtx_lock(&Giant); /* VFS */
1030 }
1031 mtx_assert(&Giant, MA_OWNED); /* VFS */
1032 vput(vp);
1033 mtx_unlock(&Giant); /* VFS */
1034 vp = NULL;
1035 NFSD_LOCK();
1036 nfsm_srvfillattr(vap, fp);
1037 tlen = len - uiop->uio_resid;
1038 cnt = cnt < tlen ? cnt : tlen;
1039 tlen = nfsm_rndup(cnt);
1040 if (len != tlen || tlen != cnt)
1041 nfsm_adj(mb, len - tlen, tlen - cnt);
1042 if (v3) {
1043 *tl++ = txdr_unsigned(cnt);
1044 if (cnt < reqlen)
1045 *tl++ = nfsrv_nfs_true;
1046 else
1047 *tl++ = nfsrv_nfs_false;
1048 }
1049 *tl = txdr_unsigned(cnt);
1050 nfsmout:
1051 NFSD_LOCK_ASSERT();
1052 if (vp) {
1053 NFSD_UNLOCK();
1054 mtx_lock(&Giant); /* VFS */
1055 vput(vp);
1056 mtx_unlock(&Giant); /* VFS */
1057 NFSD_LOCK();
1058 }
1059 return(error);
1060 }
1061
1062 /*
1063 * nfs write service
1064 */
1065 int
1066 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1067 struct thread *td, struct mbuf **mrq)
1068 {
1069 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1070 struct sockaddr *nam = nfsd->nd_nam;
1071 caddr_t dpos = nfsd->nd_dpos;
1072 struct ucred *cred = nfsd->nd_cr;
1073 struct iovec *ivp;
1074 int i, cnt;
1075 struct mbuf *mp;
1076 struct nfs_fattr *fp;
1077 struct iovec *iv;
1078 struct vattr va, forat;
1079 struct vattr *vap = &va;
1080 u_int32_t *tl;
1081 caddr_t bpos;
1082 int error = 0, rdonly, len, forat_ret = 1;
1083 int ioflags, aftat_ret = 1, retlen = 0, zeroing, adjust;
1084 int stable = NFSV3WRITE_FILESYNC;
1085 int v3 = (nfsd->nd_flag & ND_NFSV3);
1086 struct mbuf *mb, *mreq;
1087 struct vnode *vp = NULL;
1088 nfsfh_t nfh;
1089 fhandle_t *fhp;
1090 struct uio io, *uiop = &io;
1091 off_t off;
1092 struct mount *mntp = NULL;
1093
1094 NFSD_LOCK_ASSERT();
1095
1096 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1097 if (mrep == NULL) {
1098 *mrq = NULL;
1099 error = 0;
1100 goto nfsmout;
1101 }
1102 fhp = &nfh.fh_generic;
1103 nfsm_srvmtofh(fhp);
1104 if ((mntp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1105 error = ESTALE;
1106 goto ereply;
1107 }
1108 NFSD_UNLOCK();
1109 mtx_lock(&Giant); /* VFS */
1110 (void) vn_start_write(NULL, &mntp, V_WAIT);
1111 vfs_rel(mntp); /* The write holds a ref. */
1112 mtx_unlock(&Giant); /* VFS */
1113 NFSD_LOCK();
1114 if (v3) {
1115 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1116 off = fxdr_hyper(tl);
1117 tl += 3;
1118 stable = fxdr_unsigned(int, *tl++);
1119 } else {
1120 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1121 off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1122 tl += 2;
1123 if (nfs_async)
1124 stable = NFSV3WRITE_UNSTABLE;
1125 }
1126 retlen = len = fxdr_unsigned(int32_t, *tl);
1127 cnt = i = 0;
1128
1129 /*
1130 * For NFS Version 2, it is not obvious what a write of zero length
1131 * should do, but I might as well be consistent with Version 3,
1132 * which is to return ok so long as there are no permission problems.
1133 */
1134 if (len > 0) {
1135 zeroing = 1;
1136 mp = mrep;
1137 while (mp) {
1138 if (mp == md) {
1139 zeroing = 0;
1140 adjust = dpos - mtod(mp, caddr_t);
1141 mp->m_len -= adjust;
1142 if (mp->m_len > 0 && adjust > 0)
1143 mp->m_data += adjust;
1144 }
1145 if (zeroing)
1146 mp->m_len = 0;
1147 else if (mp->m_len > 0) {
1148 i += mp->m_len;
1149 if (i > len) {
1150 mp->m_len -= (i - len);
1151 zeroing = 1;
1152 }
1153 if (mp->m_len > 0)
1154 cnt++;
1155 }
1156 mp = mp->m_next;
1157 }
1158 }
1159 if (len > NFS_MAXDATA || len < 0 || i < len) {
1160 error = EIO;
1161 nfsm_reply(2 * NFSX_UNSIGNED);
1162 if (v3)
1163 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1164 error = 0;
1165 goto nfsmout;
1166 }
1167 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
1168 if (error) {
1169 vp = NULL;
1170 nfsm_reply(2 * NFSX_UNSIGNED);
1171 if (v3)
1172 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1173 error = 0;
1174 goto nfsmout;
1175 }
1176 if (v3) {
1177 NFSD_UNLOCK();
1178 mtx_lock(&Giant); /* VFS */
1179 forat_ret = VOP_GETATTR(vp, &forat, cred, td);
1180 mtx_unlock(&Giant); /* VFS */
1181 NFSD_LOCK();
1182 }
1183 if (vp->v_type != VREG) {
1184 if (v3)
1185 error = EINVAL;
1186 else
1187 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1188 }
1189 if (!error)
1190 error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1);
1191 if (error) {
1192 NFSD_UNLOCK();
1193 mtx_lock(&Giant); /* VFS */
1194 vput(vp);
1195 mtx_unlock(&Giant); /* VFS */
1196 NFSD_LOCK();
1197 vp = NULL;
1198 nfsm_reply(NFSX_WCCDATA(v3));
1199 if (v3)
1200 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1201 error = 0;
1202 goto nfsmout;
1203 }
1204
1205 NFSD_UNLOCK();
1206 if (len > 0) {
1207 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP,
1208 M_WAITOK);
1209 uiop->uio_iov = iv = ivp;
1210 uiop->uio_iovcnt = cnt;
1211 mp = mrep;
1212 while (mp) {
1213 if (mp->m_len > 0) {
1214 ivp->iov_base = mtod(mp, caddr_t);
1215 ivp->iov_len = mp->m_len;
1216 ivp++;
1217 }
1218 mp = mp->m_next;
1219 }
1220
1221 /*
1222 * XXX
1223 * The IO_METASYNC flag indicates that all metadata (and not just
1224 * enough to ensure data integrity) mus be written to stable storage
1225 * synchronously.
1226 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.)
1227 */
1228 if (stable == NFSV3WRITE_UNSTABLE)
1229 ioflags = IO_NODELOCKED;
1230 else if (stable == NFSV3WRITE_DATASYNC)
1231 ioflags = (IO_SYNC | IO_NODELOCKED);
1232 else
1233 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1234 uiop->uio_resid = len;
1235 uiop->uio_rw = UIO_WRITE;
1236 uiop->uio_segflg = UIO_SYSSPACE;
1237 uiop->uio_td = NULL;
1238 uiop->uio_offset = off;
1239 mtx_lock(&Giant); /* VFS */
1240 error = VOP_WRITE(vp, uiop, ioflags, cred);
1241 /* XXXRW: unlocked write. */
1242 nfsrvstats.srvvop_writes++;
1243 FREE((caddr_t)iv, M_TEMP);
1244 } else
1245 mtx_lock(&Giant); /* VFS */
1246 mtx_assert(&Giant, MA_OWNED); /* VFS */
1247 aftat_ret = VOP_GETATTR(vp, vap, cred, td);
1248 vput(vp);
1249 mtx_unlock(&Giant); /* VFS */
1250 NFSD_LOCK();
1251 vp = NULL;
1252 if (!error)
1253 error = aftat_ret;
1254 ereply:
1255 NFSD_LOCK_ASSERT();
1256 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) +
1257 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3));
1258 if (v3) {
1259 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap);
1260 if (error) {
1261 error = 0;
1262 goto nfsmout;
1263 }
1264 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1265 *tl++ = txdr_unsigned(retlen);
1266 /*
1267 * If nfs_async is set, then pretend the write was FILESYNC.
1268 */
1269 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async)
1270 *tl++ = txdr_unsigned(stable);
1271 else
1272 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC);
1273 /*
1274 * Actually, there is no need to txdr these fields,
1275 * but it may make the values more human readable,
1276 * for debugging purposes.
1277 */
1278 if (nfsver.tv_sec == 0)
1279 nfsver = boottime;
1280 *tl++ = txdr_unsigned(nfsver.tv_sec);
1281 *tl = txdr_unsigned(nfsver.tv_usec);
1282 } else if (!error) {
1283 /* v2 non-error case. */
1284 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1285 nfsm_srvfillattr(vap, fp);
1286 }
1287 error = 0;
1288 nfsmout:
1289 NFSD_LOCK_ASSERT();
1290 NFSD_UNLOCK();
1291 mtx_lock(&Giant); /* VFS */
1292 if (vp)
1293 vput(vp);
1294 vn_finished_write(mntp);
1295 mtx_unlock(&Giant); /* VFS */
1296 NFSD_LOCK();
1297 return(error);
1298 }
1299
1300 /*
1301 * For the purposes of write gathering, we must decide if the credential
1302 * associated with two pending requests have equivilent privileges. Since
1303 * NFS only uses a subset of the BSD ucred -- the effective uid and group
1304 * IDs -- we have a compare routine that checks only the relevant fields.
1305 */
1306 static int
1307 nfsrv_samecred(struct ucred *cr1, struct ucred *cr2)
1308 {
1309 int i;
1310
1311 if (cr1->cr_uid != cr2->cr_uid)
1312 return (0);
1313 if (cr1->cr_ngroups != cr2->cr_ngroups)
1314 return (0);
1315 for (i = 0; i < cr1->cr_ngroups; i++) {
1316 if (cr1->cr_groups[i] != cr2->cr_groups[i])
1317 return (0);
1318 }
1319 return (1);
1320 }
1321
1322 /*
1323 * NFS write service with write gathering support. Called when
1324 * nfsrvw_procrastinate > 0.
1325 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server",
1326 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco,
1327 * Jan. 1994.
1328 */
1329 int
1330 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp,
1331 struct thread *td, struct mbuf **mrq)
1332 {
1333 struct iovec *ivp;
1334 struct mbuf *mp;
1335 struct nfsrv_descript *wp, *nfsd, *owp, *swp;
1336 struct nfs_fattr *fp;
1337 int i;
1338 struct iovec *iov;
1339 struct nfsrvw_delayhash *wpp;
1340 struct ucred *cred;
1341 struct vattr va, forat;
1342 u_int32_t *tl;
1343 caddr_t bpos, dpos;
1344 int error = 0, rdonly, len, forat_ret = 1;
1345 int ioflags, aftat_ret = 1, s, adjust, v3, zeroing;
1346 struct mbuf *mb, *mreq, *mrep, *md;
1347 struct vnode *vp = NULL;
1348 struct uio io, *uiop = &io;
1349 u_quad_t cur_usec;
1350 struct mount *mntp = NULL;
1351
1352 NFSD_LOCK_ASSERT();
1353
1354 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1355 #ifndef nolint
1356 i = 0;
1357 len = 0;
1358 #endif
1359 *mrq = NULL;
1360 if (*ndp) {
1361 nfsd = *ndp;
1362 *ndp = NULL;
1363 mrep = nfsd->nd_mrep;
1364 md = nfsd->nd_md;
1365 dpos = nfsd->nd_dpos;
1366 cred = nfsd->nd_cr;
1367 v3 = (nfsd->nd_flag & ND_NFSV3);
1368 LIST_INIT(&nfsd->nd_coalesce);
1369 nfsd->nd_mreq = NULL;
1370 nfsd->nd_stable = NFSV3WRITE_FILESYNC;
1371 cur_usec = nfs_curusec();
1372 nfsd->nd_time = cur_usec +
1373 (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate);
1374
1375 /*
1376 * Now, get the write header..
1377 */
1378 nfsm_srvmtofh(&nfsd->nd_fh);
1379 if (v3) {
1380 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
1381 nfsd->nd_off = fxdr_hyper(tl);
1382 tl += 3;
1383 nfsd->nd_stable = fxdr_unsigned(int, *tl++);
1384 } else {
1385 tl = nfsm_dissect_nonblock(u_int32_t *, 4 * NFSX_UNSIGNED);
1386 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl);
1387 tl += 2;
1388 if (nfs_async)
1389 nfsd->nd_stable = NFSV3WRITE_UNSTABLE;
1390 }
1391 len = fxdr_unsigned(int32_t, *tl);
1392 nfsd->nd_len = len;
1393 nfsd->nd_eoff = nfsd->nd_off + len;
1394
1395 /*
1396 * Trim the header out of the mbuf list and trim off any trailing
1397 * junk so that the mbuf list has only the write data.
1398 */
1399 zeroing = 1;
1400 i = 0;
1401 mp = mrep;
1402 while (mp) {
1403 if (mp == md) {
1404 zeroing = 0;
1405 adjust = dpos - mtod(mp, caddr_t);
1406 mp->m_len -= adjust;
1407 if (mp->m_len > 0 && adjust > 0)
1408 mp->m_data += adjust;
1409 }
1410 if (zeroing)
1411 mp->m_len = 0;
1412 else {
1413 i += mp->m_len;
1414 if (i > len) {
1415 mp->m_len -= (i - len);
1416 zeroing = 1;
1417 }
1418 }
1419 mp = mp->m_next;
1420 }
1421 if (len > NFS_MAXDATA || len < 0 || i < len) {
1422 nfsmout:
1423 NFSD_LOCK_ASSERT();
1424 m_freem(mrep);
1425 error = EIO;
1426 nfsm_writereply(2 * NFSX_UNSIGNED);
1427 if (v3)
1428 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1429 nfsd->nd_mreq = mreq;
1430 nfsd->nd_mrep = NULL;
1431 nfsd->nd_time = 0;
1432 }
1433
1434 /*
1435 * Add this entry to the hash and time queues.
1436 */
1437 s = splsoftclock();
1438 owp = NULL;
1439 wp = LIST_FIRST(&slp->ns_tq);
1440 while (wp && wp->nd_time < nfsd->nd_time) {
1441 owp = wp;
1442 wp = LIST_NEXT(wp, nd_tq);
1443 }
1444 NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff));
1445 if (owp) {
1446 LIST_INSERT_AFTER(owp, nfsd, nd_tq);
1447 } else {
1448 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1449 }
1450 if (nfsd->nd_mrep) {
1451 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data);
1452 owp = NULL;
1453 wp = LIST_FIRST(wpp);
1454 while (wp &&
1455 bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)){
1456 owp = wp;
1457 wp = LIST_NEXT(wp, nd_hash);
1458 }
1459 while (wp && wp->nd_off < nfsd->nd_off &&
1460 !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh, NFSX_V3FH)) {
1461 owp = wp;
1462 wp = LIST_NEXT(wp, nd_hash);
1463 }
1464 if (owp) {
1465 LIST_INSERT_AFTER(owp, nfsd, nd_hash);
1466
1467 /*
1468 * Search the hash list for overlapping entries and
1469 * coalesce.
1470 */
1471 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) {
1472 wp = LIST_NEXT(nfsd, nd_hash);
1473 if (nfsrv_samecred(owp->nd_cr, nfsd->nd_cr))
1474 nfsrvw_coalesce(owp, nfsd);
1475 }
1476 } else {
1477 LIST_INSERT_HEAD(wpp, nfsd, nd_hash);
1478 }
1479 }
1480 splx(s);
1481 }
1482
1483 /*
1484 * Now, do VOP_WRITE()s for any one(s) that need to be done now
1485 * and generate the associated reply mbuf list(s).
1486 */
1487 loop1:
1488 cur_usec = nfs_curusec();
1489 s = splsoftclock();
1490 for (nfsd = LIST_FIRST(&slp->ns_tq); nfsd; nfsd = owp) {
1491 owp = LIST_NEXT(nfsd, nd_tq);
1492 if (nfsd->nd_time > cur_usec)
1493 break;
1494 if (nfsd->nd_mreq)
1495 continue;
1496 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff));
1497 LIST_REMOVE(nfsd, nd_tq);
1498 LIST_REMOVE(nfsd, nd_hash);
1499 splx(s);
1500 mrep = nfsd->nd_mrep;
1501 nfsd->nd_mrep = NULL;
1502 cred = nfsd->nd_cr;
1503 v3 = (nfsd->nd_flag & ND_NFSV3);
1504 forat_ret = aftat_ret = 1;
1505 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp,
1506 nfsd->nd_nam, &rdonly, TRUE);
1507 if (!error) {
1508 if (v3) {
1509 NFSD_UNLOCK();
1510 mtx_lock(&Giant); /* VFS */
1511 forat_ret = VOP_GETATTR(vp, &forat, cred, td);
1512 mtx_unlock(&Giant); /* VFS */
1513 NFSD_LOCK();
1514 }
1515 if (vp->v_type != VREG) {
1516 if (v3)
1517 error = EINVAL;
1518 else
1519 error = (vp->v_type == VDIR) ? EISDIR : EACCES;
1520 }
1521 } else {
1522 vp = NULL;
1523 }
1524 NFSD_UNLOCK();
1525 mtx_lock(&Giant); /* VFS */
1526 if (!error)
1527 error = nfsrv_access_withgiant(vp, VWRITE, cred, rdonly,
1528 td, 1);
1529 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE)
1530 ioflags = IO_NODELOCKED;
1531 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC)
1532 ioflags = (IO_SYNC | IO_NODELOCKED);
1533 else
1534 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED);
1535 uiop->uio_rw = UIO_WRITE;
1536 uiop->uio_segflg = UIO_SYSSPACE;
1537 uiop->uio_td = NULL;
1538 uiop->uio_offset = nfsd->nd_off;
1539 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off;
1540 if (uiop->uio_resid > 0) {
1541 mp = mrep;
1542 i = 0;
1543 while (mp) {
1544 if (mp->m_len > 0)
1545 i++;
1546 mp = mp->m_next;
1547 }
1548 uiop->uio_iovcnt = i;
1549 MALLOC(iov, struct iovec *, i * sizeof (struct iovec),
1550 M_TEMP, M_WAITOK);
1551 uiop->uio_iov = ivp = iov;
1552 mp = mrep;
1553 while (mp) {
1554 if (mp->m_len > 0) {
1555 ivp->iov_base = mtod(mp, caddr_t);
1556 ivp->iov_len = mp->m_len;
1557 ivp++;
1558 }
1559 mp = mp->m_next;
1560 }
1561 if (!error) {
1562 if (vn_start_write(vp, &mntp, V_NOWAIT) != 0) {
1563 VOP_UNLOCK(vp, 0, td);
1564 error = vn_start_write(NULL, &mntp, V_WAIT);
1565 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1566 }
1567 }
1568 if (!error) {
1569 error = VOP_WRITE(vp, uiop, ioflags, cred);
1570 /* XXXRW: unlocked write. */
1571 nfsrvstats.srvvop_writes++;
1572 vn_finished_write(mntp);
1573 }
1574 FREE((caddr_t)iov, M_TEMP);
1575 }
1576 m_freem(mrep);
1577 if (vp) {
1578 aftat_ret = VOP_GETATTR(vp, &va, cred, td);
1579 vput(vp);
1580 vp = NULL;
1581 }
1582 mtx_unlock(&Giant); /* VFS */
1583 NFSD_LOCK();
1584
1585 /*
1586 * Loop around generating replies for all write rpcs that have
1587 * now been completed.
1588 */
1589 swp = nfsd;
1590 do {
1591 NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff));
1592 if (error) {
1593 nfsm_writereply(NFSX_WCCDATA(v3));
1594 if (v3) {
1595 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1596 }
1597 } else {
1598 nfsm_writereply(NFSX_PREOPATTR(v3) +
1599 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED +
1600 NFSX_WRITEVERF(v3));
1601 if (v3) {
1602 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va);
1603 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
1604 *tl++ = txdr_unsigned(nfsd->nd_len);
1605 *tl++ = txdr_unsigned(swp->nd_stable);
1606 /*
1607 * Actually, there is no need to txdr these fields,
1608 * but it may make the values more human readable,
1609 * for debugging purposes.
1610 */
1611 if (nfsver.tv_sec == 0)
1612 nfsver = boottime;
1613 *tl++ = txdr_unsigned(nfsver.tv_sec);
1614 *tl = txdr_unsigned(nfsver.tv_usec);
1615 } else {
1616 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
1617 nfsm_srvfillattr(&va, fp);
1618 }
1619 }
1620 nfsd->nd_mreq = mreq;
1621 if (nfsd->nd_mrep)
1622 panic("nfsrv_write: nd_mrep not free");
1623
1624 /*
1625 * Done. Put it at the head of the timer queue so that
1626 * the final phase can return the reply.
1627 */
1628 s = splsoftclock();
1629 if (nfsd != swp) {
1630 nfsd->nd_time = 0;
1631 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq);
1632 }
1633 nfsd = LIST_FIRST(&swp->nd_coalesce);
1634 if (nfsd) {
1635 LIST_REMOVE(nfsd, nd_tq);
1636 }
1637 splx(s);
1638 } while (nfsd);
1639 s = splsoftclock();
1640 swp->nd_time = 0;
1641 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq);
1642 splx(s);
1643 goto loop1;
1644 }
1645 splx(s);
1646
1647 /*
1648 * Search for a reply to return.
1649 */
1650 s = splsoftclock();
1651 LIST_FOREACH(nfsd, &slp->ns_tq, nd_tq)
1652 if (nfsd->nd_mreq) {
1653 NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff));
1654 LIST_REMOVE(nfsd, nd_tq);
1655 *mrq = nfsd->nd_mreq;
1656 *ndp = nfsd;
1657 break;
1658 }
1659 splx(s);
1660 return (0);
1661 }
1662
1663 /*
1664 * Coalesce the write request nfsd into owp. To do this we must:
1665 * - remove nfsd from the queues
1666 * - merge nfsd->nd_mrep into owp->nd_mrep
1667 * - update the nd_eoff and nd_stable for owp
1668 * - put nfsd on owp's nd_coalesce list
1669 * NB: Must be called at splsoftclock().
1670 */
1671 static void
1672 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd)
1673 {
1674 int overlap;
1675 struct mbuf *mp;
1676 struct nfsrv_descript *p;
1677
1678 NFSD_LOCK_ASSERT();
1679
1680 NFS_DPF(WG, ("C%03x-%03x",
1681 nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff));
1682 LIST_REMOVE(nfsd, nd_hash);
1683 LIST_REMOVE(nfsd, nd_tq);
1684 if (owp->nd_eoff < nfsd->nd_eoff) {
1685 overlap = owp->nd_eoff - nfsd->nd_off;
1686 if (overlap < 0)
1687 panic("nfsrv_coalesce: bad off");
1688 if (overlap > 0)
1689 m_adj(nfsd->nd_mrep, overlap);
1690 mp = owp->nd_mrep;
1691 while (mp->m_next)
1692 mp = mp->m_next;
1693 mp->m_next = nfsd->nd_mrep;
1694 owp->nd_eoff = nfsd->nd_eoff;
1695 } else
1696 m_freem(nfsd->nd_mrep);
1697 nfsd->nd_mrep = NULL;
1698 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC)
1699 owp->nd_stable = NFSV3WRITE_FILESYNC;
1700 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC &&
1701 owp->nd_stable == NFSV3WRITE_UNSTABLE)
1702 owp->nd_stable = NFSV3WRITE_DATASYNC;
1703 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq);
1704
1705 /*
1706 * If nfsd had anything else coalesced into it, transfer them
1707 * to owp, otherwise their replies will never get sent.
1708 */
1709 for (p = LIST_FIRST(&nfsd->nd_coalesce); p;
1710 p = LIST_FIRST(&nfsd->nd_coalesce)) {
1711 LIST_REMOVE(p, nd_tq);
1712 LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq);
1713 }
1714 }
1715
1716 /*
1717 * nfs create service
1718 * now does a truncate to 0 length via. setattr if it already exists
1719 */
1720 int
1721 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
1722 struct thread *td, struct mbuf **mrq)
1723 {
1724 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
1725 struct sockaddr *nam = nfsd->nd_nam;
1726 caddr_t dpos = nfsd->nd_dpos;
1727 struct ucred *cred = nfsd->nd_cr;
1728 struct nfs_fattr *fp;
1729 struct vattr va, dirfor, diraft;
1730 struct vattr *vap = &va;
1731 struct nfsv2_sattr *sp;
1732 u_int32_t *tl;
1733 struct nameidata nd;
1734 caddr_t bpos;
1735 int error = 0, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1;
1736 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0;
1737 caddr_t cp;
1738 struct mbuf *mb, *mreq;
1739 struct vnode *dirp = NULL;
1740 nfsfh_t nfh;
1741 fhandle_t *fhp;
1742 u_quad_t tempsize;
1743 u_char cverf[NFSX_V3CREATEVERF];
1744 struct mount *mp = NULL;
1745
1746 NFSD_LOCK_ASSERT();
1747
1748 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
1749 #ifndef nolint
1750 rdev = 0;
1751 #endif
1752 ndclear(&nd);
1753
1754 fhp = &nfh.fh_generic;
1755 nfsm_srvmtofh(fhp);
1756 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
1757 error = ESTALE;
1758 goto ereply_locked;
1759 }
1760 NFSD_UNLOCK();
1761 mtx_lock(&Giant); /* VFS */
1762 (void) vn_start_write(NULL, &mp, V_WAIT);
1763 vfs_rel(mp); /* The write holds a ref. */
1764 mtx_unlock(&Giant); /* VFS */
1765 NFSD_LOCK();
1766 nfsm_srvnamesiz(len);
1767
1768 nd.ni_cnd.cn_cred = cred;
1769 nd.ni_cnd.cn_nameiop = CREATE;
1770 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
1771
1772 /*
1773 * Call namei and do initial cleanup to get a few things
1774 * out of the way. If we get an initial error we cleanup
1775 * and return here to avoid special-casing the invalid nd
1776 * structure through the rest of the case. dirp may be
1777 * set even if an error occurs, but the nd structure will not
1778 * be valid at all if an error occurs so we have to invalidate it
1779 * prior to calling nfsm_reply ( which might goto nfsmout ).
1780 */
1781 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
1782 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
1783 if (dirp && !v3) {
1784 NFSD_UNLOCK();
1785 mtx_lock(&Giant); /* VFS */
1786 vrele(dirp);
1787 mtx_unlock(&Giant); /* VFS */
1788 NFSD_LOCK();
1789 dirp = NULL;
1790 }
1791 if (error) {
1792 nfsm_reply(NFSX_WCCDATA(v3));
1793 if (v3)
1794 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1795 error = 0;
1796 goto nfsmout;
1797 }
1798
1799 /*
1800 * No error. Continue. State:
1801 *
1802 * startdir is valid ( we release this immediately )
1803 * dirp may be valid
1804 * nd.ni_vp may be valid
1805 * nd.ni_dvp is valid
1806 *
1807 * The error state is set through the code and we may also do some
1808 * opportunistic releasing of vnodes to avoid holding locks through
1809 * NFS I/O. The cleanup at the end is a catch-all
1810 */
1811
1812 VATTR_NULL(vap);
1813 if (v3) {
1814 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
1815 how = fxdr_unsigned(int, *tl);
1816 switch (how) {
1817 case NFSV3CREATE_GUARDED:
1818 if (nd.ni_vp) {
1819 error = EEXIST;
1820 break;
1821 }
1822 /* fall through */
1823 case NFSV3CREATE_UNCHECKED:
1824 nfsm_srvsattr(vap);
1825 break;
1826 case NFSV3CREATE_EXCLUSIVE:
1827 cp = nfsm_dissect_nonblock(caddr_t, NFSX_V3CREATEVERF);
1828 bcopy(cp, cverf, NFSX_V3CREATEVERF);
1829 exclusive_flag = 1;
1830 break;
1831 };
1832 vap->va_type = VREG;
1833 } else {
1834 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
1835 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode));
1836 if (vap->va_type == VNON)
1837 vap->va_type = VREG;
1838 vap->va_mode = nfstov_mode(sp->sa_mode);
1839 switch (vap->va_type) {
1840 case VREG:
1841 tsize = fxdr_unsigned(int32_t, sp->sa_size);
1842 if (tsize != -1)
1843 vap->va_size = (u_quad_t)tsize;
1844 break;
1845 case VCHR:
1846 case VBLK:
1847 case VFIFO:
1848 rdev = fxdr_unsigned(long, sp->sa_size);
1849 break;
1850 default:
1851 break;
1852 };
1853 }
1854
1855 /*
1856 * Iff doesn't exist, create it
1857 * otherwise just truncate to 0 length
1858 * should I set the mode too ?
1859 *
1860 * The only possible error we can have at this point is EEXIST.
1861 * nd.ni_vp will also be non-NULL in that case.
1862 */
1863 NFSD_UNLOCK();
1864 mtx_lock(&Giant); /* VFS */
1865 if (nd.ni_vp == NULL) {
1866 if (vap->va_mode == (mode_t)VNOVAL)
1867 vap->va_mode = 0;
1868 if (vap->va_type == VREG || vap->va_type == VSOCK) {
1869 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1870 if (error)
1871 NDFREE(&nd, NDF_ONLY_PNBUF);
1872 else {
1873 if (exclusive_flag) {
1874 exclusive_flag = 0;
1875 VATTR_NULL(vap);
1876 bcopy(cverf, (caddr_t)&vap->va_atime,
1877 NFSX_V3CREATEVERF);
1878 error = VOP_SETATTR(nd.ni_vp, vap, cred,
1879 td);
1880 }
1881 }
1882 } else if (vap->va_type == VCHR || vap->va_type == VBLK ||
1883 vap->va_type == VFIFO) {
1884 /*
1885 * NFSv2-specific code for creating device nodes
1886 * and fifos.
1887 *
1888 * Handle SysV FIFO node special cases. All other
1889 * devices require super user to access.
1890 */
1891 if (vap->va_type == VCHR && rdev == 0xffffffff)
1892 vap->va_type = VFIFO;
1893 if (vap->va_type != VFIFO &&
1894 (error = suser_cred(cred, 0))) {
1895 goto ereply;
1896 }
1897 vap->va_rdev = rdev;
1898 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
1899 if (error) {
1900 NDFREE(&nd, NDF_ONLY_PNBUF);
1901 goto ereply;
1902 }
1903 vput(nd.ni_vp);
1904 nd.ni_vp = NULL;
1905
1906 /*
1907 * release dvp prior to lookup
1908 */
1909 vput(nd.ni_dvp);
1910 nd.ni_dvp = NULL;
1911
1912 /*
1913 * Setup for lookup.
1914 *
1915 * Even though LOCKPARENT was cleared, ni_dvp may
1916 * be garbage.
1917 */
1918 nd.ni_cnd.cn_nameiop = LOOKUP;
1919 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
1920 nd.ni_cnd.cn_thread = td;
1921 nd.ni_cnd.cn_cred = cred;
1922
1923 error = lookup(&nd);
1924 nd.ni_dvp = NULL;
1925 if (nd.ni_cnd.cn_flags & GIANTHELD) {
1926 mtx_unlock(&Giant);
1927 nd.ni_cnd.cn_flags &= ~GIANTHELD;
1928 }
1929 if (error)
1930 goto ereply;
1931
1932 if (nd.ni_cnd.cn_flags & ISSYMLINK) {
1933 error = EINVAL;
1934 goto ereply;
1935 }
1936 } else {
1937 error = ENXIO;
1938 }
1939 } else {
1940 if (vap->va_size != -1) {
1941 error = nfsrv_access_withgiant(nd.ni_vp, VWRITE,
1942 cred, (nd.ni_cnd.cn_flags & RDONLY), td, 0);
1943 if (!error) {
1944 tempsize = vap->va_size;
1945 VATTR_NULL(vap);
1946 vap->va_size = tempsize;
1947 error = VOP_SETATTR(nd.ni_vp, vap, cred,
1948 td);
1949 }
1950 }
1951 }
1952
1953 if (!error) {
1954 bzero((caddr_t)fhp, sizeof(nfh));
1955 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
1956 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
1957 if (!error)
1958 error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
1959 }
1960 if (v3) {
1961 if (exclusive_flag && !error &&
1962 bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF))
1963 error = EEXIST;
1964 if (dirp == nd.ni_dvp)
1965 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
1966 else {
1967 /* Drop the other locks to avoid deadlock. */
1968 if (nd.ni_dvp) {
1969 if (nd.ni_dvp == nd.ni_vp)
1970 vrele(nd.ni_dvp);
1971 else
1972 vput(nd.ni_dvp);
1973 }
1974 if (nd.ni_vp)
1975 vput(nd.ni_vp);
1976 nd.ni_dvp = NULL;
1977 nd.ni_vp = NULL;
1978
1979 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
1980 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
1981 VOP_UNLOCK(dirp, 0, td);
1982 }
1983 }
1984 ereply:
1985 NFSD_UNLOCK_ASSERT();
1986 mtx_unlock(&Giant); /* VFS */
1987 NFSD_LOCK();
1988 ereply_locked:
1989 NFSD_LOCK_ASSERT();
1990 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3));
1991 if (v3) {
1992 if (!error) {
1993 nfsm_srvpostop_fh(fhp);
1994 nfsm_srvpostop_attr(0, vap);
1995 }
1996 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
1997 } else if (!error) {
1998 /* v2 non-error case. */
1999 nfsm_srvfhtom(fhp, v3);
2000 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
2001 nfsm_srvfillattr(vap, fp);
2002 }
2003 error = 0;
2004
2005 nfsmout:
2006 NFSD_LOCK_ASSERT();
2007 NFSD_UNLOCK();
2008 mtx_lock(&Giant); /* VFS */
2009 if (nd.ni_dvp) {
2010 if (nd.ni_dvp == nd.ni_vp)
2011 vrele(nd.ni_dvp);
2012 else
2013 vput(nd.ni_dvp);
2014 }
2015 if (nd.ni_vp)
2016 vput(nd.ni_vp);
2017 if (nd.ni_startdir) {
2018 vrele(nd.ni_startdir);
2019 nd.ni_startdir = NULL;
2020 }
2021 if (dirp)
2022 vrele(dirp);
2023 NDFREE(&nd, NDF_ONLY_PNBUF);
2024 vn_finished_write(mp);
2025 mtx_unlock(&Giant); /* VFS */
2026 NFSD_LOCK();
2027 return (error);
2028 }
2029
2030 /*
2031 * nfs v3 mknod service
2032 */
2033 int
2034 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2035 struct thread *td, struct mbuf **mrq)
2036 {
2037 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2038 struct sockaddr *nam = nfsd->nd_nam;
2039 caddr_t dpos = nfsd->nd_dpos;
2040 struct ucred *cred = nfsd->nd_cr;
2041 struct vattr va, dirfor, diraft;
2042 struct vattr *vap = &va;
2043 u_int32_t *tl;
2044 struct nameidata nd;
2045 caddr_t bpos;
2046 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2047 u_int32_t major, minor;
2048 enum vtype vtyp;
2049 struct mbuf *mb, *mreq;
2050 struct vnode *vp, *dirp = NULL;
2051 nfsfh_t nfh;
2052 fhandle_t *fhp;
2053 struct mount *mp = NULL;
2054 int v3 = (nfsd->nd_flag & ND_NFSV3);
2055
2056 NFSD_LOCK_ASSERT();
2057
2058 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2059 if (!v3)
2060 panic("nfsrv_mknod: v3 proc called on a v2 connection");
2061 ndclear(&nd);
2062
2063 fhp = &nfh.fh_generic;
2064 nfsm_srvmtofh(fhp);
2065 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2066 error = ESTALE;
2067 goto ereply;
2068 }
2069 NFSD_UNLOCK();
2070 mtx_lock(&Giant); /* VFS */
2071 (void) vn_start_write(NULL, &mp, V_WAIT);
2072 vfs_rel(mp); /* The write holds a ref. */
2073 mtx_unlock(&Giant); /* VFS */
2074 NFSD_LOCK();
2075 nfsm_srvnamesiz(len);
2076
2077 nd.ni_cnd.cn_cred = cred;
2078 nd.ni_cnd.cn_nameiop = CREATE;
2079 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | SAVESTART;
2080
2081 /*
2082 * Handle nfs_namei() call. If an error occurs, the nd structure
2083 * is not valid. However, nfsm_*() routines may still jump to
2084 * nfsmout.
2085 */
2086
2087 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2088 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2089 if (error) {
2090 nfsm_reply(NFSX_WCCDATA(1));
2091 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2092 error = 0;
2093 goto nfsmout;
2094 }
2095 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
2096 vtyp = nfsv3tov_type(*tl);
2097 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) {
2098 NFSD_UNLOCK();
2099 mtx_lock(&Giant); /* VFS */
2100 error = NFSERR_BADTYPE;
2101 goto out;
2102 }
2103 VATTR_NULL(vap);
2104 nfsm_srvsattr(vap);
2105 if (vtyp == VCHR || vtyp == VBLK) {
2106 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
2107 major = fxdr_unsigned(u_int32_t, *tl++);
2108 minor = fxdr_unsigned(u_int32_t, *tl);
2109 vap->va_rdev = makedev(major, minor);
2110 }
2111
2112 /*
2113 * Iff doesn't exist, create it.
2114 */
2115 if (nd.ni_vp) {
2116 NFSD_UNLOCK();
2117 mtx_lock(&Giant); /* VFS */
2118 error = EEXIST;
2119 goto out;
2120 }
2121 vap->va_type = vtyp;
2122 if (vap->va_mode == (mode_t)VNOVAL)
2123 vap->va_mode = 0;
2124 NFSD_UNLOCK();
2125 mtx_lock(&Giant); /* VFS */
2126 if (vtyp == VSOCK) {
2127 vrele(nd.ni_startdir);
2128 nd.ni_startdir = NULL;
2129 error = VOP_CREATE(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2130 if (error)
2131 NDFREE(&nd, NDF_ONLY_PNBUF);
2132 } else {
2133 if (vtyp != VFIFO && (error = suser_cred(cred, 0)))
2134 goto out;
2135 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
2136 if (error) {
2137 NDFREE(&nd, NDF_ONLY_PNBUF);
2138 goto out;
2139 }
2140 vput(nd.ni_vp);
2141 nd.ni_vp = NULL;
2142
2143 /*
2144 * Release dvp prior to lookup
2145 */
2146 vput(nd.ni_dvp);
2147 nd.ni_dvp = NULL;
2148
2149 nd.ni_cnd.cn_nameiop = LOOKUP;
2150 nd.ni_cnd.cn_flags &= ~(LOCKPARENT);
2151 nd.ni_cnd.cn_thread = td;
2152 nd.ni_cnd.cn_cred = td->td_ucred;
2153
2154 error = lookup(&nd);
2155 nd.ni_dvp = NULL;
2156 if (nd.ni_cnd.cn_flags & GIANTHELD) {
2157 mtx_unlock(&Giant);
2158 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2159 }
2160
2161 if (error)
2162 goto out;
2163 if (nd.ni_cnd.cn_flags & ISSYMLINK)
2164 error = EINVAL;
2165 }
2166
2167 /*
2168 * send response, cleanup, return.
2169 */
2170 out:
2171 NFSD_UNLOCK_ASSERT();
2172 vp = nd.ni_vp;
2173 if (!error) {
2174 bzero((caddr_t)fhp, sizeof(nfh));
2175 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid;
2176 error = VFS_VPTOFH(vp, &fhp->fh_fid);
2177 if (!error)
2178 error = VOP_GETATTR(vp, vap, cred, td);
2179 }
2180 if (nd.ni_dvp) {
2181 if (nd.ni_dvp == nd.ni_vp)
2182 vrele(nd.ni_dvp);
2183 else
2184 vput(nd.ni_dvp);
2185 nd.ni_dvp = NULL;
2186 }
2187 if (vp) {
2188 vput(vp);
2189 vp = NULL;
2190 nd.ni_vp = NULL;
2191 }
2192 if (nd.ni_startdir) {
2193 vrele(nd.ni_startdir);
2194 nd.ni_startdir = NULL;
2195 }
2196 NDFREE(&nd, NDF_ONLY_PNBUF);
2197 if (dirp) {
2198 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2199 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2200 VOP_UNLOCK(dirp, 0, td);
2201 }
2202 mtx_unlock(&Giant); /* VFS */
2203 NFSD_LOCK();
2204 ereply:
2205 NFSD_LOCK_ASSERT();
2206 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1));
2207 if (v3) {
2208 if (!error) {
2209 nfsm_srvpostop_fh(fhp);
2210 nfsm_srvpostop_attr(0, vap);
2211 }
2212 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2213 }
2214 NFSD_UNLOCK();
2215 mtx_lock(&Giant); /* VFS */
2216 vn_finished_write(mp);
2217 mtx_unlock(&Giant); /* VFS */
2218 NFSD_LOCK();
2219 return (0);
2220 nfsmout:
2221 NFSD_LOCK_ASSERT();
2222 NFSD_UNLOCK();
2223 mtx_lock(&Giant); /* VFS */
2224 if (nd.ni_dvp) {
2225 if (nd.ni_dvp == nd.ni_vp)
2226 vrele(nd.ni_dvp);
2227 else
2228 vput(nd.ni_dvp);
2229 }
2230 if (nd.ni_vp)
2231 vput(nd.ni_vp);
2232 if (dirp)
2233 vrele(dirp);
2234 if (nd.ni_startdir)
2235 vrele(nd.ni_startdir);
2236 NDFREE(&nd, NDF_ONLY_PNBUF);
2237 vn_finished_write(mp);
2238 mtx_unlock(&Giant); /* VFS */
2239 NFSD_LOCK();
2240 return (error);
2241 }
2242
2243 /*
2244 * nfs remove service
2245 */
2246 int
2247 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2248 struct thread *td, struct mbuf **mrq)
2249 {
2250 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2251 struct sockaddr *nam = nfsd->nd_nam;
2252 caddr_t dpos = nfsd->nd_dpos;
2253 struct ucred *cred = nfsd->nd_cr;
2254 struct nameidata nd;
2255 caddr_t bpos;
2256 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2257 int v3 = (nfsd->nd_flag & ND_NFSV3);
2258 struct mbuf *mb, *mreq;
2259 struct vnode *dirp;
2260 struct vattr dirfor, diraft;
2261 nfsfh_t nfh;
2262 fhandle_t *fhp;
2263 struct mount *mp = NULL;
2264
2265 NFSD_LOCK_ASSERT();
2266
2267 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2268 ndclear(&nd);
2269
2270 fhp = &nfh.fh_generic;
2271 nfsm_srvmtofh(fhp);
2272 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2273 error = ESTALE;
2274 goto ereply;
2275 }
2276 NFSD_UNLOCK();
2277 mtx_lock(&Giant); /* VFS */
2278 (void) vn_start_write(NULL, &mp, V_WAIT);
2279 vfs_rel(mp); /* The write holds a ref. */
2280 mtx_unlock(&Giant); /* VFS */
2281 NFSD_LOCK();
2282 nfsm_srvnamesiz(len);
2283
2284 nd.ni_cnd.cn_cred = cred;
2285 nd.ni_cnd.cn_nameiop = DELETE;
2286 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
2287 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2288 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2289 NFSD_UNLOCK();
2290 mtx_lock(&Giant); /* VFS */
2291 if (dirp && !v3) {
2292 vrele(dirp);
2293 dirp = NULL;
2294 }
2295 if (error == 0) {
2296 if (nd.ni_vp->v_type == VDIR) {
2297 error = EPERM; /* POSIX */
2298 goto out;
2299 }
2300 /*
2301 * The root of a mounted filesystem cannot be deleted.
2302 */
2303 if (nd.ni_vp->v_vflag & VV_ROOT) {
2304 error = EBUSY;
2305 goto out;
2306 }
2307 out:
2308 NFSD_UNLOCK_ASSERT();
2309 if (!error) {
2310 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
2311 NDFREE(&nd, NDF_ONLY_PNBUF);
2312 }
2313 }
2314 if (dirp && v3) {
2315 if (dirp == nd.ni_dvp)
2316 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2317 else {
2318 /* Drop the other locks to avoid deadlock. */
2319 if (nd.ni_dvp) {
2320 if (nd.ni_dvp == nd.ni_vp)
2321 vrele(nd.ni_dvp);
2322 else
2323 vput(nd.ni_dvp);
2324 }
2325 if (nd.ni_vp)
2326 vput(nd.ni_vp);
2327 nd.ni_dvp = NULL;
2328 nd.ni_vp = NULL;
2329
2330 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2331 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2332 VOP_UNLOCK(dirp, 0, td);
2333 }
2334 vrele(dirp);
2335 dirp = NULL;
2336 }
2337 mtx_unlock(&Giant); /* VFS */
2338 NFSD_LOCK();
2339 ereply:
2340 NFSD_LOCK_ASSERT();
2341 nfsm_reply(NFSX_WCCDATA(v3));
2342 if (v3)
2343 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2344 error = 0;
2345 nfsmout:
2346 NFSD_LOCK_ASSERT();
2347 NFSD_UNLOCK();
2348 mtx_lock(&Giant); /* VFS */
2349 NDFREE(&nd, NDF_ONLY_PNBUF);
2350 if (nd.ni_dvp) {
2351 if (nd.ni_dvp == nd.ni_vp)
2352 vrele(nd.ni_dvp);
2353 else
2354 vput(nd.ni_dvp);
2355 }
2356 if (nd.ni_vp)
2357 vput(nd.ni_vp);
2358 vn_finished_write(mp);
2359 mtx_unlock(&Giant); /* VFS */
2360 NFSD_LOCK();
2361 return(error);
2362 }
2363
2364 /*
2365 * nfs rename service
2366 */
2367 int
2368 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2369 struct thread *td, struct mbuf **mrq)
2370 {
2371 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2372 struct sockaddr *nam = nfsd->nd_nam;
2373 caddr_t dpos = nfsd->nd_dpos;
2374 struct ucred *cred = nfsd->nd_cr;
2375 caddr_t bpos;
2376 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1;
2377 int tdirfor_ret = 1, tdiraft_ret = 1;
2378 int v3 = (nfsd->nd_flag & ND_NFSV3);
2379 struct mbuf *mb, *mreq;
2380 struct nameidata fromnd, tond;
2381 struct vnode *fvp, *tvp, *tdvp, *fdirp = NULL;
2382 struct vnode *tdirp = NULL;
2383 struct vattr fdirfor, fdiraft, tdirfor, tdiraft;
2384 nfsfh_t fnfh, tnfh;
2385 fhandle_t *ffhp, *tfhp;
2386 uid_t saved_uid;
2387 struct mount *mp = NULL;
2388
2389 NFSD_LOCK_ASSERT();
2390
2391 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2392 #ifndef nolint
2393 fvp = NULL;
2394 #endif
2395 ffhp = &fnfh.fh_generic;
2396 tfhp = &tnfh.fh_generic;
2397
2398 /*
2399 * Clear fields incase goto nfsmout occurs from macro.
2400 */
2401
2402 ndclear(&fromnd);
2403 ndclear(&tond);
2404
2405 nfsm_srvmtofh(ffhp);
2406 if ((mp = vfs_getvfs(&ffhp->fh_fsid)) == NULL) {
2407 error = ESTALE;
2408 goto out1;
2409 }
2410 NFSD_UNLOCK();
2411 mtx_lock(&Giant);
2412 (void) vn_start_write(NULL, &mp, V_WAIT);
2413 vfs_rel(mp); /* The write holds a ref. */
2414 mtx_unlock(&Giant);
2415 NFSD_LOCK();
2416 nfsm_srvnamesiz(len);
2417 /*
2418 * Remember our original uid so that we can reset cr_uid before
2419 * the second nfs_namei() call, in case it is remapped.
2420 */
2421 saved_uid = cred->cr_uid;
2422 fromnd.ni_cnd.cn_cred = cred;
2423 fromnd.ni_cnd.cn_nameiop = DELETE;
2424 fromnd.ni_cnd.cn_flags = WANTPARENT | SAVESTART;
2425 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md,
2426 &dpos, &fdirp, v3, &fdirfor, &fdirfor_ret, td, FALSE);
2427 if (fdirp && !v3) {
2428 NFSD_UNLOCK();
2429 mtx_lock(&Giant); /* VFS */
2430 vrele(fdirp);
2431 mtx_unlock(&Giant); /* VFS */
2432 NFSD_LOCK();
2433 fdirp = NULL;
2434 }
2435 if (error) {
2436 nfsm_reply(2 * NFSX_WCCDATA(v3));
2437 if (v3) {
2438 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2439 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2440 }
2441 error = 0;
2442 goto nfsmout;
2443 }
2444 fvp = fromnd.ni_vp;
2445 nfsm_srvmtofh(tfhp);
2446 nfsm_srvnamesiz(len2);
2447 cred->cr_uid = saved_uid;
2448 tond.ni_cnd.cn_cred = cred;
2449 tond.ni_cnd.cn_nameiop = RENAME;
2450 tond.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART;
2451 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md,
2452 &dpos, &tdirp, v3, &tdirfor, &tdirfor_ret, td, FALSE);
2453 NFSD_UNLOCK();
2454 mtx_lock(&Giant); /* VFS */
2455 if (tdirp && !v3) {
2456 vrele(tdirp);
2457 tdirp = NULL;
2458 }
2459 if (error) {
2460 mtx_unlock(&Giant); /* VFS */
2461 NFSD_LOCK();
2462 goto out1;
2463 }
2464
2465 tdvp = tond.ni_dvp;
2466 tvp = tond.ni_vp;
2467 if (tvp != NULL) {
2468 if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
2469 if (v3)
2470 error = EEXIST;
2471 else
2472 error = EISDIR;
2473 goto out;
2474 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
2475 if (v3)
2476 error = EEXIST;
2477 else
2478 error = ENOTDIR;
2479 goto out;
2480 }
2481 if (tvp->v_type == VDIR && tvp->v_mountedhere) {
2482 if (v3)
2483 error = EXDEV;
2484 else
2485 error = ENOTEMPTY;
2486 goto out;
2487 }
2488 }
2489 if (fvp->v_type == VDIR && fvp->v_mountedhere) {
2490 if (v3)
2491 error = EXDEV;
2492 else
2493 error = ENOTEMPTY;
2494 goto out;
2495 }
2496 if (fvp->v_mount != tdvp->v_mount) {
2497 if (v3)
2498 error = EXDEV;
2499 else
2500 error = ENOTEMPTY;
2501 goto out;
2502 }
2503 if (fvp == tdvp) {
2504 if (v3)
2505 error = EINVAL;
2506 else
2507 error = ENOTEMPTY;
2508 }
2509 /*
2510 * If source is the same as the destination (that is the
2511 * same vnode with the same name in the same directory),
2512 * then there is nothing to do.
2513 */
2514 if (fvp == tvp && fromnd.ni_dvp == tdvp &&
2515 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
2516 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr,
2517 fromnd.ni_cnd.cn_namelen))
2518 error = -1;
2519 out:
2520 NFSD_UNLOCK_ASSERT();
2521 if (!error) {
2522 /*
2523 * The VOP_RENAME function releases all vnode references &
2524 * locks prior to returning so we need to clear the pointers
2525 * to bypass cleanup code later on.
2526 */
2527 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
2528 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
2529 fromnd.ni_dvp = NULL;
2530 fromnd.ni_vp = NULL;
2531 tond.ni_dvp = NULL;
2532 tond.ni_vp = NULL;
2533 if (error) {
2534 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2535 NDFREE(&tond, NDF_ONLY_PNBUF);
2536 }
2537 } else {
2538 if (error == -1)
2539 error = 0;
2540 }
2541 /* fall through */
2542
2543 mtx_unlock(&Giant); /* VFS */
2544 NFSD_LOCK();
2545 out1:
2546 NFSD_LOCK_ASSERT();
2547 nfsm_reply(2 * NFSX_WCCDATA(v3));
2548 if (v3) {
2549 /* Release existing locks to prevent deadlock. */
2550 NFSD_UNLOCK();
2551 mtx_lock(&Giant); /* VFS */
2552 if (tond.ni_dvp) {
2553 if (tond.ni_dvp == tond.ni_vp)
2554 vrele(tond.ni_dvp);
2555 else
2556 vput(tond.ni_dvp);
2557 }
2558 if (tond.ni_vp)
2559 vput(tond.ni_vp);
2560 tond.ni_dvp = NULL;
2561 tond.ni_vp = NULL;
2562
2563 if (fdirp) {
2564 vn_lock(fdirp, LK_EXCLUSIVE | LK_RETRY, td);
2565 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, cred, td);
2566 VOP_UNLOCK(fdirp, 0, td);
2567 }
2568 if (tdirp) {
2569 vn_lock(tdirp, LK_EXCLUSIVE | LK_RETRY, td);
2570 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, cred, td);
2571 VOP_UNLOCK(tdirp, 0, td);
2572 }
2573 mtx_unlock(&Giant); /* VFS */
2574 NFSD_LOCK();
2575 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft);
2576 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft);
2577 }
2578 error = 0;
2579 /* fall through */
2580
2581 nfsmout:
2582 /*
2583 * Clear out tond related fields
2584 */
2585 NFSD_LOCK_ASSERT();
2586 NFSD_UNLOCK();
2587 mtx_lock(&Giant); /* VFS */
2588 if (tond.ni_dvp) {
2589 if (tond.ni_dvp == tond.ni_vp)
2590 vrele(tond.ni_dvp);
2591 else
2592 vput(tond.ni_dvp);
2593 }
2594 if (tond.ni_vp)
2595 vput(tond.ni_vp);
2596 if (tdirp)
2597 vrele(tdirp);
2598 if (tond.ni_startdir)
2599 vrele(tond.ni_startdir);
2600 NDFREE(&tond, NDF_ONLY_PNBUF);
2601 /*
2602 * Clear out fromnd related fields
2603 */
2604 if (fdirp)
2605 vrele(fdirp);
2606 if (fromnd.ni_startdir)
2607 vrele(fromnd.ni_startdir);
2608 NDFREE(&fromnd, NDF_ONLY_PNBUF);
2609 if (fromnd.ni_dvp)
2610 vrele(fromnd.ni_dvp);
2611 if (fromnd.ni_vp)
2612 vrele(fromnd.ni_vp);
2613
2614 vn_finished_write(mp);
2615 mtx_unlock(&Giant); /* VFS */
2616 NFSD_LOCK();
2617 return (error);
2618 }
2619
2620 /*
2621 * nfs link service
2622 */
2623 int
2624 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2625 struct thread *td, struct mbuf **mrq)
2626 {
2627 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2628 struct sockaddr *nam = nfsd->nd_nam;
2629 caddr_t dpos = nfsd->nd_dpos;
2630 struct ucred *cred = nfsd->nd_cr;
2631 struct nameidata nd;
2632 caddr_t bpos;
2633 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1;
2634 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3);
2635 struct mbuf *mb, *mreq;
2636 struct vnode *vp = NULL, *xp, *dirp = NULL;
2637 struct vattr dirfor, diraft, at;
2638 nfsfh_t nfh, dnfh;
2639 fhandle_t *fhp, *dfhp;
2640 struct mount *mp = NULL;
2641
2642 NFSD_LOCK_ASSERT();
2643
2644 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2645 ndclear(&nd);
2646
2647 fhp = &nfh.fh_generic;
2648 dfhp = &dnfh.fh_generic;
2649 nfsm_srvmtofh(fhp);
2650 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2651 error = ESTALE;
2652 goto ereply;
2653 }
2654 NFSD_UNLOCK();
2655 mtx_lock(&Giant); /* VFS */
2656 (void) vn_start_write(NULL, &mp, V_WAIT);
2657 vfs_rel(mp); /* The write holds a ref. */
2658 mtx_unlock(&Giant); /* VFS */
2659 NFSD_LOCK();
2660 nfsm_srvmtofh(dfhp);
2661 nfsm_srvnamesiz(len);
2662
2663 error = nfsrv_fhtovp(fhp, TRUE, &vp, cred, slp, nam, &rdonly, TRUE);
2664 if (error) {
2665 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2666 if (v3) {
2667 nfsm_srvpostop_attr(getret, &at);
2668 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2669 }
2670 vp = NULL;
2671 error = 0;
2672 goto nfsmout;
2673 }
2674 NFSD_UNLOCK();
2675 mtx_lock(&Giant); /* VFS */
2676 if (v3)
2677 getret = VOP_GETATTR(vp, &at, cred, td);
2678 if (vp->v_type == VDIR) {
2679 error = EPERM; /* POSIX */
2680 goto out1;
2681 }
2682 VOP_UNLOCK(vp, 0, td);
2683 nd.ni_cnd.cn_cred = cred;
2684 nd.ni_cnd.cn_nameiop = CREATE;
2685 nd.ni_cnd.cn_flags = LOCKPARENT;
2686 mtx_unlock(&Giant); /* VFS */
2687 NFSD_LOCK();
2688 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos,
2689 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2690 NFSD_UNLOCK();
2691 mtx_lock(&Giant); /* VFS */
2692 if (dirp && !v3) {
2693 vrele(dirp);
2694 dirp = NULL;
2695 }
2696 if (error) {
2697 vrele(vp);
2698 vp = NULL;
2699 goto out2;
2700 }
2701 xp = nd.ni_vp;
2702 if (xp != NULL) {
2703 error = EEXIST;
2704 vrele(vp);
2705 vp = NULL;
2706 goto out2;
2707 }
2708 xp = nd.ni_dvp;
2709 if (vp->v_mount != xp->v_mount) {
2710 error = EXDEV;
2711 vrele(vp);
2712 vp = NULL;
2713 goto out2;
2714 }
2715 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2716 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
2717 NDFREE(&nd, NDF_ONLY_PNBUF);
2718 /* fall through */
2719
2720 out1:
2721 if (v3)
2722 getret = VOP_GETATTR(vp, &at, cred, td);
2723 out2:
2724 if (dirp) {
2725 if (dirp == nd.ni_dvp)
2726 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2727 else {
2728 /* Release existing locks to prevent deadlock. */
2729 if (nd.ni_dvp) {
2730 if (nd.ni_dvp == nd.ni_vp)
2731 vrele(nd.ni_dvp);
2732 else
2733 vput(nd.ni_dvp);
2734 }
2735 if (nd.ni_vp)
2736 vrele(nd.ni_vp);
2737 nd.ni_dvp = NULL;
2738 nd.ni_vp = NULL;
2739
2740 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2741 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2742 VOP_UNLOCK(dirp, 0, td);
2743 }
2744 }
2745 mtx_unlock(&Giant); /* VFS */
2746 NFSD_LOCK();
2747 ereply:
2748 NFSD_LOCK_ASSERT();
2749 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2750 if (v3) {
2751 nfsm_srvpostop_attr(getret, &at);
2752 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2753 }
2754 error = 0;
2755 /* fall through */
2756
2757 nfsmout:
2758 NFSD_LOCK_ASSERT();
2759 NFSD_UNLOCK();
2760 mtx_lock(&Giant); /* VFS */
2761 NDFREE(&nd, NDF_ONLY_PNBUF);
2762 if (vp)
2763 vput(vp);
2764 if (nd.ni_dvp) {
2765 if (nd.ni_dvp == nd.ni_vp)
2766 vrele(nd.ni_dvp);
2767 else
2768 vput(nd.ni_dvp);
2769 }
2770 if (dirp)
2771 vrele(dirp);
2772 if (nd.ni_vp)
2773 vrele(nd.ni_vp);
2774 vn_finished_write(mp);
2775 mtx_unlock(&Giant); /* VFS */
2776 NFSD_LOCK();
2777 return(error);
2778 }
2779
2780 /*
2781 * nfs symbolic link service
2782 */
2783 int
2784 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2785 struct thread *td, struct mbuf **mrq)
2786 {
2787 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2788 struct sockaddr *nam = nfsd->nd_nam;
2789 caddr_t dpos = nfsd->nd_dpos;
2790 struct ucred *cred = nfsd->nd_cr;
2791 struct vattr va, dirfor, diraft;
2792 struct nameidata nd;
2793 struct vattr *vap = &va;
2794 struct nfsv2_sattr *sp;
2795 char *bpos, *pathcp = NULL;
2796 struct uio io;
2797 struct iovec iv;
2798 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1;
2799 int v3 = (nfsd->nd_flag & ND_NFSV3);
2800 struct mbuf *mb, *mreq;
2801 struct vnode *dirp = NULL;
2802 nfsfh_t nfh;
2803 fhandle_t *fhp;
2804 struct mount *mp = NULL;
2805
2806 NFSD_LOCK_ASSERT();
2807
2808 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
2809 ndclear(&nd);
2810
2811 fhp = &nfh.fh_generic;
2812 nfsm_srvmtofh(fhp);
2813 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
2814 NFSD_UNLOCK();
2815 mtx_lock(&Giant); /* VFS */
2816 error = ESTALE;
2817 goto out;
2818 }
2819 NFSD_UNLOCK();
2820 mtx_lock(&Giant); /* VFS */
2821 (void) vn_start_write(NULL, &mp, V_WAIT);
2822 vfs_rel(mp); /* The write holds a ref. */
2823 mtx_unlock(&Giant); /* VFS */
2824 NFSD_LOCK();
2825 nfsm_srvnamesiz(len);
2826 nd.ni_cnd.cn_cred = cred;
2827 nd.ni_cnd.cn_nameiop = CREATE;
2828 nd.ni_cnd.cn_flags = LOCKPARENT | SAVESTART;
2829 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
2830 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
2831 if (error == 0) {
2832 VATTR_NULL(vap);
2833 if (v3)
2834 nfsm_srvsattr(vap);
2835 nfsm_srvpathsiz(len2);
2836 }
2837 NFSD_UNLOCK();
2838 mtx_lock(&Giant); /* VFS */
2839 if (dirp && !v3) {
2840 vrele(dirp);
2841 dirp = NULL;
2842 }
2843 if (error)
2844 goto out;
2845 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK);
2846 iv.iov_base = pathcp;
2847 iv.iov_len = len2;
2848 io.uio_resid = len2;
2849 io.uio_offset = 0;
2850 io.uio_iov = &iv;
2851 io.uio_iovcnt = 1;
2852 io.uio_segflg = UIO_SYSSPACE;
2853 io.uio_rw = UIO_READ;
2854 io.uio_td = NULL;
2855 nfsm_mtouio(&io, len2);
2856 if (!v3) {
2857 sp = nfsm_dissect_nonblock(struct nfsv2_sattr *, NFSX_V2SATTR);
2858 vap->va_mode = nfstov_mode(sp->sa_mode);
2859 }
2860 *(pathcp + len2) = '\0';
2861 if (nd.ni_vp) {
2862 error = EEXIST;
2863 goto out;
2864 }
2865
2866 /*
2867 * issue symlink op. SAVESTART is set so the underlying path component
2868 * is only freed by the VOP if an error occurs.
2869 */
2870 if (vap->va_mode == (mode_t)VNOVAL)
2871 vap->va_mode = 0;
2872 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap, pathcp);
2873 if (error)
2874 NDFREE(&nd, NDF_ONLY_PNBUF);
2875 else
2876 vput(nd.ni_vp);
2877 nd.ni_vp = NULL;
2878 /*
2879 * releases directory prior to potential lookup op.
2880 */
2881 vput(nd.ni_dvp);
2882 nd.ni_dvp = NULL;
2883
2884 if (error == 0) {
2885 if (v3) {
2886 /*
2887 * Issue lookup. Leave SAVESTART set so we can easily free
2888 * the name buffer later on.
2889 *
2890 * since LOCKPARENT is not set, ni_dvp will be garbage on
2891 * return whether an error occurs or not.
2892 */
2893 nd.ni_cnd.cn_nameiop = LOOKUP;
2894 nd.ni_cnd.cn_flags &= ~(LOCKPARENT | FOLLOW);
2895 nd.ni_cnd.cn_flags |= (NOFOLLOW | LOCKLEAF);
2896 nd.ni_cnd.cn_thread = td;
2897 nd.ni_cnd.cn_cred = cred;
2898
2899 error = lookup(&nd);
2900 nd.ni_dvp = NULL;
2901 if (nd.ni_cnd.cn_flags & GIANTHELD) {
2902 mtx_unlock(&Giant);
2903 nd.ni_cnd.cn_flags &= ~GIANTHELD;
2904 }
2905
2906 if (error == 0) {
2907 bzero((caddr_t)fhp, sizeof(nfh));
2908 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
2909 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
2910 if (!error)
2911 error = VOP_GETATTR(nd.ni_vp, vap, cred,
2912 td);
2913 vput(nd.ni_vp);
2914 nd.ni_vp = NULL;
2915 }
2916 }
2917 }
2918 out:
2919 NFSD_UNLOCK_ASSERT();
2920 /*
2921 * These releases aren't strictly required, does even doing them
2922 * make any sense? XXX can nfsm_reply() block?
2923 */
2924 if (pathcp) {
2925 FREE(pathcp, M_TEMP);
2926 pathcp = NULL;
2927 }
2928 if (dirp) {
2929 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
2930 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
2931 VOP_UNLOCK(dirp, 0, td);
2932 }
2933 if (nd.ni_startdir) {
2934 vrele(nd.ni_startdir);
2935 nd.ni_startdir = NULL;
2936 }
2937 mtx_unlock(&Giant); /* VFS */
2938 NFSD_LOCK();
2939 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
2940 if (v3) {
2941 if (!error) {
2942 nfsm_srvpostop_fh(fhp);
2943 nfsm_srvpostop_attr(0, vap);
2944 }
2945 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
2946 }
2947 error = 0;
2948 /* fall through */
2949
2950 nfsmout:
2951 NFSD_LOCK_ASSERT();
2952 NFSD_UNLOCK();
2953 mtx_lock(&Giant); /* VFS */
2954 NDFREE(&nd, NDF_ONLY_PNBUF);
2955 if (nd.ni_dvp) {
2956 if (nd.ni_dvp == nd.ni_vp)
2957 vrele(nd.ni_dvp);
2958 else
2959 vput(nd.ni_dvp);
2960 }
2961 if (nd.ni_vp)
2962 vrele(nd.ni_vp);
2963 if (nd.ni_startdir)
2964 vrele(nd.ni_startdir);
2965 if (dirp)
2966 vrele(dirp);
2967 if (pathcp)
2968 FREE(pathcp, M_TEMP);
2969
2970 vn_finished_write(mp);
2971 mtx_unlock(&Giant); /* VFS */
2972 NFSD_LOCK();
2973 return (error);
2974 }
2975
2976 /*
2977 * nfs mkdir service
2978 */
2979 int
2980 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
2981 struct thread *td, struct mbuf **mrq)
2982 {
2983 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
2984 struct sockaddr *nam = nfsd->nd_nam;
2985 caddr_t dpos = nfsd->nd_dpos;
2986 struct ucred *cred = nfsd->nd_cr;
2987 struct vattr va, dirfor, diraft;
2988 struct vattr *vap = &va;
2989 struct nfs_fattr *fp;
2990 struct nameidata nd;
2991 u_int32_t *tl;
2992 caddr_t bpos;
2993 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
2994 int v3 = (nfsd->nd_flag & ND_NFSV3);
2995 struct mbuf *mb, *mreq;
2996 struct vnode *dirp = NULL;
2997 int vpexcl = 0;
2998 nfsfh_t nfh;
2999 fhandle_t *fhp;
3000 struct mount *mp = NULL;
3001
3002 NFSD_LOCK_ASSERT();
3003
3004 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3005 ndclear(&nd);
3006
3007 fhp = &nfh.fh_generic;
3008 nfsm_srvmtofh(fhp);
3009 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3010 NFSD_UNLOCK();
3011 mtx_lock(&Giant); /* VFS */
3012 error = ESTALE;
3013 goto out;
3014 }
3015 NFSD_UNLOCK();
3016 mtx_lock(&Giant); /* VFS */
3017 (void) vn_start_write(NULL, &mp, V_WAIT);
3018 vfs_rel(mp); /* The write holds a ref. */
3019 mtx_unlock(&Giant); /* VFS */
3020 NFSD_LOCK();
3021 nfsm_srvnamesiz(len);
3022 nd.ni_cnd.cn_cred = cred;
3023 nd.ni_cnd.cn_nameiop = CREATE;
3024 nd.ni_cnd.cn_flags = LOCKPARENT;
3025
3026 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3027 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3028 if (dirp && !v3) {
3029 NFSD_UNLOCK();
3030 mtx_lock(&Giant); /* VFS */
3031 vrele(dirp);
3032 mtx_unlock(&Giant); /* VFS */
3033 NFSD_LOCK();
3034 dirp = NULL;
3035 }
3036 if (error) {
3037 nfsm_reply(NFSX_WCCDATA(v3));
3038 if (v3)
3039 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3040 error = 0;
3041 goto nfsmout;
3042 }
3043 VATTR_NULL(vap);
3044 if (v3) {
3045 nfsm_srvsattr(vap);
3046 } else {
3047 tl = nfsm_dissect_nonblock(u_int32_t *, NFSX_UNSIGNED);
3048 vap->va_mode = nfstov_mode(*tl++);
3049 }
3050
3051 /*
3052 * At this point nd.ni_dvp is referenced and exclusively locked and
3053 * nd.ni_vp, if it exists, is referenced but not locked.
3054 */
3055
3056 NFSD_UNLOCK();
3057 mtx_lock(&Giant); /* VFS */
3058 vap->va_type = VDIR;
3059 if (nd.ni_vp != NULL) {
3060 NDFREE(&nd, NDF_ONLY_PNBUF);
3061 error = EEXIST;
3062 goto out;
3063 }
3064
3065 /*
3066 * Issue mkdir op. Since SAVESTART is not set, the pathname
3067 * component is freed by the VOP call. This will fill-in
3068 * nd.ni_vp, reference, and exclusively lock it.
3069 */
3070 if (vap->va_mode == (mode_t)VNOVAL)
3071 vap->va_mode = 0;
3072 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, vap);
3073 NDFREE(&nd, NDF_ONLY_PNBUF);
3074 vpexcl = 1;
3075
3076 vput(nd.ni_dvp);
3077 nd.ni_dvp = NULL;
3078
3079 if (!error) {
3080 bzero((caddr_t)fhp, sizeof(nfh));
3081 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid;
3082 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid);
3083 if (!error)
3084 error = VOP_GETATTR(nd.ni_vp, vap, cred, td);
3085 }
3086 out:
3087 NFSD_UNLOCK_ASSERT();
3088 if (dirp) {
3089 if (dirp == nd.ni_dvp) {
3090 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3091 } else {
3092 /* Release existing locks to prevent deadlock. */
3093 if (nd.ni_dvp) {
3094 NDFREE(&nd, NDF_ONLY_PNBUF);
3095 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3096 vrele(nd.ni_dvp);
3097 else
3098 vput(nd.ni_dvp);
3099 }
3100 if (nd.ni_vp) {
3101 if (vpexcl)
3102 vput(nd.ni_vp);
3103 else
3104 vrele(nd.ni_vp);
3105 }
3106 nd.ni_dvp = NULL;
3107 nd.ni_vp = NULL;
3108 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3109 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3110 VOP_UNLOCK(dirp, 0, td);
3111 }
3112 }
3113 mtx_unlock(&Giant); /* VFS */
3114 NFSD_LOCK();
3115 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3));
3116 if (v3) {
3117 if (!error) {
3118 nfsm_srvpostop_fh(fhp);
3119 nfsm_srvpostop_attr(0, vap);
3120 }
3121 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3122 } else if (!error) {
3123 /* v2 non-error case. */
3124 nfsm_srvfhtom(fhp, v3);
3125 fp = nfsm_build(struct nfs_fattr *, NFSX_V2FATTR);
3126 nfsm_srvfillattr(vap, fp);
3127 }
3128 error = 0;
3129 /* fall through */
3130
3131 nfsmout:
3132 NFSD_LOCK_ASSERT();
3133 NFSD_UNLOCK();
3134 mtx_lock(&Giant); /* VFS */
3135 if (nd.ni_dvp) {
3136 NDFREE(&nd, NDF_ONLY_PNBUF);
3137 if (nd.ni_dvp == nd.ni_vp && vpexcl)
3138 vrele(nd.ni_dvp);
3139 else
3140 vput(nd.ni_dvp);
3141 }
3142 if (nd.ni_vp) {
3143 if (vpexcl)
3144 vput(nd.ni_vp);
3145 else
3146 vrele(nd.ni_vp);
3147 }
3148 if (dirp)
3149 vrele(dirp);
3150 vn_finished_write(mp);
3151 mtx_unlock(&Giant); /* VFS */
3152 NFSD_LOCK();
3153 return (error);
3154 }
3155
3156 /*
3157 * nfs rmdir service
3158 */
3159 int
3160 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3161 struct thread *td, struct mbuf **mrq)
3162 {
3163 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3164 struct sockaddr *nam = nfsd->nd_nam;
3165 caddr_t dpos = nfsd->nd_dpos;
3166 struct ucred *cred = nfsd->nd_cr;
3167 caddr_t bpos;
3168 int error = 0, len, dirfor_ret = 1, diraft_ret = 1;
3169 int v3 = (nfsd->nd_flag & ND_NFSV3);
3170 struct mbuf *mb, *mreq;
3171 struct vnode *vp, *dirp = NULL;
3172 struct vattr dirfor, diraft;
3173 nfsfh_t nfh;
3174 fhandle_t *fhp;
3175 struct nameidata nd;
3176 struct mount *mp = NULL;
3177
3178 NFSD_LOCK_ASSERT();
3179
3180 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3181 ndclear(&nd);
3182
3183 fhp = &nfh.fh_generic;
3184 nfsm_srvmtofh(fhp);
3185 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
3186 error = ESTALE;
3187 goto out;
3188 }
3189 NFSD_UNLOCK();
3190 mtx_lock(&Giant); /* VFS */
3191 (void) vn_start_write(NULL, &mp, V_WAIT);
3192 vfs_rel(mp); /* The write holds a ref. */
3193 mtx_unlock(&Giant); /* VFS */
3194 NFSD_LOCK();
3195 nfsm_srvnamesiz(len);
3196 nd.ni_cnd.cn_cred = cred;
3197 nd.ni_cnd.cn_nameiop = DELETE;
3198 nd.ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF;
3199 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos,
3200 &dirp, v3, &dirfor, &dirfor_ret, td, FALSE);
3201 if (dirp && !v3) {
3202 NFSD_UNLOCK();
3203 mtx_lock(&Giant); /* VFS */
3204 vrele(dirp);
3205 mtx_unlock(&Giant); /* VFS */
3206 NFSD_LOCK();
3207 dirp = NULL;
3208 }
3209 if (error) {
3210 nfsm_reply(NFSX_WCCDATA(v3));
3211 if (v3)
3212 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3213 error = 0;
3214 goto nfsmout;
3215 }
3216 vp = nd.ni_vp;
3217 if (vp->v_type != VDIR) {
3218 error = ENOTDIR;
3219 goto out;
3220 }
3221 /*
3222 * No rmdir "." please.
3223 */
3224 if (nd.ni_dvp == vp) {
3225 error = EINVAL;
3226 goto out;
3227 }
3228 /*
3229 * The root of a mounted filesystem cannot be deleted.
3230 */
3231 if (vp->v_vflag & VV_ROOT)
3232 error = EBUSY;
3233 out:
3234 /*
3235 * Issue or abort op. Since SAVESTART is not set, path name
3236 * component is freed by the VOP after either.
3237 */
3238 NFSD_LOCK_ASSERT();
3239 NFSD_UNLOCK();
3240 mtx_lock(&Giant); /* VFS */
3241 if (!error)
3242 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
3243 NDFREE(&nd, NDF_ONLY_PNBUF);
3244
3245 if (dirp) {
3246 if (dirp == nd.ni_dvp)
3247 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3248 else {
3249 /* Release existing locks to prevent deadlock. */
3250 if (nd.ni_dvp) {
3251 if (nd.ni_dvp == nd.ni_vp)
3252 vrele(nd.ni_dvp);
3253 else
3254 vput(nd.ni_dvp);
3255 }
3256 if (nd.ni_vp)
3257 vput(nd.ni_vp);
3258 nd.ni_dvp = NULL;
3259 nd.ni_vp = NULL;
3260 vn_lock(dirp, LK_EXCLUSIVE | LK_RETRY, td);
3261 diraft_ret = VOP_GETATTR(dirp, &diraft, cred, td);
3262 VOP_UNLOCK(dirp, 0, td);
3263 }
3264 }
3265 mtx_unlock(&Giant); /* VFS */
3266 NFSD_LOCK();
3267 nfsm_reply(NFSX_WCCDATA(v3));
3268 error = 0;
3269 if (v3)
3270 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft);
3271 /* fall through */
3272
3273 nfsmout:
3274 NFSD_LOCK_ASSERT();
3275 NFSD_UNLOCK();
3276 mtx_lock(&Giant); /* VFS */
3277 NDFREE(&nd, NDF_ONLY_PNBUF);
3278 if (nd.ni_dvp) {
3279 if (nd.ni_dvp == nd.ni_vp)
3280 vrele(nd.ni_dvp);
3281 else
3282 vput(nd.ni_dvp);
3283 }
3284 if (nd.ni_vp)
3285 vput(nd.ni_vp);
3286 if (dirp)
3287 vrele(dirp);
3288
3289 vn_finished_write(mp);
3290 mtx_unlock(&Giant); /* VFS */
3291 NFSD_LOCK();
3292 return(error);
3293 }
3294
3295 /*
3296 * nfs readdir service
3297 * - mallocs what it thinks is enough to read
3298 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR
3299 * - calls VOP_READDIR()
3300 * - loops around building the reply
3301 * if the output generated exceeds count break out of loop
3302 * The nfsm_clget macro is used here so that the reply will be packed
3303 * tightly in mbuf clusters.
3304 * - it only knows that it has encountered eof when the VOP_READDIR()
3305 * reads nothing
3306 * - as such one readdir rpc will return eof false although you are there
3307 * and then the next will return eof
3308 * - it trims out records with d_fileno == 0
3309 * this doesn't matter for Unix clients, but they might confuse clients
3310 * for other os'.
3311 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less
3312 * than requested, but this may not apply to all filesystems. For
3313 * example, client NFS does not { although it is never remote mounted
3314 * anyhow }
3315 * The alternate call nfsrv_readdirplus() does lookups as well.
3316 * PS: The NFS protocol spec. does not clarify what the "count" byte
3317 * argument is a count of.. just name strings and file id's or the
3318 * entire reply rpc or ...
3319 * I tried just file name and id sizes and it confused the Sun client,
3320 * so I am using the full rpc size now. The "paranoia.." comment refers
3321 * to including the status longwords that are not a part of the dir.
3322 * "entry" structures, but are in the rpc.
3323 */
3324 struct flrep {
3325 nfsuint64 fl_off;
3326 u_int32_t fl_postopok;
3327 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)];
3328 u_int32_t fl_fhok;
3329 u_int32_t fl_fhsize;
3330 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)];
3331 };
3332
3333 int
3334 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3335 struct thread *td, struct mbuf **mrq)
3336 {
3337 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3338 struct sockaddr *nam = nfsd->nd_nam;
3339 caddr_t dpos = nfsd->nd_dpos;
3340 struct ucred *cred = nfsd->nd_cr;
3341 char *bp, *be;
3342 struct mbuf *mp;
3343 struct dirent *dp;
3344 caddr_t cp;
3345 u_int32_t *tl;
3346 caddr_t bpos;
3347 struct mbuf *mb, *mreq;
3348 char *cpos, *cend, *rbuf;
3349 struct vnode *vp = NULL;
3350 struct vattr at;
3351 nfsfh_t nfh;
3352 fhandle_t *fhp;
3353 struct uio io;
3354 struct iovec iv;
3355 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3356 int siz, cnt, fullsiz, eofflag, rdonly, ncookies;
3357 int v3 = (nfsd->nd_flag & ND_NFSV3);
3358 u_quad_t off, toff, verf;
3359 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3360
3361 NFSD_LOCK_ASSERT();
3362
3363 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3364 fhp = &nfh.fh_generic;
3365 nfsm_srvmtofh(fhp);
3366 if (v3) {
3367 tl = nfsm_dissect_nonblock(u_int32_t *, 5 * NFSX_UNSIGNED);
3368 toff = fxdr_hyper(tl);
3369 tl += 2;
3370 verf = fxdr_hyper(tl);
3371 tl += 2;
3372 } else {
3373 tl = nfsm_dissect_nonblock(u_int32_t *, 2 * NFSX_UNSIGNED);
3374 toff = fxdr_unsigned(u_quad_t, *tl++);
3375 verf = 0; /* shut up gcc */
3376 }
3377 off = toff;
3378 cnt = fxdr_unsigned(int, *tl);
3379 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3380 xfer = NFS_SRVMAXDATA(nfsd);
3381 if (cnt > xfer)
3382 cnt = xfer;
3383 if (siz > xfer)
3384 siz = xfer;
3385 fullsiz = siz;
3386 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3387 if (!error && vp->v_type != VDIR) {
3388 error = ENOTDIR;
3389 NFSD_UNLOCK();
3390 mtx_lock(&Giant); /* VFS */
3391 vput(vp);
3392 mtx_unlock(&Giant); /* VFS */
3393 NFSD_LOCK();
3394 vp = NULL;
3395 }
3396 if (error) {
3397 nfsm_reply(NFSX_UNSIGNED);
3398 if (v3)
3399 nfsm_srvpostop_attr(getret, &at);
3400 error = 0;
3401 goto nfsmout;
3402 }
3403
3404 /*
3405 * Obtain lock on vnode for this section of the code
3406 */
3407 NFSD_UNLOCK();
3408 mtx_lock(&Giant); /* VFS */
3409 if (v3) {
3410 error = getret = VOP_GETATTR(vp, &at, cred, td);
3411 #if 0
3412 /*
3413 * XXX This check may be too strict for Solaris 2.5 clients.
3414 */
3415 if (!error && toff && verf && verf != at.va_filerev)
3416 error = NFSERR_BAD_COOKIE;
3417 #endif
3418 }
3419 if (!error)
3420 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3421 if (error) {
3422 vput(vp);
3423 mtx_unlock(&Giant); /* VFS */
3424 NFSD_LOCK();
3425 vp = NULL;
3426 nfsm_reply(NFSX_POSTOPATTR(v3));
3427 if (v3)
3428 nfsm_srvpostop_attr(getret, &at);
3429 error = 0;
3430 goto nfsmout;
3431 }
3432 VOP_UNLOCK(vp, 0, td);
3433
3434 /*
3435 * end section. Allocate rbuf and continue
3436 */
3437 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3438 again:
3439 NFSD_UNLOCK_ASSERT();
3440 iv.iov_base = rbuf;
3441 iv.iov_len = fullsiz;
3442 io.uio_iov = &iv;
3443 io.uio_iovcnt = 1;
3444 io.uio_offset = (off_t)off;
3445 io.uio_resid = fullsiz;
3446 io.uio_segflg = UIO_SYSSPACE;
3447 io.uio_rw = UIO_READ;
3448 io.uio_td = NULL;
3449 eofflag = 0;
3450 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3451 if (cookies) {
3452 free((caddr_t)cookies, M_TEMP);
3453 cookies = NULL;
3454 }
3455 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3456 off = (off_t)io.uio_offset;
3457 if (!cookies && !error)
3458 error = NFSERR_PERM;
3459 if (v3) {
3460 getret = VOP_GETATTR(vp, &at, cred, td);
3461 if (!error)
3462 error = getret;
3463 }
3464 VOP_UNLOCK(vp, 0, td);
3465 if (error) {
3466 vrele(vp);
3467 mtx_unlock(&Giant); /* VFS */
3468 vp = NULL;
3469 free((caddr_t)rbuf, M_TEMP);
3470 if (cookies)
3471 free((caddr_t)cookies, M_TEMP);
3472 NFSD_LOCK();
3473 nfsm_reply(NFSX_POSTOPATTR(v3));
3474 if (v3)
3475 nfsm_srvpostop_attr(getret, &at);
3476 error = 0;
3477 goto nfsmout;
3478 }
3479 if (io.uio_resid) {
3480 siz -= io.uio_resid;
3481
3482 /*
3483 * If nothing read, return eof
3484 * rpc reply
3485 */
3486 if (siz == 0) {
3487 vrele(vp);
3488 mtx_unlock(&Giant); /* VFS */
3489 vp = NULL;
3490 NFSD_LOCK();
3491 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) +
3492 2 * NFSX_UNSIGNED);
3493 if (v3) {
3494 nfsm_srvpostop_attr(getret, &at);
3495 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3496 txdr_hyper(at.va_filerev, tl);
3497 tl += 2;
3498 } else
3499 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3500 *tl++ = nfsrv_nfs_false;
3501 *tl = nfsrv_nfs_true;
3502 FREE((caddr_t)rbuf, M_TEMP);
3503 FREE((caddr_t)cookies, M_TEMP);
3504 error = 0;
3505 goto nfsmout;
3506 }
3507 }
3508
3509 /*
3510 * Check for degenerate cases of nothing useful read.
3511 * If so go try again
3512 */
3513 cpos = rbuf;
3514 cend = rbuf + siz;
3515 dp = (struct dirent *)cpos;
3516 cookiep = cookies;
3517 /*
3518 * For some reason FreeBSD's ufs_readdir() chooses to back the
3519 * directory offset up to a block boundary, so it is necessary to
3520 * skip over the records that precede the requested offset. This
3521 * requires the assumption that file offset cookies monotonically
3522 * increase.
3523 */
3524 while (cpos < cend && ncookies > 0 &&
3525 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3526 ((u_quad_t)(*cookiep)) <= toff)) {
3527 cpos += dp->d_reclen;
3528 dp = (struct dirent *)cpos;
3529 cookiep++;
3530 ncookies--;
3531 }
3532 if (cpos >= cend || ncookies == 0) {
3533 toff = off;
3534 siz = fullsiz;
3535 goto again;
3536 }
3537
3538 mtx_unlock(&Giant); /* VFS */
3539 NFSD_LOCK();
3540 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */
3541 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz);
3542 if (v3) {
3543 nfsm_srvpostop_attr(getret, &at);
3544 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3545 txdr_hyper(at.va_filerev, tl);
3546 }
3547 mp = mb;
3548 bp = bpos;
3549 be = bp + M_TRAILINGSPACE(mp);
3550
3551 /* Loop through the records and build reply */
3552 while (cpos < cend && ncookies > 0) {
3553 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3554 nlen = dp->d_namlen;
3555 rem = nfsm_rndup(nlen) - nlen;
3556 len += (4 * NFSX_UNSIGNED + nlen + rem);
3557 if (v3)
3558 len += 2 * NFSX_UNSIGNED;
3559 if (len > cnt) {
3560 eofflag = 0;
3561 break;
3562 }
3563 /*
3564 * Build the directory record xdr from
3565 * the dirent entry.
3566 */
3567 nfsm_clget;
3568 *tl = nfsrv_nfs_true;
3569 bp += NFSX_UNSIGNED;
3570 if (v3) {
3571 nfsm_clget;
3572 *tl = 0;
3573 bp += NFSX_UNSIGNED;
3574 }
3575 nfsm_clget;
3576 *tl = txdr_unsigned(dp->d_fileno);
3577 bp += NFSX_UNSIGNED;
3578 nfsm_clget;
3579 *tl = txdr_unsigned(nlen);
3580 bp += NFSX_UNSIGNED;
3581
3582 /* And loop around copying the name */
3583 xfer = nlen;
3584 cp = dp->d_name;
3585 while (xfer > 0) {
3586 nfsm_clget;
3587 if ((bp+xfer) > be)
3588 tsiz = be-bp;
3589 else
3590 tsiz = xfer;
3591 bcopy(cp, bp, tsiz);
3592 bp += tsiz;
3593 xfer -= tsiz;
3594 if (xfer > 0)
3595 cp += tsiz;
3596 }
3597 /* And null pad to an int32_t boundary. */
3598 for (i = 0; i < rem; i++)
3599 *bp++ = '\0';
3600 nfsm_clget;
3601
3602 /* Finish off the record */
3603 if (v3) {
3604 *tl = 0;
3605 bp += NFSX_UNSIGNED;
3606 nfsm_clget;
3607 }
3608 *tl = txdr_unsigned(*cookiep);
3609 bp += NFSX_UNSIGNED;
3610 }
3611 cpos += dp->d_reclen;
3612 dp = (struct dirent *)cpos;
3613 cookiep++;
3614 ncookies--;
3615 }
3616 NFSD_UNLOCK();
3617 mtx_lock(&Giant); /* VFS */
3618 vrele(vp);
3619 mtx_unlock(&Giant); /* VFS */
3620 NFSD_LOCK();
3621 vp = NULL;
3622 nfsm_clget;
3623 *tl = nfsrv_nfs_false;
3624 bp += NFSX_UNSIGNED;
3625 nfsm_clget;
3626 if (eofflag)
3627 *tl = nfsrv_nfs_true;
3628 else
3629 *tl = nfsrv_nfs_false;
3630 bp += NFSX_UNSIGNED;
3631 if (mp != mb) {
3632 if (bp < be)
3633 mp->m_len = bp - mtod(mp, caddr_t);
3634 } else
3635 mp->m_len += bp - bpos;
3636 FREE((caddr_t)rbuf, M_TEMP);
3637 FREE((caddr_t)cookies, M_TEMP);
3638
3639 nfsmout:
3640 NFSD_LOCK_ASSERT();
3641 if (vp) {
3642 NFSD_UNLOCK();
3643 mtx_lock(&Giant); /* VFS */
3644 vrele(vp);
3645 mtx_unlock(&Giant); /* VFS */
3646 NFSD_LOCK();
3647 }
3648 return(error);
3649 }
3650
3651 int
3652 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
3653 struct thread *td, struct mbuf **mrq)
3654 {
3655 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
3656 struct sockaddr *nam = nfsd->nd_nam;
3657 caddr_t dpos = nfsd->nd_dpos;
3658 struct ucred *cred = nfsd->nd_cr;
3659 char *bp, *be;
3660 struct mbuf *mp;
3661 struct dirent *dp;
3662 caddr_t cp;
3663 u_int32_t *tl;
3664 caddr_t bpos;
3665 struct mbuf *mb, *mreq;
3666 char *cpos, *cend, *rbuf;
3667 struct vnode *vp = NULL, *nvp;
3668 struct flrep fl;
3669 nfsfh_t nfh;
3670 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh;
3671 struct uio io;
3672 struct iovec iv;
3673 struct vattr va, at, *vap = &va;
3674 struct nfs_fattr *fp;
3675 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1;
3676 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies;
3677 u_quad_t off, toff, verf;
3678 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */
3679 int v3 = (nfsd->nd_flag & ND_NFSV3);
3680
3681 NFSD_LOCK_ASSERT();
3682
3683 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
3684 if (!v3)
3685 panic("nfsrv_readdirplus: v3 proc called on a v2 connection");
3686 fhp = &nfh.fh_generic;
3687 nfsm_srvmtofh(fhp);
3688 tl = nfsm_dissect_nonblock(u_int32_t *, 6 * NFSX_UNSIGNED);
3689 toff = fxdr_hyper(tl);
3690 tl += 2;
3691 verf = fxdr_hyper(tl);
3692 tl += 2;
3693 siz = fxdr_unsigned(int, *tl++);
3694 cnt = fxdr_unsigned(int, *tl);
3695 off = toff;
3696 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1));
3697 xfer = NFS_SRVMAXDATA(nfsd);
3698 if (cnt > xfer)
3699 cnt = xfer;
3700 if (siz > xfer)
3701 siz = xfer;
3702 fullsiz = siz;
3703 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
3704 if (!error && vp->v_type != VDIR) {
3705 error = ENOTDIR;
3706 NFSD_UNLOCK();
3707 mtx_lock(&Giant); /* VFS */
3708 vput(vp);
3709 mtx_unlock(&Giant); /* VFS */
3710 vp = NULL;
3711 NFSD_LOCK();
3712 }
3713 if (error) {
3714 nfsm_reply(NFSX_UNSIGNED);
3715 nfsm_srvpostop_attr(getret, &at);
3716 error = 0;
3717 goto nfsmout;
3718 }
3719 NFSD_UNLOCK();
3720 mtx_lock(&Giant); /* VFS */
3721 error = getret = VOP_GETATTR(vp, &at, cred, td);
3722 #if 0
3723 /*
3724 * XXX This check may be too strict for Solaris 2.5 clients.
3725 */
3726 if (!error && toff && verf && verf != at.va_filerev)
3727 error = NFSERR_BAD_COOKIE;
3728 #endif
3729 if (!error)
3730 error = nfsrv_access_withgiant(vp, VEXEC, cred, rdonly, td, 0);
3731 if (error) {
3732 vput(vp);
3733 mtx_unlock(&Giant); /* VFS */
3734 NFSD_LOCK();
3735 vp = NULL;
3736 nfsm_reply(NFSX_V3POSTOPATTR);
3737 nfsm_srvpostop_attr(getret, &at);
3738 error = 0;
3739 goto nfsmout;
3740 }
3741 VOP_UNLOCK(vp, 0, td);
3742 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK);
3743 again:
3744 NFSD_UNLOCK_ASSERT();
3745 iv.iov_base = rbuf;
3746 iv.iov_len = fullsiz;
3747 io.uio_iov = &iv;
3748 io.uio_iovcnt = 1;
3749 io.uio_offset = (off_t)off;
3750 io.uio_resid = fullsiz;
3751 io.uio_segflg = UIO_SYSSPACE;
3752 io.uio_rw = UIO_READ;
3753 io.uio_td = NULL;
3754 eofflag = 0;
3755 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3756 if (cookies) {
3757 free((caddr_t)cookies, M_TEMP);
3758 cookies = NULL;
3759 }
3760 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies);
3761 off = (u_quad_t)io.uio_offset;
3762 getret = VOP_GETATTR(vp, &at, cred, td);
3763 VOP_UNLOCK(vp, 0, td);
3764 if (!cookies && !error)
3765 error = NFSERR_PERM;
3766 if (!error)
3767 error = getret;
3768 if (error) {
3769 vrele(vp);
3770 mtx_unlock(&Giant); /* VFS */
3771 vp = NULL;
3772 if (cookies)
3773 free((caddr_t)cookies, M_TEMP);
3774 free((caddr_t)rbuf, M_TEMP);
3775 NFSD_LOCK();
3776 nfsm_reply(NFSX_V3POSTOPATTR);
3777 nfsm_srvpostop_attr(getret, &at);
3778 error = 0;
3779 goto nfsmout;
3780 }
3781 if (io.uio_resid) {
3782 siz -= io.uio_resid;
3783
3784 /*
3785 * If nothing read, return eof
3786 * rpc reply
3787 */
3788 if (siz == 0) {
3789 vrele(vp);
3790 mtx_unlock(&Giant); /* VFS */
3791 NFSD_LOCK();
3792 vp = NULL;
3793 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3794 2 * NFSX_UNSIGNED);
3795 nfsm_srvpostop_attr(getret, &at);
3796 tl = nfsm_build(u_int32_t *, 4 * NFSX_UNSIGNED);
3797 txdr_hyper(at.va_filerev, tl);
3798 tl += 2;
3799 *tl++ = nfsrv_nfs_false;
3800 *tl = nfsrv_nfs_true;
3801 FREE((caddr_t)cookies, M_TEMP);
3802 FREE((caddr_t)rbuf, M_TEMP);
3803 error = 0;
3804 goto nfsmout;
3805 }
3806 }
3807
3808 /*
3809 * Check for degenerate cases of nothing useful read.
3810 * If so go try again
3811 */
3812 cpos = rbuf;
3813 cend = rbuf + siz;
3814 dp = (struct dirent *)cpos;
3815 cookiep = cookies;
3816 /*
3817 * For some reason FreeBSD's ufs_readdir() chooses to back the
3818 * directory offset up to a block boundary, so it is necessary to
3819 * skip over the records that precede the requested offset. This
3820 * requires the assumption that file offset cookies monotonically
3821 * increase.
3822 */
3823 while (cpos < cend && ncookies > 0 &&
3824 (dp->d_fileno == 0 || dp->d_type == DT_WHT ||
3825 ((u_quad_t)(*cookiep)) <= toff)) {
3826 cpos += dp->d_reclen;
3827 dp = (struct dirent *)cpos;
3828 cookiep++;
3829 ncookies--;
3830 }
3831 if (cpos >= cend || ncookies == 0) {
3832 toff = off;
3833 siz = fullsiz;
3834 goto again;
3835 }
3836
3837 /*
3838 * Probe one of the directory entries to see if the filesystem
3839 * supports VGET.
3840 */
3841 if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE, &nvp) ==
3842 EOPNOTSUPP) {
3843 error = NFSERR_NOTSUPP;
3844 vrele(vp);
3845 mtx_unlock(&Giant); /* VFS */
3846 vp = NULL;
3847 free((caddr_t)cookies, M_TEMP);
3848 free((caddr_t)rbuf, M_TEMP);
3849 NFSD_LOCK();
3850 nfsm_reply(NFSX_V3POSTOPATTR);
3851 nfsm_srvpostop_attr(getret, &at);
3852 error = 0;
3853 goto nfsmout;
3854 }
3855 vput(nvp);
3856 mtx_unlock(&Giant); /* VFS */
3857 nvp = NULL;
3858
3859 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF +
3860 2 * NFSX_UNSIGNED;
3861 NFSD_LOCK();
3862 nfsm_reply(cnt);
3863 nfsm_srvpostop_attr(getret, &at);
3864 tl = nfsm_build(u_int32_t *, 2 * NFSX_UNSIGNED);
3865 txdr_hyper(at.va_filerev, tl);
3866 mp = mb;
3867 bp = bpos;
3868 be = bp + M_TRAILINGSPACE(mp);
3869
3870 NFSD_UNLOCK();
3871 mtx_lock(&Giant); /* VFS */
3872 /* Loop through the records and build reply */
3873 while (cpos < cend && ncookies > 0) {
3874 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) {
3875 nlen = dp->d_namlen;
3876 rem = nfsm_rndup(nlen)-nlen;
3877
3878 /*
3879 * For readdir_and_lookup get the vnode using
3880 * the file number.
3881 */
3882 if (VFS_VGET(vp->v_mount, dp->d_fileno, LK_EXCLUSIVE,
3883 &nvp))
3884 goto invalid;
3885 bzero((caddr_t)nfhp, NFSX_V3FH);
3886 nfhp->fh_fsid =
3887 nvp->v_mount->mnt_stat.f_fsid;
3888 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) {
3889 vput(nvp);
3890 nvp = NULL;
3891 goto invalid;
3892 }
3893 if (VOP_GETATTR(nvp, vap, cred, td)) {
3894 vput(nvp);
3895 nvp = NULL;
3896 goto invalid;
3897 }
3898 vput(nvp);
3899 nvp = NULL;
3900
3901 /*
3902 * If either the dircount or maxcount will be
3903 * exceeded, get out now. Both of these lengths
3904 * are calculated conservatively, including all
3905 * XDR overheads.
3906 */
3907 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH +
3908 NFSX_V3POSTOPATTR);
3909 dirlen += (6 * NFSX_UNSIGNED + nlen + rem);
3910 if (len > cnt || dirlen > fullsiz) {
3911 eofflag = 0;
3912 break;
3913 }
3914
3915 /*
3916 * Build the directory record xdr from
3917 * the dirent entry.
3918 */
3919 fp = (struct nfs_fattr *)&fl.fl_fattr;
3920 nfsm_srvfillattr(vap, fp);
3921 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH);
3922 fl.fl_fhok = nfsrv_nfs_true;
3923 fl.fl_postopok = nfsrv_nfs_true;
3924 fl.fl_off.nfsuquad[0] = 0;
3925 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep);
3926
3927 nfsm_clget_nolock;
3928 *tl = nfsrv_nfs_true;
3929 bp += NFSX_UNSIGNED;
3930 nfsm_clget_nolock;
3931 *tl = 0;
3932 bp += NFSX_UNSIGNED;
3933 nfsm_clget_nolock;
3934 *tl = txdr_unsigned(dp->d_fileno);
3935 bp += NFSX_UNSIGNED;
3936 nfsm_clget_nolock;
3937 *tl = txdr_unsigned(nlen);
3938 bp += NFSX_UNSIGNED;
3939
3940 /* And loop around copying the name */
3941 xfer = nlen;
3942 cp = dp->d_name;
3943 while (xfer > 0) {
3944 nfsm_clget_nolock;
3945 if ((bp + xfer) > be)
3946 tsiz = be - bp;
3947 else
3948 tsiz = xfer;
3949 bcopy(cp, bp, tsiz);
3950 bp += tsiz;
3951 xfer -= tsiz;
3952 if (xfer > 0)
3953 cp += tsiz;
3954 }
3955 /* And null pad to an int32_t boundary. */
3956 for (i = 0; i < rem; i++)
3957 *bp++ = '\0';
3958
3959 /*
3960 * Now copy the flrep structure out.
3961 */
3962 xfer = sizeof (struct flrep);
3963 cp = (caddr_t)&fl;
3964 while (xfer > 0) {
3965 nfsm_clget_nolock;
3966 if ((bp + xfer) > be)
3967 tsiz = be - bp;
3968 else
3969 tsiz = xfer;
3970 bcopy(cp, bp, tsiz);
3971 bp += tsiz;
3972 xfer -= tsiz;
3973 if (xfer > 0)
3974 cp += tsiz;
3975 }
3976 }
3977 invalid:
3978 NFSD_UNLOCK_ASSERT();
3979 cpos += dp->d_reclen;
3980 dp = (struct dirent *)cpos;
3981 cookiep++;
3982 ncookies--;
3983 }
3984 vrele(vp);
3985 mtx_unlock(&Giant); /* VFS */
3986 vp = NULL;
3987 nfsm_clget_nolock;
3988 *tl = nfsrv_nfs_false;
3989 bp += NFSX_UNSIGNED;
3990 NFSD_LOCK();
3991 nfsm_clget;
3992 if (eofflag)
3993 *tl = nfsrv_nfs_true;
3994 else
3995 *tl = nfsrv_nfs_false;
3996 bp += NFSX_UNSIGNED;
3997 if (mp != mb) {
3998 if (bp < be)
3999 mp->m_len = bp - mtod(mp, caddr_t);
4000 } else
4001 mp->m_len += bp - bpos;
4002 FREE((caddr_t)cookies, M_TEMP);
4003 FREE((caddr_t)rbuf, M_TEMP);
4004 nfsmout:
4005 NFSD_LOCK_ASSERT();
4006 if (vp) {
4007 NFSD_UNLOCK();
4008 mtx_lock(&Giant); /* VFS */
4009 vrele(vp);
4010 mtx_unlock(&Giant); /* VFS */
4011 NFSD_LOCK();
4012 }
4013 return(error);
4014 }
4015
4016 /*
4017 * nfs commit service
4018 */
4019 int
4020 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4021 struct thread *td, struct mbuf **mrq)
4022 {
4023 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4024 struct sockaddr *nam = nfsd->nd_nam;
4025 caddr_t dpos = nfsd->nd_dpos;
4026 struct ucred *cred = nfsd->nd_cr;
4027 struct vattr bfor, aft;
4028 struct vnode *vp = NULL;
4029 nfsfh_t nfh;
4030 fhandle_t *fhp;
4031 u_int32_t *tl;
4032 caddr_t bpos;
4033 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt;
4034 struct mbuf *mb, *mreq;
4035 u_quad_t off;
4036 struct mount *mp = NULL;
4037 int v3 = (nfsd->nd_flag & ND_NFSV3);
4038
4039 NFSD_LOCK_ASSERT();
4040
4041 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4042 if (!v3)
4043 panic("nfsrv_commit: v3 proc called on a v2 connection");
4044 fhp = &nfh.fh_generic;
4045 nfsm_srvmtofh(fhp);
4046 if ((mp = vfs_getvfs(&fhp->fh_fsid)) == NULL) {
4047 error = ESTALE;
4048 goto ereply;
4049 }
4050 NFSD_UNLOCK();
4051 mtx_lock(&Giant); /* VFS */
4052 (void) vn_start_write(NULL, &mp, V_WAIT);
4053 vfs_rel(mp); /* The write holds a ref. */
4054 mtx_unlock(&Giant); /* VFS */
4055 NFSD_LOCK();
4056 tl = nfsm_dissect_nonblock(u_int32_t *, 3 * NFSX_UNSIGNED);
4057
4058 /*
4059 * XXX At this time VOP_FSYNC() does not accept offset and byte
4060 * count parameters, so these arguments are useless (someday maybe).
4061 */
4062 off = fxdr_hyper(tl);
4063 tl += 2;
4064 cnt = fxdr_unsigned(int, *tl);
4065 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4066 if (error) {
4067 nfsm_reply(2 * NFSX_UNSIGNED);
4068 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4069 error = 0;
4070 goto nfsmout;
4071 }
4072 NFSD_UNLOCK();
4073 mtx_lock(&Giant); /* VFS */
4074 for_ret = VOP_GETATTR(vp, &bfor, cred, td);
4075
4076 if (cnt > MAX_COMMIT_COUNT) {
4077 /*
4078 * Give up and do the whole thing
4079 */
4080 if (vp->v_object &&
4081 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4082 VM_OBJECT_LOCK(vp->v_object);
4083 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC);
4084 VM_OBJECT_UNLOCK(vp->v_object);
4085 }
4086 error = VOP_FSYNC(vp, MNT_WAIT, td);
4087 } else {
4088 /*
4089 * Locate and synchronously write any buffers that fall
4090 * into the requested range. Note: we are assuming that
4091 * f_iosize is a power of 2.
4092 */
4093 int iosize = vp->v_mount->mnt_stat.f_iosize;
4094 int iomask = iosize - 1;
4095 int s;
4096 daddr_t lblkno;
4097
4098 /*
4099 * Align to iosize boundry, super-align to page boundry.
4100 */
4101 if (off & iomask) {
4102 cnt += off & iomask;
4103 off &= ~(u_quad_t)iomask;
4104 }
4105 if (off & PAGE_MASK) {
4106 cnt += off & PAGE_MASK;
4107 off &= ~(u_quad_t)PAGE_MASK;
4108 }
4109 lblkno = off / iosize;
4110
4111 if (vp->v_object &&
4112 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) {
4113 VM_OBJECT_LOCK(vp->v_object);
4114 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC);
4115 VM_OBJECT_UNLOCK(vp->v_object);
4116 }
4117
4118 s = splbio();
4119 VI_LOCK(vp);
4120 while (cnt > 0) {
4121 struct buf *bp;
4122
4123 /*
4124 * If we have a buffer and it is marked B_DELWRI we
4125 * have to lock and write it. Otherwise the prior
4126 * write is assumed to have already been committed.
4127 *
4128 * gbincore() can return invalid buffers now so we
4129 * have to check that bit as well (though B_DELWRI
4130 * should not be set if B_INVAL is set there could be
4131 * a race here since we haven't locked the buffer).
4132 */
4133 if ((bp = gbincore(&vp->v_bufobj, lblkno)) != NULL) {
4134 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL |
4135 LK_INTERLOCK, VI_MTX(vp)) == ENOLCK) {
4136 VI_LOCK(vp);
4137 continue; /* retry */
4138 }
4139 if ((bp->b_flags & (B_DELWRI|B_INVAL)) ==
4140 B_DELWRI) {
4141 bremfree(bp);
4142 bp->b_flags &= ~B_ASYNC;
4143 bwrite(bp);
4144 ++nfs_commit_miss;
4145 } else
4146 BUF_UNLOCK(bp);
4147 VI_LOCK(vp);
4148 }
4149 ++nfs_commit_blks;
4150 if (cnt < iosize)
4151 break;
4152 cnt -= iosize;
4153 ++lblkno;
4154 }
4155 VI_UNLOCK(vp);
4156 splx(s);
4157 }
4158
4159 aft_ret = VOP_GETATTR(vp, &aft, cred, td);
4160 vput(vp);
4161 mtx_unlock(&Giant); /* VFS */
4162 vp = NULL;
4163 NFSD_LOCK();
4164 ereply:
4165 NFSD_LOCK_ASSERT();
4166 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF);
4167 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft);
4168 if (!error) {
4169 tl = nfsm_build(u_int32_t *, NFSX_V3WRITEVERF);
4170 if (nfsver.tv_sec == 0)
4171 nfsver = boottime;
4172 *tl++ = txdr_unsigned(nfsver.tv_sec);
4173 *tl = txdr_unsigned(nfsver.tv_usec);
4174 } else {
4175 error = 0;
4176 }
4177 nfsmout:
4178 NFSD_LOCK_ASSERT();
4179 NFSD_UNLOCK();
4180 mtx_lock(&Giant); /* VFS */
4181 if (vp)
4182 vput(vp);
4183 vn_finished_write(mp);
4184 mtx_unlock(&Giant); /* VFS */
4185 NFSD_LOCK();
4186 return(error);
4187 }
4188
4189 /*
4190 * nfs statfs service
4191 */
4192 int
4193 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4194 struct thread *td, struct mbuf **mrq)
4195 {
4196 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4197 struct sockaddr *nam = nfsd->nd_nam;
4198 caddr_t dpos = nfsd->nd_dpos;
4199 struct ucred *cred = nfsd->nd_cr;
4200 struct statfs *sf;
4201 struct nfs_statfs *sfp;
4202 caddr_t bpos;
4203 int error = 0, rdonly, getret = 1;
4204 int v3 = (nfsd->nd_flag & ND_NFSV3);
4205 struct mbuf *mb, *mreq;
4206 struct vnode *vp = NULL;
4207 struct vattr at;
4208 nfsfh_t nfh;
4209 fhandle_t *fhp;
4210 struct statfs statfs;
4211 u_quad_t tval;
4212
4213 NFSD_LOCK_ASSERT();
4214
4215 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4216 fhp = &nfh.fh_generic;
4217 nfsm_srvmtofh(fhp);
4218 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4219 if (error) {
4220 nfsm_reply(NFSX_UNSIGNED);
4221 if (v3)
4222 nfsm_srvpostop_attr(getret, &at);
4223 error = 0;
4224 goto nfsmout;
4225 }
4226 sf = &statfs;
4227 NFSD_UNLOCK();
4228 mtx_lock(&Giant); /* VFS */
4229 error = VFS_STATFS(vp->v_mount, sf, td);
4230 getret = VOP_GETATTR(vp, &at, cred, td);
4231 vput(vp);
4232 mtx_unlock(&Giant); /* VFS */
4233 vp = NULL;
4234 NFSD_LOCK();
4235 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3));
4236 if (v3)
4237 nfsm_srvpostop_attr(getret, &at);
4238 if (error) {
4239 error = 0;
4240 goto nfsmout;
4241 }
4242 sfp = nfsm_build(struct nfs_statfs *, NFSX_STATFS(v3));
4243 if (v3) {
4244 tval = (u_quad_t)sf->f_blocks;
4245 tval *= (u_quad_t)sf->f_bsize;
4246 txdr_hyper(tval, &sfp->sf_tbytes);
4247 tval = (u_quad_t)sf->f_bfree;
4248 tval *= (u_quad_t)sf->f_bsize;
4249 txdr_hyper(tval, &sfp->sf_fbytes);
4250 /*
4251 * Don't send negative values for available space,
4252 * since this field is unsigned in the NFS protocol.
4253 * Otherwise, the client would see absurdly high
4254 * numbers for free space.
4255 */
4256 if (sf->f_bavail < 0)
4257 tval = 0;
4258 else
4259 tval = (u_quad_t)sf->f_bavail;
4260 tval *= (u_quad_t)sf->f_bsize;
4261 txdr_hyper(tval, &sfp->sf_abytes);
4262 sfp->sf_tfiles.nfsuquad[0] = 0;
4263 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files);
4264 sfp->sf_ffiles.nfsuquad[0] = 0;
4265 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4266 sfp->sf_afiles.nfsuquad[0] = 0;
4267 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree);
4268 sfp->sf_invarsec = 0;
4269 } else {
4270 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA);
4271 sfp->sf_bsize = txdr_unsigned(sf->f_bsize);
4272 sfp->sf_blocks = txdr_unsigned(sf->f_blocks);
4273 sfp->sf_bfree = txdr_unsigned(sf->f_bfree);
4274 if (sf->f_bavail < 0)
4275 sfp->sf_bavail = 0;
4276 else
4277 sfp->sf_bavail = txdr_unsigned(sf->f_bavail);
4278 }
4279 nfsmout:
4280 NFSD_LOCK_ASSERT();
4281 if (vp) {
4282 NFSD_UNLOCK();
4283 mtx_lock(&Giant); /* VFS */
4284 vput(vp);
4285 mtx_unlock(&Giant); /* VFS */
4286 NFSD_LOCK();
4287 }
4288 return(error);
4289 }
4290
4291 /*
4292 * nfs fsinfo service
4293 */
4294 int
4295 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4296 struct thread *td, struct mbuf **mrq)
4297 {
4298 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4299 struct sockaddr *nam = nfsd->nd_nam;
4300 caddr_t dpos = nfsd->nd_dpos;
4301 struct ucred *cred = nfsd->nd_cr;
4302 struct nfsv3_fsinfo *sip;
4303 caddr_t bpos;
4304 int error = 0, rdonly, getret = 1, pref;
4305 struct mbuf *mb, *mreq;
4306 struct vnode *vp = NULL;
4307 struct vattr at;
4308 nfsfh_t nfh;
4309 fhandle_t *fhp;
4310 u_quad_t maxfsize;
4311 struct statfs sb;
4312 int v3 = (nfsd->nd_flag & ND_NFSV3);
4313
4314 NFSD_LOCK_ASSERT();
4315
4316 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4317 if (!v3)
4318 panic("nfsrv_fsinfo: v3 proc called on a v2 connection");
4319 fhp = &nfh.fh_generic;
4320 nfsm_srvmtofh(fhp);
4321 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4322 if (error) {
4323 nfsm_reply(NFSX_UNSIGNED);
4324 nfsm_srvpostop_attr(getret, &at);
4325 error = 0;
4326 goto nfsmout;
4327 }
4328
4329 NFSD_UNLOCK();
4330 mtx_lock(&Giant); /* VFS */
4331 /* XXX Try to make a guess on the max file size. */
4332 VFS_STATFS(vp->v_mount, &sb, td);
4333 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1;
4334
4335 getret = VOP_GETATTR(vp, &at, cred, td);
4336 vput(vp);
4337 mtx_unlock(&Giant); /* VFS */
4338 vp = NULL;
4339 NFSD_LOCK();
4340 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO);
4341 nfsm_srvpostop_attr(getret, &at);
4342 sip = nfsm_build(struct nfsv3_fsinfo *, NFSX_V3FSINFO);
4343
4344 /*
4345 * XXX
4346 * There should be filesystem VFS OP(s) to get this information.
4347 * For now, assume ufs.
4348 */
4349 if (slp->ns_so->so_type == SOCK_DGRAM)
4350 pref = NFS_MAXDGRAMDATA;
4351 else
4352 pref = NFS_MAXDATA;
4353 sip->fs_rtmax = txdr_unsigned(pref);
4354 sip->fs_rtpref = txdr_unsigned(pref);
4355 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE);
4356 sip->fs_wtmax = txdr_unsigned(pref);
4357 sip->fs_wtpref = txdr_unsigned(pref);
4358 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE);
4359 sip->fs_dtpref = txdr_unsigned(pref);
4360 txdr_hyper(maxfsize, &sip->fs_maxfilesize);
4361 sip->fs_timedelta.nfsv3_sec = 0;
4362 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1);
4363 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK |
4364 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS |
4365 NFSV3FSINFO_CANSETTIME);
4366 nfsmout:
4367 NFSD_LOCK_ASSERT();
4368 if (vp) {
4369 NFSD_UNLOCK();
4370 mtx_lock(&Giant); /* VFS */
4371 vput(vp);
4372 mtx_unlock(&Giant); /* VFS */
4373 NFSD_LOCK();
4374 }
4375 return(error);
4376 }
4377
4378 /*
4379 * nfs pathconf service
4380 */
4381 int
4382 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4383 struct thread *td, struct mbuf **mrq)
4384 {
4385 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md;
4386 struct sockaddr *nam = nfsd->nd_nam;
4387 caddr_t dpos = nfsd->nd_dpos;
4388 struct ucred *cred = nfsd->nd_cr;
4389 struct nfsv3_pathconf *pc;
4390 caddr_t bpos;
4391 int error = 0, rdonly, getret = 1;
4392 register_t linkmax, namemax, chownres, notrunc;
4393 struct mbuf *mb, *mreq;
4394 struct vnode *vp = NULL;
4395 struct vattr at;
4396 nfsfh_t nfh;
4397 fhandle_t *fhp;
4398 int v3 = (nfsd->nd_flag & ND_NFSV3);
4399
4400 NFSD_LOCK_ASSERT();
4401
4402 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4403 if (!v3)
4404 panic("nfsrv_pathconf: v3 proc called on a v2 connection");
4405 fhp = &nfh.fh_generic;
4406 nfsm_srvmtofh(fhp);
4407 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, TRUE);
4408 if (error) {
4409 nfsm_reply(NFSX_UNSIGNED);
4410 nfsm_srvpostop_attr(getret, &at);
4411 error = 0;
4412 goto nfsmout;
4413 }
4414 NFSD_UNLOCK();
4415 mtx_lock(&Giant); /* VFS */
4416 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax);
4417 if (!error)
4418 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax);
4419 if (!error)
4420 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres);
4421 if (!error)
4422 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc);
4423 getret = VOP_GETATTR(vp, &at, cred, td);
4424 vput(vp);
4425 mtx_unlock(&Giant); /* VFS */
4426 vp = NULL;
4427 NFSD_LOCK();
4428 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF);
4429 nfsm_srvpostop_attr(getret, &at);
4430 if (error) {
4431 error = 0;
4432 goto nfsmout;
4433 }
4434 pc = nfsm_build(struct nfsv3_pathconf *, NFSX_V3PATHCONF);
4435
4436 pc->pc_linkmax = txdr_unsigned(linkmax);
4437 pc->pc_namemax = txdr_unsigned(namemax);
4438 pc->pc_notrunc = txdr_unsigned(notrunc);
4439 pc->pc_chownrestricted = txdr_unsigned(chownres);
4440
4441 /*
4442 * These should probably be supported by VOP_PATHCONF(), but
4443 * until msdosfs is exportable (why would you want to?), the
4444 * Unix defaults should be ok.
4445 */
4446 pc->pc_caseinsensitive = nfsrv_nfs_false;
4447 pc->pc_casepreserving = nfsrv_nfs_true;
4448 nfsmout:
4449 NFSD_LOCK_ASSERT();
4450 if (vp) {
4451 NFSD_UNLOCK();
4452 mtx_lock(&Giant); /* VFS */
4453 vput(vp);
4454 mtx_unlock(&Giant); /* VFS */
4455 NFSD_LOCK();
4456 }
4457 return(error);
4458 }
4459
4460 /*
4461 * Null operation, used by clients to ping server
4462 */
4463 /* ARGSUSED */
4464 int
4465 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4466 struct thread *td, struct mbuf **mrq)
4467 {
4468 struct mbuf *mrep = nfsd->nd_mrep;
4469 caddr_t bpos;
4470 int error = NFSERR_RETVOID;
4471 struct mbuf *mb, *mreq;
4472
4473 NFSD_LOCK_ASSERT();
4474
4475 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4476 nfsm_reply(0);
4477 nfsmout:
4478 NFSD_LOCK_ASSERT();
4479 return (error);
4480 }
4481
4482 /*
4483 * No operation, used for obsolete procedures
4484 */
4485 /* ARGSUSED */
4486 int
4487 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp,
4488 struct thread *td, struct mbuf **mrq)
4489 {
4490 struct mbuf *mrep = nfsd->nd_mrep;
4491 caddr_t bpos;
4492 int error;
4493 struct mbuf *mb, *mreq;
4494
4495 NFSD_LOCK_ASSERT();
4496
4497 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4498 if (nfsd->nd_repstat)
4499 error = nfsd->nd_repstat;
4500 else
4501 error = EPROCUNAVAIL;
4502 nfsm_reply(0);
4503 error = 0;
4504 nfsmout:
4505 NFSD_LOCK_ASSERT();
4506 return (error);
4507 }
4508
4509 /*
4510 * Perform access checking for vnodes obtained from file handles that would
4511 * refer to files already opened by a Unix client. You cannot just use
4512 * vn_writechk() and VOP_ACCESS() for two reasons.
4513 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write
4514 * case.
4515 * 2 - The owner is to be given access irrespective of mode bits for some
4516 * operations, so that processes that chmod after opening a file don't
4517 * break. I don't like this because it opens a security hole, but since
4518 * the nfs server opens a security hole the size of a barn door anyhow,
4519 * what the heck.
4520 *
4521 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS()
4522 * will return EPERM instead of EACCESS. EPERM is always an error.
4523 *
4524 * There are two versions: one to be called while holding Giant (which is
4525 * needed due to use of VFS), and the other called with the NFS server lock
4526 * (which will be dropped and reacquired). This is necessary because
4527 * nfsrv_access checks are required from both classes of contexts.
4528 */
4529 static int
4530 nfsrv_access_withgiant(struct vnode *vp, int flags, struct ucred *cred,
4531 int rdonly, struct thread *td, int override)
4532 {
4533 struct vattr vattr;
4534 int error;
4535
4536 GIANT_REQUIRED;
4537
4538 nfsdbprintf(("%s %d\n", __FILE__, __LINE__));
4539
4540 if (flags & VWRITE) {
4541 /* Just vn_writechk() changed to check rdonly */
4542 /*
4543 * Disallow write attempts on read-only filesystems;
4544 * unless the file is a socket or a block or character
4545 * device resident on the filesystem.
4546 */
4547 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) {
4548 switch (vp->v_type) {
4549 case VREG:
4550 case VDIR:
4551 case VLNK:
4552 return (EROFS);
4553 default:
4554 break;
4555 }
4556 }
4557 /*
4558 * If there's shared text associated with
4559 * the inode, we can't allow writing.
4560 */
4561 if (vp->v_vflag & VV_TEXT)
4562 return (ETXTBSY);
4563 }
4564
4565 error = VOP_GETATTR(vp, &vattr, cred, td);
4566 if (error)
4567 return (error);
4568 error = VOP_ACCESS(vp, flags, cred, td);
4569 /*
4570 * Allow certain operations for the owner (reads and writes
4571 * on files that are already open).
4572 */
4573 if (override && error == EACCES && cred->cr_uid == vattr.va_uid)
4574 error = 0;
4575 return (error);
4576 }
4577
4578 static int
4579 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, int rdonly,
4580 struct thread *td, int override)
4581 {
4582 int error;
4583
4584 NFSD_LOCK_ASSERT();
4585
4586 NFSD_UNLOCK();
4587 mtx_lock(&Giant); /* VFS */
4588 error = nfsrv_access_withgiant(vp, flags, cred, rdonly, td, override);
4589 mtx_unlock(&Giant); /* VFS */
4590 NFSD_LOCK();
4591 return (error);
4592 }
Cache object: a204980d4a72c0a399c7a2e55635d95c
|