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