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.42 2006/12/23 00:41:29 swildner 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, rdev, len, tsize, dirfor_ret = 1, diraft_ret = 1; 1544 int v3 = (nfsd->nd_flag & ND_NFSV3), how, exclusive_flag = 0; 1545 caddr_t cp; 1546 char *cp2; 1547 struct mbuf *mb, *mb2, *mreq; 1548 struct vnode *dirp; 1549 struct vnode *dvp; 1550 struct vnode *vp; 1551 nfsfh_t nfh; 1552 fhandle_t *fhp; 1553 u_quad_t tempsize; 1554 u_char cverf[NFSX_V3CREATEVERF]; 1555 1556 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1557 #ifndef nolint 1558 rdev = 0; 1559 #endif 1560 nlookup_zero(&nd); 1561 dirp = NULL; 1562 dvp = NULL; 1563 vp = NULL; 1564 1565 fhp = &nfh.fh_generic; 1566 nfsm_srvmtofh(fhp); 1567 nfsm_srvnamesiz(len); 1568 1569 /* 1570 * Call namei and do initial cleanup to get a few things 1571 * out of the way. If we get an initial error we cleanup 1572 * and return here to avoid special-casing the invalid nd 1573 * structure through the rest of the case. dirp may be 1574 * set even if an error occurs, but the nd structure will not 1575 * be valid at all if an error occurs so we have to invalidate it 1576 * prior to calling nfsm_reply ( which might goto nfsmout ). 1577 */ 1578 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 1579 fhp, len, slp, nam, &md, &dpos, &dirp, 1580 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 1581 if (dirp) { 1582 if (v3) { 1583 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 1584 } else { 1585 vrele(dirp); 1586 dirp = NULL; 1587 } 1588 } 1589 if (error) { 1590 nfsm_reply(NFSX_WCCDATA(v3)); 1591 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1592 error = 0; 1593 goto nfsmout; 1594 } 1595 1596 /* 1597 * No error. Continue. State: 1598 * 1599 * dirp may be valid 1600 * vp may be valid or NULL if the target does not 1601 * exist. 1602 * dvp is valid 1603 * 1604 * The error state is set through the code and we may also do some 1605 * opportunistic releasing of vnodes to avoid holding locks through 1606 * NFS I/O. The cleanup at the end is a catch-all 1607 */ 1608 1609 VATTR_NULL(vap); 1610 if (v3) { 1611 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1612 how = fxdr_unsigned(int, *tl); 1613 switch (how) { 1614 case NFSV3CREATE_GUARDED: 1615 if (vp) { 1616 error = EEXIST; 1617 break; 1618 } 1619 /* fall through */ 1620 case NFSV3CREATE_UNCHECKED: 1621 nfsm_srvsattr(vap); 1622 break; 1623 case NFSV3CREATE_EXCLUSIVE: 1624 nfsm_dissect(cp, caddr_t, NFSX_V3CREATEVERF); 1625 bcopy(cp, cverf, NFSX_V3CREATEVERF); 1626 exclusive_flag = 1; 1627 break; 1628 }; 1629 vap->va_type = VREG; 1630 } else { 1631 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1632 vap->va_type = IFTOVT(fxdr_unsigned(u_int32_t, sp->sa_mode)); 1633 if (vap->va_type == VNON) 1634 vap->va_type = VREG; 1635 vap->va_mode = nfstov_mode(sp->sa_mode); 1636 switch (vap->va_type) { 1637 case VREG: 1638 tsize = fxdr_unsigned(int32_t, sp->sa_size); 1639 if (tsize != -1) 1640 vap->va_size = (u_quad_t)tsize; 1641 break; 1642 case VCHR: 1643 case VBLK: 1644 case VFIFO: 1645 rdev = fxdr_unsigned(long, sp->sa_size); 1646 break; 1647 default: 1648 break; 1649 }; 1650 } 1651 1652 /* 1653 * Iff doesn't exist, create it 1654 * otherwise just truncate to 0 length 1655 * should I set the mode too ? 1656 * 1657 * The only possible error we can have at this point is EEXIST. 1658 * nd.ni_vp will also be non-NULL in that case. 1659 */ 1660 if (vp == NULL) { 1661 if (vap->va_mode == (mode_t)VNOVAL) 1662 vap->va_mode = 0; 1663 if (vap->va_type == VREG || vap->va_type == VSOCK) { 1664 vput(dvp); 1665 dvp = NULL; 1666 error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap); 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_rdev = rdev; 1692 1693 vput(dvp); 1694 dvp = NULL; 1695 error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap); 1696 if (error) 1697 goto nfsmreply0; 1698 #if 0 1699 /* 1700 * XXX what is this junk supposed to do ? 1701 */ 1702 1703 vput(vp); 1704 vp = NULL; 1705 1706 /* 1707 * release dvp prior to lookup 1708 */ 1709 vput(dvp); 1710 dvp = NULL; 1711 1712 /* 1713 * Setup for lookup. 1714 * 1715 * Even though LOCKPARENT was cleared, ni_dvp may 1716 * be garbage. 1717 */ 1718 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 1719 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT); 1720 nd.ni_cnd.cn_td = td; 1721 nd.ni_cnd.cn_cred = cred; 1722 1723 error = lookup(&nd); 1724 nd.ni_dvp = NULL; 1725 1726 if (error != 0) { 1727 nfsm_reply(0); 1728 /* fall through on certain errors */ 1729 } 1730 nfsrv_object_create(nd.ni_vp); 1731 if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) { 1732 error = EINVAL; 1733 goto nfsmreply0; 1734 } 1735 #endif 1736 } else { 1737 error = ENXIO; 1738 } 1739 } else { 1740 if (vap->va_size != -1) { 1741 error = nfsrv_access(vp, VWRITE, cred, 1742 (nd.nl_flags & NLC_NFS_RDONLY), td, 0); 1743 if (!error) { 1744 tempsize = vap->va_size; 1745 VATTR_NULL(vap); 1746 vap->va_size = tempsize; 1747 error = VOP_SETATTR(vp, vap, cred); 1748 } 1749 } 1750 } 1751 1752 if (!error) { 1753 bzero((caddr_t)fhp, sizeof(nfh)); 1754 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1755 error = VFS_VPTOFH(vp, &fhp->fh_fid); 1756 if (!error) 1757 error = VOP_GETATTR(vp, vap); 1758 } 1759 if (v3) { 1760 if (exclusive_flag && !error && 1761 bcmp(cverf, (caddr_t)&vap->va_atime, NFSX_V3CREATEVERF)) 1762 error = EEXIST; 1763 diraft_ret = VOP_GETATTR(dirp, &diraft); 1764 vrele(dirp); 1765 dirp = NULL; 1766 } 1767 nfsm_reply(NFSX_SRVFH(v3) + NFSX_FATTR(v3) + NFSX_WCCDATA(v3)); 1768 if (v3) { 1769 if (!error) { 1770 nfsm_srvpostop_fh(fhp); 1771 nfsm_srvpostop_attr(0, vap); 1772 } 1773 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1774 error = 0; 1775 } else { 1776 nfsm_srvfhtom(fhp, v3); 1777 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 1778 nfsm_srvfillattr(vap, fp); 1779 } 1780 goto nfsmout; 1781 1782 nfsmreply0: 1783 nfsm_reply(0); 1784 error = 0; 1785 /* fall through */ 1786 1787 nfsmout: 1788 if (dirp) 1789 vrele(dirp); 1790 nlookup_done(&nd); 1791 if (dvp) { 1792 if (dvp == vp) 1793 vrele(dvp); 1794 else 1795 vput(dvp); 1796 } 1797 if (vp) 1798 vput(vp); 1799 return (error); 1800 } 1801 1802 /* 1803 * nfs v3 mknod service 1804 */ 1805 int 1806 nfsrv_mknod(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 1807 struct thread *td, struct mbuf **mrq) 1808 { 1809 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1810 struct sockaddr *nam = nfsd->nd_nam; 1811 caddr_t dpos = nfsd->nd_dpos; 1812 struct ucred *cred = &nfsd->nd_cr; 1813 struct vattr va, dirfor, diraft; 1814 struct vattr *vap = &va; 1815 u_int32_t *tl; 1816 struct nlookupdata nd; 1817 int32_t t1; 1818 caddr_t bpos; 1819 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 1820 u_int32_t major, minor; 1821 enum vtype vtyp; 1822 char *cp2; 1823 struct mbuf *mb, *mb2, *mreq; 1824 struct vnode *dirp; 1825 struct vnode *dvp; 1826 struct vnode *vp; 1827 nfsfh_t nfh; 1828 fhandle_t *fhp; 1829 1830 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1831 nlookup_zero(&nd); 1832 dirp = NULL; 1833 dvp = NULL; 1834 vp = NULL; 1835 1836 fhp = &nfh.fh_generic; 1837 nfsm_srvmtofh(fhp); 1838 nfsm_srvnamesiz(len); 1839 1840 /* 1841 * Handle nfs_namei() call. If an error occurs, the nd structure 1842 * is not valid. However, nfsm_*() routines may still jump to 1843 * nfsmout. 1844 */ 1845 1846 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 1847 fhp, len, slp, nam, &md, &dpos, &dirp, 1848 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 1849 if (dirp) 1850 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 1851 if (error) { 1852 nfsm_reply(NFSX_WCCDATA(1)); 1853 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1854 error = 0; 1855 goto nfsmout; 1856 } 1857 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 1858 vtyp = nfsv3tov_type(*tl); 1859 if (vtyp != VCHR && vtyp != VBLK && vtyp != VSOCK && vtyp != VFIFO) { 1860 error = NFSERR_BADTYPE; 1861 goto out; 1862 } 1863 VATTR_NULL(vap); 1864 nfsm_srvsattr(vap); 1865 if (vtyp == VCHR || vtyp == VBLK) { 1866 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1867 major = fxdr_unsigned(u_int32_t, *tl++); 1868 minor = fxdr_unsigned(u_int32_t, *tl); 1869 vap->va_rdev = makeudev(major, minor); 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 error = VOP_NCREATE(&nd.nl_nch, &vp, nd.nl_cred, vap); 1884 } else { 1885 if (vtyp != VFIFO && (error = suser_cred(cred, 0))) 1886 goto out; 1887 1888 error = VOP_NMKNOD(&nd.nl_nch, &vp, nd.nl_cred, vap); 1889 if (error) 1890 goto out; 1891 1892 #if 0 1893 vput(vp); 1894 vp = NULL; 1895 1896 /* 1897 * Release dvp prior to lookup 1898 */ 1899 vput(dvp); 1900 dvp = NULL; 1901 1902 /* 1903 * XXX what is this stuff for? 1904 */ 1905 KKASSERT(td->td_proc); 1906 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 1907 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT); 1908 nd.ni_cnd.cn_td = td; 1909 nd.ni_cnd.cn_cred = td->td_proc->p_ucred; 1910 1911 error = lookup(&nd); 1912 nd.ni_dvp = NULL; 1913 1914 if (error) 1915 goto out; 1916 if (nd.ni_cnd.cn_flags & CNP_ISSYMLINK) 1917 error = EINVAL; 1918 #endif 1919 } 1920 1921 /* 1922 * send response, cleanup, return. 1923 */ 1924 out: 1925 nlookup_done(&nd); 1926 if (dvp) { 1927 if (dvp == vp) 1928 vrele(dvp); 1929 else 1930 vput(dvp); 1931 dvp = NULL; 1932 } 1933 if (!error) { 1934 bzero((caddr_t)fhp, sizeof(nfh)); 1935 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 1936 error = VFS_VPTOFH(vp, &fhp->fh_fid); 1937 if (!error) 1938 error = VOP_GETATTR(vp, vap); 1939 } 1940 if (vp) { 1941 vput(vp); 1942 vp = NULL; 1943 } 1944 diraft_ret = VOP_GETATTR(dirp, &diraft); 1945 if (dirp) { 1946 vrele(dirp); 1947 dirp = NULL; 1948 } 1949 nfsm_reply(NFSX_SRVFH(1) + NFSX_POSTOPATTR(1) + NFSX_WCCDATA(1)); 1950 if (!error) { 1951 nfsm_srvpostop_fh(fhp); 1952 nfsm_srvpostop_attr(0, vap); 1953 } 1954 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 1955 return (0); 1956 nfsmout: 1957 if (dirp) 1958 vrele(dirp); 1959 nlookup_done(&nd); 1960 if (dvp) { 1961 if (dvp == vp) 1962 vrele(dvp); 1963 else 1964 vput(dvp); 1965 } 1966 if (vp) 1967 vput(vp); 1968 return (error); 1969 } 1970 1971 /* 1972 * nfs remove service 1973 */ 1974 int 1975 nfsrv_remove(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 1976 struct thread *td, struct mbuf **mrq) 1977 { 1978 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 1979 struct sockaddr *nam = nfsd->nd_nam; 1980 caddr_t dpos = nfsd->nd_dpos; 1981 struct ucred *cred = &nfsd->nd_cr; 1982 struct nlookupdata nd; 1983 u_int32_t *tl; 1984 int32_t t1; 1985 caddr_t bpos; 1986 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 1987 int v3 = (nfsd->nd_flag & ND_NFSV3); 1988 char *cp2; 1989 struct mbuf *mb, *mreq; 1990 struct vnode *dirp; 1991 struct vnode *dvp; 1992 struct vnode *vp; 1993 struct vattr dirfor, diraft; 1994 nfsfh_t nfh; 1995 fhandle_t *fhp; 1996 1997 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 1998 nlookup_zero(&nd); 1999 dirp = NULL; 2000 dvp = NULL; 2001 vp = NULL; 2002 2003 fhp = &nfh.fh_generic; 2004 nfsm_srvmtofh(fhp); 2005 nfsm_srvnamesiz(len); 2006 2007 error = nfs_namei(&nd, cred, NAMEI_DELETE, &dvp, &vp, 2008 fhp, len, slp, nam, &md, &dpos, &dirp, 2009 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2010 if (dirp) { 2011 if (v3) 2012 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2013 } 2014 if (error == 0) { 2015 if (vp->v_type == VDIR) { 2016 error = EPERM; /* POSIX */ 2017 goto out; 2018 } 2019 /* 2020 * The root of a mounted filesystem cannot be deleted. 2021 */ 2022 if (vp->v_flag & VROOT) { 2023 error = EBUSY; 2024 goto out; 2025 } 2026 out: 2027 if (!error) { 2028 if (dvp) { 2029 if (dvp == vp) 2030 vrele(dvp); 2031 else 2032 vput(dvp); 2033 dvp = NULL; 2034 } 2035 if (vp) { 2036 vput(vp); 2037 vp = NULL; 2038 } 2039 error = VOP_NREMOVE(&nd.nl_nch, nd.nl_cred); 2040 } 2041 } 2042 if (dirp && v3) 2043 diraft_ret = VOP_GETATTR(dirp, &diraft); 2044 nfsm_reply(NFSX_WCCDATA(v3)); 2045 if (v3) { 2046 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2047 error = 0; 2048 } 2049 nfsmout: 2050 nlookup_done(&nd); 2051 if (dirp) 2052 vrele(dirp); 2053 if (dvp) { 2054 if (dvp == vp) 2055 vrele(dvp); 2056 else 2057 vput(dvp); 2058 } 2059 if (vp) 2060 vput(vp); 2061 return(error); 2062 } 2063 2064 /* 2065 * nfs rename service 2066 */ 2067 int 2068 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2069 struct thread *td, struct mbuf **mrq) 2070 { 2071 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2072 struct sockaddr *nam = nfsd->nd_nam; 2073 caddr_t dpos = nfsd->nd_dpos; 2074 struct ucred *cred = &nfsd->nd_cr; 2075 u_int32_t *tl; 2076 int32_t t1; 2077 caddr_t bpos; 2078 int error = 0, len, len2, fdirfor_ret = 1, fdiraft_ret = 1; 2079 int tdirfor_ret = 1, tdiraft_ret = 1; 2080 int v3 = (nfsd->nd_flag & ND_NFSV3); 2081 char *cp2; 2082 struct mbuf *mb, *mreq; 2083 struct nlookupdata fromnd, tond; 2084 struct vnode *fvp, *fdirp; 2085 struct vnode *tvp, *tdirp; 2086 struct namecache *ncp; 2087 struct vattr fdirfor, fdiraft, tdirfor, tdiraft; 2088 nfsfh_t fnfh, tnfh; 2089 fhandle_t *ffhp, *tfhp; 2090 uid_t saved_uid; 2091 2092 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2093 #ifndef nolint 2094 fvp = (struct vnode *)0; 2095 #endif 2096 ffhp = &fnfh.fh_generic; 2097 tfhp = &tnfh.fh_generic; 2098 2099 /* 2100 * Clear fields incase goto nfsmout occurs from macro. 2101 */ 2102 2103 nlookup_zero(&fromnd); 2104 nlookup_zero(&tond); 2105 fdirp = NULL; 2106 tdirp = NULL; 2107 2108 nfsm_srvmtofh(ffhp); 2109 nfsm_srvnamesiz(len); 2110 /* 2111 * Remember our original uid so that we can reset cr_uid before 2112 * the second nfs_namei() call, in case it is remapped. 2113 */ 2114 saved_uid = cred->cr_uid; 2115 error = nfs_namei(&fromnd, cred, NAMEI_DELETE, NULL, NULL, 2116 ffhp, len, slp, nam, &md, &dpos, &fdirp, 2117 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2118 if (fdirp) { 2119 if (v3) 2120 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor); 2121 } 2122 if (error) { 2123 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2124 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2125 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2126 error = 0; 2127 goto nfsmout; 2128 } 2129 2130 /* 2131 * We have to unlock the from ncp before we can safely lookup 2132 * the target ncp. 2133 */ 2134 KKASSERT(fromnd.nl_flags & NLC_NCPISLOCKED); 2135 cache_unlock(&fromnd.nl_nch); 2136 fromnd.nl_flags &= ~NLC_NCPISLOCKED; 2137 nfsm_srvmtofh(tfhp); 2138 nfsm_strsiz(len2, NFS_MAXNAMLEN); 2139 cred->cr_uid = saved_uid; 2140 2141 error = nfs_namei(&tond, cred, NAMEI_RENAME, NULL, NULL, 2142 tfhp, len2, slp, nam, &md, &dpos, &tdirp, 2143 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2144 if (tdirp) { 2145 if (v3) 2146 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor); 2147 } 2148 if (error) 2149 goto out1; 2150 2151 /* 2152 * relock the source 2153 */ 2154 if (cache_lock_nonblock(&fromnd.nl_nch) == 0) { 2155 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2156 } else if (fromnd.nl_nch.ncp > tond.nl_nch.ncp) { 2157 cache_lock(&fromnd.nl_nch); 2158 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2159 } else { 2160 cache_unlock(&tond.nl_nch); 2161 cache_lock(&fromnd.nl_nch); 2162 cache_resolve(&fromnd.nl_nch, fromnd.nl_cred); 2163 cache_lock(&tond.nl_nch); 2164 cache_resolve(&tond.nl_nch, tond.nl_cred); 2165 } 2166 fromnd.nl_flags |= NLC_NCPISLOCKED; 2167 2168 tvp = tond.nl_nch.ncp->nc_vp; 2169 fvp = fromnd.nl_nch.ncp->nc_vp; 2170 2171 if (tvp != NULL) { 2172 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2173 if (v3) 2174 error = EEXIST; 2175 else 2176 error = EISDIR; 2177 goto out; 2178 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2179 if (v3) 2180 error = EEXIST; 2181 else 2182 error = ENOTDIR; 2183 goto out; 2184 } 2185 if (tvp->v_type == VDIR && (tond.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) { 2186 if (v3) 2187 error = EXDEV; 2188 else 2189 error = ENOTEMPTY; 2190 goto out; 2191 } 2192 } 2193 if (fvp->v_type == VDIR && (fromnd.nl_nch.ncp->nc_flag & NCF_ISMOUNTPT)) { 2194 if (v3) 2195 error = EXDEV; 2196 else 2197 error = ENOTEMPTY; 2198 goto out; 2199 } 2200 if (fromnd.nl_nch.mount != tond.nl_nch.mount) { 2201 if (v3) 2202 error = EXDEV; 2203 else 2204 error = ENOTEMPTY; 2205 goto out; 2206 } 2207 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp->nc_parent) { 2208 if (v3) 2209 error = EINVAL; 2210 else 2211 error = ENOTEMPTY; 2212 } 2213 2214 /* 2215 * You cannot rename a source into itself or a subdirectory of itself. 2216 * We check this by travsering the target directory upwards looking 2217 * for a match against the source. 2218 */ 2219 if (error == 0) { 2220 for (ncp = tond.nl_nch.ncp; ncp; ncp = ncp->nc_parent) { 2221 if (fromnd.nl_nch.ncp == ncp) { 2222 error = EINVAL; 2223 break; 2224 } 2225 } 2226 } 2227 2228 /* 2229 * If source is the same as the destination (that is the 2230 * same vnode with the same name in the same directory), 2231 * then there is nothing to do. 2232 */ 2233 if (fromnd.nl_nch.ncp == tond.nl_nch.ncp) 2234 error = -1; 2235 out: 2236 if (!error) { 2237 /* 2238 * The VOP_NRENAME function releases all vnode references & 2239 * locks prior to returning so we need to clear the pointers 2240 * to bypass cleanup code later on. 2241 */ 2242 error = VOP_NRENAME(&fromnd.nl_nch, &tond.nl_nch, tond.nl_cred); 2243 } else { 2244 if (error == -1) 2245 error = 0; 2246 } 2247 /* fall through */ 2248 2249 out1: 2250 if (fdirp) 2251 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft); 2252 if (tdirp) 2253 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft); 2254 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2255 if (v3) { 2256 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2257 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2258 } 2259 error = 0; 2260 /* fall through */ 2261 2262 nfsmout: 2263 if (tdirp) 2264 vrele(tdirp); 2265 nlookup_done(&tond); 2266 if (fdirp) 2267 vrele(fdirp); 2268 nlookup_done(&fromnd); 2269 return (error); 2270 } 2271 2272 /* 2273 * nfs link service 2274 */ 2275 int 2276 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2277 struct thread *td, struct mbuf **mrq) 2278 { 2279 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2280 struct sockaddr *nam = nfsd->nd_nam; 2281 caddr_t dpos = nfsd->nd_dpos; 2282 struct ucred *cred = &nfsd->nd_cr; 2283 struct nlookupdata nd; 2284 u_int32_t *tl; 2285 int32_t t1; 2286 caddr_t bpos; 2287 int error = 0, rdonly, len, dirfor_ret = 1, diraft_ret = 1; 2288 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 2289 char *cp2; 2290 struct mbuf *mb, *mreq; 2291 struct vnode *dirp; 2292 struct vnode *dvp; 2293 struct vnode *vp; 2294 struct vnode *xp; 2295 struct vattr dirfor, diraft, at; 2296 nfsfh_t nfh, dnfh; 2297 fhandle_t *fhp, *dfhp; 2298 2299 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2300 nlookup_zero(&nd); 2301 dirp = dvp = vp = xp = NULL; 2302 2303 fhp = &nfh.fh_generic; 2304 dfhp = &dnfh.fh_generic; 2305 nfsm_srvmtofh(fhp); 2306 nfsm_srvmtofh(dfhp); 2307 nfsm_srvnamesiz(len); 2308 2309 error = nfsrv_fhtovp(fhp, FALSE, &xp, cred, slp, nam, 2310 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2311 if (error) { 2312 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2313 nfsm_srvpostop_attr(getret, &at); 2314 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2315 xp = NULL; 2316 error = 0; 2317 goto nfsmout; 2318 } 2319 if (xp->v_type == VDIR) { 2320 error = EPERM; /* POSIX */ 2321 goto out1; 2322 } 2323 2324 error = nfs_namei(&nd, cred, NAMEI_CREATE, &dvp, &vp, 2325 dfhp, len, slp, nam, &md, &dpos, &dirp, 2326 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2327 if (dirp) { 2328 if (v3) 2329 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2330 } 2331 if (error) 2332 goto out1; 2333 2334 if (vp != NULL) { 2335 error = EEXIST; 2336 goto out; 2337 } 2338 if (xp->v_mount != dvp->v_mount) 2339 error = EXDEV; 2340 out: 2341 if (!error) { 2342 error = VOP_NLINK(&nd.nl_nch, xp, nd.nl_cred); 2343 } 2344 /* fall through */ 2345 2346 out1: 2347 if (v3) 2348 getret = VOP_GETATTR(xp, &at); 2349 if (dirp) 2350 diraft_ret = VOP_GETATTR(dirp, &diraft); 2351 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2352 if (v3) { 2353 nfsm_srvpostop_attr(getret, &at); 2354 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2355 error = 0; 2356 } 2357 /* fall through */ 2358 2359 nfsmout: 2360 nlookup_done(&nd); 2361 if (dirp) 2362 vrele(dirp); 2363 if (xp) 2364 vrele(xp); 2365 if (dvp) { 2366 if (dvp == vp) 2367 vrele(dvp); 2368 else 2369 vput(dvp); 2370 } 2371 if (vp) 2372 vput(vp); 2373 return(error); 2374 } 2375 2376 /* 2377 * nfs symbolic link service 2378 */ 2379 int 2380 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2381 struct thread *td, struct mbuf **mrq) 2382 { 2383 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2384 struct sockaddr *nam = nfsd->nd_nam; 2385 caddr_t dpos = nfsd->nd_dpos; 2386 struct ucred *cred = &nfsd->nd_cr; 2387 struct vattr va, dirfor, diraft; 2388 struct nlookupdata nd; 2389 struct vattr *vap = &va; 2390 u_int32_t *tl; 2391 int32_t t1; 2392 struct nfsv2_sattr *sp; 2393 char *bpos, *pathcp = (char *)0, *cp2; 2394 struct uio io; 2395 struct iovec iv; 2396 int error = 0, len, len2, dirfor_ret = 1, diraft_ret = 1; 2397 int v3 = (nfsd->nd_flag & ND_NFSV3); 2398 struct mbuf *mb, *mreq, *mb2; 2399 struct vnode *dirp; 2400 struct vnode *vp; 2401 nfsfh_t nfh; 2402 fhandle_t *fhp; 2403 2404 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2405 nlookup_zero(&nd); 2406 dirp = 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, NULL, &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 error = VOP_NSYMLINK(&nd.nl_nch, &vp, nd.nl_cred, vap, pathcp); 2450 if (error == 0) { 2451 bzero((caddr_t)fhp, sizeof(nfh)); 2452 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 2453 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2454 if (!error) 2455 error = VOP_GETATTR(vp, vap); 2456 } 2457 2458 #if 0 2459 /* 2460 * We have a vp in hand from the new API call, we do not have to 2461 * look it up again. 2462 */ 2463 if (error == 0) { 2464 if (v3) { 2465 /* 2466 * Issue lookup. Leave SAVESTART set so we can easily free 2467 * the name buffer later on. 2468 * 2469 * since LOCKPARENT is not set, ni_dvp will be garbage on 2470 * return whether an error occurs or not. 2471 */ 2472 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 2473 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT | CNP_FOLLOW); 2474 nd.ni_cnd.cn_td = td; 2475 nd.ni_cnd.cn_cred = cred; 2476 2477 error = lookup(&nd); 2478 nd.ni_dvp = NULL; 2479 2480 if (error == 0) { 2481 bzero((caddr_t)fhp, sizeof(nfh)); 2482 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid; 2483 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid); 2484 if (!error) 2485 error = VOP_GETATTR(nd.ni_vp, vap); 2486 vput(nd.ni_vp); 2487 nd.ni_vp = NULL; 2488 } 2489 } 2490 } 2491 #endif 2492 out: 2493 if (vp) { 2494 vput(vp); 2495 vp = NULL; 2496 } 2497 if (pathcp) { 2498 FREE(pathcp, M_TEMP); 2499 pathcp = NULL; 2500 } 2501 if (dirp) { 2502 diraft_ret = VOP_GETATTR(dirp, &diraft); 2503 vrele(dirp); 2504 dirp = NULL; 2505 } 2506 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2507 if (v3) { 2508 if (!error) { 2509 nfsm_srvpostop_fh(fhp); 2510 nfsm_srvpostop_attr(0, vap); 2511 } 2512 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2513 } 2514 error = 0; 2515 /* fall through */ 2516 2517 nfsmout: 2518 nlookup_done(&nd); 2519 if (vp) 2520 vput(vp); 2521 if (dirp) 2522 vrele(dirp); 2523 if (pathcp) 2524 FREE(pathcp, M_TEMP); 2525 return (error); 2526 } 2527 2528 /* 2529 * nfs mkdir service 2530 */ 2531 int 2532 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2533 struct thread *td, struct mbuf **mrq) 2534 { 2535 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2536 struct sockaddr *nam = nfsd->nd_nam; 2537 caddr_t dpos = nfsd->nd_dpos; 2538 struct ucred *cred = &nfsd->nd_cr; 2539 struct vattr va, dirfor, diraft; 2540 struct vattr *vap = &va; 2541 struct nfs_fattr *fp; 2542 struct nlookupdata nd; 2543 caddr_t cp; 2544 u_int32_t *tl; 2545 int32_t t1; 2546 caddr_t bpos; 2547 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 2548 int v3 = (nfsd->nd_flag & ND_NFSV3); 2549 char *cp2; 2550 struct mbuf *mb, *mb2, *mreq; 2551 struct vnode *dirp; 2552 struct vnode *vp; 2553 nfsfh_t nfh; 2554 fhandle_t *fhp; 2555 2556 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2557 nlookup_zero(&nd); 2558 dirp = NULL; 2559 vp = NULL; 2560 2561 fhp = &nfh.fh_generic; 2562 nfsm_srvmtofh(fhp); 2563 nfsm_srvnamesiz(len); 2564 2565 error = nfs_namei(&nd, cred, NAMEI_CREATE, NULL, &vp, 2566 fhp, len, slp, nam, &md, &dpos, &dirp, 2567 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2568 if (dirp) { 2569 if (v3) 2570 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2571 } 2572 if (error) { 2573 nfsm_reply(NFSX_WCCDATA(v3)); 2574 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2575 error = 0; 2576 goto nfsmout; 2577 } 2578 VATTR_NULL(vap); 2579 if (v3) { 2580 nfsm_srvsattr(vap); 2581 } else { 2582 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2583 vap->va_mode = nfstov_mode(*tl++); 2584 } 2585 2586 /* 2587 * At this point nd.ni_dvp is referenced and exclusively locked and 2588 * nd.ni_vp, if it exists, is referenced but not locked. 2589 */ 2590 2591 vap->va_type = VDIR; 2592 if (vp != NULL) { 2593 error = EEXIST; 2594 goto out; 2595 } 2596 2597 /* 2598 * Issue mkdir op. Since SAVESTART is not set, the pathname 2599 * component is freed by the VOP call. This will fill-in 2600 * nd.ni_vp, reference, and exclusively lock it. 2601 */ 2602 if (vap->va_mode == (mode_t)VNOVAL) 2603 vap->va_mode = 0; 2604 error = VOP_NMKDIR(&nd.nl_nch, &vp, nd.nl_cred, vap); 2605 2606 if (error == 0) { 2607 bzero((caddr_t)fhp, sizeof(nfh)); 2608 fhp->fh_fsid = vp->v_mount->mnt_stat.f_fsid; 2609 error = VFS_VPTOFH(vp, &fhp->fh_fid); 2610 if (error == 0) 2611 error = VOP_GETATTR(vp, vap); 2612 } 2613 out: 2614 if (dirp) 2615 diraft_ret = VOP_GETATTR(dirp, &diraft); 2616 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2617 if (v3) { 2618 if (!error) { 2619 nfsm_srvpostop_fh(fhp); 2620 nfsm_srvpostop_attr(0, vap); 2621 } 2622 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2623 } else { 2624 nfsm_srvfhtom(fhp, v3); 2625 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2626 nfsm_srvfillattr(vap, fp); 2627 } 2628 error = 0; 2629 /* fall through */ 2630 2631 nfsmout: 2632 nlookup_done(&nd); 2633 if (dirp) 2634 vrele(dirp); 2635 if (vp) 2636 vput(vp); 2637 return (error); 2638 } 2639 2640 /* 2641 * nfs rmdir service 2642 */ 2643 int 2644 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2645 struct thread *td, struct mbuf **mrq) 2646 { 2647 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2648 struct sockaddr *nam = nfsd->nd_nam; 2649 caddr_t dpos = nfsd->nd_dpos; 2650 struct ucred *cred = &nfsd->nd_cr; 2651 u_int32_t *tl; 2652 int32_t t1; 2653 caddr_t bpos; 2654 int error = 0, len, dirfor_ret = 1, diraft_ret = 1; 2655 int v3 = (nfsd->nd_flag & ND_NFSV3); 2656 char *cp2; 2657 struct mbuf *mb, *mreq; 2658 struct vnode *dirp; 2659 struct vnode *vp; 2660 struct vattr dirfor, diraft; 2661 nfsfh_t nfh; 2662 fhandle_t *fhp; 2663 struct nlookupdata nd; 2664 2665 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2666 nlookup_zero(&nd); 2667 dirp = NULL; 2668 vp = NULL; 2669 2670 fhp = &nfh.fh_generic; 2671 nfsm_srvmtofh(fhp); 2672 nfsm_srvnamesiz(len); 2673 2674 error = nfs_namei(&nd, cred, NAMEI_DELETE, NULL, &vp, 2675 fhp, len, slp, nam, &md, &dpos, &dirp, 2676 td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2677 if (dirp) { 2678 if (v3) 2679 dirfor_ret = VOP_GETATTR(dirp, &dirfor); 2680 } 2681 if (error) { 2682 nfsm_reply(NFSX_WCCDATA(v3)); 2683 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2684 error = 0; 2685 goto nfsmout; 2686 } 2687 if (vp->v_type != VDIR) { 2688 error = ENOTDIR; 2689 goto out; 2690 } 2691 2692 /* 2693 * The root of a mounted filesystem cannot be deleted. 2694 */ 2695 if (vp->v_flag & VROOT) 2696 error = EBUSY; 2697 out: 2698 /* 2699 * Issue or abort op. Since SAVESTART is not set, path name 2700 * component is freed by the VOP after either. 2701 */ 2702 if (!error) { 2703 vput(vp); 2704 vp = NULL; 2705 error = VOP_NRMDIR(&nd.nl_nch, nd.nl_cred); 2706 } 2707 nlookup_done(&nd); 2708 2709 if (dirp) 2710 diraft_ret = VOP_GETATTR(dirp, &diraft); 2711 nfsm_reply(NFSX_WCCDATA(v3)); 2712 if (v3) { 2713 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2714 error = 0; 2715 } 2716 /* fall through */ 2717 2718 nfsmout: 2719 nlookup_done(&nd); 2720 if (dirp) 2721 vrele(dirp); 2722 if (vp) 2723 vput(vp); 2724 return(error); 2725 } 2726 2727 /* 2728 * nfs readdir service 2729 * - mallocs what it thinks is enough to read 2730 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 2731 * - calls VOP_READDIR() 2732 * - loops around building the reply 2733 * if the output generated exceeds count break out of loop 2734 * The nfsm_clget macro is used here so that the reply will be packed 2735 * tightly in mbuf clusters. 2736 * - it only knows that it has encountered eof when the VOP_READDIR() 2737 * reads nothing 2738 * - as such one readdir rpc will return eof false although you are there 2739 * and then the next will return eof 2740 * - it trims out records with d_fileno == 0 2741 * this doesn't matter for Unix clients, but they might confuse clients 2742 * for other os'. 2743 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2744 * than requested, but this may not apply to all filesystems. For 2745 * example, client NFS does not { although it is never remote mounted 2746 * anyhow } 2747 * The alternate call nfsrv_readdirplus() does lookups as well. 2748 * PS: The NFS protocol spec. does not clarify what the "count" byte 2749 * argument is a count of.. just name strings and file id's or the 2750 * entire reply rpc or ... 2751 * I tried just file name and id sizes and it confused the Sun client, 2752 * so I am using the full rpc size now. The "paranoia.." comment refers 2753 * to including the status longwords that are not a part of the dir. 2754 * "entry" structures, but are in the rpc. 2755 */ 2756 struct flrep { 2757 nfsuint64 fl_off; 2758 u_int32_t fl_postopok; 2759 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)]; 2760 u_int32_t fl_fhok; 2761 u_int32_t fl_fhsize; 2762 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)]; 2763 }; 2764 2765 int 2766 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2767 struct thread *td, struct mbuf **mrq) 2768 { 2769 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2770 struct sockaddr *nam = nfsd->nd_nam; 2771 caddr_t dpos = nfsd->nd_dpos; 2772 struct ucred *cred = &nfsd->nd_cr; 2773 char *bp, *be; 2774 struct mbuf *mp; 2775 struct dirent *dp; 2776 caddr_t cp; 2777 u_int32_t *tl; 2778 int32_t t1; 2779 caddr_t bpos; 2780 struct mbuf *mb, *mb2, *mreq, *mp2; 2781 char *cpos, *cend, *cp2, *rbuf; 2782 struct vnode *vp = NULL; 2783 struct vattr at; 2784 nfsfh_t nfh; 2785 fhandle_t *fhp; 2786 struct uio io; 2787 struct iovec iv; 2788 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2789 int siz, cnt, fullsiz, eofflag, rdonly, ncookies; 2790 int v3 = (nfsd->nd_flag & ND_NFSV3); 2791 u_quad_t off, toff, verf; 2792 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 2793 2794 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2795 fhp = &nfh.fh_generic; 2796 nfsm_srvmtofh(fhp); 2797 if (v3) { 2798 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2799 toff = fxdr_hyper(tl); 2800 tl += 2; 2801 verf = fxdr_hyper(tl); 2802 tl += 2; 2803 } else { 2804 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2805 toff = fxdr_unsigned(u_quad_t, *tl++); 2806 verf = 0; /* shut up gcc */ 2807 } 2808 off = toff; 2809 cnt = fxdr_unsigned(int, *tl); 2810 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2811 xfer = NFS_SRVMAXDATA(nfsd); 2812 if (cnt > xfer) 2813 cnt = xfer; 2814 if (siz > xfer) 2815 siz = xfer; 2816 fullsiz = siz; 2817 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2818 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2819 if (!error && vp->v_type != VDIR) { 2820 error = ENOTDIR; 2821 vput(vp); 2822 vp = NULL; 2823 } 2824 if (error) { 2825 nfsm_reply(NFSX_UNSIGNED); 2826 nfsm_srvpostop_attr(getret, &at); 2827 error = 0; 2828 goto nfsmout; 2829 } 2830 2831 /* 2832 * Obtain lock on vnode for this section of the code 2833 */ 2834 2835 if (v3) { 2836 error = getret = VOP_GETATTR(vp, &at); 2837 #if 0 2838 /* 2839 * XXX This check may be too strict for Solaris 2.5 clients. 2840 */ 2841 if (!error && toff && verf && verf != at.va_filerev) 2842 error = NFSERR_BAD_COOKIE; 2843 #endif 2844 } 2845 if (!error) 2846 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 2847 if (error) { 2848 vput(vp); 2849 vp = NULL; 2850 nfsm_reply(NFSX_POSTOPATTR(v3)); 2851 nfsm_srvpostop_attr(getret, &at); 2852 error = 0; 2853 goto nfsmout; 2854 } 2855 vn_unlock(vp); 2856 2857 /* 2858 * end section. Allocate rbuf and continue 2859 */ 2860 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2861 again: 2862 iv.iov_base = rbuf; 2863 iv.iov_len = fullsiz; 2864 io.uio_iov = &iv; 2865 io.uio_iovcnt = 1; 2866 io.uio_offset = (off_t)off; 2867 io.uio_resid = fullsiz; 2868 io.uio_segflg = UIO_SYSSPACE; 2869 io.uio_rw = UIO_READ; 2870 io.uio_td = NULL; 2871 eofflag = 0; 2872 if (cookies) { 2873 kfree((caddr_t)cookies, M_TEMP); 2874 cookies = NULL; 2875 } 2876 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 2877 off = (off_t)io.uio_offset; 2878 if (!cookies && !error) 2879 error = NFSERR_PERM; 2880 if (v3) { 2881 getret = VOP_GETATTR(vp, &at); 2882 if (!error) 2883 error = getret; 2884 } 2885 if (error) { 2886 vrele(vp); 2887 vp = NULL; 2888 kfree((caddr_t)rbuf, M_TEMP); 2889 if (cookies) 2890 kfree((caddr_t)cookies, M_TEMP); 2891 nfsm_reply(NFSX_POSTOPATTR(v3)); 2892 nfsm_srvpostop_attr(getret, &at); 2893 error = 0; 2894 goto nfsmout; 2895 } 2896 if (io.uio_resid) { 2897 siz -= io.uio_resid; 2898 2899 /* 2900 * If nothing read, return eof 2901 * rpc reply 2902 */ 2903 if (siz == 0) { 2904 vrele(vp); 2905 vp = NULL; 2906 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 2907 2 * NFSX_UNSIGNED); 2908 if (v3) { 2909 nfsm_srvpostop_attr(getret, &at); 2910 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 2911 txdr_hyper(at.va_filerev, tl); 2912 tl += 2; 2913 } else 2914 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2915 *tl++ = nfs_false; 2916 *tl = nfs_true; 2917 FREE((caddr_t)rbuf, M_TEMP); 2918 FREE((caddr_t)cookies, M_TEMP); 2919 error = 0; 2920 goto nfsmout; 2921 } 2922 } 2923 2924 /* 2925 * Check for degenerate cases of nothing useful read. 2926 * If so go try again 2927 */ 2928 cpos = rbuf; 2929 cend = rbuf + siz; 2930 dp = (struct dirent *)cpos; 2931 cookiep = cookies; 2932 /* 2933 * For some reason FreeBSD's ufs_readdir() chooses to back the 2934 * directory offset up to a block boundary, so it is necessary to 2935 * skip over the records that preceed the requested offset. This 2936 * requires the assumption that file offset cookies monotonically 2937 * increase. 2938 */ 2939 while (cpos < cend && ncookies > 0 && 2940 (dp->d_ino == 0 || dp->d_type == DT_WHT || 2941 ((u_quad_t)(*cookiep)) <= toff)) { 2942 dp = _DIRENT_NEXT(dp); 2943 cpos = (char *)dp; 2944 cookiep++; 2945 ncookies--; 2946 } 2947 if (cpos >= cend || ncookies == 0) { 2948 toff = off; 2949 siz = fullsiz; 2950 goto again; 2951 } 2952 2953 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 2954 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 2955 if (v3) { 2956 nfsm_srvpostop_attr(getret, &at); 2957 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2958 txdr_hyper(at.va_filerev, tl); 2959 } 2960 mp = mp2 = mb; 2961 bp = bpos; 2962 be = bp + M_TRAILINGSPACE(mp); 2963 2964 /* Loop through the records and build reply */ 2965 while (cpos < cend && ncookies > 0) { 2966 if (dp->d_ino != 0 && dp->d_type != DT_WHT) { 2967 nlen = dp->d_namlen; 2968 rem = nfsm_rndup(nlen) - nlen; 2969 len += (4 * NFSX_UNSIGNED + nlen + rem); 2970 if (v3) 2971 len += 2 * NFSX_UNSIGNED; 2972 if (len > cnt) { 2973 eofflag = 0; 2974 break; 2975 } 2976 /* 2977 * Build the directory record xdr from 2978 * the dirent entry. 2979 */ 2980 nfsm_clget; 2981 *tl = nfs_true; 2982 bp += NFSX_UNSIGNED; 2983 if (v3) { 2984 nfsm_clget; 2985 *tl = 0; 2986 bp += NFSX_UNSIGNED; 2987 } 2988 nfsm_clget; 2989 *tl = txdr_unsigned(dp->d_ino); 2990 bp += NFSX_UNSIGNED; 2991 nfsm_clget; 2992 *tl = txdr_unsigned(nlen); 2993 bp += NFSX_UNSIGNED; 2994 2995 /* And loop around copying the name */ 2996 xfer = nlen; 2997 cp = dp->d_name; 2998 while (xfer > 0) { 2999 nfsm_clget; 3000 if ((bp+xfer) > be) 3001 tsiz = be-bp; 3002 else 3003 tsiz = xfer; 3004 bcopy(cp, bp, tsiz); 3005 bp += tsiz; 3006 xfer -= tsiz; 3007 if (xfer > 0) 3008 cp += tsiz; 3009 } 3010 /* And null pad to a int32_t boundary */ 3011 for (i = 0; i < rem; i++) 3012 *bp++ = '\0'; 3013 nfsm_clget; 3014 3015 /* Finish off the record */ 3016 if (v3) { 3017 *tl = 0; 3018 bp += NFSX_UNSIGNED; 3019 nfsm_clget; 3020 } 3021 *tl = txdr_unsigned(*cookiep); 3022 bp += NFSX_UNSIGNED; 3023 } 3024 dp = _DIRENT_NEXT(dp); 3025 cpos = (char *)dp; 3026 cookiep++; 3027 ncookies--; 3028 } 3029 vrele(vp); 3030 vp = NULL; 3031 nfsm_clget; 3032 *tl = nfs_false; 3033 bp += NFSX_UNSIGNED; 3034 nfsm_clget; 3035 if (eofflag) 3036 *tl = nfs_true; 3037 else 3038 *tl = nfs_false; 3039 bp += NFSX_UNSIGNED; 3040 if (mp != mb) { 3041 if (bp < be) 3042 mp->m_len = bp - mtod(mp, caddr_t); 3043 } else 3044 mp->m_len += bp - bpos; 3045 FREE((caddr_t)rbuf, M_TEMP); 3046 FREE((caddr_t)cookies, M_TEMP); 3047 3048 nfsmout: 3049 if (vp) 3050 vrele(vp); 3051 return(error); 3052 } 3053 3054 int 3055 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3056 struct thread *td, struct mbuf **mrq) 3057 { 3058 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3059 struct sockaddr *nam = nfsd->nd_nam; 3060 caddr_t dpos = nfsd->nd_dpos; 3061 struct ucred *cred = &nfsd->nd_cr; 3062 char *bp, *be; 3063 struct mbuf *mp; 3064 struct dirent *dp; 3065 caddr_t cp; 3066 u_int32_t *tl; 3067 int32_t t1; 3068 caddr_t bpos; 3069 struct mbuf *mb, *mb2, *mreq, *mp2; 3070 char *cpos, *cend, *cp2, *rbuf; 3071 struct vnode *vp = NULL, *nvp; 3072 struct flrep fl; 3073 nfsfh_t nfh; 3074 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh; 3075 struct uio io; 3076 struct iovec iv; 3077 struct vattr va, at, *vap = &va; 3078 struct nfs_fattr *fp; 3079 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 3080 int siz, cnt, fullsiz, eofflag, rdonly, dirlen, ncookies; 3081 u_quad_t off, toff, verf; 3082 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 3083 3084 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3085 fhp = &nfh.fh_generic; 3086 nfsm_srvmtofh(fhp); 3087 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 3088 toff = fxdr_hyper(tl); 3089 tl += 2; 3090 verf = fxdr_hyper(tl); 3091 tl += 2; 3092 siz = fxdr_unsigned(int, *tl++); 3093 cnt = fxdr_unsigned(int, *tl); 3094 off = toff; 3095 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 3096 xfer = NFS_SRVMAXDATA(nfsd); 3097 if (cnt > xfer) 3098 cnt = xfer; 3099 if (siz > xfer) 3100 siz = xfer; 3101 fullsiz = siz; 3102 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3103 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3104 if (!error && vp->v_type != VDIR) { 3105 error = ENOTDIR; 3106 vput(vp); 3107 vp = NULL; 3108 } 3109 if (error) { 3110 nfsm_reply(NFSX_UNSIGNED); 3111 nfsm_srvpostop_attr(getret, &at); 3112 error = 0; 3113 goto nfsmout; 3114 } 3115 error = getret = VOP_GETATTR(vp, &at); 3116 #if 0 3117 /* 3118 * XXX This check may be too strict for Solaris 2.5 clients. 3119 */ 3120 if (!error && toff && verf && verf != at.va_filerev) 3121 error = NFSERR_BAD_COOKIE; 3122 #endif 3123 if (!error) { 3124 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 3125 } 3126 if (error) { 3127 vput(vp); 3128 vp = NULL; 3129 nfsm_reply(NFSX_V3POSTOPATTR); 3130 nfsm_srvpostop_attr(getret, &at); 3131 error = 0; 3132 goto nfsmout; 3133 } 3134 vn_unlock(vp); 3135 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 3136 again: 3137 iv.iov_base = rbuf; 3138 iv.iov_len = fullsiz; 3139 io.uio_iov = &iv; 3140 io.uio_iovcnt = 1; 3141 io.uio_offset = (off_t)off; 3142 io.uio_resid = fullsiz; 3143 io.uio_segflg = UIO_SYSSPACE; 3144 io.uio_rw = UIO_READ; 3145 io.uio_td = NULL; 3146 eofflag = 0; 3147 if (cookies) { 3148 kfree((caddr_t)cookies, M_TEMP); 3149 cookies = NULL; 3150 } 3151 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 3152 off = (u_quad_t)io.uio_offset; 3153 getret = VOP_GETATTR(vp, &at); 3154 if (!cookies && !error) 3155 error = NFSERR_PERM; 3156 if (!error) 3157 error = getret; 3158 if (error) { 3159 vrele(vp); 3160 vp = NULL; 3161 if (cookies) 3162 kfree((caddr_t)cookies, M_TEMP); 3163 kfree((caddr_t)rbuf, M_TEMP); 3164 nfsm_reply(NFSX_V3POSTOPATTR); 3165 nfsm_srvpostop_attr(getret, &at); 3166 error = 0; 3167 goto nfsmout; 3168 } 3169 if (io.uio_resid) { 3170 siz -= io.uio_resid; 3171 3172 /* 3173 * If nothing read, return eof 3174 * rpc reply 3175 */ 3176 if (siz == 0) { 3177 vrele(vp); 3178 vp = NULL; 3179 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 3180 2 * NFSX_UNSIGNED); 3181 nfsm_srvpostop_attr(getret, &at); 3182 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3183 txdr_hyper(at.va_filerev, tl); 3184 tl += 2; 3185 *tl++ = nfs_false; 3186 *tl = nfs_true; 3187 FREE((caddr_t)cookies, M_TEMP); 3188 FREE((caddr_t)rbuf, M_TEMP); 3189 error = 0; 3190 goto nfsmout; 3191 } 3192 } 3193 3194 /* 3195 * Check for degenerate cases of nothing useful read. 3196 * If so go try again 3197 */ 3198 cpos = rbuf; 3199 cend = rbuf + siz; 3200 dp = (struct dirent *)cpos; 3201 cookiep = cookies; 3202 /* 3203 * For some reason FreeBSD's ufs_readdir() chooses to back the 3204 * directory offset up to a block boundary, so it is necessary to 3205 * skip over the records that preceed the requested offset. This 3206 * requires the assumption that file offset cookies monotonically 3207 * increase. 3208 */ 3209 while (cpos < cend && ncookies > 0 && 3210 (dp->d_ino == 0 || dp->d_type == DT_WHT || 3211 ((u_quad_t)(*cookiep)) <= toff)) { 3212 dp = _DIRENT_NEXT(dp); 3213 cpos = (char *)dp; 3214 cookiep++; 3215 ncookies--; 3216 } 3217 if (cpos >= cend || ncookies == 0) { 3218 toff = off; 3219 siz = fullsiz; 3220 goto again; 3221 } 3222 3223 /* 3224 * Probe one of the directory entries to see if the filesystem 3225 * supports VGET. 3226 */ 3227 if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp) == EOPNOTSUPP) { 3228 error = NFSERR_NOTSUPP; 3229 vrele(vp); 3230 vp = NULL; 3231 kfree((caddr_t)cookies, M_TEMP); 3232 kfree((caddr_t)rbuf, M_TEMP); 3233 nfsm_reply(NFSX_V3POSTOPATTR); 3234 nfsm_srvpostop_attr(getret, &at); 3235 error = 0; 3236 goto nfsmout; 3237 } 3238 if (nvp) { 3239 vput(nvp); 3240 nvp = NULL; 3241 } 3242 3243 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 3244 nfsm_reply(cnt); 3245 nfsm_srvpostop_attr(getret, &at); 3246 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3247 txdr_hyper(at.va_filerev, tl); 3248 mp = mp2 = mb; 3249 bp = bpos; 3250 be = bp + M_TRAILINGSPACE(mp); 3251 3252 /* Loop through the records and build reply */ 3253 while (cpos < cend && ncookies > 0) { 3254 if (dp->d_ino != 0 && dp->d_type != DT_WHT) { 3255 nlen = dp->d_namlen; 3256 rem = nfsm_rndup(nlen)-nlen; 3257 3258 /* 3259 * For readdir_and_lookup get the vnode using 3260 * the file number. 3261 */ 3262 if (VFS_VGET(vp->v_mount, dp->d_ino, &nvp)) 3263 goto invalid; 3264 bzero((caddr_t)nfhp, NFSX_V3FH); 3265 nfhp->fh_fsid = 3266 nvp->v_mount->mnt_stat.f_fsid; 3267 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { 3268 vput(nvp); 3269 nvp = NULL; 3270 goto invalid; 3271 } 3272 if (VOP_GETATTR(nvp, vap)) { 3273 vput(nvp); 3274 nvp = NULL; 3275 goto invalid; 3276 } 3277 vput(nvp); 3278 nvp = NULL; 3279 3280 /* 3281 * If either the dircount or maxcount will be 3282 * exceeded, get out now. Both of these lengths 3283 * are calculated conservatively, including all 3284 * XDR overheads. 3285 */ 3286 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 3287 NFSX_V3POSTOPATTR); 3288 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 3289 if (len > cnt || dirlen > fullsiz) { 3290 eofflag = 0; 3291 break; 3292 } 3293 3294 /* 3295 * Build the directory record xdr from 3296 * the dirent entry. 3297 */ 3298 fp = (struct nfs_fattr *)&fl.fl_fattr; 3299 nfsm_srvfillattr(vap, fp); 3300 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 3301 fl.fl_fhok = nfs_true; 3302 fl.fl_postopok = nfs_true; 3303 fl.fl_off.nfsuquad[0] = 0; 3304 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); 3305 3306 nfsm_clget; 3307 *tl = nfs_true; 3308 bp += NFSX_UNSIGNED; 3309 nfsm_clget; 3310 *tl = 0; 3311 bp += NFSX_UNSIGNED; 3312 nfsm_clget; 3313 *tl = txdr_unsigned(dp->d_ino); 3314 bp += NFSX_UNSIGNED; 3315 nfsm_clget; 3316 *tl = txdr_unsigned(nlen); 3317 bp += NFSX_UNSIGNED; 3318 3319 /* And loop around copying the name */ 3320 xfer = nlen; 3321 cp = dp->d_name; 3322 while (xfer > 0) { 3323 nfsm_clget; 3324 if ((bp + xfer) > be) 3325 tsiz = be - bp; 3326 else 3327 tsiz = xfer; 3328 bcopy(cp, bp, tsiz); 3329 bp += tsiz; 3330 xfer -= tsiz; 3331 if (xfer > 0) 3332 cp += tsiz; 3333 } 3334 /* And null pad to a int32_t boundary */ 3335 for (i = 0; i < rem; i++) 3336 *bp++ = '\0'; 3337 3338 /* 3339 * Now copy the flrep structure out. 3340 */ 3341 xfer = sizeof (struct flrep); 3342 cp = (caddr_t)&fl; 3343 while (xfer > 0) { 3344 nfsm_clget; 3345 if ((bp + xfer) > be) 3346 tsiz = be - bp; 3347 else 3348 tsiz = xfer; 3349 bcopy(cp, bp, tsiz); 3350 bp += tsiz; 3351 xfer -= tsiz; 3352 if (xfer > 0) 3353 cp += tsiz; 3354 } 3355 } 3356 invalid: 3357 dp = _DIRENT_NEXT(dp); 3358 cpos = (char *)dp; 3359 cookiep++; 3360 ncookies--; 3361 } 3362 vrele(vp); 3363 vp = NULL; 3364 nfsm_clget; 3365 *tl = nfs_false; 3366 bp += NFSX_UNSIGNED; 3367 nfsm_clget; 3368 if (eofflag) 3369 *tl = nfs_true; 3370 else 3371 *tl = nfs_false; 3372 bp += NFSX_UNSIGNED; 3373 if (mp != mb) { 3374 if (bp < be) 3375 mp->m_len = bp - mtod(mp, caddr_t); 3376 } else 3377 mp->m_len += bp - bpos; 3378 FREE((caddr_t)cookies, M_TEMP); 3379 FREE((caddr_t)rbuf, M_TEMP); 3380 nfsmout: 3381 if (vp) 3382 vrele(vp); 3383 return(error); 3384 } 3385 3386 /* 3387 * nfs commit service 3388 */ 3389 int 3390 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3391 struct thread *td, struct mbuf **mrq) 3392 { 3393 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3394 struct sockaddr *nam = nfsd->nd_nam; 3395 caddr_t dpos = nfsd->nd_dpos; 3396 struct ucred *cred = &nfsd->nd_cr; 3397 struct vattr bfor, aft; 3398 struct vnode *vp = NULL; 3399 nfsfh_t nfh; 3400 fhandle_t *fhp; 3401 u_int32_t *tl; 3402 int32_t t1; 3403 caddr_t bpos; 3404 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt; 3405 char *cp2; 3406 struct mbuf *mb, *mb2, *mreq; 3407 u_quad_t off; 3408 3409 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3410 fhp = &nfh.fh_generic; 3411 nfsm_srvmtofh(fhp); 3412 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3413 3414 /* 3415 * XXX At this time VOP_FSYNC() does not accept offset and byte 3416 * count parameters, so these arguments are useless (someday maybe). 3417 */ 3418 off = fxdr_hyper(tl); 3419 tl += 2; 3420 cnt = fxdr_unsigned(int, *tl); 3421 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3422 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3423 if (error) { 3424 nfsm_reply(2 * NFSX_UNSIGNED); 3425 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3426 error = 0; 3427 goto nfsmout; 3428 } 3429 for_ret = VOP_GETATTR(vp, &bfor); 3430 3431 if (cnt > MAX_COMMIT_COUNT) { 3432 /* 3433 * Give up and do the whole thing 3434 */ 3435 if (vp->v_object && 3436 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3437 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 3438 } 3439 error = VOP_FSYNC(vp, MNT_WAIT); 3440 } else { 3441 /* 3442 * Locate and synchronously write any buffers that fall 3443 * into the requested range. Note: we are assuming that 3444 * f_iosize is a power of 2. 3445 */ 3446 int iosize = vp->v_mount->mnt_stat.f_iosize; 3447 int iomask = iosize - 1; 3448 off_t loffset; 3449 3450 /* 3451 * Align to iosize boundry, super-align to page boundry. 3452 */ 3453 if (off & iomask) { 3454 cnt += off & iomask; 3455 off &= ~(u_quad_t)iomask; 3456 } 3457 if (off & PAGE_MASK) { 3458 cnt += off & PAGE_MASK; 3459 off &= ~(u_quad_t)PAGE_MASK; 3460 } 3461 loffset = off; 3462 3463 if (vp->v_object && 3464 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3465 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC); 3466 } 3467 3468 crit_enter(); 3469 while (cnt > 0) { 3470 struct buf *bp; 3471 3472 /* 3473 * If we have a buffer and it is marked B_DELWRI we 3474 * have to lock and write it. Otherwise the prior 3475 * write is assumed to have already been committed. 3476 */ 3477 if ((bp = findblk(vp, loffset)) != NULL && (bp->b_flags & B_DELWRI)) { 3478 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { 3479 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL) == 0) 3480 BUF_UNLOCK(bp); 3481 continue; /* retry */ 3482 } 3483 bremfree(bp); 3484 bp->b_flags &= ~B_ASYNC; 3485 bwrite(bp); 3486 ++nfs_commit_miss; 3487 } 3488 ++nfs_commit_blks; 3489 if (cnt < iosize) 3490 break; 3491 cnt -= iosize; 3492 loffset += iosize; 3493 } 3494 crit_exit(); 3495 } 3496 3497 aft_ret = VOP_GETATTR(vp, &aft); 3498 vput(vp); 3499 vp = NULL; 3500 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3501 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3502 if (!error) { 3503 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3504 if (nfsver.tv_sec == 0) 3505 nfsver = boottime; 3506 *tl++ = txdr_unsigned(nfsver.tv_sec); 3507 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 3508 } else { 3509 error = 0; 3510 } 3511 nfsmout: 3512 if (vp) 3513 vput(vp); 3514 return(error); 3515 } 3516 3517 /* 3518 * nfs statfs service 3519 */ 3520 int 3521 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3522 struct thread *td, struct mbuf **mrq) 3523 { 3524 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3525 struct sockaddr *nam = nfsd->nd_nam; 3526 caddr_t dpos = nfsd->nd_dpos; 3527 struct ucred *cred = &nfsd->nd_cr; 3528 struct statfs *sf; 3529 struct nfs_statfs *sfp; 3530 u_int32_t *tl; 3531 int32_t t1; 3532 caddr_t bpos; 3533 int error = 0, rdonly, getret = 1; 3534 int v3 = (nfsd->nd_flag & ND_NFSV3); 3535 char *cp2; 3536 struct mbuf *mb, *mb2, *mreq; 3537 struct vnode *vp = NULL; 3538 struct vattr at; 3539 nfsfh_t nfh; 3540 fhandle_t *fhp; 3541 struct statfs statfs; 3542 u_quad_t tval; 3543 3544 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3545 fhp = &nfh.fh_generic; 3546 nfsm_srvmtofh(fhp); 3547 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3548 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3549 if (error) { 3550 nfsm_reply(NFSX_UNSIGNED); 3551 nfsm_srvpostop_attr(getret, &at); 3552 error = 0; 3553 goto nfsmout; 3554 } 3555 sf = &statfs; 3556 error = VFS_STATFS(vp->v_mount, sf, proc0.p_ucred); 3557 getret = VOP_GETATTR(vp, &at); 3558 vput(vp); 3559 vp = NULL; 3560 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3561 if (v3) 3562 nfsm_srvpostop_attr(getret, &at); 3563 if (error) { 3564 error = 0; 3565 goto nfsmout; 3566 } 3567 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3568 if (v3) { 3569 tval = (u_quad_t)sf->f_blocks; 3570 tval *= (u_quad_t)sf->f_bsize; 3571 txdr_hyper(tval, &sfp->sf_tbytes); 3572 tval = (u_quad_t)sf->f_bfree; 3573 tval *= (u_quad_t)sf->f_bsize; 3574 txdr_hyper(tval, &sfp->sf_fbytes); 3575 tval = (u_quad_t)sf->f_bavail; 3576 tval *= (u_quad_t)sf->f_bsize; 3577 txdr_hyper(tval, &sfp->sf_abytes); 3578 sfp->sf_tfiles.nfsuquad[0] = 0; 3579 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3580 sfp->sf_ffiles.nfsuquad[0] = 0; 3581 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3582 sfp->sf_afiles.nfsuquad[0] = 0; 3583 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3584 sfp->sf_invarsec = 0; 3585 } else { 3586 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3587 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3588 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3589 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3590 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3591 } 3592 nfsmout: 3593 if (vp) 3594 vput(vp); 3595 return(error); 3596 } 3597 3598 /* 3599 * nfs fsinfo service 3600 */ 3601 int 3602 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3603 struct thread *td, struct mbuf **mrq) 3604 { 3605 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3606 struct sockaddr *nam = nfsd->nd_nam; 3607 caddr_t dpos = nfsd->nd_dpos; 3608 struct ucred *cred = &nfsd->nd_cr; 3609 u_int32_t *tl; 3610 struct nfsv3_fsinfo *sip; 3611 int32_t t1; 3612 caddr_t bpos; 3613 int error = 0, rdonly, getret = 1, pref; 3614 char *cp2; 3615 struct mbuf *mb, *mb2, *mreq; 3616 struct vnode *vp = NULL; 3617 struct vattr at; 3618 nfsfh_t nfh; 3619 fhandle_t *fhp; 3620 u_quad_t maxfsize; 3621 struct statfs sb; 3622 3623 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3624 fhp = &nfh.fh_generic; 3625 nfsm_srvmtofh(fhp); 3626 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3627 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3628 if (error) { 3629 nfsm_reply(NFSX_UNSIGNED); 3630 nfsm_srvpostop_attr(getret, &at); 3631 error = 0; 3632 goto nfsmout; 3633 } 3634 3635 /* XXX Try to make a guess on the max file size. */ 3636 VFS_STATFS(vp->v_mount, &sb, proc0.p_ucred); 3637 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; 3638 3639 getret = VOP_GETATTR(vp, &at); 3640 vput(vp); 3641 vp = NULL; 3642 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3643 nfsm_srvpostop_attr(getret, &at); 3644 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3645 3646 /* 3647 * XXX 3648 * There should be file system VFS OP(s) to get this information. 3649 * For now, assume ufs. 3650 */ 3651 if (slp->ns_so->so_type == SOCK_DGRAM) 3652 pref = NFS_MAXDGRAMDATA; 3653 else 3654 pref = NFS_MAXDATA; 3655 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3656 sip->fs_rtpref = txdr_unsigned(pref); 3657 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3658 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3659 sip->fs_wtpref = txdr_unsigned(pref); 3660 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3661 sip->fs_dtpref = txdr_unsigned(pref); 3662 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3663 sip->fs_timedelta.nfsv3_sec = 0; 3664 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3665 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3666 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3667 NFSV3FSINFO_CANSETTIME); 3668 nfsmout: 3669 if (vp) 3670 vput(vp); 3671 return(error); 3672 } 3673 3674 /* 3675 * nfs pathconf service 3676 */ 3677 int 3678 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3679 struct thread *td, struct mbuf **mrq) 3680 { 3681 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3682 struct sockaddr *nam = nfsd->nd_nam; 3683 caddr_t dpos = nfsd->nd_dpos; 3684 struct ucred *cred = &nfsd->nd_cr; 3685 u_int32_t *tl; 3686 struct nfsv3_pathconf *pc; 3687 int32_t t1; 3688 caddr_t bpos; 3689 int error = 0, rdonly, getret = 1; 3690 register_t linkmax, namemax, chownres, notrunc; 3691 char *cp2; 3692 struct mbuf *mb, *mb2, *mreq; 3693 struct vnode *vp = NULL; 3694 struct vattr at; 3695 nfsfh_t nfh; 3696 fhandle_t *fhp; 3697 3698 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3699 fhp = &nfh.fh_generic; 3700 nfsm_srvmtofh(fhp); 3701 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3702 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3703 if (error) { 3704 nfsm_reply(NFSX_UNSIGNED); 3705 nfsm_srvpostop_attr(getret, &at); 3706 error = 0; 3707 goto nfsmout; 3708 } 3709 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3710 if (!error) 3711 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3712 if (!error) 3713 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3714 if (!error) 3715 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3716 getret = VOP_GETATTR(vp, &at); 3717 vput(vp); 3718 vp = NULL; 3719 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3720 nfsm_srvpostop_attr(getret, &at); 3721 if (error) { 3722 error = 0; 3723 goto nfsmout; 3724 } 3725 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3726 3727 pc->pc_linkmax = txdr_unsigned(linkmax); 3728 pc->pc_namemax = txdr_unsigned(namemax); 3729 pc->pc_notrunc = txdr_unsigned(notrunc); 3730 pc->pc_chownrestricted = txdr_unsigned(chownres); 3731 3732 /* 3733 * These should probably be supported by VOP_PATHCONF(), but 3734 * until msdosfs is exportable (why would you want to?), the 3735 * Unix defaults should be ok. 3736 */ 3737 pc->pc_caseinsensitive = nfs_false; 3738 pc->pc_casepreserving = nfs_true; 3739 nfsmout: 3740 if (vp) 3741 vput(vp); 3742 return(error); 3743 } 3744 3745 /* 3746 * Null operation, used by clients to ping server 3747 */ 3748 /* ARGSUSED */ 3749 int 3750 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3751 struct thread *td, struct mbuf **mrq) 3752 { 3753 struct mbuf *mrep = nfsd->nd_mrep; 3754 caddr_t bpos; 3755 int error = NFSERR_RETVOID; 3756 struct mbuf *mb, *mreq; 3757 3758 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3759 nfsm_reply(0); 3760 nfsm_srvdone; 3761 } 3762 3763 /* 3764 * No operation, used for obsolete procedures 3765 */ 3766 /* ARGSUSED */ 3767 int 3768 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3769 struct thread *td, struct mbuf **mrq) 3770 { 3771 struct mbuf *mrep = nfsd->nd_mrep; 3772 caddr_t bpos; 3773 int error; 3774 struct mbuf *mb, *mreq; 3775 3776 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3777 if (nfsd->nd_repstat) 3778 error = nfsd->nd_repstat; 3779 else 3780 error = EPROCUNAVAIL; 3781 nfsm_reply(0); 3782 error = 0; 3783 nfsm_srvdone; 3784 } 3785 3786 /* 3787 * Perform access checking for vnodes obtained from file handles that would 3788 * refer to files already opened by a Unix client. You cannot just use 3789 * vn_writechk() and VOP_ACCESS() for two reasons. 3790 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3791 * 2 - The owner is to be given access irrespective of mode bits for some 3792 * operations, so that processes that chmod after opening a file don't 3793 * break. I don't like this because it opens a security hole, but since 3794 * the nfs server opens a security hole the size of a barn door anyhow, 3795 * what the heck. 3796 * 3797 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3798 * will return EPERM instead of EACCESS. EPERM is always an error. 3799 */ 3800 static int 3801 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, 3802 int rdonly, struct thread *td, int override) 3803 { 3804 struct vattr vattr; 3805 int error; 3806 3807 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3808 if (flags & VWRITE) { 3809 /* Just vn_writechk() changed to check rdonly */ 3810 /* 3811 * Disallow write attempts on read-only file systems; 3812 * unless the file is a socket or a block or character 3813 * device resident on the file system. 3814 */ 3815 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3816 switch (vp->v_type) { 3817 case VREG: 3818 case VDIR: 3819 case VLNK: 3820 return (EROFS); 3821 default: 3822 break; 3823 } 3824 } 3825 /* 3826 * If there's shared text associated with 3827 * the inode, we can't allow writing. 3828 */ 3829 if (vp->v_flag & VTEXT) 3830 return (ETXTBSY); 3831 } 3832 error = VOP_GETATTR(vp, &vattr); 3833 if (error) 3834 return (error); 3835 error = VOP_ACCESS(vp, flags, cred); 3836 /* 3837 * Allow certain operations for the owner (reads and writes 3838 * on files that are already open). 3839 */ 3840 if (override && error == EACCES && cred->cr_uid == vattr.va_uid) 3841 error = 0; 3842 return error; 3843 } 3844 #endif /* NFS_NOSERVER */ 3845 3846