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