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