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.19 2004/10/12 19:21:01 dillon Exp $ 39 */ 40 41 /* 42 * nfs version 2 and 3 server calls to vnode ops 43 * - these routines generally have 3 phases 44 * 1 - break down and validate rpc request in mbuf list 45 * 2 - do the vnode ops for the request 46 * (surprisingly ?? many are very similar to syscalls in vfs_syscalls.c) 47 * 3 - build the rpc reply in an mbuf list 48 * nb: 49 * - do not mix the phases, since the nfsm_?? macros can return failures 50 * on a bad rpc or similar and do not do any vrele() or vput()'s 51 * 52 * - the nfsm_reply() macro generates an nfs rpc reply with the nfs 53 * error number iff error != 0 whereas 54 * returning an error from the server function implies a fatal error 55 * such as a badly constructed rpc request that should be dropped without 56 * a reply. 57 * For Version 3, nfsm_reply() does not return for the error case, since 58 * most version 3 rpcs return more than the status for error cases. 59 * 60 * Other notes: 61 * Warning: always pay careful attention to resource cleanup on return 62 * and note that nfsm_*() macros can terminate a procedure on certain 63 * errors. 64 * 65 * 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, 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 if (error == 0) 2091 cache_purge(nd.ni_vp); 2092 NDFREE(&nd, NDF_ONLY_PNBUF); 2093 } 2094 } 2095 if (dirp && v3) { 2096 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2097 vrele(dirp); 2098 dirp = NULL; 2099 } 2100 nfsm_reply(NFSX_WCCDATA(v3)); 2101 if (v3) { 2102 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2103 error = 0; 2104 } 2105 nfsmout: 2106 NDFREE(&nd, NDF_ONLY_PNBUF); 2107 if (nd.ni_dvp) { 2108 if (nd.ni_dvp == nd.ni_vp) 2109 vrele(nd.ni_dvp); 2110 else 2111 vput(nd.ni_dvp); 2112 } 2113 if (nd.ni_vp) 2114 vput(nd.ni_vp); 2115 return(error); 2116 } 2117 2118 /* 2119 * nfs rename service 2120 */ 2121 int 2122 nfsrv_rename(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2123 struct thread *td, struct mbuf **mrq) 2124 { 2125 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2126 struct sockaddr *nam = nfsd->nd_nam; 2127 caddr_t dpos = nfsd->nd_dpos; 2128 struct ucred *cred = &nfsd->nd_cr; 2129 u_int32_t *tl; 2130 int32_t t1; 2131 caddr_t bpos; 2132 int error = 0, cache, len, len2, fdirfor_ret = 1, fdiraft_ret = 1; 2133 int tdirfor_ret = 1, tdiraft_ret = 1; 2134 int v3 = (nfsd->nd_flag & ND_NFSV3); 2135 char *cp2; 2136 struct mbuf *mb, *mreq; 2137 struct nameidata fromnd, tond; 2138 struct vnode *fvp, *tvp, *tdvp, *fdirp = (struct vnode *)0; 2139 struct vnode *tdirp = (struct vnode *)0; 2140 struct vattr fdirfor, fdiraft, tdirfor, tdiraft; 2141 nfsfh_t fnfh, tnfh; 2142 fhandle_t *ffhp, *tfhp; 2143 u_quad_t frev; 2144 uid_t saved_uid; 2145 2146 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2147 #ifndef nolint 2148 fvp = (struct vnode *)0; 2149 #endif 2150 ffhp = &fnfh.fh_generic; 2151 tfhp = &tnfh.fh_generic; 2152 2153 /* 2154 * Clear fields incase goto nfsmout occurs from macro. 2155 */ 2156 2157 ndclear(&fromnd); 2158 ndclear(&tond); 2159 2160 nfsm_srvmtofh(ffhp); 2161 nfsm_srvnamesiz(len); 2162 /* 2163 * Remember our original uid so that we can reset cr_uid before 2164 * the second nfs_namei() call, in case it is remapped. 2165 */ 2166 saved_uid = cred->cr_uid; 2167 fromnd.ni_cnd.cn_cred = cred; 2168 fromnd.ni_cnd.cn_nameiop = NAMEI_DELETE; 2169 fromnd.ni_cnd.cn_flags = CNP_WANTPARENT | CNP_SAVESTART; 2170 error = nfs_namei(&fromnd, ffhp, len, slp, nam, &md, 2171 &dpos, &fdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2172 if (fdirp) { 2173 if (v3) { 2174 fdirfor_ret = VOP_GETATTR(fdirp, &fdirfor, td); 2175 } else { 2176 vrele(fdirp); 2177 fdirp = NULL; 2178 } 2179 } 2180 if (error) { 2181 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2182 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2183 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2184 error = 0; 2185 goto nfsmout; 2186 } 2187 fvp = fromnd.ni_vp; 2188 nfsm_srvmtofh(tfhp); 2189 nfsm_strsiz(len2, NFS_MAXNAMLEN); 2190 cred->cr_uid = saved_uid; 2191 tond.ni_cnd.cn_cred = cred; 2192 tond.ni_cnd.cn_nameiop = NAMEI_RENAME; 2193 tond.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF | 2194 CNP_NOCACHE | CNP_SAVESTART; 2195 error = nfs_namei(&tond, tfhp, len2, slp, nam, &md, 2196 &dpos, &tdirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2197 if (tdirp) { 2198 if (v3) { 2199 tdirfor_ret = VOP_GETATTR(tdirp, &tdirfor, td); 2200 } else { 2201 vrele(tdirp); 2202 tdirp = NULL; 2203 } 2204 } 2205 if (error) 2206 goto out1; 2207 2208 tdvp = tond.ni_dvp; 2209 tvp = tond.ni_vp; 2210 if (tvp != NULL) { 2211 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2212 if (v3) 2213 error = EEXIST; 2214 else 2215 error = EISDIR; 2216 goto out; 2217 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2218 if (v3) 2219 error = EEXIST; 2220 else 2221 error = ENOTDIR; 2222 goto out; 2223 } 2224 if (tvp->v_type == VDIR && tvp->v_mountedhere) { 2225 if (v3) 2226 error = EXDEV; 2227 else 2228 error = ENOTEMPTY; 2229 goto out; 2230 } 2231 } 2232 if (fvp->v_type == VDIR && fvp->v_mountedhere) { 2233 if (v3) 2234 error = EXDEV; 2235 else 2236 error = ENOTEMPTY; 2237 goto out; 2238 } 2239 if (fvp->v_mount != tdvp->v_mount) { 2240 if (v3) 2241 error = EXDEV; 2242 else 2243 error = ENOTEMPTY; 2244 goto out; 2245 } 2246 if (fvp == tdvp) { 2247 if (v3) 2248 error = EINVAL; 2249 else 2250 error = ENOTEMPTY; 2251 } 2252 /* 2253 * If source is the same as the destination (that is the 2254 * same vnode with the same name in the same directory), 2255 * then there is nothing to do. 2256 */ 2257 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2258 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2259 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2260 fromnd.ni_cnd.cn_namelen)) 2261 error = -1; 2262 out: 2263 if (!error) { 2264 /* 2265 * The VOP_RENAME function releases all vnode references & 2266 * locks prior to returning so we need to clear the pointers 2267 * to bypass cleanup code later on. 2268 */ 2269 nqsrv_getl(fromnd.ni_dvp, ND_WRITE); 2270 nqsrv_getl(tdvp, ND_WRITE); 2271 if (tvp) { 2272 nqsrv_getl(tvp, ND_WRITE); 2273 } 2274 error = VOP_RENAME(fromnd.ni_dvp, NCPNULL, fromnd.ni_vp, &fromnd.ni_cnd, 2275 tond.ni_dvp, NCPNULL, tond.ni_vp, &tond.ni_cnd); 2276 if (error == 0) 2277 cache_purge(fromnd.ni_vp); 2278 fromnd.ni_dvp = NULL; 2279 fromnd.ni_vp = NULL; 2280 tond.ni_dvp = NULL; 2281 tond.ni_vp = NULL; 2282 if (error) { 2283 fromnd.ni_cnd.cn_flags &= ~CNP_HASBUF; 2284 tond.ni_cnd.cn_flags &= ~CNP_HASBUF; 2285 } 2286 } else { 2287 if (error == -1) 2288 error = 0; 2289 } 2290 /* fall through */ 2291 2292 out1: 2293 if (fdirp) 2294 fdiraft_ret = VOP_GETATTR(fdirp, &fdiraft, td); 2295 if (tdirp) 2296 tdiraft_ret = VOP_GETATTR(tdirp, &tdiraft, td); 2297 nfsm_reply(2 * NFSX_WCCDATA(v3)); 2298 if (v3) { 2299 nfsm_srvwcc_data(fdirfor_ret, &fdirfor, fdiraft_ret, &fdiraft); 2300 nfsm_srvwcc_data(tdirfor_ret, &tdirfor, tdiraft_ret, &tdiraft); 2301 } 2302 error = 0; 2303 /* fall through */ 2304 2305 nfsmout: 2306 /* 2307 * Clear out tond related fields 2308 */ 2309 if (tdirp) 2310 vrele(tdirp); 2311 if (tond.ni_startdir) 2312 vrele(tond.ni_startdir); 2313 NDFREE(&tond, NDF_ONLY_PNBUF); 2314 if (tond.ni_dvp) { 2315 if (tond.ni_dvp == tond.ni_vp) 2316 vrele(tond.ni_dvp); 2317 else 2318 vput(tond.ni_dvp); 2319 } 2320 if (tond.ni_vp) 2321 vput(tond.ni_vp); 2322 2323 /* 2324 * Clear out fromnd related fields 2325 */ 2326 if (fdirp) 2327 vrele(fdirp); 2328 if (fromnd.ni_startdir) 2329 vrele(fromnd.ni_startdir); 2330 NDFREE(&fromnd, NDF_ONLY_PNBUF); 2331 if (fromnd.ni_dvp) 2332 vrele(fromnd.ni_dvp); 2333 if (fromnd.ni_vp) 2334 vrele(fromnd.ni_vp); 2335 2336 return (error); 2337 } 2338 2339 /* 2340 * nfs link service 2341 */ 2342 int 2343 nfsrv_link(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2344 struct thread *td, struct mbuf **mrq) 2345 { 2346 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2347 struct sockaddr *nam = nfsd->nd_nam; 2348 caddr_t dpos = nfsd->nd_dpos; 2349 struct ucred *cred = &nfsd->nd_cr; 2350 struct nameidata nd; 2351 u_int32_t *tl; 2352 int32_t t1; 2353 caddr_t bpos; 2354 int error = 0, rdonly, cache, len, dirfor_ret = 1, diraft_ret = 1; 2355 int getret = 1, v3 = (nfsd->nd_flag & ND_NFSV3); 2356 char *cp2; 2357 struct mbuf *mb, *mreq; 2358 struct vnode *vp = NULL, *xp, *dirp = (struct vnode *)0; 2359 struct vattr dirfor, diraft, at; 2360 nfsfh_t nfh, dnfh; 2361 fhandle_t *fhp, *dfhp; 2362 u_quad_t frev; 2363 2364 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2365 ndclear(&nd); 2366 2367 fhp = &nfh.fh_generic; 2368 dfhp = &dnfh.fh_generic; 2369 nfsm_srvmtofh(fhp); 2370 nfsm_srvmtofh(dfhp); 2371 nfsm_srvnamesiz(len); 2372 2373 error = nfsrv_fhtovp(fhp, FALSE, &vp, cred, slp, nam, 2374 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2375 if (error) { 2376 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2377 nfsm_srvpostop_attr(getret, &at); 2378 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2379 vp = NULL; 2380 error = 0; 2381 goto nfsmout; 2382 } 2383 if (vp->v_type == VDIR) { 2384 error = EPERM; /* POSIX */ 2385 goto out1; 2386 } 2387 nd.ni_cnd.cn_cred = cred; 2388 nd.ni_cnd.cn_nameiop = NAMEI_CREATE; 2389 nd.ni_cnd.cn_flags = CNP_LOCKPARENT; 2390 error = nfs_namei(&nd, dfhp, len, slp, nam, &md, &dpos, 2391 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2392 if (dirp) { 2393 if (v3) { 2394 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2395 } else { 2396 vrele(dirp); 2397 dirp = NULL; 2398 } 2399 } 2400 if (error) 2401 goto out1; 2402 2403 xp = nd.ni_vp; 2404 if (xp != NULL) { 2405 error = EEXIST; 2406 goto out; 2407 } 2408 xp = nd.ni_dvp; 2409 if (vp->v_mount != xp->v_mount) 2410 error = EXDEV; 2411 out: 2412 if (!error) { 2413 nqsrv_getl(vp, ND_WRITE); 2414 nqsrv_getl(xp, ND_WRITE); 2415 error = VOP_LINK(nd.ni_dvp, NCPNULL, vp, &nd.ni_cnd); 2416 NDFREE(&nd, NDF_ONLY_PNBUF); 2417 } 2418 /* fall through */ 2419 2420 out1: 2421 if (v3) 2422 getret = VOP_GETATTR(vp, &at, td); 2423 if (dirp) 2424 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2425 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2426 if (v3) { 2427 nfsm_srvpostop_attr(getret, &at); 2428 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2429 error = 0; 2430 } 2431 /* fall through */ 2432 2433 nfsmout: 2434 NDFREE(&nd, NDF_ONLY_PNBUF); 2435 if (dirp) 2436 vrele(dirp); 2437 if (vp) 2438 vrele(vp); 2439 if (nd.ni_dvp) { 2440 if (nd.ni_dvp == nd.ni_vp) 2441 vrele(nd.ni_dvp); 2442 else 2443 vput(nd.ni_dvp); 2444 } 2445 if (nd.ni_vp) 2446 vrele(nd.ni_vp); 2447 return(error); 2448 } 2449 2450 /* 2451 * nfs symbolic link service 2452 */ 2453 int 2454 nfsrv_symlink(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2455 struct thread *td, struct mbuf **mrq) 2456 { 2457 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2458 struct sockaddr *nam = nfsd->nd_nam; 2459 caddr_t dpos = nfsd->nd_dpos; 2460 struct ucred *cred = &nfsd->nd_cr; 2461 struct vattr va, dirfor, diraft; 2462 struct nameidata nd; 2463 struct vattr *vap = &va; 2464 u_int32_t *tl; 2465 int32_t t1; 2466 struct nfsv2_sattr *sp; 2467 char *bpos, *pathcp = (char *)0, *cp2; 2468 struct uio io; 2469 struct iovec iv; 2470 int error = 0, cache, len, len2, dirfor_ret = 1, diraft_ret = 1; 2471 int v3 = (nfsd->nd_flag & ND_NFSV3); 2472 struct mbuf *mb, *mreq, *mb2; 2473 struct vnode *dirp = (struct vnode *)0; 2474 nfsfh_t nfh; 2475 fhandle_t *fhp; 2476 u_quad_t frev; 2477 2478 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2479 ndclear(&nd); 2480 2481 fhp = &nfh.fh_generic; 2482 nfsm_srvmtofh(fhp); 2483 nfsm_srvnamesiz(len); 2484 nd.ni_cnd.cn_cred = cred; 2485 nd.ni_cnd.cn_nameiop = NAMEI_CREATE; 2486 nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_SAVESTART; 2487 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2488 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2489 if (dirp) { 2490 if (v3) { 2491 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2492 } else { 2493 vrele(dirp); 2494 dirp = NULL; 2495 } 2496 } 2497 if (error) 2498 goto out; 2499 2500 VATTR_NULL(vap); 2501 if (v3) 2502 nfsm_srvsattr(vap); 2503 nfsm_strsiz(len2, NFS_MAXPATHLEN); 2504 MALLOC(pathcp, caddr_t, len2 + 1, M_TEMP, M_WAITOK); 2505 iv.iov_base = pathcp; 2506 iv.iov_len = len2; 2507 io.uio_resid = len2; 2508 io.uio_offset = 0; 2509 io.uio_iov = &iv; 2510 io.uio_iovcnt = 1; 2511 io.uio_segflg = UIO_SYSSPACE; 2512 io.uio_rw = UIO_READ; 2513 io.uio_td = NULL; 2514 nfsm_mtouio(&io, len2); 2515 if (!v3) { 2516 nfsm_dissect(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 2517 vap->va_mode = nfstov_mode(sp->sa_mode); 2518 } 2519 *(pathcp + len2) = '\0'; 2520 if (nd.ni_vp) { 2521 error = EEXIST; 2522 goto out; 2523 } 2524 2525 /* 2526 * issue symlink op. SAVESTART is set so the underlying path component 2527 * is only freed by the VOP if an error occurs. 2528 */ 2529 if (vap->va_mode == (mode_t)VNOVAL) 2530 vap->va_mode = 0; 2531 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2532 error = VOP_SYMLINK(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, vap, pathcp); 2533 if (error) 2534 NDFREE(&nd, NDF_ONLY_PNBUF); 2535 else 2536 vput(nd.ni_vp); 2537 nd.ni_vp = NULL; 2538 /* 2539 * releases directory prior to potential lookup op. 2540 */ 2541 vput(nd.ni_dvp); 2542 nd.ni_dvp = NULL; 2543 2544 if (error == 0) { 2545 if (v3) { 2546 /* 2547 * Issue lookup. Leave SAVESTART set so we can easily free 2548 * the name buffer later on. 2549 * 2550 * since LOCKPARENT is not set, ni_dvp will be garbage on 2551 * return whether an error occurs or not. 2552 */ 2553 nd.ni_cnd.cn_nameiop = NAMEI_LOOKUP; 2554 nd.ni_cnd.cn_flags &= ~(CNP_LOCKPARENT | CNP_FOLLOW); 2555 nd.ni_cnd.cn_flags |= CNP_LOCKLEAF; 2556 nd.ni_cnd.cn_td = td; 2557 nd.ni_cnd.cn_cred = cred; 2558 2559 error = lookup(&nd); 2560 nd.ni_dvp = NULL; 2561 2562 if (error == 0) { 2563 bzero((caddr_t)fhp, sizeof(nfh)); 2564 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid; 2565 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid); 2566 if (!error) 2567 error = VOP_GETATTR(nd.ni_vp, vap, td); 2568 vput(nd.ni_vp); 2569 nd.ni_vp = NULL; 2570 } 2571 } 2572 } 2573 out: 2574 /* 2575 * These releases aren't strictly required, does even doing them 2576 * make any sense? XXX can nfsm_reply() block? 2577 */ 2578 if (pathcp) { 2579 FREE(pathcp, M_TEMP); 2580 pathcp = NULL; 2581 } 2582 if (dirp) { 2583 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2584 vrele(dirp); 2585 dirp = NULL; 2586 } 2587 if (nd.ni_startdir) { 2588 vrele(nd.ni_startdir); 2589 nd.ni_startdir = NULL; 2590 } 2591 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2592 if (v3) { 2593 if (!error) { 2594 nfsm_srvpostop_fh(fhp); 2595 nfsm_srvpostop_attr(0, vap); 2596 } 2597 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2598 } 2599 error = 0; 2600 /* fall through */ 2601 2602 nfsmout: 2603 NDFREE(&nd, NDF_ONLY_PNBUF); 2604 if (nd.ni_dvp) { 2605 if (nd.ni_dvp == nd.ni_vp) 2606 vrele(nd.ni_dvp); 2607 else 2608 vput(nd.ni_dvp); 2609 } 2610 if (nd.ni_vp) 2611 vrele(nd.ni_vp); 2612 if (nd.ni_startdir) 2613 vrele(nd.ni_startdir); 2614 if (dirp) 2615 vrele(dirp); 2616 if (pathcp) 2617 FREE(pathcp, M_TEMP); 2618 2619 return (error); 2620 } 2621 2622 /* 2623 * nfs mkdir service 2624 */ 2625 int 2626 nfsrv_mkdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2627 struct thread *td, struct mbuf **mrq) 2628 { 2629 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2630 struct sockaddr *nam = nfsd->nd_nam; 2631 caddr_t dpos = nfsd->nd_dpos; 2632 struct ucred *cred = &nfsd->nd_cr; 2633 struct vattr va, dirfor, diraft; 2634 struct vattr *vap = &va; 2635 struct nfs_fattr *fp; 2636 struct nameidata nd; 2637 caddr_t cp; 2638 u_int32_t *tl; 2639 int32_t t1; 2640 caddr_t bpos; 2641 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 2642 int v3 = (nfsd->nd_flag & ND_NFSV3); 2643 char *cp2; 2644 struct mbuf *mb, *mb2, *mreq; 2645 struct vnode *dirp = NULL; 2646 int vpexcl = 0; 2647 nfsfh_t nfh; 2648 fhandle_t *fhp; 2649 u_quad_t frev; 2650 2651 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2652 ndclear(&nd); 2653 2654 fhp = &nfh.fh_generic; 2655 nfsm_srvmtofh(fhp); 2656 nfsm_srvnamesiz(len); 2657 nd.ni_cnd.cn_cred = cred; 2658 nd.ni_cnd.cn_nameiop = NAMEI_CREATE; 2659 nd.ni_cnd.cn_flags = CNP_LOCKPARENT; 2660 2661 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2662 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2663 if (dirp) { 2664 if (v3) { 2665 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2666 } else { 2667 vrele(dirp); 2668 dirp = NULL; 2669 } 2670 } 2671 if (error) { 2672 nfsm_reply(NFSX_WCCDATA(v3)); 2673 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2674 error = 0; 2675 goto nfsmout; 2676 } 2677 VATTR_NULL(vap); 2678 if (v3) { 2679 nfsm_srvsattr(vap); 2680 } else { 2681 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2682 vap->va_mode = nfstov_mode(*tl++); 2683 } 2684 2685 /* 2686 * At this point nd.ni_dvp is referenced and exclusively locked and 2687 * nd.ni_vp, if it exists, is referenced but not locked. 2688 */ 2689 2690 vap->va_type = VDIR; 2691 if (nd.ni_vp != NULL) { 2692 NDFREE(&nd, NDF_ONLY_PNBUF); 2693 error = EEXIST; 2694 goto out; 2695 } 2696 2697 /* 2698 * Issue mkdir op. Since SAVESTART is not set, the pathname 2699 * component is freed by the VOP call. This will fill-in 2700 * nd.ni_vp, reference, and exclusively lock it. 2701 */ 2702 if (vap->va_mode == (mode_t)VNOVAL) 2703 vap->va_mode = 0; 2704 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2705 error = VOP_MKDIR(nd.ni_dvp, NCPNULL, &nd.ni_vp, &nd.ni_cnd, vap); 2706 NDFREE(&nd, NDF_ONLY_PNBUF); 2707 vpexcl = 1; 2708 2709 vput(nd.ni_dvp); 2710 nd.ni_dvp = NULL; 2711 2712 if (!error) { 2713 bzero((caddr_t)fhp, sizeof(nfh)); 2714 fhp->fh_fsid = nd.ni_vp->v_mount->mnt_stat.f_fsid; 2715 error = VFS_VPTOFH(nd.ni_vp, &fhp->fh_fid); 2716 if (!error) 2717 error = VOP_GETATTR(nd.ni_vp, vap, td); 2718 } 2719 out: 2720 if (dirp) 2721 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2722 nfsm_reply(NFSX_SRVFH(v3) + NFSX_POSTOPATTR(v3) + NFSX_WCCDATA(v3)); 2723 if (v3) { 2724 if (!error) { 2725 nfsm_srvpostop_fh(fhp); 2726 nfsm_srvpostop_attr(0, vap); 2727 } 2728 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2729 } else { 2730 nfsm_srvfhtom(fhp, v3); 2731 nfsm_build(fp, struct nfs_fattr *, NFSX_V2FATTR); 2732 nfsm_srvfillattr(vap, fp); 2733 } 2734 error = 0; 2735 /* fall through */ 2736 2737 nfsmout: 2738 if (dirp) 2739 vrele(dirp); 2740 if (nd.ni_dvp) { 2741 NDFREE(&nd, NDF_ONLY_PNBUF); 2742 if (nd.ni_dvp == nd.ni_vp && vpexcl) 2743 vrele(nd.ni_dvp); 2744 else 2745 vput(nd.ni_dvp); 2746 } 2747 if (nd.ni_vp) { 2748 if (vpexcl) 2749 vput(nd.ni_vp); 2750 else 2751 vrele(nd.ni_vp); 2752 } 2753 return (error); 2754 } 2755 2756 /* 2757 * nfs rmdir service 2758 */ 2759 int 2760 nfsrv_rmdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2761 struct thread *td, struct mbuf **mrq) 2762 { 2763 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2764 struct sockaddr *nam = nfsd->nd_nam; 2765 caddr_t dpos = nfsd->nd_dpos; 2766 struct ucred *cred = &nfsd->nd_cr; 2767 u_int32_t *tl; 2768 int32_t t1; 2769 caddr_t bpos; 2770 int error = 0, cache, len, dirfor_ret = 1, diraft_ret = 1; 2771 int v3 = (nfsd->nd_flag & ND_NFSV3); 2772 char *cp2; 2773 struct mbuf *mb, *mreq; 2774 struct vnode *vp, *dirp = (struct vnode *)0; 2775 struct vattr dirfor, diraft; 2776 nfsfh_t nfh; 2777 fhandle_t *fhp; 2778 struct nameidata nd; 2779 u_quad_t frev; 2780 2781 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2782 ndclear(&nd); 2783 2784 fhp = &nfh.fh_generic; 2785 nfsm_srvmtofh(fhp); 2786 nfsm_srvnamesiz(len); 2787 nd.ni_cnd.cn_cred = cred; 2788 nd.ni_cnd.cn_nameiop = NAMEI_DELETE; 2789 nd.ni_cnd.cn_flags = CNP_LOCKPARENT | CNP_LOCKLEAF; 2790 error = nfs_namei(&nd, fhp, len, slp, nam, &md, &dpos, 2791 &dirp, td, (nfsd->nd_flag & ND_KERBAUTH), FALSE); 2792 if (dirp) { 2793 if (v3) { 2794 dirfor_ret = VOP_GETATTR(dirp, &dirfor, td); 2795 } else { 2796 vrele(dirp); 2797 dirp = NULL; 2798 } 2799 } 2800 if (error) { 2801 nfsm_reply(NFSX_WCCDATA(v3)); 2802 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2803 error = 0; 2804 goto nfsmout; 2805 } 2806 vp = nd.ni_vp; 2807 if (vp->v_type != VDIR) { 2808 error = ENOTDIR; 2809 goto out; 2810 } 2811 /* 2812 * No rmdir "." please. 2813 */ 2814 if (nd.ni_dvp == vp) { 2815 error = EINVAL; 2816 goto out; 2817 } 2818 /* 2819 * The root of a mounted filesystem cannot be deleted. 2820 */ 2821 if (vp->v_flag & VROOT) 2822 error = EBUSY; 2823 out: 2824 /* 2825 * Issue or abort op. Since SAVESTART is not set, path name 2826 * component is freed by the VOP after either. 2827 */ 2828 if (!error) { 2829 nqsrv_getl(nd.ni_dvp, ND_WRITE); 2830 nqsrv_getl(vp, ND_WRITE); 2831 error = VOP_RMDIR(nd.ni_dvp, NCPNULL, nd.ni_vp, &nd.ni_cnd); 2832 if (error == 0) 2833 cache_purge(nd.ni_vp); 2834 } 2835 NDFREE(&nd, NDF_ONLY_PNBUF); 2836 2837 if (dirp) 2838 diraft_ret = VOP_GETATTR(dirp, &diraft, td); 2839 nfsm_reply(NFSX_WCCDATA(v3)); 2840 if (v3) { 2841 nfsm_srvwcc_data(dirfor_ret, &dirfor, diraft_ret, &diraft); 2842 error = 0; 2843 } 2844 /* fall through */ 2845 2846 nfsmout: 2847 NDFREE(&nd, NDF_ONLY_PNBUF); 2848 if (dirp) 2849 vrele(dirp); 2850 if (nd.ni_dvp) { 2851 if (nd.ni_dvp == nd.ni_vp) 2852 vrele(nd.ni_dvp); 2853 else 2854 vput(nd.ni_dvp); 2855 } 2856 if (nd.ni_vp) 2857 vput(nd.ni_vp); 2858 2859 return(error); 2860 } 2861 2862 /* 2863 * nfs readdir service 2864 * - mallocs what it thinks is enough to read 2865 * count rounded up to a multiple of NFS_DIRBLKSIZ <= NFS_MAXREADDIR 2866 * - calls VOP_READDIR() 2867 * - loops around building the reply 2868 * if the output generated exceeds count break out of loop 2869 * The nfsm_clget macro is used here so that the reply will be packed 2870 * tightly in mbuf clusters. 2871 * - it only knows that it has encountered eof when the VOP_READDIR() 2872 * reads nothing 2873 * - as such one readdir rpc will return eof false although you are there 2874 * and then the next will return eof 2875 * - it trims out records with d_fileno == 0 2876 * this doesn't matter for Unix clients, but they might confuse clients 2877 * for other os'. 2878 * NB: It is tempting to set eof to true if the VOP_READDIR() reads less 2879 * than requested, but this may not apply to all filesystems. For 2880 * example, client NFS does not { although it is never remote mounted 2881 * anyhow } 2882 * The alternate call nfsrv_readdirplus() does lookups as well. 2883 * PS: The NFS protocol spec. does not clarify what the "count" byte 2884 * argument is a count of.. just name strings and file id's or the 2885 * entire reply rpc or ... 2886 * I tried just file name and id sizes and it confused the Sun client, 2887 * so I am using the full rpc size now. The "paranoia.." comment refers 2888 * to including the status longwords that are not a part of the dir. 2889 * "entry" structures, but are in the rpc. 2890 */ 2891 struct flrep { 2892 nfsuint64 fl_off; 2893 u_int32_t fl_postopok; 2894 u_int32_t fl_fattr[NFSX_V3FATTR / sizeof (u_int32_t)]; 2895 u_int32_t fl_fhok; 2896 u_int32_t fl_fhsize; 2897 u_int32_t fl_nfh[NFSX_V3FH / sizeof (u_int32_t)]; 2898 }; 2899 2900 int 2901 nfsrv_readdir(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 2902 struct thread *td, struct mbuf **mrq) 2903 { 2904 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 2905 struct sockaddr *nam = nfsd->nd_nam; 2906 caddr_t dpos = nfsd->nd_dpos; 2907 struct ucred *cred = &nfsd->nd_cr; 2908 char *bp, *be; 2909 struct mbuf *mp; 2910 struct dirent *dp; 2911 caddr_t cp; 2912 u_int32_t *tl; 2913 int32_t t1; 2914 caddr_t bpos; 2915 struct mbuf *mb, *mb2, *mreq, *mp2; 2916 char *cpos, *cend, *cp2, *rbuf; 2917 struct vnode *vp = NULL; 2918 struct vattr at; 2919 nfsfh_t nfh; 2920 fhandle_t *fhp; 2921 struct uio io; 2922 struct iovec iv; 2923 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 2924 int siz, cnt, fullsiz, eofflag, rdonly, cache, ncookies; 2925 int v3 = (nfsd->nd_flag & ND_NFSV3); 2926 u_quad_t frev, off, toff, verf; 2927 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 2928 2929 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 2930 fhp = &nfh.fh_generic; 2931 nfsm_srvmtofh(fhp); 2932 if (v3) { 2933 nfsm_dissect(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2934 toff = fxdr_hyper(tl); 2935 tl += 2; 2936 verf = fxdr_hyper(tl); 2937 tl += 2; 2938 } else { 2939 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2940 toff = fxdr_unsigned(u_quad_t, *tl++); 2941 verf = 0; /* shut up gcc */ 2942 } 2943 off = toff; 2944 cnt = fxdr_unsigned(int, *tl); 2945 siz = ((cnt + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 2946 xfer = NFS_SRVMAXDATA(nfsd); 2947 if (cnt > xfer) 2948 cnt = xfer; 2949 if (siz > xfer) 2950 siz = xfer; 2951 fullsiz = siz; 2952 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 2953 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 2954 if (!error && vp->v_type != VDIR) { 2955 error = ENOTDIR; 2956 vput(vp); 2957 vp = NULL; 2958 } 2959 if (error) { 2960 nfsm_reply(NFSX_UNSIGNED); 2961 nfsm_srvpostop_attr(getret, &at); 2962 error = 0; 2963 goto nfsmout; 2964 } 2965 2966 /* 2967 * Obtain lock on vnode for this section of the code 2968 */ 2969 2970 nqsrv_getl(vp, ND_READ); 2971 if (v3) { 2972 error = getret = VOP_GETATTR(vp, &at, td); 2973 #if 0 2974 /* 2975 * XXX This check may be too strict for Solaris 2.5 clients. 2976 */ 2977 if (!error && toff && verf && verf != at.va_filerev) 2978 error = NFSERR_BAD_COOKIE; 2979 #endif 2980 } 2981 if (!error) 2982 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 2983 if (error) { 2984 vput(vp); 2985 vp = NULL; 2986 nfsm_reply(NFSX_POSTOPATTR(v3)); 2987 nfsm_srvpostop_attr(getret, &at); 2988 error = 0; 2989 goto nfsmout; 2990 } 2991 VOP_UNLOCK(vp, 0, td); 2992 2993 /* 2994 * end section. Allocate rbuf and continue 2995 */ 2996 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 2997 again: 2998 iv.iov_base = rbuf; 2999 iv.iov_len = fullsiz; 3000 io.uio_iov = &iv; 3001 io.uio_iovcnt = 1; 3002 io.uio_offset = (off_t)off; 3003 io.uio_resid = fullsiz; 3004 io.uio_segflg = UIO_SYSSPACE; 3005 io.uio_rw = UIO_READ; 3006 io.uio_td = NULL; 3007 eofflag = 0; 3008 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3009 if (cookies) { 3010 free((caddr_t)cookies, M_TEMP); 3011 cookies = NULL; 3012 } 3013 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 3014 off = (off_t)io.uio_offset; 3015 if (!cookies && !error) 3016 error = NFSERR_PERM; 3017 if (v3) { 3018 getret = VOP_GETATTR(vp, &at, td); 3019 if (!error) 3020 error = getret; 3021 } 3022 VOP_UNLOCK(vp, 0, td); 3023 if (error) { 3024 vrele(vp); 3025 vp = NULL; 3026 free((caddr_t)rbuf, M_TEMP); 3027 if (cookies) 3028 free((caddr_t)cookies, M_TEMP); 3029 nfsm_reply(NFSX_POSTOPATTR(v3)); 3030 nfsm_srvpostop_attr(getret, &at); 3031 error = 0; 3032 goto nfsmout; 3033 } 3034 if (io.uio_resid) { 3035 siz -= io.uio_resid; 3036 3037 /* 3038 * If nothing read, return eof 3039 * rpc reply 3040 */ 3041 if (siz == 0) { 3042 vrele(vp); 3043 vp = NULL; 3044 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + 3045 2 * NFSX_UNSIGNED); 3046 if (v3) { 3047 nfsm_srvpostop_attr(getret, &at); 3048 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3049 txdr_hyper(at.va_filerev, tl); 3050 tl += 2; 3051 } else 3052 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3053 *tl++ = nfs_false; 3054 *tl = nfs_true; 3055 FREE((caddr_t)rbuf, M_TEMP); 3056 FREE((caddr_t)cookies, M_TEMP); 3057 error = 0; 3058 goto nfsmout; 3059 } 3060 } 3061 3062 /* 3063 * Check for degenerate cases of nothing useful read. 3064 * If so go try again 3065 */ 3066 cpos = rbuf; 3067 cend = rbuf + siz; 3068 dp = (struct dirent *)cpos; 3069 cookiep = cookies; 3070 /* 3071 * For some reason FreeBSD's ufs_readdir() chooses to back the 3072 * directory offset up to a block boundary, so it is necessary to 3073 * skip over the records that preceed the requested offset. This 3074 * requires the assumption that file offset cookies monotonically 3075 * increase. 3076 */ 3077 while (cpos < cend && ncookies > 0 && 3078 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 3079 ((u_quad_t)(*cookiep)) <= toff)) { 3080 cpos += dp->d_reclen; 3081 dp = (struct dirent *)cpos; 3082 cookiep++; 3083 ncookies--; 3084 } 3085 if (cpos >= cend || ncookies == 0) { 3086 toff = off; 3087 siz = fullsiz; 3088 goto again; 3089 } 3090 3091 len = 3 * NFSX_UNSIGNED; /* paranoia, probably can be 0 */ 3092 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_COOKIEVERF(v3) + siz); 3093 if (v3) { 3094 nfsm_srvpostop_attr(getret, &at); 3095 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3096 txdr_hyper(at.va_filerev, tl); 3097 } 3098 mp = mp2 = mb; 3099 bp = bpos; 3100 be = bp + M_TRAILINGSPACE(mp); 3101 3102 /* Loop through the records and build reply */ 3103 while (cpos < cend && ncookies > 0) { 3104 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 3105 nlen = dp->d_namlen; 3106 rem = nfsm_rndup(nlen) - nlen; 3107 len += (4 * NFSX_UNSIGNED + nlen + rem); 3108 if (v3) 3109 len += 2 * NFSX_UNSIGNED; 3110 if (len > cnt) { 3111 eofflag = 0; 3112 break; 3113 } 3114 /* 3115 * Build the directory record xdr from 3116 * the dirent entry. 3117 */ 3118 nfsm_clget; 3119 *tl = nfs_true; 3120 bp += NFSX_UNSIGNED; 3121 if (v3) { 3122 nfsm_clget; 3123 *tl = 0; 3124 bp += NFSX_UNSIGNED; 3125 } 3126 nfsm_clget; 3127 *tl = txdr_unsigned(dp->d_fileno); 3128 bp += NFSX_UNSIGNED; 3129 nfsm_clget; 3130 *tl = txdr_unsigned(nlen); 3131 bp += NFSX_UNSIGNED; 3132 3133 /* And loop around copying the name */ 3134 xfer = nlen; 3135 cp = dp->d_name; 3136 while (xfer > 0) { 3137 nfsm_clget; 3138 if ((bp+xfer) > be) 3139 tsiz = be-bp; 3140 else 3141 tsiz = xfer; 3142 bcopy(cp, bp, tsiz); 3143 bp += tsiz; 3144 xfer -= tsiz; 3145 if (xfer > 0) 3146 cp += tsiz; 3147 } 3148 /* And null pad to a int32_t boundary */ 3149 for (i = 0; i < rem; i++) 3150 *bp++ = '\0'; 3151 nfsm_clget; 3152 3153 /* Finish off the record */ 3154 if (v3) { 3155 *tl = 0; 3156 bp += NFSX_UNSIGNED; 3157 nfsm_clget; 3158 } 3159 *tl = txdr_unsigned(*cookiep); 3160 bp += NFSX_UNSIGNED; 3161 } 3162 cpos += dp->d_reclen; 3163 dp = (struct dirent *)cpos; 3164 cookiep++; 3165 ncookies--; 3166 } 3167 vrele(vp); 3168 vp = NULL; 3169 nfsm_clget; 3170 *tl = nfs_false; 3171 bp += NFSX_UNSIGNED; 3172 nfsm_clget; 3173 if (eofflag) 3174 *tl = nfs_true; 3175 else 3176 *tl = nfs_false; 3177 bp += NFSX_UNSIGNED; 3178 if (mp != mb) { 3179 if (bp < be) 3180 mp->m_len = bp - mtod(mp, caddr_t); 3181 } else 3182 mp->m_len += bp - bpos; 3183 FREE((caddr_t)rbuf, M_TEMP); 3184 FREE((caddr_t)cookies, M_TEMP); 3185 3186 nfsmout: 3187 if (vp) 3188 vrele(vp); 3189 return(error); 3190 } 3191 3192 int 3193 nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3194 struct thread *td, struct mbuf **mrq) 3195 { 3196 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3197 struct sockaddr *nam = nfsd->nd_nam; 3198 caddr_t dpos = nfsd->nd_dpos; 3199 struct ucred *cred = &nfsd->nd_cr; 3200 char *bp, *be; 3201 struct mbuf *mp; 3202 struct dirent *dp; 3203 caddr_t cp; 3204 u_int32_t *tl; 3205 int32_t t1; 3206 caddr_t bpos; 3207 struct mbuf *mb, *mb2, *mreq, *mp2; 3208 char *cpos, *cend, *cp2, *rbuf; 3209 struct vnode *vp = NULL, *nvp; 3210 struct flrep fl; 3211 nfsfh_t nfh; 3212 fhandle_t *fhp, *nfhp = (fhandle_t *)fl.fl_nfh; 3213 struct uio io; 3214 struct iovec iv; 3215 struct vattr va, at, *vap = &va; 3216 struct nfs_fattr *fp; 3217 int len, nlen, rem, xfer, tsiz, i, error = 0, getret = 1; 3218 int siz, cnt, fullsiz, eofflag, rdonly, cache, dirlen, ncookies; 3219 u_quad_t frev, off, toff, verf; 3220 u_long *cookies = NULL, *cookiep; /* needs to be int64_t or off_t */ 3221 3222 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3223 fhp = &nfh.fh_generic; 3224 nfsm_srvmtofh(fhp); 3225 nfsm_dissect(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 3226 toff = fxdr_hyper(tl); 3227 tl += 2; 3228 verf = fxdr_hyper(tl); 3229 tl += 2; 3230 siz = fxdr_unsigned(int, *tl++); 3231 cnt = fxdr_unsigned(int, *tl); 3232 off = toff; 3233 siz = ((siz + DIRBLKSIZ - 1) & ~(DIRBLKSIZ - 1)); 3234 xfer = NFS_SRVMAXDATA(nfsd); 3235 if (cnt > xfer) 3236 cnt = xfer; 3237 if (siz > xfer) 3238 siz = xfer; 3239 fullsiz = siz; 3240 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3241 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3242 if (!error && vp->v_type != VDIR) { 3243 error = ENOTDIR; 3244 vput(vp); 3245 vp = NULL; 3246 } 3247 if (error) { 3248 nfsm_reply(NFSX_UNSIGNED); 3249 nfsm_srvpostop_attr(getret, &at); 3250 error = 0; 3251 goto nfsmout; 3252 } 3253 error = getret = VOP_GETATTR(vp, &at, td); 3254 #if 0 3255 /* 3256 * XXX This check may be too strict for Solaris 2.5 clients. 3257 */ 3258 if (!error && toff && verf && verf != at.va_filerev) 3259 error = NFSERR_BAD_COOKIE; 3260 #endif 3261 if (!error) { 3262 nqsrv_getl(vp, ND_READ); 3263 error = nfsrv_access(vp, VEXEC, cred, rdonly, td, 0); 3264 } 3265 if (error) { 3266 vput(vp); 3267 vp = NULL; 3268 nfsm_reply(NFSX_V3POSTOPATTR); 3269 nfsm_srvpostop_attr(getret, &at); 3270 error = 0; 3271 goto nfsmout; 3272 } 3273 VOP_UNLOCK(vp, 0, td); 3274 MALLOC(rbuf, caddr_t, siz, M_TEMP, M_WAITOK); 3275 again: 3276 iv.iov_base = rbuf; 3277 iv.iov_len = fullsiz; 3278 io.uio_iov = &iv; 3279 io.uio_iovcnt = 1; 3280 io.uio_offset = (off_t)off; 3281 io.uio_resid = fullsiz; 3282 io.uio_segflg = UIO_SYSSPACE; 3283 io.uio_rw = UIO_READ; 3284 io.uio_td = NULL; 3285 eofflag = 0; 3286 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3287 if (cookies) { 3288 free((caddr_t)cookies, M_TEMP); 3289 cookies = NULL; 3290 } 3291 error = VOP_READDIR(vp, &io, cred, &eofflag, &ncookies, &cookies); 3292 off = (u_quad_t)io.uio_offset; 3293 getret = VOP_GETATTR(vp, &at, td); 3294 VOP_UNLOCK(vp, 0, td); 3295 if (!cookies && !error) 3296 error = NFSERR_PERM; 3297 if (!error) 3298 error = getret; 3299 if (error) { 3300 vrele(vp); 3301 vp = NULL; 3302 if (cookies) 3303 free((caddr_t)cookies, M_TEMP); 3304 free((caddr_t)rbuf, M_TEMP); 3305 nfsm_reply(NFSX_V3POSTOPATTR); 3306 nfsm_srvpostop_attr(getret, &at); 3307 error = 0; 3308 goto nfsmout; 3309 } 3310 if (io.uio_resid) { 3311 siz -= io.uio_resid; 3312 3313 /* 3314 * If nothing read, return eof 3315 * rpc reply 3316 */ 3317 if (siz == 0) { 3318 vrele(vp); 3319 vp = NULL; 3320 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 3321 2 * NFSX_UNSIGNED); 3322 nfsm_srvpostop_attr(getret, &at); 3323 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 3324 txdr_hyper(at.va_filerev, tl); 3325 tl += 2; 3326 *tl++ = nfs_false; 3327 *tl = nfs_true; 3328 FREE((caddr_t)cookies, M_TEMP); 3329 FREE((caddr_t)rbuf, M_TEMP); 3330 error = 0; 3331 goto nfsmout; 3332 } 3333 } 3334 3335 /* 3336 * Check for degenerate cases of nothing useful read. 3337 * If so go try again 3338 */ 3339 cpos = rbuf; 3340 cend = rbuf + siz; 3341 dp = (struct dirent *)cpos; 3342 cookiep = cookies; 3343 /* 3344 * For some reason FreeBSD's ufs_readdir() chooses to back the 3345 * directory offset up to a block boundary, so it is necessary to 3346 * skip over the records that preceed the requested offset. This 3347 * requires the assumption that file offset cookies monotonically 3348 * increase. 3349 */ 3350 while (cpos < cend && ncookies > 0 && 3351 (dp->d_fileno == 0 || dp->d_type == DT_WHT || 3352 ((u_quad_t)(*cookiep)) <= toff)) { 3353 cpos += dp->d_reclen; 3354 dp = (struct dirent *)cpos; 3355 cookiep++; 3356 ncookies--; 3357 } 3358 if (cpos >= cend || ncookies == 0) { 3359 toff = off; 3360 siz = fullsiz; 3361 goto again; 3362 } 3363 3364 /* 3365 * Probe one of the directory entries to see if the filesystem 3366 * supports VGET. 3367 */ 3368 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp) == EOPNOTSUPP) { 3369 error = NFSERR_NOTSUPP; 3370 vrele(vp); 3371 vp = NULL; 3372 free((caddr_t)cookies, M_TEMP); 3373 free((caddr_t)rbuf, M_TEMP); 3374 nfsm_reply(NFSX_V3POSTOPATTR); 3375 nfsm_srvpostop_attr(getret, &at); 3376 error = 0; 3377 goto nfsmout; 3378 } 3379 vput(nvp); 3380 nvp = NULL; 3381 3382 dirlen = len = NFSX_V3POSTOPATTR + NFSX_V3COOKIEVERF + 2 * NFSX_UNSIGNED; 3383 nfsm_reply(cnt); 3384 nfsm_srvpostop_attr(getret, &at); 3385 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 3386 txdr_hyper(at.va_filerev, tl); 3387 mp = mp2 = mb; 3388 bp = bpos; 3389 be = bp + M_TRAILINGSPACE(mp); 3390 3391 /* Loop through the records and build reply */ 3392 while (cpos < cend && ncookies > 0) { 3393 if (dp->d_fileno != 0 && dp->d_type != DT_WHT) { 3394 nlen = dp->d_namlen; 3395 rem = nfsm_rndup(nlen)-nlen; 3396 3397 /* 3398 * For readdir_and_lookup get the vnode using 3399 * the file number. 3400 */ 3401 if (VFS_VGET(vp->v_mount, dp->d_fileno, &nvp)) 3402 goto invalid; 3403 bzero((caddr_t)nfhp, NFSX_V3FH); 3404 nfhp->fh_fsid = 3405 nvp->v_mount->mnt_stat.f_fsid; 3406 if (VFS_VPTOFH(nvp, &nfhp->fh_fid)) { 3407 vput(nvp); 3408 nvp = NULL; 3409 goto invalid; 3410 } 3411 if (VOP_GETATTR(nvp, vap, td)) { 3412 vput(nvp); 3413 nvp = NULL; 3414 goto invalid; 3415 } 3416 vput(nvp); 3417 nvp = NULL; 3418 3419 /* 3420 * If either the dircount or maxcount will be 3421 * exceeded, get out now. Both of these lengths 3422 * are calculated conservatively, including all 3423 * XDR overheads. 3424 */ 3425 len += (8 * NFSX_UNSIGNED + nlen + rem + NFSX_V3FH + 3426 NFSX_V3POSTOPATTR); 3427 dirlen += (6 * NFSX_UNSIGNED + nlen + rem); 3428 if (len > cnt || dirlen > fullsiz) { 3429 eofflag = 0; 3430 break; 3431 } 3432 3433 /* 3434 * Build the directory record xdr from 3435 * the dirent entry. 3436 */ 3437 fp = (struct nfs_fattr *)&fl.fl_fattr; 3438 nfsm_srvfillattr(vap, fp); 3439 fl.fl_fhsize = txdr_unsigned(NFSX_V3FH); 3440 fl.fl_fhok = nfs_true; 3441 fl.fl_postopok = nfs_true; 3442 fl.fl_off.nfsuquad[0] = 0; 3443 fl.fl_off.nfsuquad[1] = txdr_unsigned(*cookiep); 3444 3445 nfsm_clget; 3446 *tl = nfs_true; 3447 bp += NFSX_UNSIGNED; 3448 nfsm_clget; 3449 *tl = 0; 3450 bp += NFSX_UNSIGNED; 3451 nfsm_clget; 3452 *tl = txdr_unsigned(dp->d_fileno); 3453 bp += NFSX_UNSIGNED; 3454 nfsm_clget; 3455 *tl = txdr_unsigned(nlen); 3456 bp += NFSX_UNSIGNED; 3457 3458 /* And loop around copying the name */ 3459 xfer = nlen; 3460 cp = dp->d_name; 3461 while (xfer > 0) { 3462 nfsm_clget; 3463 if ((bp + xfer) > be) 3464 tsiz = be - bp; 3465 else 3466 tsiz = xfer; 3467 bcopy(cp, bp, tsiz); 3468 bp += tsiz; 3469 xfer -= tsiz; 3470 if (xfer > 0) 3471 cp += tsiz; 3472 } 3473 /* And null pad to a int32_t boundary */ 3474 for (i = 0; i < rem; i++) 3475 *bp++ = '\0'; 3476 3477 /* 3478 * Now copy the flrep structure out. 3479 */ 3480 xfer = sizeof (struct flrep); 3481 cp = (caddr_t)&fl; 3482 while (xfer > 0) { 3483 nfsm_clget; 3484 if ((bp + xfer) > be) 3485 tsiz = be - bp; 3486 else 3487 tsiz = xfer; 3488 bcopy(cp, bp, tsiz); 3489 bp += tsiz; 3490 xfer -= tsiz; 3491 if (xfer > 0) 3492 cp += tsiz; 3493 } 3494 } 3495 invalid: 3496 cpos += dp->d_reclen; 3497 dp = (struct dirent *)cpos; 3498 cookiep++; 3499 ncookies--; 3500 } 3501 vrele(vp); 3502 vp = NULL; 3503 nfsm_clget; 3504 *tl = nfs_false; 3505 bp += NFSX_UNSIGNED; 3506 nfsm_clget; 3507 if (eofflag) 3508 *tl = nfs_true; 3509 else 3510 *tl = nfs_false; 3511 bp += NFSX_UNSIGNED; 3512 if (mp != mb) { 3513 if (bp < be) 3514 mp->m_len = bp - mtod(mp, caddr_t); 3515 } else 3516 mp->m_len += bp - bpos; 3517 FREE((caddr_t)cookies, M_TEMP); 3518 FREE((caddr_t)rbuf, M_TEMP); 3519 nfsmout: 3520 if (vp) 3521 vrele(vp); 3522 return(error); 3523 } 3524 3525 /* 3526 * nfs commit service 3527 */ 3528 int 3529 nfsrv_commit(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3530 struct thread *td, struct mbuf **mrq) 3531 { 3532 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3533 struct sockaddr *nam = nfsd->nd_nam; 3534 caddr_t dpos = nfsd->nd_dpos; 3535 struct ucred *cred = &nfsd->nd_cr; 3536 struct vattr bfor, aft; 3537 struct vnode *vp = NULL; 3538 nfsfh_t nfh; 3539 fhandle_t *fhp; 3540 u_int32_t *tl; 3541 int32_t t1; 3542 caddr_t bpos; 3543 int error = 0, rdonly, for_ret = 1, aft_ret = 1, cnt, cache; 3544 char *cp2; 3545 struct mbuf *mb, *mb2, *mreq; 3546 u_quad_t frev, off; 3547 3548 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3549 #ifndef nolint 3550 cache = 0; 3551 #endif 3552 fhp = &nfh.fh_generic; 3553 nfsm_srvmtofh(fhp); 3554 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3555 3556 /* 3557 * XXX At this time VOP_FSYNC() does not accept offset and byte 3558 * count parameters, so these arguments are useless (someday maybe). 3559 */ 3560 off = fxdr_hyper(tl); 3561 tl += 2; 3562 cnt = fxdr_unsigned(int, *tl); 3563 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3564 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3565 if (error) { 3566 nfsm_reply(2 * NFSX_UNSIGNED); 3567 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3568 error = 0; 3569 goto nfsmout; 3570 } 3571 for_ret = VOP_GETATTR(vp, &bfor, td); 3572 3573 if (cnt > MAX_COMMIT_COUNT) { 3574 /* 3575 * Give up and do the whole thing 3576 */ 3577 if (vp->v_object && 3578 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3579 vm_object_page_clean(vp->v_object, 0, 0, OBJPC_SYNC); 3580 } 3581 error = VOP_FSYNC(vp, MNT_WAIT, td); 3582 } else { 3583 /* 3584 * Locate and synchronously write any buffers that fall 3585 * into the requested range. Note: we are assuming that 3586 * f_iosize is a power of 2. 3587 */ 3588 int iosize = vp->v_mount->mnt_stat.f_iosize; 3589 int iomask = iosize - 1; 3590 int s; 3591 daddr_t lblkno; 3592 3593 /* 3594 * Align to iosize boundry, super-align to page boundry. 3595 */ 3596 if (off & iomask) { 3597 cnt += off & iomask; 3598 off &= ~(u_quad_t)iomask; 3599 } 3600 if (off & PAGE_MASK) { 3601 cnt += off & PAGE_MASK; 3602 off &= ~(u_quad_t)PAGE_MASK; 3603 } 3604 lblkno = off / iosize; 3605 3606 if (vp->v_object && 3607 (vp->v_object->flags & OBJ_MIGHTBEDIRTY)) { 3608 vm_object_page_clean(vp->v_object, off / PAGE_SIZE, (cnt + PAGE_MASK) / PAGE_SIZE, OBJPC_SYNC); 3609 } 3610 3611 s = splbio(); 3612 while (cnt > 0) { 3613 struct buf *bp; 3614 3615 /* 3616 * If we have a buffer and it is marked B_DELWRI we 3617 * have to lock and write it. Otherwise the prior 3618 * write is assumed to have already been committed. 3619 */ 3620 if ((bp = gbincore(vp, lblkno)) != NULL && (bp->b_flags & B_DELWRI)) { 3621 if (BUF_LOCK(bp, LK_EXCLUSIVE | LK_NOWAIT)) { 3622 BUF_LOCK(bp, LK_EXCLUSIVE | LK_SLEEPFAIL); 3623 continue; /* retry */ 3624 } 3625 bremfree(bp); 3626 bp->b_flags &= ~B_ASYNC; 3627 VOP_BWRITE(bp->b_vp, bp); 3628 ++nfs_commit_miss; 3629 } 3630 ++nfs_commit_blks; 3631 if (cnt < iosize) 3632 break; 3633 cnt -= iosize; 3634 ++lblkno; 3635 } 3636 splx(s); 3637 } 3638 3639 aft_ret = VOP_GETATTR(vp, &aft, td); 3640 vput(vp); 3641 vp = NULL; 3642 nfsm_reply(NFSX_V3WCCDATA + NFSX_V3WRITEVERF); 3643 nfsm_srvwcc_data(for_ret, &bfor, aft_ret, &aft); 3644 if (!error) { 3645 nfsm_build(tl, u_int32_t *, NFSX_V3WRITEVERF); 3646 if (nfsver.tv_sec == 0) 3647 nfsver = boottime; 3648 *tl++ = txdr_unsigned(nfsver.tv_sec); 3649 *tl = txdr_unsigned(nfsver.tv_nsec / 1000); 3650 } else { 3651 error = 0; 3652 } 3653 nfsmout: 3654 if (vp) 3655 vput(vp); 3656 return(error); 3657 } 3658 3659 /* 3660 * nfs statfs service 3661 */ 3662 int 3663 nfsrv_statfs(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3664 struct thread *td, struct mbuf **mrq) 3665 { 3666 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3667 struct sockaddr *nam = nfsd->nd_nam; 3668 caddr_t dpos = nfsd->nd_dpos; 3669 struct ucred *cred = &nfsd->nd_cr; 3670 struct statfs *sf; 3671 struct nfs_statfs *sfp; 3672 u_int32_t *tl; 3673 int32_t t1; 3674 caddr_t bpos; 3675 int error = 0, rdonly, cache, getret = 1; 3676 int v3 = (nfsd->nd_flag & ND_NFSV3); 3677 char *cp2; 3678 struct mbuf *mb, *mb2, *mreq; 3679 struct vnode *vp = NULL; 3680 struct vattr at; 3681 nfsfh_t nfh; 3682 fhandle_t *fhp; 3683 struct statfs statfs; 3684 u_quad_t frev, tval; 3685 3686 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3687 #ifndef nolint 3688 cache = 0; 3689 #endif 3690 fhp = &nfh.fh_generic; 3691 nfsm_srvmtofh(fhp); 3692 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3693 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3694 if (error) { 3695 nfsm_reply(NFSX_UNSIGNED); 3696 nfsm_srvpostop_attr(getret, &at); 3697 error = 0; 3698 goto nfsmout; 3699 } 3700 sf = &statfs; 3701 error = VFS_STATFS(vp->v_mount, sf, td); 3702 getret = VOP_GETATTR(vp, &at, td); 3703 vput(vp); 3704 vp = NULL; 3705 nfsm_reply(NFSX_POSTOPATTR(v3) + NFSX_STATFS(v3)); 3706 if (v3) 3707 nfsm_srvpostop_attr(getret, &at); 3708 if (error) { 3709 error = 0; 3710 goto nfsmout; 3711 } 3712 nfsm_build(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); 3713 if (v3) { 3714 tval = (u_quad_t)sf->f_blocks; 3715 tval *= (u_quad_t)sf->f_bsize; 3716 txdr_hyper(tval, &sfp->sf_tbytes); 3717 tval = (u_quad_t)sf->f_bfree; 3718 tval *= (u_quad_t)sf->f_bsize; 3719 txdr_hyper(tval, &sfp->sf_fbytes); 3720 tval = (u_quad_t)sf->f_bavail; 3721 tval *= (u_quad_t)sf->f_bsize; 3722 txdr_hyper(tval, &sfp->sf_abytes); 3723 sfp->sf_tfiles.nfsuquad[0] = 0; 3724 sfp->sf_tfiles.nfsuquad[1] = txdr_unsigned(sf->f_files); 3725 sfp->sf_ffiles.nfsuquad[0] = 0; 3726 sfp->sf_ffiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3727 sfp->sf_afiles.nfsuquad[0] = 0; 3728 sfp->sf_afiles.nfsuquad[1] = txdr_unsigned(sf->f_ffree); 3729 sfp->sf_invarsec = 0; 3730 } else { 3731 sfp->sf_tsize = txdr_unsigned(NFS_MAXDGRAMDATA); 3732 sfp->sf_bsize = txdr_unsigned(sf->f_bsize); 3733 sfp->sf_blocks = txdr_unsigned(sf->f_blocks); 3734 sfp->sf_bfree = txdr_unsigned(sf->f_bfree); 3735 sfp->sf_bavail = txdr_unsigned(sf->f_bavail); 3736 } 3737 nfsmout: 3738 if (vp) 3739 vput(vp); 3740 return(error); 3741 } 3742 3743 /* 3744 * nfs fsinfo service 3745 */ 3746 int 3747 nfsrv_fsinfo(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3748 struct thread *td, struct mbuf **mrq) 3749 { 3750 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3751 struct sockaddr *nam = nfsd->nd_nam; 3752 caddr_t dpos = nfsd->nd_dpos; 3753 struct ucred *cred = &nfsd->nd_cr; 3754 u_int32_t *tl; 3755 struct nfsv3_fsinfo *sip; 3756 int32_t t1; 3757 caddr_t bpos; 3758 int error = 0, rdonly, cache, getret = 1, pref; 3759 char *cp2; 3760 struct mbuf *mb, *mb2, *mreq; 3761 struct vnode *vp = NULL; 3762 struct vattr at; 3763 nfsfh_t nfh; 3764 fhandle_t *fhp; 3765 u_quad_t frev, maxfsize; 3766 struct statfs sb; 3767 3768 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3769 #ifndef nolint 3770 cache = 0; 3771 #endif 3772 fhp = &nfh.fh_generic; 3773 nfsm_srvmtofh(fhp); 3774 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3775 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3776 if (error) { 3777 nfsm_reply(NFSX_UNSIGNED); 3778 nfsm_srvpostop_attr(getret, &at); 3779 error = 0; 3780 goto nfsmout; 3781 } 3782 3783 /* XXX Try to make a guess on the max file size. */ 3784 VFS_STATFS(vp->v_mount, &sb, td); 3785 maxfsize = (u_quad_t)0x80000000 * sb.f_bsize - 1; 3786 3787 getret = VOP_GETATTR(vp, &at, td); 3788 vput(vp); 3789 vp = NULL; 3790 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3FSINFO); 3791 nfsm_srvpostop_attr(getret, &at); 3792 nfsm_build(sip, struct nfsv3_fsinfo *, NFSX_V3FSINFO); 3793 3794 /* 3795 * XXX 3796 * There should be file system VFS OP(s) to get this information. 3797 * For now, assume ufs. 3798 */ 3799 if (slp->ns_so->so_type == SOCK_DGRAM) 3800 pref = NFS_MAXDGRAMDATA; 3801 else 3802 pref = NFS_MAXDATA; 3803 sip->fs_rtmax = txdr_unsigned(NFS_MAXDATA); 3804 sip->fs_rtpref = txdr_unsigned(pref); 3805 sip->fs_rtmult = txdr_unsigned(NFS_FABLKSIZE); 3806 sip->fs_wtmax = txdr_unsigned(NFS_MAXDATA); 3807 sip->fs_wtpref = txdr_unsigned(pref); 3808 sip->fs_wtmult = txdr_unsigned(NFS_FABLKSIZE); 3809 sip->fs_dtpref = txdr_unsigned(pref); 3810 txdr_hyper(maxfsize, &sip->fs_maxfilesize); 3811 sip->fs_timedelta.nfsv3_sec = 0; 3812 sip->fs_timedelta.nfsv3_nsec = txdr_unsigned(1); 3813 sip->fs_properties = txdr_unsigned(NFSV3FSINFO_LINK | 3814 NFSV3FSINFO_SYMLINK | NFSV3FSINFO_HOMOGENEOUS | 3815 NFSV3FSINFO_CANSETTIME); 3816 nfsmout: 3817 if (vp) 3818 vput(vp); 3819 return(error); 3820 } 3821 3822 /* 3823 * nfs pathconf service 3824 */ 3825 int 3826 nfsrv_pathconf(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3827 struct thread *td, struct mbuf **mrq) 3828 { 3829 struct mbuf *mrep = nfsd->nd_mrep, *md = nfsd->nd_md; 3830 struct sockaddr *nam = nfsd->nd_nam; 3831 caddr_t dpos = nfsd->nd_dpos; 3832 struct ucred *cred = &nfsd->nd_cr; 3833 u_int32_t *tl; 3834 struct nfsv3_pathconf *pc; 3835 int32_t t1; 3836 caddr_t bpos; 3837 int error = 0, rdonly, cache, getret = 1; 3838 register_t linkmax, namemax, chownres, notrunc; 3839 char *cp2; 3840 struct mbuf *mb, *mb2, *mreq; 3841 struct vnode *vp = NULL; 3842 struct vattr at; 3843 nfsfh_t nfh; 3844 fhandle_t *fhp; 3845 u_quad_t frev; 3846 3847 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3848 #ifndef nolint 3849 cache = 0; 3850 #endif 3851 fhp = &nfh.fh_generic; 3852 nfsm_srvmtofh(fhp); 3853 error = nfsrv_fhtovp(fhp, 1, &vp, cred, slp, nam, 3854 &rdonly, (nfsd->nd_flag & ND_KERBAUTH), TRUE); 3855 if (error) { 3856 nfsm_reply(NFSX_UNSIGNED); 3857 nfsm_srvpostop_attr(getret, &at); 3858 error = 0; 3859 goto nfsmout; 3860 } 3861 error = VOP_PATHCONF(vp, _PC_LINK_MAX, &linkmax); 3862 if (!error) 3863 error = VOP_PATHCONF(vp, _PC_NAME_MAX, &namemax); 3864 if (!error) 3865 error = VOP_PATHCONF(vp, _PC_CHOWN_RESTRICTED, &chownres); 3866 if (!error) 3867 error = VOP_PATHCONF(vp, _PC_NO_TRUNC, ¬runc); 3868 getret = VOP_GETATTR(vp, &at, td); 3869 vput(vp); 3870 vp = NULL; 3871 nfsm_reply(NFSX_V3POSTOPATTR + NFSX_V3PATHCONF); 3872 nfsm_srvpostop_attr(getret, &at); 3873 if (error) { 3874 error = 0; 3875 goto nfsmout; 3876 } 3877 nfsm_build(pc, struct nfsv3_pathconf *, NFSX_V3PATHCONF); 3878 3879 pc->pc_linkmax = txdr_unsigned(linkmax); 3880 pc->pc_namemax = txdr_unsigned(namemax); 3881 pc->pc_notrunc = txdr_unsigned(notrunc); 3882 pc->pc_chownrestricted = txdr_unsigned(chownres); 3883 3884 /* 3885 * These should probably be supported by VOP_PATHCONF(), but 3886 * until msdosfs is exportable (why would you want to?), the 3887 * Unix defaults should be ok. 3888 */ 3889 pc->pc_caseinsensitive = nfs_false; 3890 pc->pc_casepreserving = nfs_true; 3891 nfsmout: 3892 if (vp) 3893 vput(vp); 3894 return(error); 3895 } 3896 3897 /* 3898 * Null operation, used by clients to ping server 3899 */ 3900 /* ARGSUSED */ 3901 int 3902 nfsrv_null(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3903 struct thread *td, struct mbuf **mrq) 3904 { 3905 struct mbuf *mrep = nfsd->nd_mrep; 3906 caddr_t bpos; 3907 int error = NFSERR_RETVOID, cache; 3908 struct mbuf *mb, *mreq; 3909 u_quad_t frev; 3910 3911 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3912 #ifndef nolint 3913 cache = 0; 3914 #endif 3915 nfsm_reply(0); 3916 nfsm_srvdone; 3917 } 3918 3919 /* 3920 * No operation, used for obsolete procedures 3921 */ 3922 /* ARGSUSED */ 3923 int 3924 nfsrv_noop(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, 3925 struct thread *td, struct mbuf **mrq) 3926 { 3927 struct mbuf *mrep = nfsd->nd_mrep; 3928 caddr_t bpos; 3929 int error, cache; 3930 struct mbuf *mb, *mreq; 3931 u_quad_t frev; 3932 3933 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3934 #ifndef nolint 3935 cache = 0; 3936 #endif 3937 if (nfsd->nd_repstat) 3938 error = nfsd->nd_repstat; 3939 else 3940 error = EPROCUNAVAIL; 3941 nfsm_reply(0); 3942 error = 0; 3943 nfsm_srvdone; 3944 } 3945 3946 /* 3947 * Perform access checking for vnodes obtained from file handles that would 3948 * refer to files already opened by a Unix client. You cannot just use 3949 * vn_writechk() and VOP_ACCESS() for two reasons. 3950 * 1 - You must check for exported rdonly as well as MNT_RDONLY for the write case 3951 * 2 - The owner is to be given access irrespective of mode bits for some 3952 * operations, so that processes that chmod after opening a file don't 3953 * break. I don't like this because it opens a security hole, but since 3954 * the nfs server opens a security hole the size of a barn door anyhow, 3955 * what the heck. 3956 * 3957 * The exception to rule 2 is EPERM. If a file is IMMUTABLE, VOP_ACCESS() 3958 * will return EPERM instead of EACCESS. EPERM is always an error. 3959 */ 3960 static int 3961 nfsrv_access(struct vnode *vp, int flags, struct ucred *cred, 3962 int rdonly, struct thread *td, int override) 3963 { 3964 struct vattr vattr; 3965 int error; 3966 3967 nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); 3968 if (flags & VWRITE) { 3969 /* Just vn_writechk() changed to check rdonly */ 3970 /* 3971 * Disallow write attempts on read-only file systems; 3972 * unless the file is a socket or a block or character 3973 * device resident on the file system. 3974 */ 3975 if (rdonly || (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3976 switch (vp->v_type) { 3977 case VREG: 3978 case VDIR: 3979 case VLNK: 3980 return (EROFS); 3981 default: 3982 break; 3983 } 3984 } 3985 /* 3986 * If there's shared text associated with 3987 * the inode, we can't allow writing. 3988 */ 3989 if (vp->v_flag & VTEXT) 3990 return (ETXTBSY); 3991 } 3992 error = VOP_GETATTR(vp, &vattr, td); 3993 if (error) 3994 return (error); 3995 error = VOP_ACCESS(vp, flags, cred, td); 3996 /* 3997 * Allow certain operations for the owner (reads and writes 3998 * on files that are already open). 3999 */ 4000 if (override && error == EACCES && cred->cr_uid == vattr.va_uid) 4001 error = 0; 4002 return error; 4003 } 4004 #endif /* NFS_NOSERVER */ 4005 4006