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