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.22 2004/12/29 02:41:26 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 "nfsproto.h" 92 #include "rpcv2.h" 93 #include "nfs.h" 94 #include "xdr_subs.h" 95 #include "nfsm_subs.h" 96 #include "nqnfs.h" 97 98 #ifdef NFSRV_DEBUG 99 #define nfsdbprintf(info) printf info 100 #else 101 #define nfsdbprintf(info) 102 #endif 103 104 #define MAX_COMMIT_COUNT (1024 * 1024) 105 106 #define NUM_HEURISTIC 1017 107 #define NHUSE_INIT 64 108 #define NHUSE_INC 16 109 #define NHUSE_MAX 2048 110 111 static struct nfsheur { 112 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */ 113 off_t nh_nextr; /* next offset for sequential detection */ 114 int nh_use; /* use count for selection */ 115 int nh_seqcount; /* heuristic */ 116 } nfsheur[NUM_HEURISTIC]; 117 118 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, 119 NFFIFO, NFNON }; 120 #ifndef NFS_NOSERVER 121 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 122 NFCHR, NFNON }; 123 /* Global vars */ 124 extern u_int32_t nfs_xdrneg1; 125 extern u_int32_t nfs_false, nfs_true; 126 extern enum vtype nv3tov_type[8]; 127 extern struct nfsstats nfsstats; 128 129 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000; 130 int nfsrvw_procrastinate_v3 = 0; 131 132 static struct timespec nfsver; 133 134 SYSCTL_DECL(_vfs_nfs); 135 136 static int nfs_async; 137 SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, ""); 138 static int nfs_commit_blks; 139 static int nfs_commit_miss; 140 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, ""); 141 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, ""); 142 143 static int nfsrv_access (struct vnode *,int,struct ucred *,int, 144 struct thread *, int); 145 static void nfsrvw_coalesce (struct nfsrv_descript *, 146 struct nfsrv_descript *); 147 148 /* 149 * nfs v3 access service 150 */ 151 int 152 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 153 struct thread *td, struct mbuf **mrq) 154 { 155 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 156 struct sockaddr *nam = nfsd->nd_nam; 157 caddr_t dpos = nfsd->nd_dpos; 158 struct ucred *cred = &nfsd->nd_cr; 159 struct vnode *vp = NULL; 160 nfsfh_t nfh; 161 fhandle_t *fhp; 162 u_int32_t *tl; 163 int32_t t1; 164 caddr_t bpos; 165 int error = 0, rdonly, cache, getret; 166 char *cp2; 167 struct mbuf *mb, *mreq, *mb2; 168 struct vattr vattr, *vap = &vattr; 169 u_long testmode, nfsmode; 170 u_quad_t frev; 171 172 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 173 #ifndef nolint 174 cache = 0; 175 #endif 176 fhp = &nfh.fh_generic; 177 nfsm_srvmtofh(fhp); 178 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 179 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, 180 (nfsd->nd_flag & ND_KERBAUTH), TRUE); 181 if (error) { 182 nfsm_reply(NFSX_UNSIGNED); 183 nfsm_srvpostop_attr(1, (struct vattr *)0); 184 error = 0; 185 goto nfsmout; 186 } 187 nfsmode = fxdr_unsigned(u_int32_t, *tl); 188 if ((nfsmode & NFSV3ACCESS_READ) && 189 nfsrv_access(vp, VREAD, cred, rdonly, td, 0)) 190 nfsmode &= ~NFSV3ACCESS_READ; 191 if (vp->v_type == VDIR) 192 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 193 NFSV3ACCESS_DELETE); 194 else 195 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 196 if ((nfsmode & testmode) && 197 nfsrv_access(vp, VWRITE, cred, rdonly, td, 0)) 198 nfsmode &= ~testmode; 199 if (vp->v_type == VDIR) 200 testmode = NFSV3ACCESS_LOOKUP; 201 else 202 testmode = NFSV3ACCESS_EXECUTE; 203 if ((nfsmode & testmode) && 204 nfsrv_access(vp, VEXEC, cred, rdonly, td, 0)) 205 nfsmode &= ~testmode; 206 getret = VOP_GETATTR(vp, vap, td); 207 vput(vp); 208 vp = NULL; 209 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED); 210 nfsm_srvpostop_attr(getret, vap); 211 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 212 *tl = txdr_unsigned(nfsmode); 213 nfsmout: 214 if (vp) 215 vput(vp); 216 return(error); 217 } 218 219 /* 220 * nfs getattr service 221 */ 222 int 223 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 224 struct thread *td, struct mbuf **mrq) 225 { 226 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 227 struct sockaddr *nam = nfsd->nd_nam; 228 caddr_t dpos = nfsd->nd_dpos; 229 struct ucred *cred = &nfsd->nd_cr; 230 struct nfs_fattr *fp; 231 struct vattr va; 232 struct vattr *vap = &va; 233 struct vnode *vp = NULL; 234 nfsfh_t nfh; 235 fhandle_t *fhp; 236 u_int32_t *tl; 237 int32_t t1; 238 caddr_t bpos; 239 int error = 0, rdonly, cache; 240 char *cp2; 241 struct mbuf *mb, *mb2, *mreq; 242 u_quad_t frev; 243 244 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 245 fhp = &nfh.fh_generic; 246 nfsm_srvmtofh(fhp); 247 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 248 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 249 if (error) { 250 nfsm_reply(0); 251 error = 0; 252 goto nfsmout; 253 } 254 nqsrv_getl(vp, ND_READ); 255 error = VOP_GETATTR(vp, vap, td); 256 vput(vp); 257 vp = NULL; 258 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 259 if (error) { 260 error = 0; 261 goto nfsmout; 262 } 263 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 264 nfsm_srvfillattr(vap, fp); 265 /* fall through */ 266 267 nfsmout: 268 if (vp) 269 vput(vp); 270 return(error); 271 } 272 273 /* 274 * nfs setattr service 275 */ 276 int 277 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 278 struct thread *td, struct mbuf **mrq) 279 { 280 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 281 struct sockaddr *nam = nfsd->nd_nam; 282 caddr_t dpos = nfsd->nd_dpos; 283 struct ucred *cred = &nfsd->nd_cr; 284 struct vattr va, preat; 285 struct vattr *vap = &va; 286 struct nfsv2_sattr *sp; 287 struct nfs_fattr *fp; 288 struct vnode *vp = NULL; 289 nfsfh_t nfh; 290 fhandle_t *fhp; 291 u_int32_t *tl; 292 int32_t t1; 293 caddr_t bpos; 294 int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1; 295 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0; 296 char *cp2; 297 struct mbuf *mb, *mb2, *mreq; 298 u_quad_t frev; 299 struct timespec guard; 300 301 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 302 fhp = &nfh.fh_generic; 303 nfsm_srvmtofh(fhp); 304 VATTR_NULL(vap); 305 if (v3) { 306 nfsm_srvsattr(vap); 307 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 308 gcheck = fxdr_unsigned(int, *tl); 309 if (gcheck) { 310 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 311 fxdr_nfsv3time(tl, &guard); 312 } 313 } else { 314 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 315 /* 316 * Nah nah nah nah na nah 317 * There is a bug in the Sun client that puts 0xffff in the mode 318 * field of sattr when it should put in 0xffffffff. The u_short 319 * doesn't sign extend. 320 * --> check the low order 2 bytes for 0xffff 321 */ 322 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 323 vap->va_mode = nfstov_mode(sp->sa_mode); 324 if (sp->sa_uid != nfs_xdrneg1) 325 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 326 if (sp->sa_gid != nfs_xdrneg1) 327 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 328 if (sp->sa_size != nfs_xdrneg1) 329 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size); 330 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) { 331 #ifdef notyet 332 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime); 333 #else 334 vap->va_atime.tv_sec = 335 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec); 336 vap->va_atime.tv_nsec = 0; 337 #endif 338 } 339 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1) 340 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime); 341 342 } 343 344 /* 345 * Now that we have all the fields, lets do it. 346 */ 347 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, 348 (nfsd->nd_flag & ND_KERBAUTH), TRUE); 349 if (error) { 350 nfsm_reply(2 * NFSX_UNSIGNED); 351 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 352 error = 0; 353 goto nfsmout; 354 } 355 356 /* 357 * vp now an active resource, pay careful attention to cleanup 358 */ 359 360 nqsrv_getl(vp, ND_WRITE); 361 if (v3) { 362 error = preat_ret = VOP_GETATTR(vp, &preat, td); 363 if (!error && gcheck && 364 (preat.va_ctime.tv_sec != guard.tv_sec || 365 preat.va_ctime.tv_nsec != guard.tv_nsec)) 366 error = NFSERR_NOT_SYNC; 367 if (error) { 368 vput(vp); 369 vp = NULL; 370 nfsm_reply(NFSX_WCCDATA(v3)); 371 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 372 error = 0; 373 goto nfsmout; 374 } 375 } 376 377 /* 378 * If the size is being changed write acces is required, otherwise 379 * just check for a read only file system. 380 */ 381 if (vap->va_size == ((u_quad_t)((quad_t) -1))) { 382 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 383 error = EROFS; 384 goto out; 385 } 386 } else { 387 if (vp->v_type == VDIR) { 388 error = EISDIR; 389 goto out; 390 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly, 391 td, 0)) != 0){ 392 goto out; 393 } 394 } 395 error = VOP_SETATTR(vp, vap, cred, td); 396 postat_ret = VOP_GETATTR(vp, vap, td); 397 if (!error) 398 error = postat_ret; 399 out: 400 vput(vp); 401 vp = NULL; 402 nfsm_reply(NFSX_WCCORFATTR(v3)); 403 if (v3) { 404 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 405 error = 0; 406 goto nfsmout; 407 } else { 408 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 409 nfsm_srvfillattr(vap, fp); 410 } 411 /* fall through */ 412 413 nfsmout: 414 if (vp) 415 vput(vp); 416 return(error); 417 } 418 419 /* 420 * nfs lookup rpc 421 */ 422 int 423 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 424 struct thread *td, struct mbuf **mrq) 425 { 426 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 427 struct sockaddr *nam = nfsd->nd_nam; 428 caddr_t dpos = nfsd->nd_dpos; 429 struct ucred *cred = &nfsd->nd_cr; 430 struct nfs_fattr *fp; 431 struct nlookupdata nd; 432 struct vnode *vp; 433 struct vnode *dirp; 434 struct namecache *ncp; 435 nfsfh_t nfh; 436 fhandle_t *fhp; 437 caddr_t cp; 438 u_int32_t *tl; 439 int32_t t1; 440 caddr_t bpos; 441 int error = 0, cache = 0, len, dirattr_ret = 1; 442 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag; 443 char *cp2; 444 struct mbuf *mb, *mb2, *mreq; 445 struct vattr va, dirattr, *vap = &va; 446 u_quad_t frev; 447 448 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 449 nlookup_zero(&nd); 450 dirp = NULL; 451 vp = NULL; 452 453 fhp = &nfh.fh_generic; 454 nfsm_srvmtofh(fhp); 455 nfsm_srvnamesiz(len); 456 457 pubflag = nfs_ispublicfh(fhp); 458 459 error = nfs_namei(&nd, cred, NAMEI_LOOKUP, NULL, &vp, 460 fhp, len, slp, nam, &md, &dpos, 461 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag); 462 463 /* 464 * namei failure, only dirp to cleanup. Clear out garbarge from 465 * structure in case macros jump to nfsmout. 466 */ 467 468 if (error) { 469 if (dirp) { 470 if (v3) 471 dirattr_ret = VOP_GETATTR(dirp, &dirattr, td); 472 vrele(dirp); 473 dirp = NULL; 474 } 475 nfsm_reply(NFSX_POSTOPATTR(v3)); 476 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 477 error = 0; 478 goto nfsmout; 479 } 480 481 /* 482 * Locate index file for public filehandle 483 * 484 * error is 0 on entry and 0 on exit from this block. 485 */ 486 487 if (pubflag) { 488 if (vp->v_type == VDIR && nfs_pub.np_index != NULL) { 489 /* 490 * Setup call to lookup() to see if we can find 491 * the index file. Arguably, this doesn't belong 492 * in a kernel.. Ugh. If an error occurs, do not 493 * try to install an index file and then clear the 494 * error. 495 * 496 * When we replace nd with ind and redirect ndp, 497 * maintenance of ni_startdir and ni_vp shift to 498 * ind and we have to clean them up in the old nd. 499 * However, the cnd resource continues to be maintained 500 * via the original nd. Confused? You aren't alone! 501 */ 502 VOP_UNLOCK(vp, 0, td); 503 ncp = cache_hold(nd.nl_ncp); 504 nlookup_done(&nd); 505 error = nlookup_init_raw(&nd, nfs_pub.np_index, 506 UIO_SYSSPACE, 0, cred, ncp); 507 cache_drop(ncp); 508 if (error == 0) 509 error = nlookup(&nd); 510 511 if (error == 0) { 512 /* 513 * Found an index file. Get rid of 514 * the old references. transfer vp and 515 * load up the new vp. Fortunately we do 516 * not have to deal with dvp, that would be 517 * a huge mess. 518 */ 519 if (dirp) 520 vrele(dirp); 521 dirp = vp; 522 vp = NULL; 523 error = cache_vget(nd.nl_ncp, nd.nl_cred, 524 LK_EXCLUSIVE, &vp); 525 KKASSERT(error == 0); 526 } 527 error = 0; 528 } 529 /* 530 * If the public filehandle was used, check that this lookup 531 * didn't result in a filehandle outside the publicly exported 532 * filesystem. We clear the poor vp here to avoid lockups due 533 * to NFS I/O. 534 */ 535 536 if (vp->v_mount != nfs_pub.np_mount) { 537 vput(vp); 538 vp = NULL; 539 error = EPERM; 540 } 541 } 542 543 if (dirp) { 544 if (v3) 545 dirattr_ret = VOP_GETATTR(dirp, &dirattr, td); 546 vrele(dirp); 547 dirp = NULL; 548 } 549 550 /* 551 * Resources at this point: 552 * ndp->ni_vp may not be NULL 553 * 554 */ 555 556 if (error) { 557 nfsm_reply(NFSX_POSTOPATTR(v3)); 558 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 559 error = 0; 560 goto nfsmout; 561 } 562 563 #if 0 564 /* XXX not sure how to deal with this */ 565 nqsrv_getl(ndp->ni_startdir, ND_READ); 566 #endif 567 568 /* 569 * Clear out some resources prior to potentially blocking. This 570 * is not as critical as ni_dvp resources in other routines, but 571 * it helps. 572 */ 573 nlookup_done(&nd); 574 575 /* 576 * Get underlying attribute, then release remaining resources ( for 577 * the same potential blocking reason ) and reply. 578 */ 579 bzero((caddr_t)fhp, sizeof(nfh)); 580 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 581 error = VFS_VPTOFH(vp, &fhp->fh_fid); 582 if (!error) 583 error = VOP_GETATTR(vp, vap, td); 584 585 vput(vp); 586 vp = NULL; 587 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3)); 588 if (error) { 589 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 590 error = 0; 591 goto nfsmout; 592 } 593 nfsm_srvfhtom(fhp, v3); 594 if (v3) { 595 nfsm_srvpostop_attr(0, vap); 596 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 597 } else { 598 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 599 nfsm_srvfillattr(vap, fp); 600 } 601 602 nfsmout: 603 if (dirp) 604 vrele(dirp); 605 nlookup_done(&nd); /* may be called twice */ 606 if (vp) 607 vput(vp); 608 return (error); 609 } 610 611 /* 612 * nfs readlink service 613 */ 614 int 615 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 616 struct thread *td, struct mbuf **mrq) 617 { 618 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 619 struct sockaddr *nam = nfsd->nd_nam; 620 caddr_t dpos = nfsd->nd_dpos; 621 struct ucred *cred = &nfsd->nd_cr; 622 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 623 struct iovec *ivp = iv; 624 struct mbuf *mp; 625 u_int32_t *tl; 626 int32_t t1; 627 caddr_t bpos; 628 int error = 0, rdonly, cache, i, tlen, len, getret; 629 int v3 = (nfsd->nd_flag & ND_NFSV3); 630 char *cp2; 631 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq; 632 struct vnode *vp = NULL; 633 struct vattr attr; 634 nfsfh_t nfh; 635 fhandle_t *fhp; 636 struct uio io, *uiop = &io; 637 u_quad_t frev; 638 639 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 640 #ifndef nolint 641 mp2 = (struct mbuf *)0; 642 #endif 643 mp3 = NULL; 644 fhp = &nfh.fh_generic; 645 nfsm_srvmtofh(fhp); 646 len = 0; 647 i = 0; 648 while (len < NFS_MAXPATHLEN) { 649 MGET(mp, MB_WAIT, MT_DATA); 650 MCLGET(mp, MB_WAIT); 651 mp->m_len = NFSMSIZ(mp); 652 if (len == 0) 653 mp3 = mp2 = mp; 654 else { 655 mp2->m_next = mp; 656 mp2 = mp; 657 } 658 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 659 mp->m_len = NFS_MAXPATHLEN-len; 660 len = NFS_MAXPATHLEN; 661 } else 662 len += mp->m_len; 663 ivp->iov_base = mtod(mp, caddr_t); 664 ivp->iov_len = mp->m_len; 665 i++; 666 ivp++; 667 } 668 uiop->uio_iov = iv; 669 uiop->uio_iovcnt = i; 670 uiop->uio_offset = 0; 671 uiop->uio_resid = len; 672 uiop->uio_rw = UIO_READ; 673 uiop->uio_segflg = UIO_SYSSPACE; 674 uiop->uio_td = NULL; 675 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 676 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 677 if (error) { 678 nfsm_reply(2 * NFSX_UNSIGNED); 679 nfsm_srvpostop_attr(1, (struct vattr *)0); 680 error = 0; 681 goto nfsmout; 682 } 683 if (vp->v_type != VLNK) { 684 if (v3) 685 error = EINVAL; 686 else 687 error = ENXIO; 688 goto out; 689 } 690 nqsrv_getl(vp, ND_READ); 691 error = VOP_READLINK(vp, uiop, cred); 692 out: 693 getret = VOP_GETATTR(vp, &attr, td); 694 vput(vp); 695 vp = NULL; 696 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED); 697 if (v3) { 698 nfsm_srvpostop_attr(getret, &attr); 699 if (error) { 700 error = 0; 701 goto nfsmout; 702 } 703 } 704 if (uiop->uio_resid > 0) { 705 len -= uiop->uio_resid; 706 tlen = nfsm_rndup(len); 707 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 708 } 709 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 710 *tl = txdr_unsigned(len); 711 mb->m_next = mp3; 712 mp3 = NULL; 713 nfsmout: 714 if (mp3) 715 m_freem(mp3); 716 if (vp) 717 vput(vp); 718 return(error); 719 } 720 721 /* 722 * nfs read service 723 */ 724 int 725 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 726 struct thread *td, struct mbuf **mrq) 727 { 728 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 729 struct sockaddr *nam = nfsd->nd_nam; 730 caddr_t dpos = nfsd->nd_dpos; 731 struct ucred *cred = &nfsd->nd_cr; 732 struct iovec *iv; 733 struct iovec *iv2; 734 struct mbuf *m; 735 struct nfs_fattr *fp; 736 u_int32_t *tl; 737 int32_t t1; 738 int i; 739 caddr_t bpos; 740 int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret; 741 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen; 742 char *cp2; 743 struct mbuf *mb, *mb2, *mreq; 744 struct mbuf *m2; 745 struct vnode *vp = NULL; 746 nfsfh_t nfh; 747 fhandle_t *fhp; 748 struct uio io, *uiop = &io; 749 struct vattr va, *vap = &va; 750 struct nfsheur *nh; 751 off_t off; 752 int ioflag = 0; 753 u_quad_t frev; 754 755 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 756 fhp = &nfh.fh_generic; 757 nfsm_srvmtofh(fhp); 758 if (v3) { 759 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 760 off = fxdr_hyper(tl); 761 } else { 762 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 763 off = (off_t)fxdr_unsigned(u_int32_t, *tl); 764 } 765 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd)); 766 767 /* 768 * Reference vp. If an error occurs, vp will be invalid, but we 769 * have to NULL it just in case. The macros might goto nfsmout 770 * as well. 771 */ 772 773 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 774 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 775 if (error) { 776 vp = NULL; 777 nfsm_reply(2 * NFSX_UNSIGNED); 778 nfsm_srvpostop_attr(1, (struct vattr *)0); 779 error = 0; 780 goto nfsmout; 781 } 782 783 if (vp->v_type != VREG) { 784 if (v3) 785 error = EINVAL; 786 else 787 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 788 } 789 if (!error) { 790 nqsrv_getl(vp, ND_READ); 791 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0) 792 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1); 793 } 794 getret = VOP_GETATTR(vp, vap, td); 795 if (!error) 796 error = getret; 797 if (error) { 798 vput(vp); 799 vp = NULL; 800 nfsm_reply(NFSX_POSTOPATTR(v3)); 801 nfsm_srvpostop_attr(getret, vap); 802 error = 0; 803 goto nfsmout; 804 } 805 806 /* 807 * Calculate byte count to read 808 */ 809 810 if (off >= vap->va_size) 811 cnt = 0; 812 else if ((off + reqlen) > vap->va_size) 813 cnt = vap->va_size - off; 814 else 815 cnt = reqlen; 816 817 /* 818 * Calculate seqcount for heuristic 819 */ 820 821 { 822 int hi; 823 int try = 32; 824 825 /* 826 * Locate best candidate 827 */ 828 829 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC; 830 nh = &nfsheur[hi]; 831 832 while (try--) { 833 if (nfsheur[hi].nh_vp == vp) { 834 nh = &nfsheur[hi]; 835 break; 836 } 837 if (nfsheur[hi].nh_use > 0) 838 --nfsheur[hi].nh_use; 839 hi = (hi + 1) % NUM_HEURISTIC; 840 if (nfsheur[hi].nh_use < nh->nh_use) 841 nh = &nfsheur[hi]; 842 } 843 844 if (nh->nh_vp != vp) { 845 nh->nh_vp = vp; 846 nh->nh_nextr = off; 847 nh->nh_use = NHUSE_INIT; 848 if (off == 0) 849 nh->nh_seqcount = 4; 850 else 851 nh->nh_seqcount = 1; 852 } 853 854 /* 855 * Calculate heuristic 856 */ 857 858 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) { 859 if (++nh->nh_seqcount > IO_SEQMAX) 860 nh->nh_seqcount = IO_SEQMAX; 861 } else if (nh->nh_seqcount > 1) { 862 nh->nh_seqcount = 1; 863 } else { 864 nh->nh_seqcount = 0; 865 } 866 nh->nh_use += NHUSE_INC; 867 if (nh->nh_use > NHUSE_MAX) 868 nh->nh_use = NHUSE_MAX; 869 ioflag |= nh->nh_seqcount << IO_SEQSHIFT; 870 } 871 872 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt)); 873 if (v3) { 874 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED); 875 *tl++ = nfs_true; 876 fp = (struct nfs_fattr *)tl; 877 tl += (NFSX_V3FATTR / sizeof (u_int32_t)); 878 } else { 879 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED); 880 fp = (struct nfs_fattr *)tl; 881 tl += (NFSX_V2FATTR / sizeof (u_int32_t)); 882 } 883 len = left = nfsm_rndup(cnt); 884 if (cnt > 0) { 885 /* 886 * Generate the mbuf list with the uio_iov ref. to it. 887 */ 888 i = 0; 889 m = m2 = mb; 890 while (left > 0) { 891 siz = min(M_TRAILINGSPACE(m), left); 892 if (siz > 0) { 893 left -= siz; 894 i++; 895 } 896 if (left > 0) { 897 MGET(m, MB_WAIT, MT_DATA); 898 MCLGET(m, MB_WAIT); 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, s, 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 s = splsoftclock(); 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 splx(s); 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 s = splsoftclock(); 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 splx(s); 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 s = splsoftclock(); 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 splx(s); 1469 } while (nfsd); 1470 s = splsoftclock(); 1471 swp->nd_time = 0; 1472 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq); 1473 splx(s); 1474 goto loop1; 1475 } 1476 splx(s); 1477 1478 /* 1479 * Search for a reply to return. 1480 */ 1481 s = splsoftclock(); 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 splx(s); 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 error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap); 1688 if (error == 0) { 1689 nfsrv_object_create(vp); 1690 if (exclusive_flag) { 1691 exclusive_flag = 0; 1692 VATTR_NULL(vap); 1693 bcopy(cverf, (caddr_t)&vap->va_atime, 1694 NFSX_V3CREATEVERF); 1695 error = VOP_SETATTR(vp, vap, cred, td); 1696 } 1697 } 1698 } else if ( 1699 vap->va_type == VCHR || 1700 vap->va_type == VBLK || 1701 vap->va_type == VFIFO 1702 ) { 1703 /* 1704 * Handle SysV FIFO node special cases. All other 1705 * devices require super user to access. 1706 */ 1707 if (vap->va_type == VCHR && rdev == 0xffffffff) 1708 vap->va_type = VFIFO; 1709 if (vap->va_type != VFIFO && 1710 (error = suser_cred(cred, 0))) { 1711 goto nfsmreply0; 1712 } 1713 vap->va_rdev = rdev; 1714 nqsrv_getl(dvp, ND_WRITE); 1715 1716 error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap); 1717 if (error) 1718 goto nfsmreply0; 1719 #if 0 1720 /* 1721 * XXX what is this junk supposed to do ? 1722 */ 1723 1724 vput(vp); 1725 vp = NULL; 1726 1727 /* 1728 * release dvp prior to lookup 1729 */ 1730 vput(dvp); 1731 dvp = NULL; 1732 1733 /* 1734 * Setup for lookup. 1735 * 1736 * Even though LOCKPARENT was cleared, ni_dvp may 1737 * be garbage. 1738 */ 1739 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 1740 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT); 1741 nd.ni_cnd.cn_td = td; 1742 nd.ni_cnd.cn_cred = cred; 1743 1744 error = lookup(&nd); 1745 nd.ni_dvp = NULL; 1746 1747 if (error != 0) { 1748 nfsm_reply(0); 1749 /* fall through on certain errors */ 1750 } 1751 nfsrv_object_create(nd.ni_vp); 1752 if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) { 1753 error = EINVAL; 1754 goto nfsmreply0; 1755 } 1756 #endif 1757 } else { 1758 error = ENXIO; 1759 } 1760 } else { 1761 if (vap->va_size != -1) { 1762 error = nfsrv_access(vp, VWRITE, cred, 1763 (nd.nl_flags & NLC_NFS_RDONLY), td, 0); 1764 if (!error) { 1765 nqsrv_getl(vp, ND_WRITE); 1766 tempsize = vap->va_size; 1767 VATTR_NULL(vap); 1768 vap->va_size = tempsize; 1769 error = VOP_SETATTR(vp, vap, cred, td); 1770 } 1771 } 1772 } 1773 1774 if (!error) { 1775 bzero((caddr_t)fhp, sizeof(nfh)); 1776 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1777 error = VFS_VPTOFH(vp, &fhp->fh_fid); 1778 if (!error) 1779 error = VOP_GETATTR(vp, vap, td); 1780 } 1781 if (v3) { 1782 if (exclusive_flag && !error && 1783 bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF)) 1784 error = EEXIST; 1785 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 1786 vrele(dirp); 1787 dirp = NULL; 1788 } 1789 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3)); 1790 if (v3) { 1791 if (!error) { 1792 nfsm_srvpostop_fh(fhp); 1793 nfsm_srvpostop_attr(0, vap); 1794 } 1795 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1796 error = 0; 1797 } else { 1798 nfsm_srvfhtom(fhp, v3); 1799 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1800 nfsm_srvfillattr(vap, fp); 1801 } 1802 goto nfsmout; 1803 1804 nfsmreply0: 1805 nfsm_reply(0); 1806 error = 0; 1807 /* fall through */ 1808 1809 nfsmout: 1810 if (dirp) 1811 vrele(dirp); 1812 nlookup_done(&nd); 1813 if (dvp) { 1814 if (dvp == vp) 1815 vrele(dvp); 1816 else 1817 vput(dvp); 1818 } 1819 if (vp) 1820 vput(vp); 1821 return (error); 1822 } 1823 1824 /* 1825 * nfs v3 mknod service 1826 */ 1827 int 1828 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 1829 struct thread *td, struct mbuf **mrq) 1830 { 1831 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1832 struct sockaddr *nam = nfsd->nd_nam; 1833 caddr_t dpos = nfsd->nd_dpos; 1834 struct ucred *cred = &nfsd->nd_cr; 1835 struct vattr va, dirfor, diraft; 1836 struct vattr *vap = &va; 1837 u_int32_t *tl; 1838 struct nlookupdata nd; 1839 int32_t t1; 1840 caddr_t bpos; 1841 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 1842 u_int32_t major, minor; 1843 enum vtype vtyp; 1844 char *cp2; 1845 struct mbuf *mb, *mb2, *mreq; 1846 struct vnode *dirp; 1847 struct vnode *dvp; 1848 struct vnode *vp; 1849 nfsfh_t nfh; 1850 fhandle_t *fhp; 1851 u_quad_t frev; 1852 1853 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1854 nlookup_zero(&nd); 1855 dirp = NULL; 1856 dvp = NULL; 1857 vp = NULL; 1858 1859 fhp = &nfh.fh_generic; 1860 nfsm_srvmtofh(fhp); 1861 nfsm_srvnamesiz(len); 1862 1863 /* 1864 * Handle nfs_namei() call. If an error occurs, the nd structure 1865 * is not valid. However, nfsm_*() routines may still jump to 1866 * nfsmout. 1867 */ 1868 1869 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 1870 fhp, len, slp, nam, &md, &dpos, &dirp, 1871 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 1872 if (dirp) 1873 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 1874 if (error) { 1875 nfsm_reply(NFSX_WCCDATA(1)); 1876 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1877 error = 0; 1878 goto nfsmout; 1879 } 1880 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1881 vtyp = nfsv3tov_type(*tl); 1882 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 1883 error = NFSERR_BADTYPE; 1884 goto out; 1885 } 1886 VATTR_NULL(vap); 1887 nfsm_srvsattr(vap); 1888 if (vtyp == VCHR || vtyp == VBLK) { 1889 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1890 major = fxdr_unsigned(u_int32_t, *tl++); 1891 minor = fxdr_unsigned(u_int32_t, *tl); 1892 vap->va_rdev = makeudev(major, minor); 1893 } 1894 1895 /* 1896 * Iff doesn't exist, create it. 1897 */ 1898 if (vp) { 1899 error = EEXIST; 1900 goto out; 1901 } 1902 vap->va_type = vtyp; 1903 if (vap->va_mode == (mode_t)VNOVAL) 1904 vap->va_mode = 0; 1905 if (vtyp == VSOCK) { 1906 nqsrv_getl(dvp, ND_WRITE); 1907 error = VOP_NCREATE(nd.nl_ncp, &vp, nd.nl_cred, vap); 1908 } else { 1909 if (vtyp != VFIFO && (error = suser_cred(cred, 0))) 1910 goto out; 1911 nqsrv_getl(dvp, ND_WRITE); 1912 1913 error = VOP_NMKNOD(nd.nl_ncp, &vp, nd.nl_cred, vap); 1914 if (error) 1915 goto out; 1916 1917 #if 0 1918 vput(vp); 1919 vp = NULL; 1920 1921 /* 1922 * Release dvp prior to lookup 1923 */ 1924 vput(dvp); 1925 dvp = NULL; 1926 1927 /* 1928 * XXX what is this stuff for? 1929 */ 1930 KKASSERT(td->td_proc); 1931 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 1932 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT); 1933 nd.ni_cnd.cn_td = td; 1934 nd.ni_cnd.cn_cred = td->td_proc->p_ucred; 1935 1936 error = lookup(&nd); 1937 nd.ni_dvp = NULL; 1938 1939 if (error) 1940 goto out; 1941 if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) 1942 error = EINVAL; 1943 #endif 1944 } 1945 1946 /* 1947 * send response, cleanup, return. 1948 */ 1949 out: 1950 nlookup_done(&nd); 1951 if (dvp) { 1952 if (dvp == vp) 1953 vrele(dvp); 1954 else 1955 vput(dvp); 1956 dvp = NULL; 1957 } 1958 if (!error) { 1959 bzero((caddr_t)fhp, sizeof(nfh)); 1960 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1961 error = VFS_VPTOFH(vp, &fhp->fh_fid); 1962 if (!error) 1963 error = VOP_GETATTR(vp, vap, td); 1964 } 1965 if (vp) { 1966 vput(vp); 1967 vp = NULL; 1968 } 1969 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 1970 if (dirp) { 1971 vrele(dirp); 1972 dirp = NULL; 1973 } 1974 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1)); 1975 if (!error) { 1976 nfsm_srvpostop_fh(fhp); 1977 nfsm_srvpostop_attr(0, vap); 1978 } 1979 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1980 return (0); 1981 nfsmout: 1982 if (dirp) 1983 vrele(dirp); 1984 nlookup_done(&nd); 1985 if (dvp) { 1986 if (dvp == vp) 1987 vrele(dvp); 1988 else 1989 vput(dvp); 1990 } 1991 if (vp) 1992 vput(vp); 1993 return (error); 1994 } 1995 1996 /* 1997 * nfs remove service 1998 */ 1999 int 2000 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2001 struct thread *td, struct mbuf **mrq) 2002 { 2003 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2004 struct sockaddr *nam = nfsd->nd_nam; 2005 caddr_t dpos = nfsd->nd_dpos; 2006 struct ucred *cred = &nfsd->nd_cr; 2007 struct nlookupdata nd; 2008 u_int32_t *tl; 2009 int32_t t1; 2010 caddr_t bpos; 2011 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 2012 int v3 = (nfsd->nd_flag & ND_NFSV3); 2013 char *cp2; 2014 struct mbuf *mb, *mreq; 2015 struct vnode *dirp; 2016 struct vnode *dvp; 2017 struct vnode *vp; 2018 struct vattr dirfor, diraft; 2019 nfsfh_t nfh; 2020 fhandle_t *fhp; 2021 u_quad_t frev; 2022 2023 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2024 nlookup_zero(&nd); 2025 dirp = NULL; 2026 dvp = NULL; 2027 vp = NULL; 2028 2029 fhp = &nfh.fh_generic; 2030 nfsm_srvmtofh(fhp); 2031 nfsm_srvnamesiz(len); 2032 2033 error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp, 2034 fhp, len, slp, nam, &md, &dpos, &dirp, 2035 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2036 if (dirp) { 2037 if (v3) 2038 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2039 } 2040 if (error == 0) { 2041 if (vp->v_type == VDIR) { 2042 error = EPERM; /* POSIX */ 2043 goto out; 2044 } 2045 /* 2046 * The root of a mounted filesystem cannot be deleted. 2047 */ 2048 if (vp->v_flag & VROOT) { 2049 error = EBUSY; 2050 goto out; 2051 } 2052 out: 2053 if (!error) { 2054 nqsrv_getl(dvp, ND_WRITE); 2055 nqsrv_getl(vp, ND_WRITE); 2056 error = VOP_NREMOVE(nd.nl_ncp, nd.nl_cred); 2057 } 2058 } 2059 if (dirp && v3) 2060 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2061 nfsm_reply(NFSX_WCCDATA(v3)); 2062 if (v3) { 2063 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2064 error = 0; 2065 } 2066 nfsmout: 2067 nlookup_done(&nd); 2068 if (dirp) 2069 vrele(dirp); 2070 if (dvp) { 2071 if (dvp == vp) 2072 vrele(dvp); 2073 else 2074 vput(dvp); 2075 } 2076 if (vp) 2077 vput(vp); 2078 return(error); 2079 } 2080 2081 /* 2082 * nfs rename service 2083 */ 2084 int 2085 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2086 struct thread *td, struct mbuf **mrq) 2087 { 2088 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2089 struct sockaddr *nam = nfsd->nd_nam; 2090 caddr_t dpos = nfsd->nd_dpos; 2091 struct ucred *cred = &nfsd->nd_cr; 2092 u_int32_t *tl; 2093 int32_t t1; 2094 caddr_t bpos; 2095 int error = 0, cache = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1; 2096 int tdirfor_ret = 1, tdiraft_ret = 1; 2097 int v3 = (nfsd->nd_flag & ND_NFSV3); 2098 char *cp2; 2099 struct mbuf *mb, *mreq; 2100 struct nlookupdata fromnd, tond; 2101 struct vnode *fvp, *fdirp; 2102 struct vnode *tvp, *tdirp; 2103 struct namecache *ncp; 2104 struct vattr fdirfor, fdiraft, tdirfor, tdiraft; 2105 nfsfh_t fnfh, tnfh; 2106 fhandle_t *ffhp, *tfhp; 2107 u_quad_t frev; 2108 uid_t saved_uid; 2109 2110 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2111 #ifndef nolint 2112 fvp = (struct vnode *)0; 2113 #endif 2114 ffhp = &fnfh.fh_generic; 2115 tfhp = &tnfh.fh_generic; 2116 2117 /* 2118 * Clear fields incase goto nfsmout occurs from macro. 2119 */ 2120 2121 nlookup_zero(&fromnd); 2122 nlookup_zero(&tond); 2123 fdirp = NULL; 2124 tdirp = NULL; 2125 2126 nfsm_srvmtofh(ffhp); 2127 nfsm_srvnamesiz(len); 2128 /* 2129 * Remember our original uid so that we can reset cr_uid before 2130 * the second nfs_namei() call, in case it is remapped. 2131 */ 2132 saved_uid = cred->cr_uid; 2133 error = nfs_namei(&fromnd, cred, NAMEI_DELETE, NULL, NULL, 2134 ffhp, len, slp, nam, &md, &dpos, &fdirp, 2135 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2136 if (fdirp) { 2137 if (v3) 2138 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, td); 2139 } 2140 if (error) { 2141 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2142 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2143 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2144 error = 0; 2145 goto nfsmout; 2146 } 2147 2148 /* 2149 * We have to unlock the from ncp before we can safely lookup 2150 * the target ncp. 2151 */ 2152 KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED); 2153 cache_unlock(fromnd.nl_ncp); 2154 fromnd.nl_flags &= ~NLC_NCPISLOCKED; 2155 nfsm_srvmtofh(tfhp); 2156 nfsm_strsiz(len2, NFS_MAXNAMLEN); 2157 cred->cr_uid = saved_uid; 2158 2159 error = nfs_namei(&tond, cred, NAMEI_RENAME, NULL, NULL, 2160 tfhp, len2, slp, nam, &md, &dpos, &tdirp, 2161 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2162 if (tdirp) { 2163 if (v3) 2164 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, td); 2165 } 2166 if (error) 2167 goto out1; 2168 2169 /* 2170 * relock the source 2171 */ 2172 if (cache_lock_nonblock(fromnd.nl_ncp) == 0) { 2173 cache_resolve(fromnd.nl_ncp, fromnd.nl_cred); 2174 } else if (fromnd.nl_ncp > tond.nl_ncp) { 2175 cache_lock(fromnd.nl_ncp); 2176 cache_resolve(fromnd.nl_ncp, fromnd.nl_cred); 2177 } else { 2178 cache_unlock(tond.nl_ncp); 2179 cache_lock(fromnd.nl_ncp); 2180 cache_resolve(fromnd.nl_ncp, fromnd.nl_cred); 2181 cache_lock(tond.nl_ncp); 2182 cache_resolve(tond.nl_ncp, tond.nl_cred); 2183 } 2184 fromnd.nl_flags |= NLC_NCPISLOCKED; 2185 2186 tvp = tond.nl_ncp->nc_vp; 2187 fvp = fromnd.nl_ncp->nc_vp; 2188 2189 if (tvp != NULL) { 2190 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2191 if (v3) 2192 error = EEXIST; 2193 else 2194 error = EISDIR; 2195 goto out; 2196 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2197 if (v3) 2198 error = EEXIST; 2199 else 2200 error = ENOTDIR; 2201 goto out; 2202 } 2203 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 2204 if (v3) 2205 error = EXDEV; 2206 else 2207 error = ENOTEMPTY; 2208 goto out; 2209 } 2210 } 2211 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 2212 if (v3) 2213 error = EXDEV; 2214 else 2215 error = ENOTEMPTY; 2216 goto out; 2217 } 2218 if (fromnd.nl_ncp->nc_mount != tond.nl_ncp->nc_mount) { 2219 if (v3) 2220 error = EXDEV; 2221 else 2222 error = ENOTEMPTY; 2223 goto out; 2224 } 2225 if (fromnd.nl_ncp == tond.nl_ncp->nc_parent) { 2226 if (v3) 2227 error = EINVAL; 2228 else 2229 error = ENOTEMPTY; 2230 } 2231 2232 /* 2233 * You cannot rename a source into itself or a subdirectory of itself. 2234 * We check this by travsering the target directory upwards looking 2235 * for a match against the source. 2236 */ 2237 if (error == 0) { 2238 for (ncp = tond.nl_ncp; ncp; ncp = ncp->nc_parent) { 2239 if (fromnd.nl_ncp == ncp) { 2240 error = EINVAL; 2241 break; 2242 } 2243 } 2244 } 2245 2246 /* 2247 * If source is the same as the destination (that is the 2248 * same vnode with the same name in the same directory), 2249 * then there is nothing to do. 2250 */ 2251 if (fromnd.nl_ncp == tond.nl_ncp) 2252 error = -1; 2253 out: 2254 if (!error) { 2255 /* 2256 * The VOP_NRENAME function releases all vnode references & 2257 * locks prior to returning so we need to clear the pointers 2258 * to bypass cleanup code later on. 2259 */ 2260 #if 0 2261 /* XXX should be handled by NRENAME */ 2262 nqsrv_getl(fdvp, ND_WRITE); 2263 nqsrv_getl(tdvp, ND_WRITE); 2264 if (tvp) { 2265 nqsrv_getl(tvp, ND_WRITE); 2266 } 2267 #endif 2268 error = VOP_NRENAME(fromnd.nl_ncp, tond.nl_ncp, tond.nl_cred); 2269 } else { 2270 if (error == -1) 2271 error = 0; 2272 } 2273 /* fall through */ 2274 2275 out1: 2276 if (fdirp) 2277 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, td); 2278 if (tdirp) 2279 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, td); 2280 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2281 if (v3) { 2282 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2283 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2284 } 2285 error = 0; 2286 /* fall through */ 2287 2288 nfsmout: 2289 if (tdirp) 2290 vrele(tdirp); 2291 nlookup_done(&tond); 2292 if (fdirp) 2293 vrele(fdirp); 2294 nlookup_done(&fromnd); 2295 return (error); 2296 } 2297 2298 /* 2299 * nfs link service 2300 */ 2301 int 2302 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2303 struct thread *td, struct mbuf **mrq) 2304 { 2305 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2306 struct sockaddr *nam = nfsd->nd_nam; 2307 caddr_t dpos = nfsd->nd_dpos; 2308 struct ucred *cred = &nfsd->nd_cr; 2309 struct nlookupdata nd; 2310 u_int32_t *tl; 2311 int32_t t1; 2312 caddr_t bpos; 2313 int error = 0, rdonly, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2314 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 2315 char *cp2; 2316 struct mbuf *mb, *mreq; 2317 struct vnode *dirp; 2318 struct vnode *dvp; 2319 struct vnode *vp; 2320 struct vnode *xp; 2321 struct vattr dirfor, diraft, at; 2322 nfsfh_t nfh, dnfh; 2323 fhandle_t *fhp, *dfhp; 2324 u_quad_t frev; 2325 2326 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2327 nlookup_zero(&nd); 2328 dirp = dvp = vp = xp = NULL; 2329 2330 fhp = &nfh.fh_generic; 2331 dfhp = &dnfh.fh_generic; 2332 nfsm_srvmtofh(fhp); 2333 nfsm_srvmtofh(dfhp); 2334 nfsm_srvnamesiz(len); 2335 2336 error = nfsrv_fhtovp(fhp, FALSE, &xp, cred, slp, nam, 2337 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2338 if (error) { 2339 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2340 nfsm_srvpostop_attr(getret, &at); 2341 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2342 xp = NULL; 2343 error = 0; 2344 goto nfsmout; 2345 } 2346 if (xp->v_type == VDIR) { 2347 error = EPERM; /* POSIX */ 2348 goto out1; 2349 } 2350 2351 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 2352 dfhp, len, slp, nam, &md, &dpos, &dirp, 2353 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2354 if (dirp) { 2355 if (v3) 2356 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2357 } 2358 if (error) 2359 goto out1; 2360 2361 if (vp != NULL) { 2362 error = EEXIST; 2363 goto out; 2364 } 2365 if (xp->v_mount != dvp->v_mount) 2366 error = EXDEV; 2367 out: 2368 if (!error) { 2369 #if 0 2370 nqsrv_getl(xp, ND_WRITE); 2371 nqsrv_getl(vp, ND_WRITE); 2372 #endif 2373 error = VOP_NLINK(nd.nl_ncp, xp, nd.nl_cred); 2374 } 2375 /* fall through */ 2376 2377 out1: 2378 if (v3) 2379 getret = VOP_GETATTR(xp, &at, td); 2380 if (dirp) 2381 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2382 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2383 if (v3) { 2384 nfsm_srvpostop_attr(getret, &at); 2385 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2386 error = 0; 2387 } 2388 /* fall through */ 2389 2390 nfsmout: 2391 nlookup_done(&nd); 2392 if (dirp) 2393 vrele(dirp); 2394 if (xp) 2395 vrele(xp); 2396 if (dvp) { 2397 if (dvp == vp) 2398 vrele(dvp); 2399 else 2400 vput(dvp); 2401 } 2402 if (vp) 2403 vput(vp); 2404 return(error); 2405 } 2406 2407 /* 2408 * nfs symbolic link service 2409 */ 2410 int 2411 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2412 struct thread *td, struct mbuf **mrq) 2413 { 2414 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2415 struct sockaddr *nam = nfsd->nd_nam; 2416 caddr_t dpos = nfsd->nd_dpos; 2417 struct ucred *cred = &nfsd->nd_cr; 2418 struct vattr va, dirfor, diraft; 2419 struct nlookupdata nd; 2420 struct vattr *vap = &va; 2421 u_int32_t *tl; 2422 int32_t t1; 2423 struct nfsv2_sattr *sp; 2424 char *bpos, *pathcp = (char *)0, *cp2; 2425 struct uio io; 2426 struct iovec iv; 2427 int error = 0, cache = 0, len, len2, dirfor_ret = 1, diraft_ret = 1; 2428 int v3 = (nfsd->nd_flag & ND_NFSV3); 2429 struct mbuf *mb, *mreq, *mb2; 2430 struct vnode *dirp; 2431 struct vnode *vp; 2432 nfsfh_t nfh; 2433 fhandle_t *fhp; 2434 u_quad_t frev; 2435 2436 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2437 nlookup_zero(&nd); 2438 dirp = vp = NULL; 2439 2440 fhp = &nfh.fh_generic; 2441 nfsm_srvmtofh(fhp); 2442 nfsm_srvnamesiz(len); 2443 2444 error = nfs_namei(&nd, cred, NAMEI_CREATE, NULL, &vp, 2445 fhp, len, slp, nam, &md, &dpos, &dirp, 2446 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2447 if (dirp) { 2448 if (v3) 2449 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2450 } 2451 if (error) 2452 goto out; 2453 2454 VATTR_NULL(vap); 2455 if (v3) 2456 nfsm_srvsattr(vap); 2457 nfsm_strsiz(len2, NFS_MAXPATHLEN); 2458 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 2459 iv.iov_base = pathcp; 2460 iv.iov_len = len2; 2461 io.uio_resid = len2; 2462 io.uio_offset = 0; 2463 io.uio_iov = &iv; 2464 io.uio_iovcnt = 1; 2465 io.uio_segflg = UIO_SYSSPACE; 2466 io.uio_rw = UIO_READ; 2467 io.uio_td = NULL; 2468 nfsm_mtouio(&io, len2); 2469 if (!v3) { 2470 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2471 vap->va_mode = nfstov_mode(sp->sa_mode); 2472 } 2473 *(pathcp + len2) = '\0'; 2474 if (vp) { 2475 error = EEXIST; 2476 goto out; 2477 } 2478 2479 if (vap->va_mode == (mode_t)VNOVAL) 2480 vap->va_mode = 0; 2481 #if 0 2482 nqsrv_getl(dvp, ND_WRITE); 2483 #endif 2484 error = VOP_NSYMLINK(nd.nl_ncp, &vp, nd.nl_cred, vap, pathcp); 2485 if (error == 0) { 2486 bzero((caddr_t)fhp, sizeof(nfh)); 2487 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 2488 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2489 if (!error) 2490 error = VOP_GETATTR(vp, vap, td); 2491 } 2492 2493 #if 0 2494 /* 2495 * We have a vp in hand from the new API call, we do not have to 2496 * look it up again. 2497 */ 2498 if (error == 0) { 2499 if (v3) { 2500 /* 2501 * Issue lookup. Leave SAVESTART set so we can easily free 2502 * the name buffer later on. 2503 * 2504 * since LOCKPARENT is not set, ni_dvp will be garbage on 2505 * return whether an error occurs or not. 2506 */ 2507 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 2508 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT | CNP_FOLLOW); 2509 nd.ni_cnd.cn_td = td; 2510 nd.ni_cnd.cn_cred = cred; 2511 2512 error = lookup(&nd); 2513 nd.ni_dvp = NULL; 2514 2515 if (error == 0) { 2516 bzero((caddr_t)fhp, sizeof(nfh)); 2517 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid; 2518 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid); 2519 if (!error) 2520 error = VOP_GETATTR(nd.ni_vp, vap, td); 2521 vput(nd.ni_vp); 2522 nd.ni_vp = NULL; 2523 } 2524 } 2525 } 2526 #endif 2527 out: 2528 if (vp) { 2529 vput(vp); 2530 vp = NULL; 2531 } 2532 if (pathcp) { 2533 FREE(pathcp, M_TEMP); 2534 pathcp = NULL; 2535 } 2536 if (dirp) { 2537 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2538 vrele(dirp); 2539 dirp = NULL; 2540 } 2541 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2542 if (v3) { 2543 if (!error) { 2544 nfsm_srvpostop_fh(fhp); 2545 nfsm_srvpostop_attr(0, vap); 2546 } 2547 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2548 } 2549 error = 0; 2550 /* fall through */ 2551 2552 nfsmout: 2553 nlookup_done(&nd); 2554 if (vp) 2555 vput(vp); 2556 if (dirp) 2557 vrele(dirp); 2558 if (pathcp) 2559 FREE(pathcp, M_TEMP); 2560 return (error); 2561 } 2562 2563 /* 2564 * nfs mkdir service 2565 */ 2566 int 2567 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2568 struct thread *td, struct mbuf **mrq) 2569 { 2570 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2571 struct sockaddr *nam = nfsd->nd_nam; 2572 caddr_t dpos = nfsd->nd_dpos; 2573 struct ucred *cred = &nfsd->nd_cr; 2574 struct vattr va, dirfor, diraft; 2575 struct vattr *vap = &va; 2576 struct nfs_fattr *fp; 2577 struct nlookupdata nd; 2578 caddr_t cp; 2579 u_int32_t *tl; 2580 int32_t t1; 2581 caddr_t bpos; 2582 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2583 int v3 = (nfsd->nd_flag & ND_NFSV3); 2584 char *cp2; 2585 struct mbuf *mb, *mb2, *mreq; 2586 struct vnode *dirp; 2587 struct vnode *vp; 2588 nfsfh_t nfh; 2589 fhandle_t *fhp; 2590 u_quad_t frev; 2591 2592 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2593 nlookup_zero(&nd); 2594 dirp = NULL; 2595 vp = NULL; 2596 2597 fhp = &nfh.fh_generic; 2598 nfsm_srvmtofh(fhp); 2599 nfsm_srvnamesiz(len); 2600 2601 error = nfs_namei(&nd, cred, NAMEI_CREATE, NULL, &vp, 2602 fhp, len, slp, nam, &md, &dpos, &dirp, 2603 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2604 if (dirp) { 2605 if (v3) 2606 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2607 } 2608 if (error) { 2609 nfsm_reply(NFSX_WCCDATA(v3)); 2610 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2611 error = 0; 2612 goto nfsmout; 2613 } 2614 VATTR_NULL(vap); 2615 if (v3) { 2616 nfsm_srvsattr(vap); 2617 } else { 2618 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2619 vap->va_mode = nfstov_mode(*tl++); 2620 } 2621 2622 /* 2623 * At this point nd.ni_dvp is referenced and exclusively locked and 2624 * nd.ni_vp, if it exists, is referenced but not locked. 2625 */ 2626 2627 vap->va_type = VDIR; 2628 if (vp != NULL) { 2629 error = EEXIST; 2630 goto out; 2631 } 2632 2633 /* 2634 * Issue mkdir op. Since SAVESTART is not set, the pathname 2635 * component is freed by the VOP call. This will fill-in 2636 * nd.ni_vp, reference, and exclusively lock it. 2637 */ 2638 if (vap->va_mode == (mode_t)VNOVAL) 2639 vap->va_mode = 0; 2640 #if 0 2641 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2642 #endif 2643 error = VOP_NMKDIR(nd.nl_ncp, &vp, nd.nl_cred, vap); 2644 2645 if (error == 0) { 2646 bzero((caddr_t)fhp, sizeof(nfh)); 2647 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 2648 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2649 if (error == 0) 2650 error = VOP_GETATTR(vp, vap, td); 2651 } 2652 out: 2653 if (dirp) 2654 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2655 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2656 if (v3) { 2657 if (!error) { 2658 nfsm_srvpostop_fh(fhp); 2659 nfsm_srvpostop_attr(0, vap); 2660 } 2661 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2662 } else { 2663 nfsm_srvfhtom(fhp, v3); 2664 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2665 nfsm_srvfillattr(vap, fp); 2666 } 2667 error = 0; 2668 /* fall through */ 2669 2670 nfsmout: 2671 nlookup_done(&nd); 2672 if (dirp) 2673 vrele(dirp); 2674 if (vp) 2675 vput(vp); 2676 return (error); 2677 } 2678 2679 /* 2680 * nfs rmdir service 2681 */ 2682 int 2683 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2684 struct thread *td, struct mbuf **mrq) 2685 { 2686 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2687 struct sockaddr *nam = nfsd->nd_nam; 2688 caddr_t dpos = nfsd->nd_dpos; 2689 struct ucred *cred = &nfsd->nd_cr; 2690 u_int32_t *tl; 2691 int32_t t1; 2692 caddr_t bpos; 2693 int error = 0, cache = 0, len, dirfor_ret = 1, diraft_ret = 1; 2694 int v3 = (nfsd->nd_flag & ND_NFSV3); 2695 char *cp2; 2696 struct mbuf *mb, *mreq; 2697 struct vnode *dirp; 2698 struct vnode *vp; 2699 struct vattr dirfor, diraft; 2700 nfsfh_t nfh; 2701 fhandle_t *fhp; 2702 struct nlookupdata nd; 2703 u_quad_t frev; 2704 2705 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2706 nlookup_zero(&nd); 2707 dirp = NULL; 2708 vp = NULL; 2709 2710 fhp = &nfh.fh_generic; 2711 nfsm_srvmtofh(fhp); 2712 nfsm_srvnamesiz(len); 2713 2714 error = nfs_namei(&nd, cred, NAMEI_DELETE, NULL, &vp, 2715 fhp, len, slp, nam, &md, &dpos, &dirp, 2716 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2717 if (dirp) { 2718 if (v3) 2719 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2720 } 2721 if (error) { 2722 nfsm_reply(NFSX_WCCDATA(v3)); 2723 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2724 error = 0; 2725 goto nfsmout; 2726 } 2727 if (vp->v_type != VDIR) { 2728 error = ENOTDIR; 2729 goto out; 2730 } 2731 2732 /* 2733 * The root of a mounted filesystem cannot be deleted. 2734 */ 2735 if (vp->v_flag & VROOT) 2736 error = EBUSY; 2737 out: 2738 /* 2739 * Issue or abort op. Since SAVESTART is not set, path name 2740 * component is freed by the VOP after either. 2741 */ 2742 if (!error) { 2743 #if 0 2744 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2745 nqsrv_getl(vp, ND_WRITE); 2746 #endif 2747 vput(vp); 2748 vp = NULL; 2749 error = VOP_NRMDIR(nd.nl_ncp, nd.nl_cred); 2750 } 2751 nlookup_done(&nd); 2752 2753 if (dirp) 2754 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2755 nfsm_reply(NFSX_WCCDATA(v3)); 2756 if (v3) { 2757 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2758 error = 0; 2759 } 2760 /* fall through */ 2761 2762 nfsmout: 2763 nlookup_done(&nd); 2764 if (dirp) 2765 vrele(dirp); 2766 if (vp) 2767 vput(vp); 2768 return(error); 2769 } 2770 2771 /* 2772 * nfs readdir service 2773 * - mallocs what it thinks is enough to read 2774 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 2775 * - calls VOP_READDIR() 2776 * - loops around building the reply 2777 * if the output generated exceeds count break out of loop 2778 * The nfsm_clget macro is used here so that the reply will be packed 2779 * tightly in mbuf clusters. 2780 * - it only knows that it has encountered eof when the VOP_READDIR() 2781 * reads nothing 2782 * - as such one readdir rpc will return eof false although you are there 2783 * and then the next will return eof 2784 * - it trims out records with d_fileno == 0 2785 * this doesn't matter for Unix clients, but they might confuse clients 2786 * for other os'. 2787 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2788 * than requested, but this may not apply to all filesystems. For 2789 * example, client NFS does not { although it is never remote mounted 2790 * anyhow } 2791 * The alternate call nfsrv_readdirplus() does lookups as well. 2792 * PS: The NFS protocol spec. does not clarify what the "count" byte 2793 * argument is a count of.. just name strings and file id's or the 2794 * entire reply rpc or ... 2795 * I tried just file name and id sizes and it confused the Sun client, 2796 * so I am using the full rpc size now. The "paranoia.." comment refers 2797 * to including the status longwords that are not a part of the dir. 2798 * "entry" structures, but are in the rpc. 2799 */ 2800 struct flrep { 2801 nfsuint64 fl_off; 2802 u_int32_t fl_postopok; 2803 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)]; 2804 u_int32_t fl_fhok; 2805 u_int32_t fl_fhsize; 2806 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)]; 2807 }; 2808 2809 int 2810 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2811 struct thread *td, struct mbuf **mrq) 2812 { 2813 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2814 struct sockaddr *nam = nfsd->nd_nam; 2815 caddr_t dpos = nfsd->nd_dpos; 2816 struct ucred *cred = &nfsd->nd_cr; 2817 char *bp, *be; 2818 struct mbuf *mp; 2819 struct dirent *dp; 2820 caddr_t cp; 2821 u_int32_t *tl; 2822 int32_t t1; 2823 caddr_t bpos; 2824 struct mbuf *mb, *mb2, *mreq, *mp2; 2825 char *cpos, *cend, *cp2, *rbuf; 2826 struct vnode *vp = NULL; 2827 struct vattr at; 2828 nfsfh_t nfh; 2829 fhandle_t *fhp; 2830 struct uio io; 2831 struct iovec iv; 2832 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2833 int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies; 2834 int v3 = (nfsd->nd_flag & ND_NFSV3); 2835 u_quad_t frev, off, toff, verf; 2836 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 2837 2838 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2839 fhp = &nfh.fh_generic; 2840 nfsm_srvmtofh(fhp); 2841 if (v3) { 2842 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2843 toff = fxdr_hyper(tl); 2844 tl += 2; 2845 verf = fxdr_hyper(tl); 2846 tl += 2; 2847 } else { 2848 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2849 toff = fxdr_unsigned(u_quad_t, *tl++); 2850 verf = 0; /* shut up gcc */ 2851 } 2852 off = toff; 2853 cnt = fxdr_unsigned(int, *tl); 2854 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2855 xfer = NFS_SRVMAXDATA(nfsd); 2856 if (cnt > xfer) 2857 cnt = xfer; 2858 if (siz > xfer) 2859 siz = xfer; 2860 fullsiz = siz; 2861 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2862 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2863 if (!error && vp->v_type != VDIR) { 2864 error = ENOTDIR; 2865 vput(vp); 2866 vp = NULL; 2867 } 2868 if (error) { 2869 nfsm_reply(NFSX_UNSIGNED); 2870 nfsm_srvpostop_attr(getret, &at); 2871 error = 0; 2872 goto nfsmout; 2873 } 2874 2875 /* 2876 * Obtain lock on vnode for this section of the code 2877 */ 2878 2879 nqsrv_getl(vp, ND_READ); 2880 if (v3) { 2881 error = getret = VOP_GETATTR(vp, &at, td); 2882 #if 0 2883 /* 2884 * XXX This check may be too strict for Solaris 2.5 clients. 2885 */ 2886 if (!error && toff && verf && verf != at.va_filerev) 2887 error = NFSERR_BAD_COOKIE; 2888 #endif 2889 } 2890 if (!error) 2891 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 2892 if (error) { 2893 vput(vp); 2894 vp = NULL; 2895 nfsm_reply(NFSX_POSTOPATTR(v3)); 2896 nfsm_srvpostop_attr(getret, &at); 2897 error = 0; 2898 goto nfsmout; 2899 } 2900 VOP_UNLOCK(vp, 0, td); 2901 2902 /* 2903 * end section. Allocate rbuf and continue 2904 */ 2905 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2906 again: 2907 iv.iov_base = rbuf; 2908 iv.iov_len = fullsiz; 2909 io.uio_iov = &iv; 2910 io.uio_iovcnt = 1; 2911 io.uio_offset = (off_t)off; 2912 io.uio_resid = fullsiz; 2913 io.uio_segflg = UIO_SYSSPACE; 2914 io.uio_rw = UIO_READ; 2915 io.uio_td = NULL; 2916 eofflag = 0; 2917 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2918 if (cookies) { 2919 free((caddr_t)cookies, M_TEMP); 2920 cookies = NULL; 2921 } 2922 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 2923 off = (off_t)io.uio_offset; 2924 if (!cookies && !error) 2925 error = NFSERR_PERM; 2926 if (v3) { 2927 getret = VOP_GETATTR(vp, &at, td); 2928 if (!error) 2929 error = getret; 2930 } 2931 VOP_UNLOCK(vp, 0, td); 2932 if (error) { 2933 vrele(vp); 2934 vp = NULL; 2935 free((caddr_t)rbuf, M_TEMP); 2936 if (cookies) 2937 free((caddr_t)cookies, M_TEMP); 2938 nfsm_reply(NFSX_POSTOPATTR(v3)); 2939 nfsm_srvpostop_attr(getret, &at); 2940 error = 0; 2941 goto nfsmout; 2942 } 2943 if (io.uio_resid) { 2944 siz -= io.uio_resid; 2945 2946 /* 2947 * If nothing read, return eof 2948 * rpc reply 2949 */ 2950 if (siz == 0) { 2951 vrele(vp); 2952 vp = NULL; 2953 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2954 2 * NFSX_UNSIGNED); 2955 if (v3) { 2956 nfsm_srvpostop_attr(getret, &at); 2957 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2958 txdr_hyper(at.va_filerev, tl); 2959 tl += 2; 2960 } else 2961 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2962 *tl++ = nfs_false; 2963 *tl = nfs_true; 2964 FREE((caddr_t)rbuf, M_TEMP); 2965 FREE((caddr_t)cookies, M_TEMP); 2966 error = 0; 2967 goto nfsmout; 2968 } 2969 } 2970 2971 /* 2972 * Check for degenerate cases of nothing useful read. 2973 * If so go try again 2974 */ 2975 cpos = rbuf; 2976 cend = rbuf + siz; 2977 dp = (struct dirent *)cpos; 2978 cookiep = cookies; 2979 /* 2980 * For some reason FreeBSD's ufs_readdir() chooses to back the 2981 * directory offset up to a block boundary, so it is necessary to 2982 * skip over the records that preceed the requested offset. This 2983 * requires the assumption that file offset cookies monotonically 2984 * increase. 2985 */ 2986 while (cpos < cend && ncookies > 0 && 2987 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 2988 ((u_quad_t)(*cookiep)) <= toff)) { 2989 cpos += dp->d_reclen; 2990 dp = (struct dirent *)cpos; 2991 cookiep++; 2992 ncookies--; 2993 } 2994 if (cpos >= cend || ncookies == 0) { 2995 toff = off; 2996 siz = fullsiz; 2997 goto again; 2998 } 2999 3000 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 3001 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 3002 if (v3) { 3003 nfsm_srvpostop_attr(getret, &at); 3004 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3005 txdr_hyper(at.va_filerev, tl); 3006 } 3007 mp = mp2 = mb; 3008 bp = bpos; 3009 be = bp + M_TRAILINGSPACE(mp); 3010 3011 /* Loop through the records and build reply */ 3012 while (cpos < cend && ncookies > 0) { 3013 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 3014 nlen = dp->d_namlen; 3015 rem = nfsm_rndup(nlen) - nlen; 3016 len += (4 * NFSX_UNSIGNED + nlen + rem); 3017 if (v3) 3018 len += 2 * NFSX_UNSIGNED; 3019 if (len > cnt) { 3020 eofflag = 0; 3021 break; 3022 } 3023 /* 3024 * Build the directory record xdr from 3025 * the dirent entry. 3026 */ 3027 nfsm_clget; 3028 *tl = nfs_true; 3029 bp += NFSX_UNSIGNED; 3030 if (v3) { 3031 nfsm_clget; 3032 *tl = 0; 3033 bp += NFSX_UNSIGNED; 3034 } 3035 nfsm_clget; 3036 *tl = txdr_unsigned(dp->d_fileno); 3037 bp += NFSX_UNSIGNED; 3038 nfsm_clget; 3039 *tl = txdr_unsigned(nlen); 3040 bp += NFSX_UNSIGNED; 3041 3042 /* And loop around copying the name */ 3043 xfer = nlen; 3044 cp = dp->d_name; 3045 while (xfer > 0) { 3046 nfsm_clget; 3047 if ((bp+xfer) > be) 3048 tsiz = be-bp; 3049 else 3050 tsiz = xfer; 3051 bcopy(cp, bp, tsiz); 3052 bp += tsiz; 3053 xfer -= tsiz; 3054 if (xfer > 0) 3055 cp += tsiz; 3056 } 3057 /* And null pad to a int32_t boundary */ 3058 for (i = 0; i < rem; i++) 3059 *bp++ = '\0'; 3060 nfsm_clget; 3061 3062 /* Finish off the record */ 3063 if (v3) { 3064 *tl = 0; 3065 bp += NFSX_UNSIGNED; 3066 nfsm_clget; 3067 } 3068 *tl = txdr_unsigned(*cookiep); 3069 bp += NFSX_UNSIGNED; 3070 } 3071 cpos += dp->d_reclen; 3072 dp = (struct dirent *)cpos; 3073 cookiep++; 3074 ncookies--; 3075 } 3076 vrele(vp); 3077 vp = NULL; 3078 nfsm_clget; 3079 *tl = nfs_false; 3080 bp += NFSX_UNSIGNED; 3081 nfsm_clget; 3082 if (eofflag) 3083 *tl = nfs_true; 3084 else 3085 *tl = nfs_false; 3086 bp += NFSX_UNSIGNED; 3087 if (mp != mb) { 3088 if (bp < be) 3089 mp->m_len = bp - mtod(mp, caddr_t); 3090 } else 3091 mp->m_len += bp - bpos; 3092 FREE((caddr_t)rbuf, M_TEMP); 3093 FREE((caddr_t)cookies, M_TEMP); 3094 3095 nfsmout: 3096 if (vp) 3097 vrele(vp); 3098 return(error); 3099 } 3100 3101 int 3102 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3103 struct thread *td, struct mbuf **mrq) 3104 { 3105 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3106 struct sockaddr *nam = nfsd->nd_nam; 3107 caddr_t dpos = nfsd->nd_dpos; 3108 struct ucred *cred = &nfsd->nd_cr; 3109 char *bp, *be; 3110 struct mbuf *mp; 3111 struct dirent *dp; 3112 caddr_t cp; 3113 u_int32_t *tl; 3114 int32_t t1; 3115 caddr_t bpos; 3116 struct mbuf *mb, *mb2, *mreq, *mp2; 3117 char *cpos, *cend, *cp2, *rbuf; 3118 struct vnode *vp = NULL, *nvp; 3119 struct flrep fl; 3120 nfsfh_t nfh; 3121 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh; 3122 struct uio io; 3123 struct iovec iv; 3124 struct vattr va, at, *vap = &va; 3125 struct nfs_fattr *fp; 3126 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 3127 int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies; 3128 u_quad_t frev, off, toff, verf; 3129 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 3130 3131 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3132 fhp = &nfh.fh_generic; 3133 nfsm_srvmtofh(fhp); 3134 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 3135 toff = fxdr_hyper(tl); 3136 tl += 2; 3137 verf = fxdr_hyper(tl); 3138 tl += 2; 3139 siz = fxdr_unsigned(int, *tl++); 3140 cnt = fxdr_unsigned(int, *tl); 3141 off = toff; 3142 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 3143 xfer = NFS_SRVMAXDATA(nfsd); 3144 if (cnt > xfer) 3145 cnt = xfer; 3146 if (siz > xfer) 3147 siz = xfer; 3148 fullsiz = siz; 3149 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3150 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3151 if (!error && vp->v_type != VDIR) { 3152 error = ENOTDIR; 3153 vput(vp); 3154 vp = NULL; 3155 } 3156 if (error) { 3157 nfsm_reply(NFSX_UNSIGNED); 3158 nfsm_srvpostop_attr(getret, &at); 3159 error = 0; 3160 goto nfsmout; 3161 } 3162 error = getret = VOP_GETATTR(vp, &at, td); 3163 #if 0 3164 /* 3165 * XXX This check may be too strict for Solaris 2.5 clients. 3166 */ 3167 if (!error && toff && verf && verf != at.va_filerev) 3168 error = NFSERR_BAD_COOKIE; 3169 #endif 3170 if (!error) { 3171 nqsrv_getl(vp, ND_READ); 3172 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 3173 } 3174 if (error) { 3175 vput(vp); 3176 vp = NULL; 3177 nfsm_reply(NFSX_V3POSTOPATTR); 3178 nfsm_srvpostop_attr(getret, &at); 3179 error = 0; 3180 goto nfsmout; 3181 } 3182 VOP_UNLOCK(vp, 0, td); 3183 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 3184 again: 3185 iv.iov_base = rbuf; 3186 iv.iov_len = fullsiz; 3187 io.uio_iov = &iv; 3188 io.uio_iovcnt = 1; 3189 io.uio_offset = (off_t)off; 3190 io.uio_resid = fullsiz; 3191 io.uio_segflg = UIO_SYSSPACE; 3192 io.uio_rw = UIO_READ; 3193 io.uio_td = NULL; 3194 eofflag = 0; 3195 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3196 if (cookies) { 3197 free((caddr_t)cookies, M_TEMP); 3198 cookies = NULL; 3199 } 3200 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 3201 off = (u_quad_t)io.uio_offset; 3202 getret = VOP_GETATTR(vp, &at, td); 3203 VOP_UNLOCK(vp, 0, td); 3204 if (!cookies && !error) 3205 error = NFSERR_PERM; 3206 if (!error) 3207 error = getret; 3208 if (error) { 3209 vrele(vp); 3210 vp = NULL; 3211 if (cookies) 3212 free((caddr_t)cookies, M_TEMP); 3213 free((caddr_t)rbuf, M_TEMP); 3214 nfsm_reply(NFSX_V3POSTOPATTR); 3215 nfsm_srvpostop_attr(getret, &at); 3216 error = 0; 3217 goto nfsmout; 3218 } 3219 if (io.uio_resid) { 3220 siz -= io.uio_resid; 3221 3222 /* 3223 * If nothing read, return eof 3224 * rpc reply 3225 */ 3226 if (siz == 0) { 3227 vrele(vp); 3228 vp = NULL; 3229 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 3230 2 * NFSX_UNSIGNED); 3231 nfsm_srvpostop_attr(getret, &at); 3232 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3233 txdr_hyper(at.va_filerev, tl); 3234 tl += 2; 3235 *tl++ = nfs_false; 3236 *tl = nfs_true; 3237 FREE((caddr_t)cookies, M_TEMP); 3238 FREE((caddr_t)rbuf, M_TEMP); 3239 error = 0; 3240 goto nfsmout; 3241 } 3242 } 3243 3244 /* 3245 * Check for degenerate cases of nothing useful read. 3246 * If so go try again 3247 */ 3248 cpos = rbuf; 3249 cend = rbuf + siz; 3250 dp = (struct dirent *)cpos; 3251 cookiep = cookies; 3252 /* 3253 * For some reason FreeBSD's ufs_readdir() chooses to back the 3254 * directory offset up to a block boundary, so it is necessary to 3255 * skip over the records that preceed the requested offset. This 3256 * requires the assumption that file offset cookies monotonically 3257 * increase. 3258 */ 3259 while (cpos < cend && ncookies > 0 && 3260 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 3261 ((u_quad_t)(*cookiep)) <= toff)) { 3262 cpos += dp->d_reclen; 3263 dp = (struct dirent *)cpos; 3264 cookiep++; 3265 ncookies--; 3266 } 3267 if (cpos >= cend || ncookies == 0) { 3268 toff = off; 3269 siz = fullsiz; 3270 goto again; 3271 } 3272 3273 /* 3274 * Probe one of the directory entries to see if the filesystem 3275 * supports VGET. 3276 */ 3277 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) { 3278 error = NFSERR_NOTSUPP; 3279 vrele(vp); 3280 vp = NULL; 3281 free((caddr_t)cookies, M_TEMP); 3282 free((caddr_t)rbuf, M_TEMP); 3283 nfsm_reply(NFSX_V3POSTOPATTR); 3284 nfsm_srvpostop_attr(getret, &at); 3285 error = 0; 3286 goto nfsmout; 3287 } 3288 if (nvp) { 3289 vput(nvp); 3290 nvp = NULL; 3291 } 3292 3293 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 3294 nfsm_reply(cnt); 3295 nfsm_srvpostop_attr(getret, &at); 3296 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3297 txdr_hyper(at.va_filerev, tl); 3298 mp = mp2 = mb; 3299 bp = bpos; 3300 be = bp + M_TRAILINGSPACE(mp); 3301 3302 /* Loop through the records and build reply */ 3303 while (cpos < cend && ncookies > 0) { 3304 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 3305 nlen = dp->d_namlen; 3306 rem = nfsm_rndup(nlen)-nlen; 3307 3308 /* 3309 * For readdir_and_lookup get the vnode using 3310 * the file number. 3311 */ 3312 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp)) 3313 goto invalid; 3314 bzero((caddr_t)nfhp, NFSX_V3FH); 3315 nfhp->fh_fsid = 3316 nvp->v_mount->mnt_stat.f_fsid; 3317 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { 3318 vput(nvp); 3319 nvp = NULL; 3320 goto invalid; 3321 } 3322 if (VOP_GETATTR(nvp, vap, td)) { 3323 vput(nvp); 3324 nvp = NULL; 3325 goto invalid; 3326 } 3327 vput(nvp); 3328 nvp = NULL; 3329 3330 /* 3331 * If either the dircount or maxcount will be 3332 * exceeded, get out now. Both of these lengths 3333 * are calculated conservatively, including all 3334 * XDR overheads. 3335 */ 3336 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 3337 NFSX_V3POSTOPATTR); 3338 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 3339 if (len > cnt || dirlen > fullsiz) { 3340 eofflag = 0; 3341 break; 3342 } 3343 3344 /* 3345 * Build the directory record xdr from 3346 * the dirent entry. 3347 */ 3348 fp = (struct nfs_fattr *)&fl.fl_fattr; 3349 nfsm_srvfillattr(vap, fp); 3350 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 3351 fl.fl_fhok = nfs_true; 3352 fl.fl_postopok = nfs_true; 3353 fl.fl_off.nfsuquad[0] = 0; 3354 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); 3355 3356 nfsm_clget; 3357 *tl = nfs_true; 3358 bp += NFSX_UNSIGNED; 3359 nfsm_clget; 3360 *tl = 0; 3361 bp += NFSX_UNSIGNED; 3362 nfsm_clget; 3363 *tl = txdr_unsigned(dp->d_fileno); 3364 bp += NFSX_UNSIGNED; 3365 nfsm_clget; 3366 *tl = txdr_unsigned(nlen); 3367 bp += NFSX_UNSIGNED; 3368 3369 /* And loop around copying the name */ 3370 xfer = nlen; 3371 cp = dp->d_name; 3372 while (xfer > 0) { 3373 nfsm_clget; 3374 if ((bp + xfer) > be) 3375 tsiz = be - bp; 3376 else 3377 tsiz = xfer; 3378 bcopy(cp, bp, tsiz); 3379 bp += tsiz; 3380 xfer -= tsiz; 3381 if (xfer > 0) 3382 cp += tsiz; 3383 } 3384 /* And null pad to a int32_t boundary */ 3385 for (i = 0; i < rem; i++) 3386 *bp++ = '\0'; 3387 3388 /* 3389 * Now copy the flrep structure out. 3390 */ 3391 xfer = sizeof (struct flrep); 3392 cp = (caddr_t)&fl; 3393 while (xfer > 0) { 3394 nfsm_clget; 3395 if ((bp + xfer) > be) 3396 tsiz = be - bp; 3397 else 3398 tsiz = xfer; 3399 bcopy(cp, bp, tsiz); 3400 bp += tsiz; 3401 xfer -= tsiz; 3402 if (xfer > 0) 3403 cp += tsiz; 3404 } 3405 } 3406 invalid: 3407 cpos += dp->d_reclen; 3408 dp = (struct dirent *)cpos; 3409 cookiep++; 3410 ncookies--; 3411 } 3412 vrele(vp); 3413 vp = NULL; 3414 nfsm_clget; 3415 *tl = nfs_false; 3416 bp += NFSX_UNSIGNED; 3417 nfsm_clget; 3418 if (eofflag) 3419 *tl = nfs_true; 3420 else 3421 *tl = nfs_false; 3422 bp += NFSX_UNSIGNED; 3423 if (mp != mb) { 3424 if (bp < be) 3425 mp->m_len = bp - mtod(mp, caddr_t); 3426 } else 3427 mp->m_len += bp - bpos; 3428 FREE((caddr_t)cookies, M_TEMP); 3429 FREE((caddr_t)rbuf, M_TEMP); 3430 nfsmout: 3431 if (vp) 3432 vrele(vp); 3433 return(error); 3434 } 3435 3436 /* 3437 * nfs commit service 3438 */ 3439 int 3440 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3441 struct thread *td, struct mbuf **mrq) 3442 { 3443 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3444 struct sockaddr *nam = nfsd->nd_nam; 3445 caddr_t dpos = nfsd->nd_dpos; 3446 struct ucred *cred = &nfsd->nd_cr; 3447 struct vattr bfor, aft; 3448 struct vnode *vp = NULL; 3449 nfsfh_t nfh; 3450 fhandle_t *fhp; 3451 u_int32_t *tl; 3452 int32_t t1; 3453 caddr_t bpos; 3454 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache; 3455 char *cp2; 3456 struct mbuf *mb, *mb2, *mreq; 3457 u_quad_t frev, off; 3458 3459 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3460 #ifndef nolint 3461 cache = 0; 3462 #endif 3463 fhp = &nfh.fh_generic; 3464 nfsm_srvmtofh(fhp); 3465 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3466 3467 /* 3468 * XXX At this time VOP_FSYNC() does not accept offset and byte 3469 * count parameters, so these arguments are useless (someday maybe). 3470 */ 3471 off = fxdr_hyper(tl); 3472 tl += 2; 3473 cnt = fxdr_unsigned(int, *tl); 3474 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3475 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3476 if (error) { 3477 nfsm_reply(2 * NFSX_UNSIGNED); 3478 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3479 error = 0; 3480 goto nfsmout; 3481 } 3482 for_ret = VOP_GETATTR(vp, &bfor, td); 3483 3484 if (cnt > MAX_COMMIT_COUNT) { 3485 /* 3486 * Give up and do the whole thing 3487 */ 3488 if (vp->v_object && 3489 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3490 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 3491 } 3492 error = VOP_FSYNC(vp, MNT_WAIT, td); 3493 } else { 3494 /* 3495 * Locate and synchronously write any buffers that fall 3496 * into the requested range. Note: we are assuming that 3497 * f_iosize is a power of 2. 3498 */ 3499 int iosize = vp->v_mount->mnt_stat.f_iosize; 3500 int iomask = iosize - 1; 3501 int s; 3502 daddr_t lblkno; 3503 3504 /* 3505 * Align to iosize boundry, super-align to page boundry. 3506 */ 3507 if (off & iomask) { 3508 cnt += off & iomask; 3509 off &= ~(u_quad_t)iomask; 3510 } 3511 if (off & PAGE_MASK) { 3512 cnt += off & PAGE_MASK; 3513 off &= ~(u_quad_t)PAGE_MASK; 3514 } 3515 lblkno = off / iosize; 3516 3517 if (vp->v_object && 3518 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3519 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC); 3520 } 3521 3522 s = splbio(); 3523 while (cnt > 0) { 3524 struct buf *bp; 3525 3526 /* 3527 * If we have a buffer and it is marked B_DELWRI we 3528 * have to lock and write it. Otherwise the prior 3529 * write is assumed to have already been committed. 3530 */ 3531 if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) { 3532 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { 3533 BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL); 3534 continue; /* retry */ 3535 } 3536 bremfree(bp); 3537 bp->b_flags &= ~B_ASYNC; 3538 VOP_BWRITE(bp->b_vp, bp); 3539 ++nfs_commit_miss; 3540 } 3541 ++nfs_commit_blks; 3542 if (cnt < iosize) 3543 break; 3544 cnt -= iosize; 3545 ++lblkno; 3546 } 3547 splx(s); 3548 } 3549 3550 aft_ret = VOP_GETATTR(vp, &aft, td); 3551 vput(vp); 3552 vp = NULL; 3553 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3554 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3555 if (!error) { 3556 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3557 if (nfsver.tv_sec == 0) 3558 nfsver = boottime; 3559 *tl++ = txdr_unsigned(nfsver.tv_sec); 3560 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 3561 } else { 3562 error = 0; 3563 } 3564 nfsmout: 3565 if (vp) 3566 vput(vp); 3567 return(error); 3568 } 3569 3570 /* 3571 * nfs statfs service 3572 */ 3573 int 3574 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3575 struct thread *td, struct mbuf **mrq) 3576 { 3577 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3578 struct sockaddr *nam = nfsd->nd_nam; 3579 caddr_t dpos = nfsd->nd_dpos; 3580 struct ucred *cred = &nfsd->nd_cr; 3581 struct statfs *sf; 3582 struct nfs_statfs *sfp; 3583 u_int32_t *tl; 3584 int32_t t1; 3585 caddr_t bpos; 3586 int error = 0, rdonly, cache, getret = 1; 3587 int v3 = (nfsd->nd_flag & ND_NFSV3); 3588 char *cp2; 3589 struct mbuf *mb, *mb2, *mreq; 3590 struct vnode *vp = NULL; 3591 struct vattr at; 3592 nfsfh_t nfh; 3593 fhandle_t *fhp; 3594 struct statfs statfs; 3595 u_quad_t frev, tval; 3596 3597 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3598 #ifndef nolint 3599 cache = 0; 3600 #endif 3601 fhp = &nfh.fh_generic; 3602 nfsm_srvmtofh(fhp); 3603 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3604 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3605 if (error) { 3606 nfsm_reply(NFSX_UNSIGNED); 3607 nfsm_srvpostop_attr(getret, &at); 3608 error = 0; 3609 goto nfsmout; 3610 } 3611 sf = &statfs; 3612 error = VFS_STATFS(vp->v_mount, sf, td); 3613 getret = VOP_GETATTR(vp, &at, td); 3614 vput(vp); 3615 vp = NULL; 3616 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3617 if (v3) 3618 nfsm_srvpostop_attr(getret, &at); 3619 if (error) { 3620 error = 0; 3621 goto nfsmout; 3622 } 3623 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3624 if (v3) { 3625 tval = (u_quad_t)sf->f_blocks; 3626 tval *= (u_quad_t)sf->f_bsize; 3627 txdr_hyper(tval, &sfp->sf_tbytes); 3628 tval = (u_quad_t)sf->f_bfree; 3629 tval *= (u_quad_t)sf->f_bsize; 3630 txdr_hyper(tval, &sfp->sf_fbytes); 3631 tval = (u_quad_t)sf->f_bavail; 3632 tval *= (u_quad_t)sf->f_bsize; 3633 txdr_hyper(tval, &sfp->sf_abytes); 3634 sfp->sf_tfiles.nfsuquad[0] = 0; 3635 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3636 sfp->sf_ffiles.nfsuquad[0] = 0; 3637 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3638 sfp->sf_afiles.nfsuquad[0] = 0; 3639 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3640 sfp->sf_invarsec = 0; 3641 } else { 3642 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3643 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3644 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3645 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3646 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3647 } 3648 nfsmout: 3649 if (vp) 3650 vput(vp); 3651 return(error); 3652 } 3653 3654 /* 3655 * nfs fsinfo service 3656 */ 3657 int 3658 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3659 struct thread *td, struct mbuf **mrq) 3660 { 3661 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3662 struct sockaddr *nam = nfsd->nd_nam; 3663 caddr_t dpos = nfsd->nd_dpos; 3664 struct ucred *cred = &nfsd->nd_cr; 3665 u_int32_t *tl; 3666 struct nfsv3_fsinfo *sip; 3667 int32_t t1; 3668 caddr_t bpos; 3669 int error = 0, rdonly, cache, getret = 1, pref; 3670 char *cp2; 3671 struct mbuf *mb, *mb2, *mreq; 3672 struct vnode *vp = NULL; 3673 struct vattr at; 3674 nfsfh_t nfh; 3675 fhandle_t *fhp; 3676 u_quad_t frev, maxfsize; 3677 struct statfs sb; 3678 3679 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3680 #ifndef nolint 3681 cache = 0; 3682 #endif 3683 fhp = &nfh.fh_generic; 3684 nfsm_srvmtofh(fhp); 3685 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3686 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3687 if (error) { 3688 nfsm_reply(NFSX_UNSIGNED); 3689 nfsm_srvpostop_attr(getret, &at); 3690 error = 0; 3691 goto nfsmout; 3692 } 3693 3694 /* XXX Try to make a guess on the max file size. */ 3695 VFS_STATFS(vp->v_mount, &sb, td); 3696 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; 3697 3698 getret = VOP_GETATTR(vp, &at, td); 3699 vput(vp); 3700 vp = NULL; 3701 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3702 nfsm_srvpostop_attr(getret, &at); 3703 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3704 3705 /* 3706 * XXX 3707 * There should be file system VFS OP(s) to get this information. 3708 * For now, assume ufs. 3709 */ 3710 if (slp->ns_so->so_type == SOCK_DGRAM) 3711 pref = NFS_MAXDGRAMDATA; 3712 else 3713 pref = NFS_MAXDATA; 3714 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3715 sip->fs_rtpref = txdr_unsigned(pref); 3716 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3717 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3718 sip->fs_wtpref = txdr_unsigned(pref); 3719 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3720 sip->fs_dtpref = txdr_unsigned(pref); 3721 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3722 sip->fs_timedelta.nfsv3_sec = 0; 3723 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3724 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3725 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3726 NFSV3FSINFO_CANSETTIME); 3727 nfsmout: 3728 if (vp) 3729 vput(vp); 3730 return(error); 3731 } 3732 3733 /* 3734 * nfs pathconf service 3735 */ 3736 int 3737 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3738 struct thread *td, struct mbuf **mrq) 3739 { 3740 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3741 struct sockaddr *nam = nfsd->nd_nam; 3742 caddr_t dpos = nfsd->nd_dpos; 3743 struct ucred *cred = &nfsd->nd_cr; 3744 u_int32_t *tl; 3745 struct nfsv3_pathconf *pc; 3746 int32_t t1; 3747 caddr_t bpos; 3748 int error = 0, rdonly, cache, getret = 1; 3749 register_t linkmax, namemax, chownres, notrunc; 3750 char *cp2; 3751 struct mbuf *mb, *mb2, *mreq; 3752 struct vnode *vp = NULL; 3753 struct vattr at; 3754 nfsfh_t nfh; 3755 fhandle_t *fhp; 3756 u_quad_t frev; 3757 3758 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3759 #ifndef nolint 3760 cache = 0; 3761 #endif 3762 fhp = &nfh.fh_generic; 3763 nfsm_srvmtofh(fhp); 3764 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3765 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3766 if (error) { 3767 nfsm_reply(NFSX_UNSIGNED); 3768 nfsm_srvpostop_attr(getret, &at); 3769 error = 0; 3770 goto nfsmout; 3771 } 3772 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3773 if (!error) 3774 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3775 if (!error) 3776 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3777 if (!error) 3778 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3779 getret = VOP_GETATTR(vp, &at, td); 3780 vput(vp); 3781 vp = NULL; 3782 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3783 nfsm_srvpostop_attr(getret, &at); 3784 if (error) { 3785 error = 0; 3786 goto nfsmout; 3787 } 3788 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3789 3790 pc->pc_linkmax = txdr_unsigned(linkmax); 3791 pc->pc_namemax = txdr_unsigned(namemax); 3792 pc->pc_notrunc = txdr_unsigned(notrunc); 3793 pc->pc_chownrestricted = txdr_unsigned(chownres); 3794 3795 /* 3796 * These should probably be supported by VOP_PATHCONF(), but 3797 * until msdosfs is exportable (why would you want to?), the 3798 * Unix defaults should be ok. 3799 */ 3800 pc->pc_caseinsensitive = nfs_false; 3801 pc->pc_casepreserving = nfs_true; 3802 nfsmout: 3803 if (vp) 3804 vput(vp); 3805 return(error); 3806 } 3807 3808 /* 3809 * Null operation, used by clients to ping server 3810 */ 3811 /* ARGSUSED */ 3812 int 3813 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3814 struct thread *td, struct mbuf **mrq) 3815 { 3816 struct mbuf *mrep = nfsd->nd_mrep; 3817 caddr_t bpos; 3818 int error = NFSERR_RETVOID, cache; 3819 struct mbuf *mb, *mreq; 3820 u_quad_t frev; 3821 3822 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3823 #ifndef nolint 3824 cache = 0; 3825 #endif 3826 nfsm_reply(0); 3827 nfsm_srvdone; 3828 } 3829 3830 /* 3831 * No operation, used for obsolete procedures 3832 */ 3833 /* ARGSUSED */ 3834 int 3835 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3836 struct thread *td, struct mbuf **mrq) 3837 { 3838 struct mbuf *mrep = nfsd->nd_mrep; 3839 caddr_t bpos; 3840 int error, cache; 3841 struct mbuf *mb, *mreq; 3842 u_quad_t frev; 3843 3844 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3845 #ifndef nolint 3846 cache = 0; 3847 #endif 3848 if (nfsd->nd_repstat) 3849 error = nfsd->nd_repstat; 3850 else 3851 error = EPROCUNAVAIL; 3852 nfsm_reply(0); 3853 error = 0; 3854 nfsm_srvdone; 3855 } 3856 3857 /* 3858 * Perform access checking for vnodes obtained from file handles that would 3859 * refer to files already opened by a Unix client. You cannot just use 3860 * vn_writechk() and VOP_ACCESS() for two reasons. 3861 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3862 * 2 - The owner is to be given access irrespective of mode bits for some 3863 * operations, so that processes that chmod after opening a file don't 3864 * break. I don't like this because it opens a security hole, but since 3865 * the nfs server opens a security hole the size of a barn door anyhow, 3866 * what the heck. 3867 * 3868 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3869 * will return EPERM instead of EACCESS. EPERM is always an error. 3870 */ 3871 static int 3872 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, 3873 int rdonly, struct thread *td, int override) 3874 { 3875 struct vattr vattr; 3876 int error; 3877 3878 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3879 if (flags & VWRITE) { 3880 /* Just vn_writechk() changed to check rdonly */ 3881 /* 3882 * Disallow write attempts on read-only file systems; 3883 * unless the file is a socket or a block or character 3884 * device resident on the file system. 3885 */ 3886 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3887 switch (vp->v_type) { 3888 case VREG: 3889 case VDIR: 3890 case VLNK: 3891 return (EROFS); 3892 default: 3893 break; 3894 } 3895 } 3896 /* 3897 * If there's shared text associated with 3898 * the inode, we can't allow writing. 3899 */ 3900 if (vp->v_flag & VTEXT) 3901 return (ETXTBSY); 3902 } 3903 error = VOP_GETATTR(vp, &vattr, td); 3904 if (error) 3905 return (error); 3906 error = VOP_ACCESS(vp, flags, cred, td); 3907 /* 3908 * Allow certain operations for the owner (reads and writes 3909 * on files that are already open). 3910 */ 3911 if (override && error == EACCES && cred->cr_uid == vattr.va_uid) 3912 error = 0; 3913 return error; 3914 } 3915 #endif /* NFS_NOSERVER */ 3916 3917