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