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, NAMEI_LOOKUP, 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, NAMEI_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, NAMEI_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, NAMEI_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, NAMEI_DELETE, NULL, NULL, 2097 ffhp, len, slp, nam, &md, &dpos, &fdirp, 2098 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2099 if (fdirp) { 2100 if (v3) 2101 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor); 2102 } 2103 if (error) { 2104 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2105 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2106 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2107 error = 0; 2108 goto nfsmout; 2109 } 2110 2111 /* 2112 * We have to unlock the from ncp before we can safely lookup 2113 * the target ncp. 2114 */ 2115 KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED); 2116 cache_unlock(&fromnd.nl_nch); 2117 fromnd.nl_flags &= ~NLC_NCPISLOCKED; 2118 nfsm_srvmtofh(tfhp); 2119 nfsm_strsiz(len2, NFS_MAXNAMLEN); 2120 cred->cr_uid = saved_uid; 2121 2122 error = nfs_namei(&tond, cred, NAMEI_RENAME, NULL, NULL, 2123 tfhp, len2, slp, nam, &md, &dpos, &tdirp, 2124 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2125 if (tdirp) { 2126 if (v3) 2127 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor); 2128 } 2129 if (error) 2130 goto out1; 2131 2132 /* 2133 * relock the source 2134 */ 2135 if (cache_lock_nonblock(&fromnd.nl_nch) == 0) { 2136 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2137 } else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) { 2138 cache_lock(&fromnd.nl_nch); 2139 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2140 } else { 2141 cache_unlock(&tond.nl_nch); 2142 cache_lock(&fromnd.nl_nch); 2143 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2144 cache_lock(&tond.nl_nch); 2145 cache_resolve(&tond.nl_nch, tond.nl_cred); 2146 } 2147 fromnd.nl_flags |= NLC_NCPISLOCKED; 2148 2149 fvp = fromnd.nl_nch.ncp->nc_vp; 2150 tvp = tond.nl_nch.ncp->nc_vp; 2151 2152 /* 2153 * Set fdvp and tdvp. We haven't done all the topology checks 2154 * so these can wind up NULL (e.g. if either fvp or tvp is a mount 2155 * point). If we get through the checks these will be guarenteed 2156 * to be non-NULL. 2157 * 2158 * Holding the children ncp's should be sufficient to prevent 2159 * fdvp and tdvp ripouts. 2160 */ 2161 if (fromnd.nl_nch.ncp->nc_parent) 2162 fdvp = fromnd.nl_nch.ncp->nc_parent->nc_vp; 2163 else 2164 fdvp = NULL; 2165 if (tond.nl_nch.ncp->nc_parent) 2166 tdvp = tond.nl_nch.ncp->nc_parent->nc_vp; 2167 else 2168 tdvp = NULL; 2169 2170 if (tvp != NULL) { 2171 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2172 if (v3) 2173 error = EEXIST; 2174 else 2175 error = EISDIR; 2176 goto out; 2177 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2178 if (v3) 2179 error = EEXIST; 2180 else 2181 error = ENOTDIR; 2182 goto out; 2183 } 2184 if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) { 2185 if (v3) 2186 error = EXDEV; 2187 else 2188 error = ENOTEMPTY; 2189 goto out; 2190 } 2191 } 2192 if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) { 2193 if (v3) 2194 error = EXDEV; 2195 else 2196 error = ENOTEMPTY; 2197 goto out; 2198 } 2199 if (fromnd.nl_nch.mount != tond.nl_nch.mount) { 2200 if (v3) 2201 error = EXDEV; 2202 else 2203 error = ENOTEMPTY; 2204 goto out; 2205 } 2206 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) { 2207 if (v3) 2208 error = EINVAL; 2209 else 2210 error = ENOTEMPTY; 2211 } 2212 2213 /* 2214 * You cannot rename a source into itself or a subdirectory of itself. 2215 * We check this by travsering the target directory upwards looking 2216 * for a match against the source. 2217 */ 2218 if (error == 0) { 2219 for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) { 2220 if (fromnd.nl_nch.ncp == ncp) { 2221 error = EINVAL; 2222 break; 2223 } 2224 } 2225 } 2226 2227 /* 2228 * If source is the same as the destination (that is the 2229 * same vnode with the same name in the same directory), 2230 * then there is nothing to do. 2231 */ 2232 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp) 2233 error = -1; 2234 out: 2235 if (!error) { 2236 /* 2237 * The VOP_NRENAME function releases all vnode references & 2238 * locks prior to returning so we need to clear the pointers 2239 * to bypass cleanup code later on. 2240 */ 2241 error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch, 2242 fdvp, tdvp, tond.nl_cred); 2243 } else { 2244 if (error == -1) 2245 error = 0; 2246 } 2247 /* fall through */ 2248 2249 out1: 2250 if (fdirp) 2251 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft); 2252 if (tdirp) 2253 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft); 2254 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2255 if (v3) { 2256 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2257 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2258 } 2259 error = 0; 2260 /* fall through */ 2261 2262 nfsmout: 2263 if (tdirp) 2264 vrele(tdirp); 2265 nlookup_done(&tond); 2266 if (fdirp) 2267 vrele(fdirp); 2268 nlookup_done(&fromnd); 2269 return (error); 2270 } 2271 2272 /* 2273 * nfs link service 2274 */ 2275 int 2276 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2277 struct thread *td, struct mbuf **mrq) 2278 { 2279 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2280 struct sockaddr *nam = nfsd->nd_nam; 2281 caddr_t dpos = nfsd->nd_dpos; 2282 struct ucred *cred = &nfsd->nd_cr; 2283 struct nlookupdata nd; 2284 u_int32_t *tl; 2285 int32_t t1; 2286 caddr_t bpos; 2287 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1; 2288 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 2289 char *cp2; 2290 struct mbuf *mb, *mreq; 2291 struct vnode *dirp; 2292 struct vnode *dvp; 2293 struct vnode *vp; 2294 struct vnode *xp; 2295 struct mount *mp; 2296 struct mount *xmp; 2297 struct vattr dirfor, diraft, at; 2298 nfsfh_t nfh, dnfh; 2299 fhandle_t *fhp, *dfhp; 2300 2301 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2302 nlookup_zero(&nd); 2303 dirp = dvp = vp = xp = NULL; 2304 mp = xmp = NULL; 2305 2306 fhp = &nfh.fh_generic; 2307 dfhp = &dnfh.fh_generic; 2308 nfsm_srvmtofh(fhp); 2309 nfsm_srvmtofh(dfhp); 2310 nfsm_srvnamesiz(len); 2311 2312 error = nfsrv_fhtovp(fhp, FALSE, &xmp, &xp, cred, slp, nam, 2313 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2314 if (error) { 2315 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2316 nfsm_srvpostop_attr(getret, &at); 2317 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2318 xp = NULL; 2319 error = 0; 2320 goto nfsmout; 2321 } 2322 if (xp->v_type == VDIR) { 2323 error = EPERM; /* POSIX */ 2324 goto out1; 2325 } 2326 2327 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 2328 dfhp, len, slp, nam, &md, &dpos, &dirp, 2329 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2330 if (dirp) { 2331 if (v3) 2332 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2333 } 2334 if (error) 2335 goto out1; 2336 2337 if (vp != NULL) { 2338 error = EEXIST; 2339 goto out; 2340 } 2341 if (xp->v_mount != dvp->v_mount) 2342 error = EXDEV; 2343 out: 2344 if (!error) { 2345 vn_unlock(dvp); 2346 error = VOP_NLINK(&nd.nl_nch, dvp, xp, nd.nl_cred); 2347 vrele(dvp); 2348 dvp = NULL; 2349 } 2350 /* fall through */ 2351 2352 out1: 2353 if (v3) 2354 getret = VOP_GETATTR(xp, &at); 2355 if (dirp) 2356 diraft_ret = VOP_GETATTR(dirp, &diraft); 2357 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2358 if (v3) { 2359 nfsm_srvpostop_attr(getret, &at); 2360 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2361 error = 0; 2362 } 2363 /* fall through */ 2364 2365 nfsmout: 2366 nlookup_done(&nd); 2367 if (dirp) 2368 vrele(dirp); 2369 if (xp) 2370 vrele(xp); 2371 if (dvp) { 2372 if (dvp == vp) 2373 vrele(dvp); 2374 else 2375 vput(dvp); 2376 } 2377 if (vp) 2378 vput(vp); 2379 return(error); 2380 } 2381 2382 /* 2383 * nfs symbolic link service 2384 */ 2385 int 2386 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2387 struct thread *td, struct mbuf **mrq) 2388 { 2389 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2390 struct sockaddr *nam = nfsd->nd_nam; 2391 caddr_t dpos = nfsd->nd_dpos; 2392 struct ucred *cred = &nfsd->nd_cr; 2393 struct vattr va, dirfor, diraft; 2394 struct nlookupdata nd; 2395 struct vattr *vap = &va; 2396 u_int32_t *tl; 2397 int32_t t1; 2398 struct nfsv2_sattr *sp; 2399 char *bpos, *pathcp = NULL, *cp2; 2400 struct uio io; 2401 struct iovec iv; 2402 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1; 2403 int v3 = (nfsd->nd_flag & ND_NFSV3); 2404 struct mbuf *mb, *mreq, *mb2; 2405 struct vnode *dirp; 2406 struct vnode *vp; 2407 struct vnode *dvp; 2408 nfsfh_t nfh; 2409 fhandle_t *fhp; 2410 2411 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2412 nlookup_zero(&nd); 2413 dirp = NULL; 2414 dvp = NULL; 2415 vp = NULL; 2416 2417 fhp = &nfh.fh_generic; 2418 nfsm_srvmtofh(fhp); 2419 nfsm_srvnamesiz(len); 2420 2421 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 2422 fhp, len, slp, nam, &md, &dpos, &dirp, 2423 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2424 if (dirp) { 2425 if (v3) 2426 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2427 } 2428 if (error) 2429 goto out; 2430 2431 VATTR_NULL(vap); 2432 if (v3) 2433 nfsm_srvsattr(vap); 2434 nfsm_strsiz(len2, NFS_MAXPATHLEN); 2435 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 2436 iv.iov_base = pathcp; 2437 iv.iov_len = len2; 2438 io.uio_resid = len2; 2439 io.uio_offset = 0; 2440 io.uio_iov = &iv; 2441 io.uio_iovcnt = 1; 2442 io.uio_segflg = UIO_SYSSPACE; 2443 io.uio_rw = UIO_READ; 2444 io.uio_td = NULL; 2445 nfsm_mtouio(&io, len2); 2446 if (!v3) { 2447 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2448 vap->va_mode = nfstov_mode(sp->sa_mode); 2449 } 2450 *(pathcp + len2) = '\0'; 2451 if (vp) { 2452 error = EEXIST; 2453 goto out; 2454 } 2455 2456 if (vap->va_mode == (mode_t)VNOVAL) 2457 vap->va_mode = 0; 2458 if (dvp != vp) 2459 vn_unlock(dvp); 2460 error = VOP_NSYMLINK(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap, pathcp); 2461 vrele(dvp); 2462 dvp = NULL; 2463 if (error == 0) { 2464 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid)); 2465 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2466 if (!error) 2467 error = VOP_GETATTR(vp, vap); 2468 } 2469 2470 out: 2471 if (dvp) { 2472 if (dvp == vp) 2473 vrele(dvp); 2474 else 2475 vput(dvp); 2476 } 2477 if (vp) { 2478 vput(vp); 2479 vp = NULL; 2480 } 2481 if (pathcp) { 2482 FREE(pathcp, M_TEMP); 2483 pathcp = NULL; 2484 } 2485 if (dirp) { 2486 diraft_ret = VOP_GETATTR(dirp, &diraft); 2487 vrele(dirp); 2488 dirp = NULL; 2489 } 2490 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2491 if (v3) { 2492 if (!error) { 2493 nfsm_srvpostop_fh(fhp); 2494 nfsm_srvpostop_attr(0, vap); 2495 } 2496 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2497 } 2498 error = 0; 2499 /* fall through */ 2500 2501 nfsmout: 2502 nlookup_done(&nd); 2503 if (vp) 2504 vput(vp); 2505 if (dirp) 2506 vrele(dirp); 2507 if (pathcp) 2508 FREE(pathcp, M_TEMP); 2509 return (error); 2510 } 2511 2512 /* 2513 * nfs mkdir service 2514 */ 2515 int 2516 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2517 struct thread *td, struct mbuf **mrq) 2518 { 2519 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2520 struct sockaddr *nam = nfsd->nd_nam; 2521 caddr_t dpos = nfsd->nd_dpos; 2522 struct ucred *cred = &nfsd->nd_cr; 2523 struct vattr va, dirfor, diraft; 2524 struct vattr *vap = &va; 2525 struct nfs_fattr *fp; 2526 struct nlookupdata nd; 2527 caddr_t cp; 2528 u_int32_t *tl; 2529 int32_t t1; 2530 caddr_t bpos; 2531 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 2532 int v3 = (nfsd->nd_flag & ND_NFSV3); 2533 char *cp2; 2534 struct mbuf *mb, *mb2, *mreq; 2535 struct vnode *dirp; 2536 struct vnode *dvp; 2537 struct vnode *vp; 2538 nfsfh_t nfh; 2539 fhandle_t *fhp; 2540 2541 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2542 nlookup_zero(&nd); 2543 dirp = NULL; 2544 dvp = NULL; 2545 vp = NULL; 2546 2547 fhp = &nfh.fh_generic; 2548 nfsm_srvmtofh(fhp); 2549 nfsm_srvnamesiz(len); 2550 2551 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 2552 fhp, len, slp, nam, &md, &dpos, &dirp, 2553 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2554 if (dirp) { 2555 if (v3) 2556 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2557 } 2558 if (error) { 2559 nfsm_reply(NFSX_WCCDATA(v3)); 2560 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2561 error = 0; 2562 goto nfsmout; 2563 } 2564 VATTR_NULL(vap); 2565 if (v3) { 2566 nfsm_srvsattr(vap); 2567 } else { 2568 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2569 vap->va_mode = nfstov_mode(*tl++); 2570 } 2571 2572 /* 2573 * At this point nd.ni_dvp is referenced and exclusively locked and 2574 * nd.ni_vp, if it exists, is referenced but not locked. 2575 */ 2576 2577 vap->va_type = VDIR; 2578 if (vp != NULL) { 2579 error = EEXIST; 2580 goto out; 2581 } 2582 2583 /* 2584 * Issue mkdir op. Since SAVESTART is not set, the pathname 2585 * component is freed by the VOP call. This will fill-in 2586 * nd.ni_vp, reference, and exclusively lock it. 2587 */ 2588 if (vap->va_mode == (mode_t)VNOVAL) 2589 vap->va_mode = 0; 2590 vn_unlock(dvp); 2591 error = VOP_NMKDIR(&nd.nl_nch, dvp, &vp, nd.nl_cred, vap); 2592 vrele(dvp); 2593 dvp = NULL; 2594 2595 if (error == 0) { 2596 bzero(&fhp->fh_fid, sizeof(fhp->fh_fid)); 2597 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2598 if (error == 0) 2599 error = VOP_GETATTR(vp, vap); 2600 } 2601 out: 2602 if (dirp) 2603 diraft_ret = VOP_GETATTR(dirp, &diraft); 2604 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2605 if (v3) { 2606 if (!error) { 2607 nfsm_srvpostop_fh(fhp); 2608 nfsm_srvpostop_attr(0, vap); 2609 } 2610 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2611 } else { 2612 nfsm_srvfhtom(fhp, v3); 2613 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2614 nfsm_srvfillattr(vap, fp); 2615 } 2616 error = 0; 2617 /* fall through */ 2618 2619 nfsmout: 2620 nlookup_done(&nd); 2621 if (dirp) 2622 vrele(dirp); 2623 if (dvp) { 2624 if (dvp == vp) 2625 vrele(dvp); 2626 else 2627 vput(dvp); 2628 } 2629 if (vp) 2630 vput(vp); 2631 return (error); 2632 } 2633 2634 /* 2635 * nfs rmdir service 2636 */ 2637 int 2638 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2639 struct thread *td, struct mbuf **mrq) 2640 { 2641 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2642 struct sockaddr *nam = nfsd->nd_nam; 2643 caddr_t dpos = nfsd->nd_dpos; 2644 struct ucred *cred = &nfsd->nd_cr; 2645 u_int32_t *tl; 2646 int32_t t1; 2647 caddr_t bpos; 2648 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 2649 int v3 = (nfsd->nd_flag & ND_NFSV3); 2650 char *cp2; 2651 struct mbuf *mb, *mreq; 2652 struct vnode *dirp; 2653 struct vnode *dvp; 2654 struct vnode *vp; 2655 struct vattr dirfor, diraft; 2656 nfsfh_t nfh; 2657 fhandle_t *fhp; 2658 struct nlookupdata nd; 2659 2660 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2661 nlookup_zero(&nd); 2662 dirp = NULL; 2663 dvp = NULL; 2664 vp = NULL; 2665 2666 fhp = &nfh.fh_generic; 2667 nfsm_srvmtofh(fhp); 2668 nfsm_srvnamesiz(len); 2669 2670 error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp, 2671 fhp, len, slp, nam, &md, &dpos, &dirp, 2672 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2673 if (dirp) { 2674 if (v3) 2675 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2676 } 2677 if (error) { 2678 nfsm_reply(NFSX_WCCDATA(v3)); 2679 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2680 error = 0; 2681 goto nfsmout; 2682 } 2683 if (vp->v_type != VDIR) { 2684 error = ENOTDIR; 2685 goto out; 2686 } 2687 2688 /* 2689 * The root of a mounted filesystem cannot be deleted. 2690 */ 2691 if (vp->v_flag & VROOT) 2692 error = EBUSY; 2693 out: 2694 /* 2695 * Issue or abort op. Since SAVESTART is not set, path name 2696 * component is freed by the VOP after either. 2697 */ 2698 if (!error) { 2699 if (dvp != vp) 2700 vn_unlock(dvp); 2701 vput(vp); 2702 vp = NULL; 2703 error = VOP_NRMDIR(&nd.nl_nch, dvp, nd.nl_cred); 2704 vrele(dvp); 2705 dvp = NULL; 2706 } 2707 nlookup_done(&nd); 2708 2709 if (dirp) 2710 diraft_ret = VOP_GETATTR(dirp, &diraft); 2711 nfsm_reply(NFSX_WCCDATA(v3)); 2712 if (v3) { 2713 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2714 error = 0; 2715 } 2716 /* fall through */ 2717 2718 nfsmout: 2719 if (dvp) { 2720 if (dvp == vp) 2721 vrele(dvp); 2722 else 2723 vput(dvp); 2724 } 2725 nlookup_done(&nd); 2726 if (dirp) 2727 vrele(dirp); 2728 if (vp) 2729 vput(vp); 2730 return(error); 2731 } 2732 2733 /* 2734 * nfs readdir service 2735 * - mallocs what it thinks is enough to read 2736 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 2737 * - calls VOP_READDIR() 2738 * - loops around building the reply 2739 * if the output generated exceeds count break out of loop 2740 * The nfsm_clget macro is used here so that the reply will be packed 2741 * tightly in mbuf clusters. 2742 * - it only knows that it has encountered eof when the VOP_READDIR() 2743 * reads nothing 2744 * - as such one readdir rpc will return eof false although you are there 2745 * and then the next will return eof 2746 * - it trims out records with d_fileno == 0 2747 * this doesn't matter for Unix clients, but they might confuse clients 2748 * for other os'. 2749 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2750 * than requested, but this may not apply to all filesystems. For 2751 * example, client NFS does not { although it is never remote mounted 2752 * anyhow } 2753 * The alternate call nfsrv_readdirplus() does lookups as well. 2754 * PS: The NFS protocol spec. does not clarify what the "count" byte 2755 * argument is a count of.. just name strings and file id's or the 2756 * entire reply rpc or ... 2757 * I tried just file name and id sizes and it confused the Sun client, 2758 * so I am using the full rpc size now. The "paranoia.." comment refers 2759 * to including the status longwords that are not a part of the dir. 2760 * "entry" structures, but are in the rpc. 2761 */ 2762 struct flrep { 2763 nfsuint64 fl_off; 2764 u_int32_t fl_postopok; 2765 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)]; 2766 u_int32_t fl_fhok; 2767 u_int32_t fl_fhsize; 2768 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)]; 2769 }; 2770 2771 int 2772 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2773 struct thread *td, struct mbuf **mrq) 2774 { 2775 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2776 struct sockaddr *nam = nfsd->nd_nam; 2777 caddr_t dpos = nfsd->nd_dpos; 2778 struct ucred *cred = &nfsd->nd_cr; 2779 char *bp, *be; 2780 struct dirent *dp; 2781 caddr_t cp; 2782 u_int32_t *tl; 2783 int32_t t1; 2784 caddr_t bpos; 2785 struct mbuf *mb, *mb2, *mreq, *mp1, *mp2; 2786 char *cpos, *cend, *cp2, *rbuf; 2787 struct vnode *vp = NULL; 2788 struct mount *mp = NULL; 2789 struct vattr at; 2790 nfsfh_t nfh; 2791 fhandle_t *fhp; 2792 struct uio io; 2793 struct iovec iv; 2794 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2795 int siz, cnt, fullsiz, eofflag, rdonly, ncookies; 2796 int v3 = (nfsd->nd_flag & ND_NFSV3); 2797 u_quad_t off, toff, verf; 2798 off_t *cookies = NULL, *cookiep; 2799 2800 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2801 fhp = &nfh.fh_generic; 2802 nfsm_srvmtofh(fhp); 2803 if (v3) { 2804 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2805 toff = fxdr_hyper(tl); 2806 tl += 2; 2807 verf = fxdr_hyper(tl); 2808 tl += 2; 2809 } else { 2810 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2811 toff = fxdr_unsigned(u_quad_t, *tl++); 2812 verf = 0; /* shut up gcc */ 2813 } 2814 off = toff; 2815 cnt = fxdr_unsigned(int, *tl); 2816 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2817 xfer = NFS_SRVMAXDATA(nfsd); 2818 if (cnt > xfer) 2819 cnt = xfer; 2820 if (siz > xfer) 2821 siz = xfer; 2822 fullsiz = siz; 2823 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 2824 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2825 if (!error && vp->v_type != VDIR) { 2826 error = ENOTDIR; 2827 vput(vp); 2828 vp = NULL; 2829 } 2830 if (error) { 2831 nfsm_reply(NFSX_UNSIGNED); 2832 nfsm_srvpostop_attr(getret, &at); 2833 error = 0; 2834 goto nfsmout; 2835 } 2836 2837 /* 2838 * Obtain lock on vnode for this section of the code 2839 */ 2840 2841 if (v3) { 2842 error = getret = VOP_GETATTR(vp, &at); 2843 #if 0 2844 /* 2845 * XXX This check may be too strict for Solaris 2.5 clients. 2846 */ 2847 if (!error && toff && verf && verf != at.va_filerev) 2848 error = NFSERR_BAD_COOKIE; 2849 #endif 2850 } 2851 if (!error) 2852 error = nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 0); 2853 if (error) { 2854 vput(vp); 2855 vp = NULL; 2856 nfsm_reply(NFSX_POSTOPATTR(v3)); 2857 nfsm_srvpostop_attr(getret, &at); 2858 error = 0; 2859 goto nfsmout; 2860 } 2861 vn_unlock(vp); 2862 2863 /* 2864 * end section. Allocate rbuf and continue 2865 */ 2866 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2867 again: 2868 iv.iov_base = rbuf; 2869 iv.iov_len = fullsiz; 2870 io.uio_iov = &iv; 2871 io.uio_iovcnt = 1; 2872 io.uio_offset = (off_t)off; 2873 io.uio_resid = fullsiz; 2874 io.uio_segflg = UIO_SYSSPACE; 2875 io.uio_rw = UIO_READ; 2876 io.uio_td = NULL; 2877 eofflag = 0; 2878 if (cookies) { 2879 kfree((caddr_t)cookies, M_TEMP); 2880 cookies = NULL; 2881 } 2882 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 2883 off = (off_t)io.uio_offset; 2884 if (!cookies && !error) 2885 error = NFSERR_PERM; 2886 if (v3) { 2887 getret = VOP_GETATTR(vp, &at); 2888 if (!error) 2889 error = getret; 2890 } 2891 if (error) { 2892 vrele(vp); 2893 vp = NULL; 2894 kfree((caddr_t)rbuf, M_TEMP); 2895 if (cookies) 2896 kfree((caddr_t)cookies, M_TEMP); 2897 nfsm_reply(NFSX_POSTOPATTR(v3)); 2898 nfsm_srvpostop_attr(getret, &at); 2899 error = 0; 2900 goto nfsmout; 2901 } 2902 if (io.uio_resid) { 2903 siz -= io.uio_resid; 2904 2905 /* 2906 * If nothing read, return eof 2907 * rpc reply 2908 */ 2909 if (siz == 0) { 2910 vrele(vp); 2911 vp = NULL; 2912 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2913 2 * NFSX_UNSIGNED); 2914 if (v3) { 2915 nfsm_srvpostop_attr(getret, &at); 2916 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2917 txdr_hyper(at.va_filerev, tl); 2918 tl += 2; 2919 } else 2920 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2921 *tl++ = nfs_false; 2922 *tl = nfs_true; 2923 FREE((caddr_t)rbuf, M_TEMP); 2924 FREE((caddr_t)cookies, M_TEMP); 2925 error = 0; 2926 goto nfsmout; 2927 } 2928 } 2929 2930 /* 2931 * Check for degenerate cases of nothing useful read. 2932 * If so go try again 2933 */ 2934 cpos = rbuf; 2935 cend = rbuf + siz; 2936 dp = (struct dirent *)cpos; 2937 cookiep = cookies; 2938 /* 2939 * For some reason FreeBSD's ufs_readdir() chooses to back the 2940 * directory offset up to a block boundary, so it is necessary to 2941 * skip over the records that preceed the requested offset. This 2942 * requires the assumption that file offset cookies monotonically 2943 * increase. 2944 */ 2945 while (cpos < cend && ncookies > 0 && 2946 (dp->d_ino == 0 || dp->d_type == DT_WHT || 2947 ((u_quad_t)(*cookiep)) <= toff)) { 2948 dp = _DIRENT_NEXT(dp); 2949 cpos = (char *)dp; 2950 cookiep++; 2951 ncookies--; 2952 } 2953 if (cpos >= cend || ncookies == 0) { 2954 toff = off; 2955 siz = fullsiz; 2956 goto again; 2957 } 2958 2959 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 2960 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 2961 if (v3) { 2962 nfsm_srvpostop_attr(getret, &at); 2963 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2964 txdr_hyper(at.va_filerev, tl); 2965 } 2966 mp1 = mp2 = mb; 2967 bp = bpos; 2968 be = bp + M_TRAILINGSPACE(mp1); 2969 2970 /* Loop through the records and build reply */ 2971 while (cpos < cend && ncookies > 0) { 2972 if (dp->d_ino != 0 && dp->d_type != DT_WHT) { 2973 nlen = dp->d_namlen; 2974 rem = nfsm_rndup(nlen) - nlen; 2975 len += (4 * NFSX_UNSIGNED + nlen + rem); 2976 if (v3) 2977 len += 2 * NFSX_UNSIGNED; 2978 if (len > cnt) { 2979 eofflag = 0; 2980 break; 2981 } 2982 /* 2983 * Build the directory record xdr from 2984 * the dirent entry. 2985 */ 2986 nfsm_clget(mp1, mp2, mb, bp, be, tl); 2987 *tl = nfs_true; 2988 bp += NFSX_UNSIGNED; 2989 if (v3) { 2990 nfsm_clget(mp1, mp2, mb, bp, be, tl); 2991 *tl = 0; 2992 bp += NFSX_UNSIGNED; 2993 } 2994 nfsm_clget(mp1, mp2, mb, bp, be, tl); 2995 *tl = txdr_unsigned(dp->d_ino); 2996 bp += NFSX_UNSIGNED; 2997 nfsm_clget(mp1, mp2, mb, bp, be, tl); 2998 *tl = txdr_unsigned(nlen); 2999 bp += NFSX_UNSIGNED; 3000 3001 /* And loop around copying the name */ 3002 xfer = nlen; 3003 cp = dp->d_name; 3004 while (xfer > 0) { 3005 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3006 if ((bp+xfer) > be) 3007 tsiz = be-bp; 3008 else 3009 tsiz = xfer; 3010 bcopy(cp, bp, tsiz); 3011 bp += tsiz; 3012 xfer -= tsiz; 3013 if (xfer > 0) 3014 cp += tsiz; 3015 } 3016 /* And null pad to a int32_t boundary */ 3017 for (i = 0; i < rem; i++) 3018 *bp++ = '\0'; 3019 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3020 3021 /* Finish off the record */ 3022 if (v3) { 3023 *tl = txdr_unsigned(*cookiep >> 32); 3024 bp += NFSX_UNSIGNED; 3025 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3026 } 3027 *tl = txdr_unsigned(*cookiep); 3028 bp += NFSX_UNSIGNED; 3029 } 3030 dp = _DIRENT_NEXT(dp); 3031 cpos = (char *)dp; 3032 cookiep++; 3033 ncookies--; 3034 } 3035 vrele(vp); 3036 vp = NULL; 3037 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3038 *tl = nfs_false; 3039 bp += NFSX_UNSIGNED; 3040 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3041 if (eofflag) 3042 *tl = nfs_true; 3043 else 3044 *tl = nfs_false; 3045 bp += NFSX_UNSIGNED; 3046 if (mp1 != mb) { 3047 if (bp < be) 3048 mp1->m_len = bp - mtod(mp1, caddr_t); 3049 } else 3050 mp1->m_len += bp - bpos; 3051 FREE((caddr_t)rbuf, M_TEMP); 3052 FREE((caddr_t)cookies, M_TEMP); 3053 3054 nfsmout: 3055 if (vp) 3056 vrele(vp); 3057 return(error); 3058 } 3059 3060 int 3061 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3062 struct thread *td, struct mbuf **mrq) 3063 { 3064 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3065 struct sockaddr *nam = nfsd->nd_nam; 3066 caddr_t dpos = nfsd->nd_dpos; 3067 struct ucred *cred = &nfsd->nd_cr; 3068 char *bp, *be; 3069 struct dirent *dp; 3070 caddr_t cp; 3071 u_int32_t *tl; 3072 int32_t t1; 3073 caddr_t bpos; 3074 struct mbuf *mb, *mb2, *mreq, *mp1, *mp2; 3075 char *cpos, *cend, *cp2, *rbuf; 3076 struct vnode *vp = NULL, *nvp; 3077 struct mount *mp = NULL; 3078 struct flrep fl; 3079 nfsfh_t nfh; 3080 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh; 3081 struct uio io; 3082 struct iovec iv; 3083 struct vattr va, at, *vap = &va; 3084 struct nfs_fattr *fp; 3085 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 3086 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies; 3087 u_quad_t off, toff, verf; 3088 off_t *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 3089 3090 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3091 fhp = &nfh.fh_generic; 3092 nfsm_srvmtofh(fhp); 3093 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 3094 toff = fxdr_hyper(tl); 3095 tl += 2; 3096 verf = fxdr_hyper(tl); 3097 tl += 2; 3098 siz = fxdr_unsigned(int, *tl++); 3099 cnt = fxdr_unsigned(int, *tl); 3100 off = toff; 3101 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 3102 xfer = NFS_SRVMAXDATA(nfsd); 3103 if (cnt > xfer) 3104 cnt = xfer; 3105 if (siz > xfer) 3106 siz = xfer; 3107 fullsiz = siz; 3108 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 3109 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3110 if (!error && vp->v_type != VDIR) { 3111 error = ENOTDIR; 3112 vput(vp); 3113 vp = NULL; 3114 } 3115 if (error) { 3116 nfsm_reply(NFSX_UNSIGNED); 3117 nfsm_srvpostop_attr(getret, &at); 3118 error = 0; 3119 goto nfsmout; 3120 } 3121 error = getret = VOP_GETATTR(vp, &at); 3122 #if 0 3123 /* 3124 * XXX This check may be too strict for Solaris 2.5 clients. 3125 */ 3126 if (!error && toff && verf && verf != at.va_filerev) 3127 error = NFSERR_BAD_COOKIE; 3128 #endif 3129 if (!error) { 3130 error = nfsrv_access(mp, vp, VEXEC, cred, rdonly, td, 0); 3131 } 3132 if (error) { 3133 vput(vp); 3134 vp = NULL; 3135 nfsm_reply(NFSX_V3POSTOPATTR); 3136 nfsm_srvpostop_attr(getret, &at); 3137 error = 0; 3138 goto nfsmout; 3139 } 3140 vn_unlock(vp); 3141 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 3142 again: 3143 iv.iov_base = rbuf; 3144 iv.iov_len = fullsiz; 3145 io.uio_iov = &iv; 3146 io.uio_iovcnt = 1; 3147 io.uio_offset = (off_t)off; 3148 io.uio_resid = fullsiz; 3149 io.uio_segflg = UIO_SYSSPACE; 3150 io.uio_rw = UIO_READ; 3151 io.uio_td = NULL; 3152 eofflag = 0; 3153 if (cookies) { 3154 kfree((caddr_t)cookies, M_TEMP); 3155 cookies = NULL; 3156 } 3157 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 3158 off = (u_quad_t)io.uio_offset; 3159 getret = VOP_GETATTR(vp, &at); 3160 if (!cookies && !error) 3161 error = NFSERR_PERM; 3162 if (!error) 3163 error = getret; 3164 if (error) { 3165 vrele(vp); 3166 vp = NULL; 3167 if (cookies) 3168 kfree((caddr_t)cookies, M_TEMP); 3169 kfree((caddr_t)rbuf, M_TEMP); 3170 nfsm_reply(NFSX_V3POSTOPATTR); 3171 nfsm_srvpostop_attr(getret, &at); 3172 error = 0; 3173 goto nfsmout; 3174 } 3175 if (io.uio_resid) { 3176 siz -= io.uio_resid; 3177 3178 /* 3179 * If nothing read, return eof 3180 * rpc reply 3181 */ 3182 if (siz == 0) { 3183 vrele(vp); 3184 vp = NULL; 3185 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 3186 2 * NFSX_UNSIGNED); 3187 nfsm_srvpostop_attr(getret, &at); 3188 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3189 txdr_hyper(at.va_filerev, tl); 3190 tl += 2; 3191 *tl++ = nfs_false; 3192 *tl = nfs_true; 3193 FREE((caddr_t)cookies, M_TEMP); 3194 FREE((caddr_t)rbuf, M_TEMP); 3195 error = 0; 3196 goto nfsmout; 3197 } 3198 } 3199 3200 /* 3201 * Check for degenerate cases of nothing useful read. 3202 * If so go try again 3203 */ 3204 cpos = rbuf; 3205 cend = rbuf + siz; 3206 dp = (struct dirent *)cpos; 3207 cookiep = cookies; 3208 /* 3209 * For some reason FreeBSD's ufs_readdir() chooses to back the 3210 * directory offset up to a block boundary, so it is necessary to 3211 * skip over the records that preceed the requested offset. This 3212 * requires the assumption that file offset cookies monotonically 3213 * increase. 3214 */ 3215 while (cpos < cend && ncookies > 0 && 3216 (dp->d_ino == 0 || dp->d_type == DT_WHT || 3217 ((u_quad_t)(*cookiep)) <= toff)) { 3218 dp = _DIRENT_NEXT(dp); 3219 cpos = (char *)dp; 3220 cookiep++; 3221 ncookies--; 3222 } 3223 if (cpos >= cend || ncookies == 0) { 3224 toff = off; 3225 siz = fullsiz; 3226 goto again; 3227 } 3228 3229 /* 3230 * Probe one of the directory entries to see if the filesystem 3231 * supports VGET. 3232 */ 3233 if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp) == EOPNOTSUPP) { 3234 error = NFSERR_NOTSUPP; 3235 vrele(vp); 3236 vp = NULL; 3237 kfree((caddr_t)cookies, M_TEMP); 3238 kfree((caddr_t)rbuf, M_TEMP); 3239 nfsm_reply(NFSX_V3POSTOPATTR); 3240 nfsm_srvpostop_attr(getret, &at); 3241 error = 0; 3242 goto nfsmout; 3243 } 3244 if (nvp) { 3245 vput(nvp); 3246 nvp = NULL; 3247 } 3248 3249 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 3250 nfsm_reply(cnt); 3251 nfsm_srvpostop_attr(getret, &at); 3252 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3253 txdr_hyper(at.va_filerev, tl); 3254 mp1 = mp2 = mb; 3255 bp = bpos; 3256 be = bp + M_TRAILINGSPACE(mp1); 3257 3258 /* Loop through the records and build reply */ 3259 while (cpos < cend && ncookies > 0) { 3260 if (dp->d_ino != 0 && dp->d_type != DT_WHT) { 3261 nlen = dp->d_namlen; 3262 rem = nfsm_rndup(nlen)-nlen; 3263 3264 /* 3265 * For readdir_and_lookup get the vnode using 3266 * the file number. 3267 */ 3268 if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp)) 3269 goto invalid; 3270 bzero((caddr_t)nfhp, NFSX_V3FH); 3271 nfhp->fh_fsid = fhp->fh_fsid; 3272 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { 3273 vput(nvp); 3274 nvp = NULL; 3275 goto invalid; 3276 } 3277 if (VOP_GETATTR(nvp, vap)) { 3278 vput(nvp); 3279 nvp = NULL; 3280 goto invalid; 3281 } 3282 vput(nvp); 3283 nvp = NULL; 3284 3285 /* 3286 * If either the dircount or maxcount will be 3287 * exceeded, get out now. Both of these lengths 3288 * are calculated conservatively, including all 3289 * XDR overheads. 3290 */ 3291 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 3292 NFSX_V3POSTOPATTR); 3293 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 3294 if (len > cnt || dirlen > fullsiz) { 3295 eofflag = 0; 3296 break; 3297 } 3298 3299 /* 3300 * Build the directory record xdr from 3301 * the dirent entry. 3302 */ 3303 fp = (struct nfs_fattr *)&fl.fl_fattr; 3304 nfsm_srvfillattr(vap, fp); 3305 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 3306 fl.fl_fhok = nfs_true; 3307 fl.fl_postopok = nfs_true; 3308 fl.fl_off.nfsuquad[0] = txdr_unsigned(*cookiep >> 32); 3309 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); 3310 3311 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3312 *tl = nfs_true; 3313 bp += NFSX_UNSIGNED; 3314 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3315 *tl = 0; 3316 bp += NFSX_UNSIGNED; 3317 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3318 *tl = txdr_unsigned(dp->d_ino); 3319 bp += NFSX_UNSIGNED; 3320 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3321 *tl = txdr_unsigned(nlen); 3322 bp += NFSX_UNSIGNED; 3323 3324 /* And loop around copying the name */ 3325 xfer = nlen; 3326 cp = dp->d_name; 3327 while (xfer > 0) { 3328 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3329 if ((bp + xfer) > be) 3330 tsiz = be - bp; 3331 else 3332 tsiz = xfer; 3333 bcopy(cp, bp, tsiz); 3334 bp += tsiz; 3335 xfer -= tsiz; 3336 if (xfer > 0) 3337 cp += tsiz; 3338 } 3339 /* And null pad to a int32_t boundary */ 3340 for (i = 0; i < rem; i++) 3341 *bp++ = '\0'; 3342 3343 /* 3344 * Now copy the flrep structure out. 3345 */ 3346 xfer = sizeof (struct flrep); 3347 cp = (caddr_t)&fl; 3348 while (xfer > 0) { 3349 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3350 if ((bp + xfer) > be) 3351 tsiz = be - bp; 3352 else 3353 tsiz = xfer; 3354 bcopy(cp, bp, tsiz); 3355 bp += tsiz; 3356 xfer -= tsiz; 3357 if (xfer > 0) 3358 cp += tsiz; 3359 } 3360 } 3361 invalid: 3362 dp = _DIRENT_NEXT(dp); 3363 cpos = (char *)dp; 3364 cookiep++; 3365 ncookies--; 3366 } 3367 vrele(vp); 3368 vp = NULL; 3369 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3370 *tl = nfs_false; 3371 bp += NFSX_UNSIGNED; 3372 nfsm_clget(mp1, mp2, mb, bp, be, tl); 3373 if (eofflag) 3374 *tl = nfs_true; 3375 else 3376 *tl = nfs_false; 3377 bp += NFSX_UNSIGNED; 3378 if (mp1 != mb) { 3379 if (bp < be) 3380 mp1->m_len = bp - mtod(mp1, caddr_t); 3381 } else 3382 mp1->m_len += bp - bpos; 3383 FREE((caddr_t)cookies, M_TEMP); 3384 FREE((caddr_t)rbuf, M_TEMP); 3385 nfsmout: 3386 if (vp) 3387 vrele(vp); 3388 return(error); 3389 } 3390 3391 /* 3392 * nfs commit service 3393 */ 3394 int 3395 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3396 struct thread *td, struct mbuf **mrq) 3397 { 3398 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3399 struct sockaddr *nam = nfsd->nd_nam; 3400 caddr_t dpos = nfsd->nd_dpos; 3401 struct ucred *cred = &nfsd->nd_cr; 3402 struct vattr bfor, aft; 3403 struct vnode *vp = NULL; 3404 struct mount *mp = NULL; 3405 nfsfh_t nfh; 3406 fhandle_t *fhp; 3407 u_int32_t *tl; 3408 int32_t t1; 3409 caddr_t bpos; 3410 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt; 3411 char *cp2; 3412 struct mbuf *mb, *mb2, *mreq; 3413 u_quad_t off; 3414 3415 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3416 fhp = &nfh.fh_generic; 3417 nfsm_srvmtofh(fhp); 3418 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3419 3420 /* 3421 * XXX At this time VOP_FSYNC() does not accept offset and byte 3422 * count parameters, so these arguments are useless (someday maybe). 3423 */ 3424 off = fxdr_hyper(tl); 3425 tl += 2; 3426 cnt = fxdr_unsigned(int, *tl); 3427 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 3428 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3429 if (error) { 3430 nfsm_reply(2 * NFSX_UNSIGNED); 3431 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3432 error = 0; 3433 goto nfsmout; 3434 } 3435 for_ret = VOP_GETATTR(vp, &bfor); 3436 3437 if (cnt > MAX_COMMIT_COUNT) { 3438 /* 3439 * Give up and do the whole thing 3440 */ 3441 if (vp->v_object && 3442 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3443 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 3444 } 3445 error = VOP_FSYNC(vp, MNT_WAIT); 3446 } else { 3447 /* 3448 * Locate and synchronously write any buffers that fall 3449 * into the requested range. Note: we are assuming that 3450 * f_iosize is a power of 2. 3451 */ 3452 int iosize = vp->v_mount->mnt_stat.f_iosize; 3453 int iomask = iosize - 1; 3454 off_t loffset; 3455 3456 /* 3457 * Align to iosize boundry, super-align to page boundry. 3458 */ 3459 if (off & iomask) { 3460 cnt += off & iomask; 3461 off &= ~(u_quad_t)iomask; 3462 } 3463 if (off & PAGE_MASK) { 3464 cnt += off & PAGE_MASK; 3465 off &= ~(u_quad_t)PAGE_MASK; 3466 } 3467 loffset = off; 3468 3469 if (vp->v_object && 3470 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3471 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC); 3472 } 3473 3474 crit_enter(); 3475 while (cnt > 0) { 3476 struct buf *bp; 3477 3478 /* 3479 * If we have a buffer and it is marked B_DELWRI we 3480 * have to lock and write it. Otherwise the prior 3481 * write is assumed to have already been committed. 3482 */ 3483 if ((bp = findblk(vp, loffset)) != NULL && (bp->b_flags & B_DELWRI)) { 3484 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { 3485 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL) == 0) 3486 BUF_UNLOCK(bp); 3487 continue; /* retry */ 3488 } 3489 bremfree(bp); 3490 bp->b_flags &= ~B_ASYNC; 3491 bwrite(bp); 3492 ++nfs_commit_miss; 3493 } 3494 ++nfs_commit_blks; 3495 if (cnt < iosize) 3496 break; 3497 cnt -= iosize; 3498 loffset += iosize; 3499 } 3500 crit_exit(); 3501 } 3502 3503 aft_ret = VOP_GETATTR(vp, &aft); 3504 vput(vp); 3505 vp = NULL; 3506 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3507 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3508 if (!error) { 3509 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3510 if (nfsver.tv_sec == 0) 3511 nfsver = boottime; 3512 *tl++ = txdr_unsigned(nfsver.tv_sec); 3513 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 3514 } else { 3515 error = 0; 3516 } 3517 nfsmout: 3518 if (vp) 3519 vput(vp); 3520 return(error); 3521 } 3522 3523 /* 3524 * nfs statfs service 3525 */ 3526 int 3527 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3528 struct thread *td, struct mbuf **mrq) 3529 { 3530 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3531 struct sockaddr *nam = nfsd->nd_nam; 3532 caddr_t dpos = nfsd->nd_dpos; 3533 struct ucred *cred = &nfsd->nd_cr; 3534 struct statfs *sf; 3535 struct nfs_statfs *sfp; 3536 u_int32_t *tl; 3537 int32_t t1; 3538 caddr_t bpos; 3539 int error = 0, rdonly, getret = 1; 3540 int v3 = (nfsd->nd_flag & ND_NFSV3); 3541 char *cp2; 3542 struct mbuf *mb, *mb2, *mreq; 3543 struct vnode *vp = NULL; 3544 struct mount *mp = NULL; 3545 struct vattr at; 3546 nfsfh_t nfh; 3547 fhandle_t *fhp; 3548 struct statfs statfs; 3549 u_quad_t tval; 3550 3551 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3552 fhp = &nfh.fh_generic; 3553 nfsm_srvmtofh(fhp); 3554 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 3555 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3556 if (error) { 3557 nfsm_reply(NFSX_UNSIGNED); 3558 nfsm_srvpostop_attr(getret, &at); 3559 error = 0; 3560 goto nfsmout; 3561 } 3562 sf = &statfs; 3563 error = VFS_STATFS(vp->v_mount, sf, proc0.p_ucred); 3564 getret = VOP_GETATTR(vp, &at); 3565 vput(vp); 3566 vp = NULL; 3567 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3568 if (v3) 3569 nfsm_srvpostop_attr(getret, &at); 3570 if (error) { 3571 error = 0; 3572 goto nfsmout; 3573 } 3574 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3575 if (v3) { 3576 tval = (u_quad_t)sf->f_blocks; 3577 tval *= (u_quad_t)sf->f_bsize; 3578 txdr_hyper(tval, &sfp->sf_tbytes); 3579 tval = (u_quad_t)sf->f_bfree; 3580 tval *= (u_quad_t)sf->f_bsize; 3581 txdr_hyper(tval, &sfp->sf_fbytes); 3582 tval = (u_quad_t)sf->f_bavail; 3583 tval *= (u_quad_t)sf->f_bsize; 3584 txdr_hyper(tval, &sfp->sf_abytes); 3585 sfp->sf_tfiles.nfsuquad[0] = 0; 3586 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3587 sfp->sf_ffiles.nfsuquad[0] = 0; 3588 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3589 sfp->sf_afiles.nfsuquad[0] = 0; 3590 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3591 sfp->sf_invarsec = 0; 3592 } else { 3593 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3594 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3595 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3596 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3597 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3598 } 3599 nfsmout: 3600 if (vp) 3601 vput(vp); 3602 return(error); 3603 } 3604 3605 /* 3606 * nfs fsinfo service 3607 */ 3608 int 3609 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3610 struct thread *td, struct mbuf **mrq) 3611 { 3612 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3613 struct sockaddr *nam = nfsd->nd_nam; 3614 caddr_t dpos = nfsd->nd_dpos; 3615 struct ucred *cred = &nfsd->nd_cr; 3616 u_int32_t *tl; 3617 struct nfsv3_fsinfo *sip; 3618 int32_t t1; 3619 caddr_t bpos; 3620 int error = 0, rdonly, getret = 1, pref; 3621 char *cp2; 3622 struct mbuf *mb, *mb2, *mreq; 3623 struct vnode *vp = NULL; 3624 struct mount *mp = NULL; 3625 struct vattr at; 3626 nfsfh_t nfh; 3627 fhandle_t *fhp; 3628 u_quad_t maxfsize; 3629 struct statfs sb; 3630 3631 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3632 fhp = &nfh.fh_generic; 3633 nfsm_srvmtofh(fhp); 3634 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 3635 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3636 if (error) { 3637 nfsm_reply(NFSX_UNSIGNED); 3638 nfsm_srvpostop_attr(getret, &at); 3639 error = 0; 3640 goto nfsmout; 3641 } 3642 3643 /* XXX Try to make a guess on the max file size. */ 3644 VFS_STATFS(vp->v_mount, &sb, proc0.p_ucred); 3645 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; 3646 3647 getret = VOP_GETATTR(vp, &at); 3648 vput(vp); 3649 vp = NULL; 3650 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3651 nfsm_srvpostop_attr(getret, &at); 3652 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3653 3654 /* 3655 * XXX 3656 * There should be file system VFS OP(s) to get this information. 3657 * For now, assume ufs. 3658 */ 3659 if (slp->ns_so->so_type == SOCK_DGRAM) 3660 pref = NFS_MAXDGRAMDATA; 3661 else 3662 pref = NFS_MAXDATA; 3663 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3664 sip->fs_rtpref = txdr_unsigned(pref); 3665 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3666 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3667 sip->fs_wtpref = txdr_unsigned(pref); 3668 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3669 sip->fs_dtpref = txdr_unsigned(pref); 3670 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3671 sip->fs_timedelta.nfsv3_sec = 0; 3672 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3673 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3674 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3675 NFSV3FSINFO_CANSETTIME); 3676 nfsmout: 3677 if (vp) 3678 vput(vp); 3679 return(error); 3680 } 3681 3682 /* 3683 * nfs pathconf service 3684 */ 3685 int 3686 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3687 struct thread *td, struct mbuf **mrq) 3688 { 3689 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3690 struct sockaddr *nam = nfsd->nd_nam; 3691 caddr_t dpos = nfsd->nd_dpos; 3692 struct ucred *cred = &nfsd->nd_cr; 3693 u_int32_t *tl; 3694 struct nfsv3_pathconf *pc; 3695 int32_t t1; 3696 caddr_t bpos; 3697 int error = 0, rdonly, getret = 1; 3698 register_t linkmax, namemax, chownres, notrunc; 3699 char *cp2; 3700 struct mbuf *mb, *mb2, *mreq; 3701 struct vnode *vp = NULL; 3702 struct mount *mp = NULL; 3703 struct vattr at; 3704 nfsfh_t nfh; 3705 fhandle_t *fhp; 3706 3707 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3708 fhp = &nfh.fh_generic; 3709 nfsm_srvmtofh(fhp); 3710 error = nfsrv_fhtovp(fhp, 1, &mp, &vp, cred, slp, nam, 3711 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3712 if (error) { 3713 nfsm_reply(NFSX_UNSIGNED); 3714 nfsm_srvpostop_attr(getret, &at); 3715 error = 0; 3716 goto nfsmout; 3717 } 3718 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3719 if (!error) 3720 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3721 if (!error) 3722 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3723 if (!error) 3724 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3725 getret = VOP_GETATTR(vp, &at); 3726 vput(vp); 3727 vp = NULL; 3728 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3729 nfsm_srvpostop_attr(getret, &at); 3730 if (error) { 3731 error = 0; 3732 goto nfsmout; 3733 } 3734 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3735 3736 pc->pc_linkmax = txdr_unsigned(linkmax); 3737 pc->pc_namemax = txdr_unsigned(namemax); 3738 pc->pc_notrunc = txdr_unsigned(notrunc); 3739 pc->pc_chownrestricted = txdr_unsigned(chownres); 3740 3741 /* 3742 * These should probably be supported by VOP_PATHCONF(), but 3743 * until msdosfs is exportable (why would you want to?), the 3744 * Unix defaults should be ok. 3745 */ 3746 pc->pc_caseinsensitive = nfs_false; 3747 pc->pc_casepreserving = nfs_true; 3748 nfsmout: 3749 if (vp) 3750 vput(vp); 3751 return(error); 3752 } 3753 3754 /* 3755 * Null operation, used by clients to ping server 3756 */ 3757 /* ARGSUSED */ 3758 int 3759 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3760 struct thread *td, struct mbuf **mrq) 3761 { 3762 struct mbuf *mrep = nfsd->nd_mrep; 3763 caddr_t bpos; 3764 int error = NFSERR_RETVOID; 3765 struct mbuf *mb, *mreq; 3766 3767 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3768 nfsm_reply(0); 3769 nfsm_srvdone; 3770 } 3771 3772 /* 3773 * No operation, used for obsolete procedures 3774 */ 3775 /* ARGSUSED */ 3776 int 3777 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3778 struct thread *td, struct mbuf **mrq) 3779 { 3780 struct mbuf *mrep = nfsd->nd_mrep; 3781 caddr_t bpos; 3782 int error; 3783 struct mbuf *mb, *mreq; 3784 3785 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3786 if (nfsd->nd_repstat) 3787 error = nfsd->nd_repstat; 3788 else 3789 error = EPROCUNAVAIL; 3790 nfsm_reply(0); 3791 error = 0; 3792 nfsm_srvdone; 3793 } 3794 3795 /* 3796 * Perform access checking for vnodes obtained from file handles that would 3797 * refer to files already opened by a Unix client. You cannot just use 3798 * vn_writechk() and VOP_ACCESS() for two reasons. 3799 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3800 * 2 - The owner is to be given access irrespective of mode bits for some 3801 * operations, so that processes that chmod after opening a file don't 3802 * break. I don't like this because it opens a security hole, but since 3803 * the nfs server opens a security hole the size of a barn door anyhow, 3804 * what the heck. 3805 * 3806 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3807 * will return EPERM instead of EACCESS. EPERM is always an error. 3808 */ 3809 static int 3810 nfsrv_access(struct mount *mp, struct vnode *vp, int flags, struct ucred *cred, 3811 int rdonly, struct thread *td, int override) 3812 { 3813 struct vattr vattr; 3814 int error; 3815 3816 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3817 if (flags & VWRITE) { 3818 /* Just vn_writechk() changed to check rdonly */ 3819 /* 3820 * Disallow write attempts on read-only file systems; 3821 * unless the file is a socket or a block or character 3822 * device resident on the file system. 3823 */ 3824 if (rdonly || 3825 ((mp->mnt_flag | vp->v_mount->mnt_flag) & MNT_RDONLY)) { 3826 switch (vp->v_type) { 3827 case VREG: 3828 case VDIR: 3829 case VLNK: 3830 return (EROFS); 3831 default: 3832 break; 3833 } 3834 } 3835 /* 3836 * If there's shared text associated with 3837 * the inode, we can't allow writing. 3838 */ 3839 if (vp->v_flag & VTEXT) 3840 return (ETXTBSY); 3841 } 3842 error = VOP_GETATTR(vp, &vattr); 3843 if (error) 3844 return (error); 3845 error = VOP_ACCESS(vp, flags, cred); 3846 /* 3847 * Allow certain operations for the owner (reads and writes 3848 * on files that are already open). 3849 */ 3850 if (override && error == EACCES && cred->cr_uid == vattr.va_uid) 3851 error = 0; 3852 return error; 3853 } 3854 #endif /* NFS_NOSERVER */ 3855 3856