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.24 2005/06/06 15:09:38 drhodus Exp $ 39 */ 40 41 /* 42 * nfs version 2 and 3 server calls to vnode ops 43 * - these routines generally have 3 phases 44 * 1 - break down and validate rpc request in mbuf list 45 * 2 - do the vnode ops for the request 46 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 47 * 3 - build the rpc reply in an mbuf list 48 * nb: 49 * - do not mix the phases, since the nfsm_?? macros can return failures 50 * on a bad rpc or similar and do not do any vrele() or vput()'s 51 * 52 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 53 * error number iff error != 0 whereas 54 * returning an error from the server function implies a fatal error 55 * such as a badly constructed rpc request that should be dropped without 56 * a reply. 57 * For Version 3, nfsm_reply() does not return for the error case, since 58 * most version 3 rpcs return more than the status for error cases. 59 * 60 * Other notes: 61 * Warning: always pay careful attention to resource cleanup on return 62 * and note that nfsm_*() macros can terminate a procedure on certain 63 * errors. 64 */ 65 66 #include <sys/param.h> 67 #include <sys/systm.h> 68 #include <sys/proc.h> 69 #include <sys/nlookup.h> 70 #include <sys/namei.h> 71 #include <sys/unistd.h> 72 #include <sys/vnode.h> 73 #include <sys/mount.h> 74 #include <sys/socket.h> 75 #include <sys/socketvar.h> 76 #include <sys/malloc.h> 77 #include <sys/mbuf.h> 78 #include <sys/dirent.h> 79 #include <sys/stat.h> 80 #include <sys/kernel.h> 81 #include <sys/sysctl.h> 82 #include <sys/buf.h> 83 84 #include <vm/vm.h> 85 #include <vm/vm_extern.h> 86 #include <vm/vm_zone.h> 87 #include <vm/vm_object.h> 88 89 #include <sys/buf2.h> 90 91 #include <sys/thread2.h> 92 93 #include "nfsproto.h" 94 #include "rpcv2.h" 95 #include "nfs.h" 96 #include "xdr_subs.h" 97 #include "nfsm_subs.h" 98 #include "nqnfs.h" 99 100 #ifdef NFSRV_DEBUG 101 #define nfsdbprintf(info) printf info 102 #else 103 #define nfsdbprintf(info) 104 #endif 105 106 #define MAX_COMMIT_COUNT (1024 * 1024) 107 108 #define NUM_HEURISTIC 1017 109 #define NHUSE_INIT 64 110 #define NHUSE_INC 16 111 #define NHUSE_MAX 2048 112 113 static struct nfsheur { 114 struct vnode *nh_vp; /* vp to match (unreferenced pointer) */ 115 off_t nh_nextr; /* next offset for sequential detection */ 116 int nh_use; /* use count for selection */ 117 int nh_seqcount; /* heuristic */ 118 } nfsheur[NUM_HEURISTIC]; 119 120 nfstype nfsv3_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFSOCK, 121 NFFIFO, NFNON }; 122 #ifndef NFS_NOSERVER 123 nfstype nfsv2_type[9] = { NFNON, NFREG, NFDIR, NFBLK, NFCHR, NFLNK, NFNON, 124 NFCHR, NFNON }; 125 /* Global vars */ 126 extern u_int32_t nfs_xdrneg1; 127 extern u_int32_t nfs_false, nfs_true; 128 extern enum vtype nv3tov_type[8]; 129 extern struct nfsstats nfsstats; 130 131 int nfsrvw_procrastinate = NFS_GATHERDELAY * 1000; 132 int nfsrvw_procrastinate_v3 = 0; 133 134 static struct timespec nfsver; 135 136 SYSCTL_DECL(_vfs_nfs); 137 138 static int nfs_async; 139 SYSCTL_INT(_vfs_nfs, OID_AUTO, async, CTLFLAG_RW, &nfs_async, 0, ""); 140 static int nfs_commit_blks; 141 static int nfs_commit_miss; 142 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_blks, CTLFLAG_RW, &nfs_commit_blks, 0, ""); 143 SYSCTL_INT(_vfs_nfs, OID_AUTO, commit_miss, CTLFLAG_RW, &nfs_commit_miss, 0, ""); 144 145 static int nfsrv_access (struct vnode *,int,struct ucred *,int, 146 struct thread *, int); 147 static void nfsrvw_coalesce (struct nfsrv_descript *, 148 struct nfsrv_descript *); 149 150 /* 151 * nfs v3 access service 152 */ 153 int 154 nfsrv3_access(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 155 struct thread *td, struct mbuf **mrq) 156 { 157 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 158 struct sockaddr *nam = nfsd->nd_nam; 159 caddr_t dpos = nfsd->nd_dpos; 160 struct ucred *cred = &nfsd->nd_cr; 161 struct vnode *vp = NULL; 162 nfsfh_t nfh; 163 fhandle_t *fhp; 164 u_int32_t *tl; 165 int32_t t1; 166 caddr_t bpos; 167 int error = 0, rdonly, cache, getret; 168 char *cp2; 169 struct mbuf *mb, *mreq, *mb2; 170 struct vattr vattr, *vap = &vattr; 171 u_long testmode, nfsmode; 172 u_quad_t frev; 173 174 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 175 #ifndef nolint 176 cache = 0; 177 #endif 178 fhp = &nfh.fh_generic; 179 nfsm_srvmtofh(fhp); 180 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 181 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, 182 (nfsd->nd_flag & ND_KERBAUTH), TRUE); 183 if (error) { 184 nfsm_reply(NFSX_UNSIGNED); 185 nfsm_srvpostop_attr(1, (struct vattr *)0); 186 error = 0; 187 goto nfsmout; 188 } 189 nfsmode = fxdr_unsigned(u_int32_t, *tl); 190 if ((nfsmode & NFSV3ACCESS_READ) && 191 nfsrv_access(vp, VREAD, cred, rdonly, td, 0)) 192 nfsmode &= ~NFSV3ACCESS_READ; 193 if (vp->v_type == VDIR) 194 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 195 NFSV3ACCESS_DELETE); 196 else 197 testmode = (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 198 if ((nfsmode & testmode) && 199 nfsrv_access(vp, VWRITE, cred, rdonly, td, 0)) 200 nfsmode &= ~testmode; 201 if (vp->v_type == VDIR) 202 testmode = NFSV3ACCESS_LOOKUP; 203 else 204 testmode = NFSV3ACCESS_EXECUTE; 205 if ((nfsmode & testmode) && 206 nfsrv_access(vp, VEXEC, cred, rdonly, td, 0)) 207 nfsmode &= ~testmode; 208 getret = VOP_GETATTR(vp, vap, td); 209 vput(vp); 210 vp = NULL; 211 nfsm_reply(NFSX_POSTOPATTR(1) + NFSX_UNSIGNED); 212 nfsm_srvpostop_attr(getret, vap); 213 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 214 *tl = txdr_unsigned(nfsmode); 215 nfsmout: 216 if (vp) 217 vput(vp); 218 return(error); 219 } 220 221 /* 222 * nfs getattr service 223 */ 224 int 225 nfsrv_getattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 226 struct thread *td, struct mbuf **mrq) 227 { 228 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 229 struct sockaddr *nam = nfsd->nd_nam; 230 caddr_t dpos = nfsd->nd_dpos; 231 struct ucred *cred = &nfsd->nd_cr; 232 struct nfs_fattr *fp; 233 struct vattr va; 234 struct vattr *vap = &va; 235 struct vnode *vp = NULL; 236 nfsfh_t nfh; 237 fhandle_t *fhp; 238 u_int32_t *tl; 239 int32_t t1; 240 caddr_t bpos; 241 int error = 0, rdonly, cache; 242 char *cp2; 243 struct mbuf *mb, *mb2, *mreq; 244 u_quad_t frev; 245 246 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 247 fhp = &nfh.fh_generic; 248 nfsm_srvmtofh(fhp); 249 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 250 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 251 if (error) { 252 nfsm_reply(0); 253 error = 0; 254 goto nfsmout; 255 } 256 nqsrv_getl(vp, ND_READ); 257 error = VOP_GETATTR(vp, vap, td); 258 vput(vp); 259 vp = NULL; 260 nfsm_reply(NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 261 if (error) { 262 error = 0; 263 goto nfsmout; 264 } 265 nfsm_build(fp, struct nfs_fattr *, NFSX_FATTR(nfsd->nd_flag & ND_NFSV3)); 266 nfsm_srvfillattr(vap, fp); 267 /* fall through */ 268 269 nfsmout: 270 if (vp) 271 vput(vp); 272 return(error); 273 } 274 275 /* 276 * nfs setattr service 277 */ 278 int 279 nfsrv_setattr(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 280 struct thread *td, struct mbuf **mrq) 281 { 282 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 283 struct sockaddr *nam = nfsd->nd_nam; 284 caddr_t dpos = nfsd->nd_dpos; 285 struct ucred *cred = &nfsd->nd_cr; 286 struct vattr va, preat; 287 struct vattr *vap = &va; 288 struct nfsv2_sattr *sp; 289 struct nfs_fattr *fp; 290 struct vnode *vp = NULL; 291 nfsfh_t nfh; 292 fhandle_t *fhp; 293 u_int32_t *tl; 294 int32_t t1; 295 caddr_t bpos; 296 int error = 0, rdonly, cache, preat_ret = 1, postat_ret = 1; 297 int v3 = (nfsd->nd_flag & ND_NFSV3), gcheck = 0; 298 char *cp2; 299 struct mbuf *mb, *mb2, *mreq; 300 u_quad_t frev; 301 struct timespec guard; 302 303 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 304 fhp = &nfh.fh_generic; 305 nfsm_srvmtofh(fhp); 306 VATTR_NULL(vap); 307 if (v3) { 308 nfsm_srvsattr(vap); 309 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 310 gcheck = fxdr_unsigned(int, *tl); 311 if (gcheck) { 312 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 313 fxdr_nfsv3time(tl, &guard); 314 } 315 } else { 316 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 317 /* 318 * Nah nah nah nah na nah 319 * There is a bug in the Sun client that puts 0xffff in the mode 320 * field of sattr when it should put in 0xffffffff. The u_short 321 * doesn't sign extend. 322 * --> check the low order 2 bytes for 0xffff 323 */ 324 if ((fxdr_unsigned(int, sp->sa_mode) & 0xffff) != 0xffff) 325 vap->va_mode = nfstov_mode(sp->sa_mode); 326 if (sp->sa_uid != nfs_xdrneg1) 327 vap->va_uid = fxdr_unsigned(uid_t, sp->sa_uid); 328 if (sp->sa_gid != nfs_xdrneg1) 329 vap->va_gid = fxdr_unsigned(gid_t, sp->sa_gid); 330 if (sp->sa_size != nfs_xdrneg1) 331 vap->va_size = fxdr_unsigned(u_quad_t, sp->sa_size); 332 if (sp->sa_atime.nfsv2_sec != nfs_xdrneg1) { 333 #ifdef notyet 334 fxdr_nfsv2time(&sp->sa_atime, &vap->va_atime); 335 #else 336 vap->va_atime.tv_sec = 337 fxdr_unsigned(int32_t, sp->sa_atime.nfsv2_sec); 338 vap->va_atime.tv_nsec = 0; 339 #endif 340 } 341 if (sp->sa_mtime.nfsv2_sec != nfs_xdrneg1) 342 fxdr_nfsv2time(&sp->sa_mtime, &vap->va_mtime); 343 344 } 345 346 /* 347 * Now that we have all the fields, lets do it. 348 */ 349 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, &rdonly, 350 (nfsd->nd_flag & ND_KERBAUTH), TRUE); 351 if (error) { 352 nfsm_reply(2 * NFSX_UNSIGNED); 353 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 354 error = 0; 355 goto nfsmout; 356 } 357 358 /* 359 * vp now an active resource, pay careful attention to cleanup 360 */ 361 362 nqsrv_getl(vp, ND_WRITE); 363 if (v3) { 364 error = preat_ret = VOP_GETATTR(vp, &preat, td); 365 if (!error && gcheck && 366 (preat.va_ctime.tv_sec != guard.tv_sec || 367 preat.va_ctime.tv_nsec != guard.tv_nsec)) 368 error = NFSERR_NOT_SYNC; 369 if (error) { 370 vput(vp); 371 vp = NULL; 372 nfsm_reply(NFSX_WCCDATA(v3)); 373 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 374 error = 0; 375 goto nfsmout; 376 } 377 } 378 379 /* 380 * If the size is being changed write acces is required, otherwise 381 * just check for a read only file system. 382 */ 383 if (vap->va_size == ((u_quad_t)((quad_t) -1))) { 384 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 385 error = EROFS; 386 goto out; 387 } 388 } else { 389 if (vp->v_type == VDIR) { 390 error = EISDIR; 391 goto out; 392 } else if ((error = nfsrv_access(vp, VWRITE, cred, rdonly, 393 td, 0)) != 0){ 394 goto out; 395 } 396 } 397 error = VOP_SETATTR(vp, vap, cred, td); 398 postat_ret = VOP_GETATTR(vp, vap, td); 399 if (!error) 400 error = postat_ret; 401 out: 402 vput(vp); 403 vp = NULL; 404 nfsm_reply(NFSX_WCCORFATTR(v3)); 405 if (v3) { 406 nfsm_srvwcc_data(preat_ret, &preat, postat_ret, vap); 407 error = 0; 408 goto nfsmout; 409 } else { 410 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 411 nfsm_srvfillattr(vap, fp); 412 } 413 /* fall through */ 414 415 nfsmout: 416 if (vp) 417 vput(vp); 418 return(error); 419 } 420 421 /* 422 * nfs lookup rpc 423 */ 424 int 425 nfsrv_lookup(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 426 struct thread *td, struct mbuf **mrq) 427 { 428 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 429 struct sockaddr *nam = nfsd->nd_nam; 430 caddr_t dpos = nfsd->nd_dpos; 431 struct ucred *cred = &nfsd->nd_cr; 432 struct nfs_fattr *fp; 433 struct nlookupdata nd; 434 struct vnode *vp; 435 struct vnode *dirp; 436 struct namecache *ncp; 437 nfsfh_t nfh; 438 fhandle_t *fhp; 439 caddr_t cp; 440 u_int32_t *tl; 441 int32_t t1; 442 caddr_t bpos; 443 int error = 0, cache = 0, len, dirattr_ret = 1; 444 int v3 = (nfsd->nd_flag & ND_NFSV3), pubflag; 445 char *cp2; 446 struct mbuf *mb, *mb2, *mreq; 447 struct vattr va, dirattr, *vap = &va; 448 u_quad_t frev; 449 450 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 451 nlookup_zero(&nd); 452 dirp = NULL; 453 vp = NULL; 454 455 fhp = &nfh.fh_generic; 456 nfsm_srvmtofh(fhp); 457 nfsm_srvnamesiz(len); 458 459 pubflag = nfs_ispublicfh(fhp); 460 461 error = nfs_namei(&nd, cred, NAMEI_LOOKUP, NULL, &vp, 462 fhp, len, slp, nam, &md, &dpos, 463 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), pubflag); 464 465 /* 466 * namei failure, only dirp to cleanup. Clear out garbarge from 467 * structure in case macros jump to nfsmout. 468 */ 469 470 if (error) { 471 if (dirp) { 472 if (v3) 473 dirattr_ret = VOP_GETATTR(dirp, &dirattr, td); 474 vrele(dirp); 475 dirp = NULL; 476 } 477 nfsm_reply(NFSX_POSTOPATTR(v3)); 478 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 479 error = 0; 480 goto nfsmout; 481 } 482 483 /* 484 * Locate index file for public filehandle 485 * 486 * error is 0 on entry and 0 on exit from this block. 487 */ 488 489 if (pubflag) { 490 if (vp->v_type == VDIR && nfs_pub.np_index != NULL) { 491 /* 492 * Setup call to lookup() to see if we can find 493 * the index file. Arguably, this doesn't belong 494 * in a kernel.. Ugh. If an error occurs, do not 495 * try to install an index file and then clear the 496 * error. 497 * 498 * When we replace nd with ind and redirect ndp, 499 * maintenance of ni_startdir and ni_vp shift to 500 * ind and we have to clean them up in the old nd. 501 * However, the cnd resource continues to be maintained 502 * via the original nd. Confused? You aren't alone! 503 */ 504 VOP_UNLOCK(vp, 0, td); 505 ncp = cache_hold(nd.nl_ncp); 506 nlookup_done(&nd); 507 error = nlookup_init_raw(&nd, nfs_pub.np_index, 508 UIO_SYSSPACE, 0, cred, ncp); 509 cache_drop(ncp); 510 if (error == 0) 511 error = nlookup(&nd); 512 513 if (error == 0) { 514 /* 515 * Found an index file. Get rid of 516 * the old references. transfer vp and 517 * load up the new vp. Fortunately we do 518 * not have to deal with dvp, that would be 519 * a huge mess. 520 */ 521 if (dirp) 522 vrele(dirp); 523 dirp = vp; 524 vp = NULL; 525 error = cache_vget(nd.nl_ncp, nd.nl_cred, 526 LK_EXCLUSIVE, &vp); 527 KKASSERT(error == 0); 528 } 529 error = 0; 530 } 531 /* 532 * If the public filehandle was used, check that this lookup 533 * didn't result in a filehandle outside the publicly exported 534 * filesystem. We clear the poor vp here to avoid lockups due 535 * to NFS I/O. 536 */ 537 538 if (vp->v_mount != nfs_pub.np_mount) { 539 vput(vp); 540 vp = NULL; 541 error = EPERM; 542 } 543 } 544 545 if (dirp) { 546 if (v3) 547 dirattr_ret = VOP_GETATTR(dirp, &dirattr, td); 548 vrele(dirp); 549 dirp = NULL; 550 } 551 552 /* 553 * Resources at this point: 554 * ndp->ni_vp may not be NULL 555 * 556 */ 557 558 if (error) { 559 nfsm_reply(NFSX_POSTOPATTR(v3)); 560 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 561 error = 0; 562 goto nfsmout; 563 } 564 565 #if 0 566 /* XXX not sure how to deal with this */ 567 nqsrv_getl(ndp->ni_startdir, ND_READ); 568 #endif 569 570 /* 571 * Clear out some resources prior to potentially blocking. This 572 * is not as critical as ni_dvp resources in other routines, but 573 * it helps. 574 */ 575 nlookup_done(&nd); 576 577 /* 578 * Get underlying attribute, then release remaining resources ( for 579 * the same potential blocking reason ) and reply. 580 */ 581 bzero((caddr_t)fhp, sizeof(nfh)); 582 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 583 error = VFS_VPTOFH(vp, &fhp->fh_fid); 584 if (!error) 585 error = VOP_GETATTR(vp, vap, td); 586 587 vput(vp); 588 vp = NULL; 589 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPORFATTR(v3) + NFSX_POSTOPATTR(v3)); 590 if (error) { 591 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 592 error = 0; 593 goto nfsmout; 594 } 595 nfsm_srvfhtom(fhp, v3); 596 if (v3) { 597 nfsm_srvpostop_attr(0, vap); 598 nfsm_srvpostop_attr(dirattr_ret, &dirattr); 599 } else { 600 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 601 nfsm_srvfillattr(vap, fp); 602 } 603 604 nfsmout: 605 if (dirp) 606 vrele(dirp); 607 nlookup_done(&nd); /* may be called twice */ 608 if (vp) 609 vput(vp); 610 return (error); 611 } 612 613 /* 614 * nfs readlink service 615 */ 616 int 617 nfsrv_readlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 618 struct thread *td, struct mbuf **mrq) 619 { 620 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 621 struct sockaddr *nam = nfsd->nd_nam; 622 caddr_t dpos = nfsd->nd_dpos; 623 struct ucred *cred = &nfsd->nd_cr; 624 struct iovec iv[(NFS_MAXPATHLEN+MLEN-1)/MLEN]; 625 struct iovec *ivp = iv; 626 struct mbuf *mp; 627 u_int32_t *tl; 628 int32_t t1; 629 caddr_t bpos; 630 int error = 0, rdonly, cache, i, tlen, len, getret; 631 int v3 = (nfsd->nd_flag & ND_NFSV3); 632 char *cp2; 633 struct mbuf *mb, *mb2, *mp2, *mp3, *mreq; 634 struct vnode *vp = NULL; 635 struct vattr attr; 636 nfsfh_t nfh; 637 fhandle_t *fhp; 638 struct uio io, *uiop = &io; 639 u_quad_t frev; 640 641 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 642 #ifndef nolint 643 mp2 = (struct mbuf *)0; 644 #endif 645 mp3 = NULL; 646 fhp = &nfh.fh_generic; 647 nfsm_srvmtofh(fhp); 648 len = 0; 649 i = 0; 650 while (len < NFS_MAXPATHLEN) { 651 mp = m_getcl(MB_WAIT, MT_DATA, 0); 652 mp->m_len = MCLBYTES; 653 if (len == 0) 654 mp3 = mp2 = mp; 655 else { 656 mp2->m_next = mp; 657 mp2 = mp; 658 } 659 if ((len+mp->m_len) > NFS_MAXPATHLEN) { 660 mp->m_len = NFS_MAXPATHLEN-len; 661 len = NFS_MAXPATHLEN; 662 } else 663 len += mp->m_len; 664 ivp->iov_base = mtod(mp, caddr_t); 665 ivp->iov_len = mp->m_len; 666 i++; 667 ivp++; 668 } 669 uiop->uio_iov = iv; 670 uiop->uio_iovcnt = i; 671 uiop->uio_offset = 0; 672 uiop->uio_resid = len; 673 uiop->uio_rw = UIO_READ; 674 uiop->uio_segflg = UIO_SYSSPACE; 675 uiop->uio_td = NULL; 676 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 677 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 678 if (error) { 679 nfsm_reply(2 * NFSX_UNSIGNED); 680 nfsm_srvpostop_attr(1, (struct vattr *)0); 681 error = 0; 682 goto nfsmout; 683 } 684 if (vp->v_type != VLNK) { 685 if (v3) 686 error = EINVAL; 687 else 688 error = ENXIO; 689 goto out; 690 } 691 nqsrv_getl(vp, ND_READ); 692 error = VOP_READLINK(vp, uiop, cred); 693 out: 694 getret = VOP_GETATTR(vp, &attr, td); 695 vput(vp); 696 vp = NULL; 697 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_UNSIGNED); 698 if (v3) { 699 nfsm_srvpostop_attr(getret, &attr); 700 if (error) { 701 error = 0; 702 goto nfsmout; 703 } 704 } 705 if (uiop->uio_resid > 0) { 706 len -= uiop->uio_resid; 707 tlen = nfsm_rndup(len); 708 nfsm_adj(mp3, NFS_MAXPATHLEN-tlen, tlen-len); 709 } 710 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 711 *tl = txdr_unsigned(len); 712 mb->m_next = mp3; 713 mp3 = NULL; 714 nfsmout: 715 if (mp3) 716 m_freem(mp3); 717 if (vp) 718 vput(vp); 719 return(error); 720 } 721 722 /* 723 * nfs read service 724 */ 725 int 726 nfsrv_read(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 727 struct thread *td, struct mbuf **mrq) 728 { 729 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 730 struct sockaddr *nam = nfsd->nd_nam; 731 caddr_t dpos = nfsd->nd_dpos; 732 struct ucred *cred = &nfsd->nd_cr; 733 struct iovec *iv; 734 struct iovec *iv2; 735 struct mbuf *m; 736 struct nfs_fattr *fp; 737 u_int32_t *tl; 738 int32_t t1; 739 int i; 740 caddr_t bpos; 741 int error = 0, rdonly, cache, cnt, len, left, siz, tlen, getret; 742 int v3 = (nfsd->nd_flag & ND_NFSV3), reqlen; 743 char *cp2; 744 struct mbuf *mb, *mb2, *mreq; 745 struct mbuf *m2; 746 struct vnode *vp = NULL; 747 nfsfh_t nfh; 748 fhandle_t *fhp; 749 struct uio io, *uiop = &io; 750 struct vattr va, *vap = &va; 751 struct nfsheur *nh; 752 off_t off; 753 int ioflag = 0; 754 u_quad_t frev; 755 756 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 757 fhp = &nfh.fh_generic; 758 nfsm_srvmtofh(fhp); 759 if (v3) { 760 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 761 off = fxdr_hyper(tl); 762 } else { 763 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 764 off = (off_t)fxdr_unsigned(u_int32_t, *tl); 765 } 766 nfsm_srvstrsiz(reqlen, NFS_SRVMAXDATA(nfsd)); 767 768 /* 769 * Reference vp. If an error occurs, vp will be invalid, but we 770 * have to NULL it just in case. The macros might goto nfsmout 771 * as well. 772 */ 773 774 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 775 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 776 if (error) { 777 vp = NULL; 778 nfsm_reply(2 * NFSX_UNSIGNED); 779 nfsm_srvpostop_attr(1, (struct vattr *)0); 780 error = 0; 781 goto nfsmout; 782 } 783 784 if (vp->v_type != VREG) { 785 if (v3) 786 error = EINVAL; 787 else 788 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 789 } 790 if (!error) { 791 nqsrv_getl(vp, ND_READ); 792 if ((error = nfsrv_access(vp, VREAD, cred, rdonly, td, 1)) != 0) 793 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 1); 794 } 795 getret = VOP_GETATTR(vp, vap, td); 796 if (!error) 797 error = getret; 798 if (error) { 799 vput(vp); 800 vp = NULL; 801 nfsm_reply(NFSX_POSTOPATTR(v3)); 802 nfsm_srvpostop_attr(getret, vap); 803 error = 0; 804 goto nfsmout; 805 } 806 807 /* 808 * Calculate byte count to read 809 */ 810 811 if (off >= vap->va_size) 812 cnt = 0; 813 else if ((off + reqlen) > vap->va_size) 814 cnt = vap->va_size - off; 815 else 816 cnt = reqlen; 817 818 /* 819 * Calculate seqcount for heuristic 820 */ 821 822 { 823 int hi; 824 int try = 32; 825 826 /* 827 * Locate best candidate 828 */ 829 830 hi = ((int)(vm_offset_t)vp / sizeof(struct vnode)) % NUM_HEURISTIC; 831 nh = &nfsheur[hi]; 832 833 while (try--) { 834 if (nfsheur[hi].nh_vp == vp) { 835 nh = &nfsheur[hi]; 836 break; 837 } 838 if (nfsheur[hi].nh_use > 0) 839 --nfsheur[hi].nh_use; 840 hi = (hi + 1) % NUM_HEURISTIC; 841 if (nfsheur[hi].nh_use < nh->nh_use) 842 nh = &nfsheur[hi]; 843 } 844 845 if (nh->nh_vp != vp) { 846 nh->nh_vp = vp; 847 nh->nh_nextr = off; 848 nh->nh_use = NHUSE_INIT; 849 if (off == 0) 850 nh->nh_seqcount = 4; 851 else 852 nh->nh_seqcount = 1; 853 } 854 855 /* 856 * Calculate heuristic 857 */ 858 859 if ((off == 0 && nh->nh_seqcount > 0) || off == nh->nh_nextr) { 860 if (++nh->nh_seqcount > IO_SEQMAX) 861 nh->nh_seqcount = IO_SEQMAX; 862 } else if (nh->nh_seqcount > 1) { 863 nh->nh_seqcount = 1; 864 } else { 865 nh->nh_seqcount = 0; 866 } 867 nh->nh_use += NHUSE_INC; 868 if (nh->nh_use > NHUSE_MAX) 869 nh->nh_use = NHUSE_MAX; 870 ioflag |= nh->nh_seqcount << IO_SEQSHIFT; 871 } 872 873 nfsm_reply(NFSX_POSTOPORFATTR(v3) + 3 * NFSX_UNSIGNED+nfsm_rndup(cnt)); 874 if (v3) { 875 nfsm_build(tl, u_int32_t *, NFSX_V3FATTR + 4 * NFSX_UNSIGNED); 876 *tl++ = nfs_true; 877 fp = (struct nfs_fattr *)tl; 878 tl += (NFSX_V3FATTR / sizeof (u_int32_t)); 879 } else { 880 nfsm_build(tl, u_int32_t *, NFSX_V2FATTR + NFSX_UNSIGNED); 881 fp = (struct nfs_fattr *)tl; 882 tl += (NFSX_V2FATTR / sizeof (u_int32_t)); 883 } 884 len = left = nfsm_rndup(cnt); 885 if (cnt > 0) { 886 /* 887 * Generate the mbuf list with the uio_iov ref. to it. 888 */ 889 i = 0; 890 m = m2 = mb; 891 while (left > 0) { 892 siz = min(M_TRAILINGSPACE(m), left); 893 if (siz > 0) { 894 left -= siz; 895 i++; 896 } 897 if (left > 0) { 898 m = m_getcl(MB_WAIT, MT_DATA, 0); 899 m->m_len = 0; 900 m2->m_next = m; 901 m2 = m; 902 } 903 } 904 MALLOC(iv, struct iovec *, i * sizeof (struct iovec), 905 M_TEMP, M_WAITOK); 906 uiop->uio_iov = iv2 = iv; 907 m = mb; 908 left = len; 909 i = 0; 910 while (left > 0) { 911 if (m == NULL) 912 panic("nfsrv_read iov"); 913 siz = min(M_TRAILINGSPACE(m), left); 914 if (siz > 0) { 915 iv->iov_base = mtod(m, caddr_t) + m->m_len; 916 iv->iov_len = siz; 917 m->m_len += siz; 918 left -= siz; 919 iv++; 920 i++; 921 } 922 m = m->m_next; 923 } 924 uiop->uio_iovcnt = i; 925 uiop->uio_offset = off; 926 uiop->uio_resid = len; 927 uiop->uio_rw = UIO_READ; 928 uiop->uio_segflg = UIO_SYSSPACE; 929 error = VOP_READ(vp, uiop, IO_NODELOCKED | ioflag, cred); 930 off = uiop->uio_offset; 931 nh->nh_nextr = off; 932 FREE((caddr_t)iv2, M_TEMP); 933 if (error || (getret = VOP_GETATTR(vp, vap, td))) { 934 if (!error) 935 error = getret; 936 m_freem(mreq); 937 vput(vp); 938 vp = NULL; 939 nfsm_reply(NFSX_POSTOPATTR(v3)); 940 nfsm_srvpostop_attr(getret, vap); 941 error = 0; 942 goto nfsmout; 943 } 944 } else { 945 uiop->uio_resid = 0; 946 } 947 vput(vp); 948 vp = NULL; 949 nfsm_srvfillattr(vap, fp); 950 tlen = len - uiop->uio_resid; 951 cnt = cnt < tlen ? cnt : tlen; 952 tlen = nfsm_rndup(cnt); 953 if (len != tlen || tlen != cnt) 954 nfsm_adj(mb, len - tlen, tlen - cnt); 955 if (v3) { 956 *tl++ = txdr_unsigned(cnt); 957 if (len < reqlen) 958 *tl++ = nfs_true; 959 else 960 *tl++ = nfs_false; 961 } 962 *tl = txdr_unsigned(cnt); 963 nfsmout: 964 if (vp) 965 vput(vp); 966 return(error); 967 } 968 969 /* 970 * nfs write service 971 */ 972 int 973 nfsrv_write(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 974 struct thread *td, struct mbuf **mrq) 975 { 976 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 977 struct sockaddr *nam = nfsd->nd_nam; 978 caddr_t dpos = nfsd->nd_dpos; 979 struct ucred *cred = &nfsd->nd_cr; 980 struct iovec *ivp; 981 int i, cnt; 982 struct mbuf *mp; 983 struct nfs_fattr *fp; 984 struct iovec *iv; 985 struct vattr va, forat; 986 struct vattr *vap = &va; 987 u_int32_t *tl; 988 int32_t t1; 989 caddr_t bpos; 990 int error = 0, rdonly, cache, len, forat_ret = 1; 991 int ioflags, aftat_ret = 1, retlen, zeroing, adjust; 992 int stable = NFSV3WRITE_FILESYNC; 993 int v3 = (nfsd->nd_flag & ND_NFSV3); 994 char *cp2; 995 struct mbuf *mb, *mb2, *mreq; 996 struct vnode *vp = NULL; 997 nfsfh_t nfh; 998 fhandle_t *fhp; 999 struct uio io, *uiop = &io; 1000 off_t off; 1001 u_quad_t frev; 1002 1003 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1004 if (mrep == NULL) { 1005 *mrq = NULL; 1006 error = 0; 1007 goto nfsmout; 1008 } 1009 fhp = &nfh.fh_generic; 1010 nfsm_srvmtofh(fhp); 1011 if (v3) { 1012 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1013 off = fxdr_hyper(tl); 1014 tl += 3; 1015 stable = fxdr_unsigned(int, *tl++); 1016 } else { 1017 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1018 off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 1019 tl += 2; 1020 if (nfs_async) 1021 stable = NFSV3WRITE_UNSTABLE; 1022 } 1023 retlen = len = fxdr_unsigned(int32_t, *tl); 1024 cnt = i = 0; 1025 1026 /* 1027 * For NFS Version 2, it is not obvious what a write of zero length 1028 * should do, but I might as well be consistent with Version 3, 1029 * which is to return ok so long as there are no permission problems. 1030 */ 1031 if (len > 0) { 1032 zeroing = 1; 1033 mp = mrep; 1034 while (mp) { 1035 if (mp == md) { 1036 zeroing = 0; 1037 adjust = dpos - mtod(mp, caddr_t); 1038 mp->m_len -= adjust; 1039 if (mp->m_len > 0 && adjust > 0) 1040 NFSMADV(mp, adjust); 1041 } 1042 if (zeroing) 1043 mp->m_len = 0; 1044 else if (mp->m_len > 0) { 1045 i += mp->m_len; 1046 if (i > len) { 1047 mp->m_len -= (i - len); 1048 zeroing = 1; 1049 } 1050 if (mp->m_len > 0) 1051 cnt++; 1052 } 1053 mp = mp->m_next; 1054 } 1055 } 1056 if (len > NFS_MAXDATA || len < 0 || i < len) { 1057 error = EIO; 1058 nfsm_reply(2 * NFSX_UNSIGNED); 1059 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); 1060 error = 0; 1061 goto nfsmout; 1062 } 1063 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 1064 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 1065 if (error) { 1066 vp = NULL; 1067 nfsm_reply(2 * NFSX_UNSIGNED); 1068 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); 1069 error = 0; 1070 goto nfsmout; 1071 } 1072 if (v3) 1073 forat_ret = VOP_GETATTR(vp, &forat, td); 1074 if (vp->v_type != VREG) { 1075 if (v3) 1076 error = EINVAL; 1077 else 1078 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 1079 } 1080 if (!error) { 1081 nqsrv_getl(vp, ND_WRITE); 1082 error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); 1083 } 1084 if (error) { 1085 vput(vp); 1086 vp = NULL; 1087 nfsm_reply(NFSX_WCCDATA(v3)); 1088 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); 1089 error = 0; 1090 goto nfsmout; 1091 } 1092 1093 if (len > 0) { 1094 MALLOC(ivp, struct iovec *, cnt * sizeof (struct iovec), M_TEMP, 1095 M_WAITOK); 1096 uiop->uio_iov = iv = ivp; 1097 uiop->uio_iovcnt = cnt; 1098 mp = mrep; 1099 while (mp) { 1100 if (mp->m_len > 0) { 1101 ivp->iov_base = mtod(mp, caddr_t); 1102 ivp->iov_len = mp->m_len; 1103 ivp++; 1104 } 1105 mp = mp->m_next; 1106 } 1107 1108 /* 1109 * XXX 1110 * The IO_METASYNC flag indicates that all metadata (and not just 1111 * enough to ensure data integrity) mus be written to stable storage 1112 * synchronously. 1113 * (IO_METASYNC is not yet implemented in 4.4BSD-Lite.) 1114 */ 1115 if (stable == NFSV3WRITE_UNSTABLE) 1116 ioflags = IO_NODELOCKED; 1117 else if (stable == NFSV3WRITE_DATASYNC) 1118 ioflags = (IO_SYNC | IO_NODELOCKED); 1119 else 1120 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED); 1121 uiop->uio_resid = len; 1122 uiop->uio_rw = UIO_WRITE; 1123 uiop->uio_segflg = UIO_SYSSPACE; 1124 uiop->uio_td = NULL; 1125 uiop->uio_offset = off; 1126 error = VOP_WRITE(vp, uiop, ioflags, cred); 1127 nfsstats.srvvop_writes++; 1128 FREE((caddr_t)iv, M_TEMP); 1129 } 1130 aftat_ret = VOP_GETATTR(vp, vap, td); 1131 vput(vp); 1132 vp = NULL; 1133 if (!error) 1134 error = aftat_ret; 1135 nfsm_reply(NFSX_PREOPATTR(v3) + NFSX_POSTOPORFATTR(v3) + 1136 2 * NFSX_UNSIGNED + NFSX_WRITEVERF(v3)); 1137 if (v3) { 1138 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, vap); 1139 if (error) { 1140 error = 0; 1141 goto nfsmout; 1142 } 1143 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1144 *tl++ = txdr_unsigned(retlen); 1145 /* 1146 * If nfs_async is set, then pretend the write was FILESYNC. 1147 */ 1148 if (stable == NFSV3WRITE_UNSTABLE && !nfs_async) 1149 *tl++ = txdr_unsigned(stable); 1150 else 1151 *tl++ = txdr_unsigned(NFSV3WRITE_FILESYNC); 1152 /* 1153 * Actually, there is no need to txdr these fields, 1154 * but it may make the values more human readable, 1155 * for debugging purposes. 1156 */ 1157 if (nfsver.tv_sec == 0) 1158 nfsver = boottime; 1159 *tl++ = txdr_unsigned(nfsver.tv_sec); 1160 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 1161 } else { 1162 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1163 nfsm_srvfillattr(vap, fp); 1164 } 1165 nfsmout: 1166 if (vp) 1167 vput(vp); 1168 return(error); 1169 } 1170 1171 /* 1172 * NFS write service with write gathering support. Called when 1173 * nfsrvw_procrastinate > 0. 1174 * See: Chet Juszczak, "Improving the Write Performance of an NFS Server", 1175 * in Proc. of the Winter 1994 Usenix Conference, pg. 247-259, San Franscisco, 1176 * Jan. 1994. 1177 */ 1178 int 1179 nfsrv_writegather(struct nfsrv_descript **ndp, struct nfssvc_sock *slp, 1180 struct thread *td, struct mbuf **mrq) 1181 { 1182 struct iovec *ivp; 1183 struct mbuf *mp; 1184 struct nfsrv_descript *wp, *nfsd, *owp, *swp; 1185 struct nfs_fattr *fp; 1186 int i; 1187 struct iovec *iov; 1188 struct nfsrvw_delayhash *wpp; 1189 struct ucred *cred; 1190 struct vattr va, forat; 1191 u_int32_t *tl; 1192 int32_t t1; 1193 caddr_t bpos, dpos; 1194 int error = 0, rdonly, cache, len, forat_ret = 1; 1195 int ioflags, aftat_ret = 1, adjust, v3, zeroing; 1196 char *cp2; 1197 struct mbuf *mb, *mb2, *mreq, *mrep, *md; 1198 struct vnode *vp = NULL; 1199 struct uio io, *uiop = &io; 1200 u_quad_t frev, cur_usec; 1201 1202 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1203 #ifndef nolint 1204 i = 0; 1205 len = 0; 1206 #endif 1207 *mrq = NULL; 1208 if (*ndp) { 1209 nfsd = *ndp; 1210 *ndp = NULL; 1211 mrep = nfsd->nd_mrep; 1212 md = nfsd->nd_md; 1213 dpos = nfsd->nd_dpos; 1214 cred = &nfsd->nd_cr; 1215 v3 = (nfsd->nd_flag & ND_NFSV3); 1216 LIST_INIT(&nfsd->nd_coalesce); 1217 nfsd->nd_mreq = NULL; 1218 nfsd->nd_stable = NFSV3WRITE_FILESYNC; 1219 cur_usec = nfs_curusec(); 1220 nfsd->nd_time = cur_usec + 1221 (v3 ? nfsrvw_procrastinate_v3 : nfsrvw_procrastinate); 1222 1223 /* 1224 * Now, get the write header.. 1225 */ 1226 nfsm_srvmtofh(&nfsd->nd_fh); 1227 if (v3) { 1228 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 1229 nfsd->nd_off = fxdr_hyper(tl); 1230 tl += 3; 1231 nfsd->nd_stable = fxdr_unsigned(int, *tl++); 1232 } else { 1233 nfsm_dissect(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1234 nfsd->nd_off = (off_t)fxdr_unsigned(u_int32_t, *++tl); 1235 tl += 2; 1236 if (nfs_async) 1237 nfsd->nd_stable = NFSV3WRITE_UNSTABLE; 1238 } 1239 len = fxdr_unsigned(int32_t, *tl); 1240 nfsd->nd_len = len; 1241 nfsd->nd_eoff = nfsd->nd_off + len; 1242 1243 /* 1244 * Trim the header out of the mbuf list and trim off any trailing 1245 * junk so that the mbuf list has only the write data. 1246 */ 1247 zeroing = 1; 1248 i = 0; 1249 mp = mrep; 1250 while (mp) { 1251 if (mp == md) { 1252 zeroing = 0; 1253 adjust = dpos - mtod(mp, caddr_t); 1254 mp->m_len -= adjust; 1255 if (mp->m_len > 0 && adjust > 0) 1256 NFSMADV(mp, adjust); 1257 } 1258 if (zeroing) 1259 mp->m_len = 0; 1260 else { 1261 i += mp->m_len; 1262 if (i > len) { 1263 mp->m_len -= (i - len); 1264 zeroing = 1; 1265 } 1266 } 1267 mp = mp->m_next; 1268 } 1269 if (len > NFS_MAXDATA || len < 0 || i < len) { 1270 nfsmout: 1271 m_freem(mrep); 1272 error = EIO; 1273 nfsm_writereply(2 * NFSX_UNSIGNED, v3); 1274 if (v3) 1275 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1276 nfsd->nd_mreq = mreq; 1277 nfsd->nd_mrep = NULL; 1278 nfsd->nd_time = 0; 1279 } 1280 1281 /* 1282 * Add this entry to the hash and time queues. 1283 */ 1284 crit_enter(); 1285 owp = NULL; 1286 wp = slp->ns_tq.lh_first; 1287 while (wp && wp->nd_time < nfsd->nd_time) { 1288 owp = wp; 1289 wp = wp->nd_tq.le_next; 1290 } 1291 NFS_DPF(WG, ("Q%03x", nfsd->nd_retxid & 0xfff)); 1292 if (owp) { 1293 LIST_INSERT_AFTER(owp, nfsd, nd_tq); 1294 } else { 1295 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq); 1296 } 1297 if (nfsd->nd_mrep) { 1298 wpp = NWDELAYHASH(slp, nfsd->nd_fh.fh_fid.fid_data); 1299 owp = NULL; 1300 wp = wpp->lh_first; 1301 while (wp && 1302 bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) { 1303 owp = wp; 1304 wp = wp->nd_hash.le_next; 1305 } 1306 while (wp && wp->nd_off < nfsd->nd_off && 1307 !bcmp((caddr_t)&nfsd->nd_fh,(caddr_t)&wp->nd_fh,NFSX_V3FH)) { 1308 owp = wp; 1309 wp = wp->nd_hash.le_next; 1310 } 1311 if (owp) { 1312 LIST_INSERT_AFTER(owp, nfsd, nd_hash); 1313 1314 /* 1315 * Search the hash list for overlapping entries and 1316 * coalesce. 1317 */ 1318 for(; nfsd && NFSW_CONTIG(owp, nfsd); nfsd = wp) { 1319 wp = nfsd->nd_hash.le_next; 1320 if (NFSW_SAMECRED(owp, nfsd)) 1321 nfsrvw_coalesce(owp, nfsd); 1322 } 1323 } else { 1324 LIST_INSERT_HEAD(wpp, nfsd, nd_hash); 1325 } 1326 } 1327 crit_exit(); 1328 } 1329 1330 /* 1331 * Now, do VOP_WRITE()s for any one(s) that need to be done now 1332 * and generate the associated reply mbuf list(s). 1333 */ 1334 loop1: 1335 cur_usec = nfs_curusec(); 1336 crit_enter(); 1337 for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = owp) { 1338 owp = nfsd->nd_tq.le_next; 1339 if (nfsd->nd_time > cur_usec) 1340 break; 1341 if (nfsd->nd_mreq) 1342 continue; 1343 NFS_DPF(WG, ("P%03x", nfsd->nd_retxid & 0xfff)); 1344 LIST_REMOVE(nfsd, nd_tq); 1345 LIST_REMOVE(nfsd, nd_hash); 1346 crit_exit(); 1347 mrep = nfsd->nd_mrep; 1348 nfsd->nd_mrep = NULL; 1349 cred = &nfsd->nd_cr; 1350 v3 = (nfsd->nd_flag & ND_NFSV3); 1351 forat_ret = aftat_ret = 1; 1352 error = nfsrv_fhtovp(&nfsd->nd_fh, 1, &vp, cred, slp, 1353 nfsd->nd_nam, &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 1354 if (!error) { 1355 if (v3) 1356 forat_ret = VOP_GETATTR(vp, &forat, td); 1357 if (vp->v_type != VREG) { 1358 if (v3) 1359 error = EINVAL; 1360 else 1361 error = (vp->v_type == VDIR) ? EISDIR : EACCES; 1362 } 1363 } else { 1364 vp = NULL; 1365 } 1366 if (!error) { 1367 nqsrv_getl(vp, ND_WRITE); 1368 error = nfsrv_access(vp, VWRITE, cred, rdonly, td, 1); 1369 } 1370 1371 if (nfsd->nd_stable == NFSV3WRITE_UNSTABLE) 1372 ioflags = IO_NODELOCKED; 1373 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC) 1374 ioflags = (IO_SYNC | IO_NODELOCKED); 1375 else 1376 ioflags = (IO_METASYNC | IO_SYNC | IO_NODELOCKED); 1377 uiop->uio_rw = UIO_WRITE; 1378 uiop->uio_segflg = UIO_SYSSPACE; 1379 uiop->uio_td = NULL; 1380 uiop->uio_offset = nfsd->nd_off; 1381 uiop->uio_resid = nfsd->nd_eoff - nfsd->nd_off; 1382 if (uiop->uio_resid > 0) { 1383 mp = mrep; 1384 i = 0; 1385 while (mp) { 1386 if (mp->m_len > 0) 1387 i++; 1388 mp = mp->m_next; 1389 } 1390 uiop->uio_iovcnt = i; 1391 MALLOC(iov, struct iovec *, i * sizeof (struct iovec), 1392 M_TEMP, M_WAITOK); 1393 uiop->uio_iov = ivp = iov; 1394 mp = mrep; 1395 while (mp) { 1396 if (mp->m_len > 0) { 1397 ivp->iov_base = mtod(mp, caddr_t); 1398 ivp->iov_len = mp->m_len; 1399 ivp++; 1400 } 1401 mp = mp->m_next; 1402 } 1403 if (!error) { 1404 error = VOP_WRITE(vp, uiop, ioflags, cred); 1405 nfsstats.srvvop_writes++; 1406 } 1407 FREE((caddr_t)iov, M_TEMP); 1408 } 1409 m_freem(mrep); 1410 if (vp) { 1411 aftat_ret = VOP_GETATTR(vp, &va, td); 1412 vput(vp); 1413 vp = NULL; 1414 } 1415 1416 /* 1417 * Loop around generating replies for all write rpcs that have 1418 * now been completed. 1419 */ 1420 swp = nfsd; 1421 do { 1422 NFS_DPF(WG, ("R%03x", nfsd->nd_retxid & 0xfff)); 1423 if (error) { 1424 nfsm_writereply(NFSX_WCCDATA(v3), v3); 1425 if (v3) { 1426 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1427 } 1428 } else { 1429 nfsm_writereply(NFSX_PREOPATTR(v3) + 1430 NFSX_POSTOPORFATTR(v3) + 2 * NFSX_UNSIGNED + 1431 NFSX_WRITEVERF(v3), v3); 1432 if (v3) { 1433 nfsm_srvwcc_data(forat_ret, &forat, aftat_ret, &va); 1434 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1435 *tl++ = txdr_unsigned(nfsd->nd_len); 1436 *tl++ = txdr_unsigned(swp->nd_stable); 1437 /* 1438 * Actually, there is no need to txdr these fields, 1439 * but it may make the values more human readable, 1440 * for debugging purposes. 1441 */ 1442 if (nfsver.tv_sec == 0) 1443 nfsver = boottime; 1444 *tl++ = txdr_unsigned(nfsver.tv_sec); 1445 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 1446 } else { 1447 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1448 nfsm_srvfillattr(&va, fp); 1449 } 1450 } 1451 nfsd->nd_mreq = mreq; 1452 if (nfsd->nd_mrep) 1453 panic("nfsrv_write: nd_mrep not free"); 1454 1455 /* 1456 * Done. Put it at the head of the timer queue so that 1457 * the final phase can return the reply. 1458 */ 1459 crit_enter(); 1460 if (nfsd != swp) { 1461 nfsd->nd_time = 0; 1462 LIST_INSERT_HEAD(&slp->ns_tq, nfsd, nd_tq); 1463 } 1464 nfsd = swp->nd_coalesce.lh_first; 1465 if (nfsd) { 1466 LIST_REMOVE(nfsd, nd_tq); 1467 } 1468 crit_exit(); 1469 } while (nfsd); 1470 crit_enter(); 1471 swp->nd_time = 0; 1472 LIST_INSERT_HEAD(&slp->ns_tq, swp, nd_tq); 1473 crit_exit(); 1474 goto loop1; 1475 } 1476 crit_exit(); 1477 1478 /* 1479 * Search for a reply to return. 1480 */ 1481 crit_enter(); 1482 for (nfsd = slp->ns_tq.lh_first; nfsd; nfsd = nfsd->nd_tq.le_next) 1483 if (nfsd->nd_mreq) { 1484 NFS_DPF(WG, ("X%03x", nfsd->nd_retxid & 0xfff)); 1485 LIST_REMOVE(nfsd, nd_tq); 1486 *mrq = nfsd->nd_mreq; 1487 *ndp = nfsd; 1488 break; 1489 } 1490 crit_exit(); 1491 return (0); 1492 } 1493 1494 /* 1495 * Coalesce the write request nfsd into owp. To do this we must: 1496 * - remove nfsd from the queues 1497 * - merge nfsd->nd_mrep into owp->nd_mrep 1498 * - update the nd_eoff and nd_stable for owp 1499 * - put nfsd on owp's nd_coalesce list 1500 * NB: Must be called at splsoftclock(). 1501 */ 1502 static void 1503 nfsrvw_coalesce(struct nfsrv_descript *owp, struct nfsrv_descript *nfsd) 1504 { 1505 int overlap; 1506 struct mbuf *mp; 1507 struct nfsrv_descript *p; 1508 1509 NFS_DPF(WG, ("C%03x-%03x", 1510 nfsd->nd_retxid & 0xfff, owp->nd_retxid & 0xfff)); 1511 LIST_REMOVE(nfsd, nd_hash); 1512 LIST_REMOVE(nfsd, nd_tq); 1513 if (owp->nd_eoff < nfsd->nd_eoff) { 1514 overlap = owp->nd_eoff - nfsd->nd_off; 1515 if (overlap < 0) 1516 panic("nfsrv_coalesce: bad off"); 1517 if (overlap > 0) 1518 m_adj(nfsd->nd_mrep, overlap); 1519 mp = owp->nd_mrep; 1520 while (mp->m_next) 1521 mp = mp->m_next; 1522 mp->m_next = nfsd->nd_mrep; 1523 owp->nd_eoff = nfsd->nd_eoff; 1524 } else 1525 m_freem(nfsd->nd_mrep); 1526 nfsd->nd_mrep = NULL; 1527 if (nfsd->nd_stable == NFSV3WRITE_FILESYNC) 1528 owp->nd_stable = NFSV3WRITE_FILESYNC; 1529 else if (nfsd->nd_stable == NFSV3WRITE_DATASYNC && 1530 owp->nd_stable == NFSV3WRITE_UNSTABLE) 1531 owp->nd_stable = NFSV3WRITE_DATASYNC; 1532 LIST_INSERT_HEAD(&owp->nd_coalesce, nfsd, nd_tq); 1533 1534 /* 1535 * If nfsd had anything else coalesced into it, transfer them 1536 * to owp, otherwise their replies will never get sent. 1537 */ 1538 for (p = nfsd->nd_coalesce.lh_first; p; 1539 p = nfsd->nd_coalesce.lh_first) { 1540 LIST_REMOVE(p, nd_tq); 1541 LIST_INSERT_HEAD(&owp->nd_coalesce, p, nd_tq); 1542 } 1543 } 1544 1545 /* 1546 * nfs create service 1547 * now does a truncate to 0 length via. setattr if it already exists 1548 */ 1549 int 1550 nfsrv_create(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 1551 struct thread *td, struct mbuf **mrq) 1552 { 1553 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1554 struct sockaddr *nam = nfsd->nd_nam; 1555 caddr_t dpos = nfsd->nd_dpos; 1556 struct ucred *cred = &nfsd->nd_cr; 1557 struct nfs_fattr *fp; 1558 struct vattr va, dirfor, diraft; 1559 struct vattr *vap = &va; 1560 struct nfsv2_sattr *sp; 1561 u_int32_t *tl; 1562 struct nlookupdata nd; 1563 int32_t t1; 1564 caddr_t bpos; 1565 int error = 0, rdev, cache, len, tsize, dirfor_ret = 1, diraft_ret = 1; 1566 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0; 1567 caddr_t cp; 1568 char *cp2; 1569 struct mbuf *mb, *mb2, *mreq; 1570 struct vnode *dirp; 1571 struct vnode *dvp; 1572 struct vnode *vp; 1573 nfsfh_t nfh; 1574 fhandle_t *fhp; 1575 u_quad_t frev, tempsize; 1576 u_char cverf[NFSX_V3CREATEVERF]; 1577 1578 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1579 #ifndef nolint 1580 rdev = 0; 1581 #endif 1582 nlookup_zero(&nd); 1583 dirp = NULL; 1584 dvp = NULL; 1585 vp = NULL; 1586 1587 fhp = &nfh.fh_generic; 1588 nfsm_srvmtofh(fhp); 1589 nfsm_srvnamesiz(len); 1590 1591 /* 1592 * Call namei and do initial cleanup to get a few things 1593 * out of the way. If we get an initial error we cleanup 1594 * and return here to avoid special-casing the invalid nd 1595 * structure through the rest of the case. dirp may be 1596 * set even if an error occurs, but the nd structure will not 1597 * be valid at all if an error occurs so we have to invalidate it 1598 * prior to calling nfsm_reply ( which might goto nfsmout ). 1599 */ 1600 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 1601 fhp, len, slp, nam, &md, &dpos, &dirp, 1602 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 1603 if (dirp) { 1604 if (v3) { 1605 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 1606 } else { 1607 vrele(dirp); 1608 dirp = NULL; 1609 } 1610 } 1611 if (error) { 1612 nfsm_reply(NFSX_WCCDATA(v3)); 1613 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1614 error = 0; 1615 goto nfsmout; 1616 } 1617 1618 /* 1619 * No error. Continue. State: 1620 * 1621 * dirp may be valid 1622 * vp may be valid or NULL if the target does not 1623 * exist. 1624 * dvp is valid 1625 * 1626 * The error state is set through the code and we may also do some 1627 * opportunistic releasing of vnodes to avoid holding locks through 1628 * NFS I/O. The cleanup at the end is a catch-all 1629 */ 1630 1631 VATTR_NULL(vap); 1632 if (v3) { 1633 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1634 how = fxdr_unsigned(int, *tl); 1635 switch (how) { 1636 case NFSV3CREATE_GUARDED: 1637 if (vp) { 1638 error = EEXIST; 1639 break; 1640 } 1641 /* fall through */ 1642 case NFSV3CREATE_UNCHECKED: 1643 nfsm_srvsattr(vap); 1644 break; 1645 case NFSV3CREATE_EXCLUSIVE: 1646 nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF); 1647 bcopy(cp, cverf, NFSX_V3CREATEVERF); 1648 exclusive_flag = 1; 1649 break; 1650 }; 1651 vap->va_type = VREG; 1652 } else { 1653 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1654 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); 1655 if (vap->va_type == VNON) 1656 vap->va_type = VREG; 1657 vap->va_mode = nfstov_mode(sp->sa_mode); 1658 switch (vap->va_type) { 1659 case VREG: 1660 tsize = fxdr_unsigned(int32_t, sp->sa_size); 1661 if (tsize != -1) 1662 vap->va_size = (u_quad_t)tsize; 1663 break; 1664 case VCHR: 1665 case VBLK: 1666 case VFIFO: 1667 rdev = fxdr_unsigned(long, sp->sa_size); 1668 break; 1669 default: 1670 break; 1671 }; 1672 } 1673 1674 /* 1675 * Iff doesn't exist, create it 1676 * otherwise just truncate to 0 length 1677 * should I set the mode too ? 1678 * 1679 * The only possible error we can have at this point is EEXIST. 1680 * nd.ni_vp will also be non-NULL in that case. 1681 */ 1682 if (vp == NULL) { 1683 if (vap->va_mode == (mode_t)VNOVAL) 1684 vap->va_mode = 0; 1685 if (vap->va_type == VREG || vap->va_type == VSOCK) { 1686 nqsrv_getl(dvp, ND_WRITE); 1687 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 daddr_t lblkno; 3502 3503 /* 3504 * Align to iosize boundry, super-align to page boundry. 3505 */ 3506 if (off & iomask) { 3507 cnt += off & iomask; 3508 off &= ~(u_quad_t)iomask; 3509 } 3510 if (off & PAGE_MASK) { 3511 cnt += off & PAGE_MASK; 3512 off &= ~(u_quad_t)PAGE_MASK; 3513 } 3514 lblkno = off / iosize; 3515 3516 if (vp->v_object && 3517 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3518 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC); 3519 } 3520 3521 crit_enter(); 3522 while (cnt > 0) { 3523 struct buf *bp; 3524 3525 /* 3526 * If we have a buffer and it is marked B_DELWRI we 3527 * have to lock and write it. Otherwise the prior 3528 * write is assumed to have already been committed. 3529 */ 3530 if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) { 3531 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { 3532 BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL); 3533 continue; /* retry */ 3534 } 3535 bremfree(bp); 3536 bp->b_flags &= ~B_ASYNC; 3537 VOP_BWRITE(bp->b_vp, bp); 3538 ++nfs_commit_miss; 3539 } 3540 ++nfs_commit_blks; 3541 if (cnt < iosize) 3542 break; 3543 cnt -= iosize; 3544 ++lblkno; 3545 } 3546 crit_exit(); 3547 } 3548 3549 aft_ret = VOP_GETATTR(vp, &aft, td); 3550 vput(vp); 3551 vp = NULL; 3552 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3553 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3554 if (!error) { 3555 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3556 if (nfsver.tv_sec == 0) 3557 nfsver = boottime; 3558 *tl++ = txdr_unsigned(nfsver.tv_sec); 3559 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 3560 } else { 3561 error = 0; 3562 } 3563 nfsmout: 3564 if (vp) 3565 vput(vp); 3566 return(error); 3567 } 3568 3569 /* 3570 * nfs statfs service 3571 */ 3572 int 3573 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3574 struct thread *td, struct mbuf **mrq) 3575 { 3576 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3577 struct sockaddr *nam = nfsd->nd_nam; 3578 caddr_t dpos = nfsd->nd_dpos; 3579 struct ucred *cred = &nfsd->nd_cr; 3580 struct statfs *sf; 3581 struct nfs_statfs *sfp; 3582 u_int32_t *tl; 3583 int32_t t1; 3584 caddr_t bpos; 3585 int error = 0, rdonly, cache, getret = 1; 3586 int v3 = (nfsd->nd_flag & ND_NFSV3); 3587 char *cp2; 3588 struct mbuf *mb, *mb2, *mreq; 3589 struct vnode *vp = NULL; 3590 struct vattr at; 3591 nfsfh_t nfh; 3592 fhandle_t *fhp; 3593 struct statfs statfs; 3594 u_quad_t frev, tval; 3595 3596 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3597 #ifndef nolint 3598 cache = 0; 3599 #endif 3600 fhp = &nfh.fh_generic; 3601 nfsm_srvmtofh(fhp); 3602 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3603 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3604 if (error) { 3605 nfsm_reply(NFSX_UNSIGNED); 3606 nfsm_srvpostop_attr(getret, &at); 3607 error = 0; 3608 goto nfsmout; 3609 } 3610 sf = &statfs; 3611 error = VFS_STATFS(vp->v_mount, sf, td); 3612 getret = VOP_GETATTR(vp, &at, td); 3613 vput(vp); 3614 vp = NULL; 3615 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3616 if (v3) 3617 nfsm_srvpostop_attr(getret, &at); 3618 if (error) { 3619 error = 0; 3620 goto nfsmout; 3621 } 3622 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3623 if (v3) { 3624 tval = (u_quad_t)sf->f_blocks; 3625 tval *= (u_quad_t)sf->f_bsize; 3626 txdr_hyper(tval, &sfp->sf_tbytes); 3627 tval = (u_quad_t)sf->f_bfree; 3628 tval *= (u_quad_t)sf->f_bsize; 3629 txdr_hyper(tval, &sfp->sf_fbytes); 3630 tval = (u_quad_t)sf->f_bavail; 3631 tval *= (u_quad_t)sf->f_bsize; 3632 txdr_hyper(tval, &sfp->sf_abytes); 3633 sfp->sf_tfiles.nfsuquad[0] = 0; 3634 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3635 sfp->sf_ffiles.nfsuquad[0] = 0; 3636 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3637 sfp->sf_afiles.nfsuquad[0] = 0; 3638 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3639 sfp->sf_invarsec = 0; 3640 } else { 3641 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3642 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3643 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3644 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3645 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3646 } 3647 nfsmout: 3648 if (vp) 3649 vput(vp); 3650 return(error); 3651 } 3652 3653 /* 3654 * nfs fsinfo service 3655 */ 3656 int 3657 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3658 struct thread *td, struct mbuf **mrq) 3659 { 3660 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3661 struct sockaddr *nam = nfsd->nd_nam; 3662 caddr_t dpos = nfsd->nd_dpos; 3663 struct ucred *cred = &nfsd->nd_cr; 3664 u_int32_t *tl; 3665 struct nfsv3_fsinfo *sip; 3666 int32_t t1; 3667 caddr_t bpos; 3668 int error = 0, rdonly, cache, getret = 1, pref; 3669 char *cp2; 3670 struct mbuf *mb, *mb2, *mreq; 3671 struct vnode *vp = NULL; 3672 struct vattr at; 3673 nfsfh_t nfh; 3674 fhandle_t *fhp; 3675 u_quad_t frev, maxfsize; 3676 struct statfs sb; 3677 3678 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3679 #ifndef nolint 3680 cache = 0; 3681 #endif 3682 fhp = &nfh.fh_generic; 3683 nfsm_srvmtofh(fhp); 3684 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3685 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3686 if (error) { 3687 nfsm_reply(NFSX_UNSIGNED); 3688 nfsm_srvpostop_attr(getret, &at); 3689 error = 0; 3690 goto nfsmout; 3691 } 3692 3693 /* XXX Try to make a guess on the max file size. */ 3694 VFS_STATFS(vp->v_mount, &sb, td); 3695 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; 3696 3697 getret = VOP_GETATTR(vp, &at, td); 3698 vput(vp); 3699 vp = NULL; 3700 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3701 nfsm_srvpostop_attr(getret, &at); 3702 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3703 3704 /* 3705 * XXX 3706 * There should be file system VFS OP(s) to get this information. 3707 * For now, assume ufs. 3708 */ 3709 if (slp->ns_so->so_type == SOCK_DGRAM) 3710 pref = NFS_MAXDGRAMDATA; 3711 else 3712 pref = NFS_MAXDATA; 3713 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3714 sip->fs_rtpref = txdr_unsigned(pref); 3715 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3716 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3717 sip->fs_wtpref = txdr_unsigned(pref); 3718 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3719 sip->fs_dtpref = txdr_unsigned(pref); 3720 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3721 sip->fs_timedelta.nfsv3_sec = 0; 3722 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3723 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3724 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3725 NFSV3FSINFO_CANSETTIME); 3726 nfsmout: 3727 if (vp) 3728 vput(vp); 3729 return(error); 3730 } 3731 3732 /* 3733 * nfs pathconf service 3734 */ 3735 int 3736 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3737 struct thread *td, struct mbuf **mrq) 3738 { 3739 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3740 struct sockaddr *nam = nfsd->nd_nam; 3741 caddr_t dpos = nfsd->nd_dpos; 3742 struct ucred *cred = &nfsd->nd_cr; 3743 u_int32_t *tl; 3744 struct nfsv3_pathconf *pc; 3745 int32_t t1; 3746 caddr_t bpos; 3747 int error = 0, rdonly, cache, getret = 1; 3748 register_t linkmax, namemax, chownres, notrunc; 3749 char *cp2; 3750 struct mbuf *mb, *mb2, *mreq; 3751 struct vnode *vp = NULL; 3752 struct vattr at; 3753 nfsfh_t nfh; 3754 fhandle_t *fhp; 3755 u_quad_t frev; 3756 3757 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3758 #ifndef nolint 3759 cache = 0; 3760 #endif 3761 fhp = &nfh.fh_generic; 3762 nfsm_srvmtofh(fhp); 3763 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3764 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3765 if (error) { 3766 nfsm_reply(NFSX_UNSIGNED); 3767 nfsm_srvpostop_attr(getret, &at); 3768 error = 0; 3769 goto nfsmout; 3770 } 3771 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3772 if (!error) 3773 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3774 if (!error) 3775 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3776 if (!error) 3777 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3778 getret = VOP_GETATTR(vp, &at, td); 3779 vput(vp); 3780 vp = NULL; 3781 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3782 nfsm_srvpostop_attr(getret, &at); 3783 if (error) { 3784 error = 0; 3785 goto nfsmout; 3786 } 3787 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3788 3789 pc->pc_linkmax = txdr_unsigned(linkmax); 3790 pc->pc_namemax = txdr_unsigned(namemax); 3791 pc->pc_notrunc = txdr_unsigned(notrunc); 3792 pc->pc_chownrestricted = txdr_unsigned(chownres); 3793 3794 /* 3795 * These should probably be supported by VOP_PATHCONF(), but 3796 * until msdosfs is exportable (why would you want to?), the 3797 * Unix defaults should be ok. 3798 */ 3799 pc->pc_caseinsensitive = nfs_false; 3800 pc->pc_casepreserving = nfs_true; 3801 nfsmout: 3802 if (vp) 3803 vput(vp); 3804 return(error); 3805 } 3806 3807 /* 3808 * Null operation, used by clients to ping server 3809 */ 3810 /* ARGSUSED */ 3811 int 3812 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3813 struct thread *td, struct mbuf **mrq) 3814 { 3815 struct mbuf *mrep = nfsd->nd_mrep; 3816 caddr_t bpos; 3817 int error = NFSERR_RETVOID, cache; 3818 struct mbuf *mb, *mreq; 3819 u_quad_t frev; 3820 3821 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3822 #ifndef nolint 3823 cache = 0; 3824 #endif 3825 nfsm_reply(0); 3826 nfsm_srvdone; 3827 } 3828 3829 /* 3830 * No operation, used for obsolete procedures 3831 */ 3832 /* ARGSUSED */ 3833 int 3834 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3835 struct thread *td, struct mbuf **mrq) 3836 { 3837 struct mbuf *mrep = nfsd->nd_mrep; 3838 caddr_t bpos; 3839 int error, cache; 3840 struct mbuf *mb, *mreq; 3841 u_quad_t frev; 3842 3843 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3844 #ifndef nolint 3845 cache = 0; 3846 #endif 3847 if (nfsd->nd_repstat) 3848 error = nfsd->nd_repstat; 3849 else 3850 error = EPROCUNAVAIL; 3851 nfsm_reply(0); 3852 error = 0; 3853 nfsm_srvdone; 3854 } 3855 3856 /* 3857 * Perform access checking for vnodes obtained from file handles that would 3858 * refer to files already opened by a Unix client. You cannot just use 3859 * vn_writechk() and VOP_ACCESS() for two reasons. 3860 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3861 * 2 - The owner is to be given access irrespective of mode bits for some 3862 * operations, so that processes that chmod after opening a file don't 3863 * break. I don't like this because it opens a security hole, but since 3864 * the nfs server opens a security hole the size of a barn door anyhow, 3865 * what the heck. 3866 * 3867 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3868 * will return EPERM instead of EACCESS. EPERM is always an error. 3869 */ 3870 static int 3871 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, 3872 int rdonly, struct thread *td, int override) 3873 { 3874 struct vattr vattr; 3875 int error; 3876 3877 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3878 if (flags & VWRITE) { 3879 /* Just vn_writechk() changed to check rdonly */ 3880 /* 3881 * Disallow write attempts on read-only file systems; 3882 * unless the file is a socket or a block or character 3883 * device resident on the file system. 3884 */ 3885 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3886 switch (vp->v_type) { 3887 case VREG: 3888 case VDIR: 3889 case VLNK: 3890 return (EROFS); 3891 default: 3892 break; 3893 } 3894 } 3895 /* 3896 * If there's shared text associated with 3897 * the inode, we can't allow writing. 3898 */ 3899 if (vp->v_flag & VTEXT) 3900 return (ETXTBSY); 3901 } 3902 error = VOP_GETATTR(vp, &vattr, td); 3903 if (error) 3904 return (error); 3905 error = VOP_ACCESS(vp, flags, cred, td); 3906 /* 3907 * Allow certain operations for the owner (reads and writes 3908 * on files that are already open). 3909 */ 3910 if (override && error == EACCES && cred->cr_uid == vattr.va_uid) 3911 error = 0; 3912 return error; 3913 } 3914 #endif /* NFS_NOSERVER */ 3915 3916