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