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