|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1989, 1993, 1995 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * ! 27: * This code is derived from software contributed to Berkeley by ! 28: * Rick Macklem at The University of Guelph. ! 29: * ! 30: * Redistribution and use in source and binary forms, with or without ! 31: * modification, are permitted provided that the following conditions ! 32: * are met: ! 33: * 1. Redistributions of source code must retain the above copyright ! 34: * notice, this list of conditions and the following disclaimer. ! 35: * 2. Redistributions in binary form must reproduce the above copyright ! 36: * notice, this list of conditions and the following disclaimer in the ! 37: * documentation and/or other materials provided with the distribution. ! 38: * 3. All advertising materials mentioning features or use of this software ! 39: * must display the following acknowledgement: ! 40: * This product includes software developed by the University of ! 41: * California, Berkeley and its contributors. ! 42: * 4. Neither the name of the University nor the names of its contributors ! 43: * may be used to endorse or promote products derived from this software ! 44: * without specific prior written permission. ! 45: * ! 46: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 47: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 48: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 49: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 50: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 51: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 52: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 53: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 54: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 55: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 56: * SUCH DAMAGE. ! 57: * ! 58: * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 ! 59: * FreeBSD-Id: nfs_vfsops.c,v 1.52 1997/11/12 05:42:21 julian Exp $ ! 60: * ! 61: * History: ! 62: * ! 63: * ! 64: * 23-May-97 Umesh Vaishampayan ([email protected]) ! 65: * Added the ability to mount "/private" separately. ! 66: * Fixed bug which caused incorrect reporting of "mounted on" ! 67: * directory name in case of nfs root. ! 68: */ ! 69: ! 70: #include <sys/param.h> ! 71: #include <sys/systm.h> ! 72: #include <sys/conf.h> ! 73: #include <sys/ioctl.h> ! 74: #include <sys/signal.h> ! 75: #include <sys/proc.h> ! 76: #include <sys/namei.h> ! 77: #include <sys/vnode.h> ! 78: #include <sys/malloc.h> ! 79: #include <sys/kernel.h> ! 80: #include <sys/sysctl.h> ! 81: #include <sys/mount.h> ! 82: #include <sys/buf.h> ! 83: #include <sys/mbuf.h> ! 84: #include <sys/socket.h> ! 85: #include <sys/socketvar.h> ! 86: ! 87: #include <sys/vm.h> ! 88: #include <sys/vmparam.h> ! 89: ! 90: #if !defined(NO_MOUNT_PRIVATE) ! 91: #include <sys/filedesc.h> ! 92: #endif /* NO_MOUNT_PRIVATE */ ! 93: ! 94: #include <net/if.h> ! 95: #include <net/route.h> ! 96: #include <netinet/in.h> ! 97: ! 98: #include <nfs/rpcv2.h> ! 99: #include <nfs/nfsproto.h> ! 100: #include <nfs/nfs.h> ! 101: #include <nfs/nfsnode.h> ! 102: #include <nfs/nfsmount.h> ! 103: #include <nfs/xdr_subs.h> ! 104: #include <nfs/nfsm_subs.h> ! 105: #include <nfs/nfsdiskless.h> ! 106: #include <nfs/nqnfs.h> ! 107: ! 108: extern int nfs_mountroot __P((void)); ! 109: ! 110: extern int nfs_ticks; ! 111: ! 112: struct nfsstats nfsstats; ! 113: static int nfs_sysctl(int *, u_int, void *, size_t *, void *, size_t, ! 114: struct proc *); ! 115: /* XXX CSM 11/25/97 Upgrade sysctl.h someday */ ! 116: #ifdef notyet ! 117: SYSCTL_NODE(_vfs, MOUNT_NFS, nfs, CTLFLAG_RW, 0, "NFS filesystem"); ! 118: SYSCTL_STRUCT(_vfs_nfs, NFS_NFSSTATS, nfsstats, CTLFLAG_RD, ! 119: &nfsstats, nfsstats, ""); ! 120: #endif ! 121: #if DIAGNOSTIC ! 122: int nfs_debug; ! 123: /* XXX CSM 11/25/97 Upgrade sysctl.h someday */ ! 124: #ifdef notyet ! 125: SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); ! 126: #endif ! 127: #endif ! 128: ! 129: static int nfs_iosize __P((struct nfsmount *nmp)); ! 130: static int mountnfs __P((struct nfs_args *,struct mount *, ! 131: struct mbuf *,char *,char *,struct vnode **)); ! 132: static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, ! 133: struct nameidata *ndp, struct proc *p)); ! 134: static int nfs_start __P(( struct mount *mp, int flags, ! 135: struct proc *p)); ! 136: static int nfs_unmount __P(( struct mount *mp, int mntflags, ! 137: struct proc *p)); ! 138: static int nfs_root __P(( struct mount *mp, struct vnode **vpp)); ! 139: static int nfs_quotactl __P(( struct mount *mp, int cmds, uid_t uid, ! 140: caddr_t arg, struct proc *p)); ! 141: static int nfs_statfs __P(( struct mount *mp, struct statfs *sbp, ! 142: struct proc *p)); ! 143: static int nfs_sync __P(( struct mount *mp, int waitfor, ! 144: struct ucred *cred, struct proc *p)); ! 145: static int nfs_vptofh __P(( struct vnode *vp, struct fid *fhp)); ! 146: static int nfs_fhtovp __P((struct mount *mp, struct fid *fhp, ! 147: struct mbuf *nam, struct vnode **vpp, ! 148: int *exflagsp, struct ucred **credanonp)); ! 149: static int nfs_vget __P((struct mount *, ino_t, struct vnode **)); ! 150: ! 151: ! 152: /* ! 153: * nfs vfs operations. ! 154: */ ! 155: struct vfsops nfs_vfsops = { ! 156: nfs_mount, ! 157: nfs_start, ! 158: nfs_unmount, ! 159: nfs_root, ! 160: nfs_quotactl, ! 161: nfs_statfs, ! 162: nfs_sync, ! 163: nfs_vget, ! 164: nfs_fhtovp, ! 165: nfs_vptofh, ! 166: nfs_init, ! 167: nfs_sysctl ! 168: }; ! 169: /* XXX CSM 11/25/97 Mysterious kernel.h ld crud */ ! 170: #ifdef notyet ! 171: VFS_SET(nfs_vfsops, nfs, MOUNT_NFS, VFCF_NETWORK); ! 172: #endif ! 173: ! 174: /* ! 175: * This structure must be filled in by a primary bootstrap or bootstrap ! 176: * server for a diskless/dataless machine. It is initialized below just ! 177: * to ensure that it is allocated to initialized data (.data not .bss). ! 178: */ ! 179: struct nfs_diskless nfs_diskless = { 0 }; ! 180: int nfs_diskless_valid = 0; ! 181: ! 182: /* XXX CSM 11/25/97 Upgrade sysctl.h someday */ ! 183: #ifdef notyet ! 184: SYSCTL_INT(_vfs_nfs, OID_AUTO, diskless_valid, CTLFLAG_RD, ! 185: &nfs_diskless_valid, 0, ""); ! 186: ! 187: SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_rootpath, CTLFLAG_RD, ! 188: nfs_diskless.root_hostnam, 0, ""); ! 189: ! 190: SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_rootaddr, CTLFLAG_RD, ! 191: &nfs_diskless.root_saddr, sizeof nfs_diskless.root_saddr, ! 192: "%Ssockaddr_in", ""); ! 193: ! 194: SYSCTL_STRING(_vfs_nfs, OID_AUTO, diskless_swappath, CTLFLAG_RD, ! 195: nfs_diskless.swap_hostnam, 0, ""); ! 196: ! 197: SYSCTL_OPAQUE(_vfs_nfs, OID_AUTO, diskless_swapaddr, CTLFLAG_RD, ! 198: &nfs_diskless.swap_saddr, sizeof nfs_diskless.swap_saddr, ! 199: "%Ssockaddr_in",""); ! 200: #endif ! 201: ! 202: ! 203: void nfsargs_ntoh __P((struct nfs_args *)); ! 204: static int ! 205: nfs_mount_diskless __P((struct nfs_dlmount *, char *, int, struct vnode **, ! 206: struct mount **)); ! 207: #if !defined(NO_MOUNT_PRIVATE) ! 208: static int ! 209: nfs_mount_diskless_private __P((struct nfs_dlmount *, char *, int, ! 210: struct vnode **, struct mount **)); ! 211: #endif /* NO_MOUNT_PRIVATE */ ! 212: static void nfs_convert_oargs __P((struct nfs_args *args, ! 213: struct onfs_args *oargs)); ! 214: ! 215: static int nfs_iosize(nmp) ! 216: struct nfsmount* nmp; ! 217: { ! 218: int iosize; ! 219: ! 220: /* ! 221: * Calculate the size used for io buffers. Use the larger ! 222: * of the two sizes to minimise nfs requests but make sure ! 223: * that it is at least one VM page to avoid wasting buffer ! 224: * space. ! 225: */ ! 226: iosize = max(nmp->nm_rsize, nmp->nm_wsize); ! 227: if (iosize < PAGE_SIZE) iosize = PAGE_SIZE; ! 228: return iosize; ! 229: } ! 230: ! 231: static void nfs_convert_oargs(args,oargs) ! 232: struct nfs_args *args; ! 233: struct onfs_args *oargs; ! 234: { ! 235: args->version = NFS_ARGSVERSION; ! 236: args->addr = oargs->addr; ! 237: args->addrlen = oargs->addrlen; ! 238: args->sotype = oargs->sotype; ! 239: args->proto = oargs->proto; ! 240: args->fh = oargs->fh; ! 241: args->fhsize = oargs->fhsize; ! 242: args->flags = oargs->flags; ! 243: args->wsize = oargs->wsize; ! 244: args->rsize = oargs->rsize; ! 245: args->readdirsize = oargs->readdirsize; ! 246: args->timeo = oargs->timeo; ! 247: args->retrans = oargs->retrans; ! 248: args->maxgrouplist = oargs->maxgrouplist; ! 249: args->readahead = oargs->readahead; ! 250: args->leaseterm = oargs->leaseterm; ! 251: args->deadthresh = oargs->deadthresh; ! 252: args->hostname = oargs->hostname; ! 253: } ! 254: ! 255: /* ! 256: * nfs statfs call ! 257: */ ! 258: int ! 259: nfs_statfs(mp, sbp, p) ! 260: struct mount *mp; ! 261: register struct statfs *sbp; ! 262: struct proc *p; ! 263: { ! 264: register struct vnode *vp; ! 265: register struct nfs_statfs *sfp; ! 266: register caddr_t cp; ! 267: register u_long *tl; ! 268: register long t1, t2; ! 269: caddr_t bpos, dpos, cp2; ! 270: struct nfsmount *nmp = VFSTONFS(mp); ! 271: int error = 0, v3 = (nmp->nm_flag & NFSMNT_NFSV3), retattr; ! 272: struct mbuf *mreq, *mrep, *md, *mb, *mb2; ! 273: struct ucred *cred; ! 274: struct nfsnode *np; ! 275: u_quad_t tquad; ! 276: extern int nfs_mount_type; ! 277: ! 278: #ifndef nolint ! 279: sfp = (struct nfs_statfs *)0; ! 280: #endif ! 281: error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); ! 282: if (error) ! 283: return (error); ! 284: vp = NFSTOV(np); ! 285: cred = crget(); ! 286: cred->cr_ngroups = 1; ! 287: if (v3 && (nmp->nm_flag & NFSMNT_GOTFSINFO) == 0) ! 288: (void)nfs_fsinfo(nmp, vp, cred, p); ! 289: nfsstats.rpccnt[NFSPROC_FSSTAT]++; ! 290: nfsm_reqhead(vp, NFSPROC_FSSTAT, NFSX_FH(v3)); ! 291: nfsm_fhtom(vp, v3); ! 292: nfsm_request(vp, NFSPROC_FSSTAT, p, cred); ! 293: if (v3) ! 294: nfsm_postop_attr(vp, retattr); ! 295: if (!error) { ! 296: nfsm_dissect(sfp, struct nfs_statfs *, NFSX_STATFS(v3)); ! 297: } else ! 298: goto nfsmout; ! 299: ! 300: /* XXX CSM 12/2/97 Cleanup when/if we integrate FreeBSD mount.h */ ! 301: #ifdef notyet ! 302: sbp->f_type = MOUNT_NFS; ! 303: #else ! 304: sbp->f_type = nfs_mount_type; ! 305: #endif ! 306: sbp->f_flags = nmp->nm_flag; ! 307: sbp->f_iosize = nfs_iosize(nmp); ! 308: if (v3) { ! 309: sbp->f_bsize = NFS_FABLKSIZE; ! 310: fxdr_hyper(&sfp->sf_tbytes, &tquad); ! 311: sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); ! 312: fxdr_hyper(&sfp->sf_fbytes, &tquad); ! 313: sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); ! 314: fxdr_hyper(&sfp->sf_abytes, &tquad); ! 315: sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); ! 316: sbp->f_files = (fxdr_unsigned(long, sfp->sf_tfiles.nfsuquad[1]) ! 317: & 0x7fffffff); ! 318: sbp->f_ffree = (fxdr_unsigned(long, sfp->sf_ffiles.nfsuquad[1]) ! 319: & 0x7fffffff); ! 320: } else { ! 321: sbp->f_bsize = fxdr_unsigned(long, sfp->sf_bsize); ! 322: sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); ! 323: sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); ! 324: sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); ! 325: sbp->f_files = 0; ! 326: sbp->f_ffree = 0; ! 327: } ! 328: if (sbp != &mp->mnt_stat) { ! 329: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); ! 330: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); ! 331: } ! 332: nfsm_reqdone; ! 333: vput(vp); ! 334: crfree(cred); ! 335: return (error); ! 336: } ! 337: ! 338: /* ! 339: * nfs version 3 fsinfo rpc call ! 340: */ ! 341: int ! 342: nfs_fsinfo(nmp, vp, cred, p) ! 343: register struct nfsmount *nmp; ! 344: register struct vnode *vp; ! 345: struct ucred *cred; ! 346: struct proc *p; ! 347: { ! 348: register struct nfsv3_fsinfo *fsp; ! 349: register caddr_t cp; ! 350: register long t1, t2; ! 351: register u_long *tl, pref, max; ! 352: caddr_t bpos, dpos, cp2; ! 353: int error = 0, retattr; ! 354: struct mbuf *mreq, *mrep, *md, *mb, *mb2; ! 355: ! 356: nfsstats.rpccnt[NFSPROC_FSINFO]++; ! 357: nfsm_reqhead(vp, NFSPROC_FSINFO, NFSX_FH(1)); ! 358: nfsm_fhtom(vp, 1); ! 359: nfsm_request(vp, NFSPROC_FSINFO, p, cred); ! 360: nfsm_postop_attr(vp, retattr); ! 361: if (!error) { ! 362: nfsm_dissect(fsp, struct nfsv3_fsinfo *, NFSX_V3FSINFO); ! 363: pref = fxdr_unsigned(u_long, fsp->fs_wtpref); ! 364: if (pref < nmp->nm_wsize) ! 365: nmp->nm_wsize = (pref + NFS_FABLKSIZE - 1) & ! 366: ~(NFS_FABLKSIZE - 1); ! 367: max = fxdr_unsigned(u_long, fsp->fs_wtmax); ! 368: if (max < nmp->nm_wsize) { ! 369: nmp->nm_wsize = max & ~(NFS_FABLKSIZE - 1); ! 370: if (nmp->nm_wsize == 0) ! 371: nmp->nm_wsize = max; ! 372: } ! 373: pref = fxdr_unsigned(u_long, fsp->fs_rtpref); ! 374: if (pref < nmp->nm_rsize) ! 375: nmp->nm_rsize = (pref + NFS_FABLKSIZE - 1) & ! 376: ~(NFS_FABLKSIZE - 1); ! 377: max = fxdr_unsigned(u_long, fsp->fs_rtmax); ! 378: if (max < nmp->nm_rsize) { ! 379: nmp->nm_rsize = max & ~(NFS_FABLKSIZE - 1); ! 380: if (nmp->nm_rsize == 0) ! 381: nmp->nm_rsize = max; ! 382: } ! 383: pref = fxdr_unsigned(u_long, fsp->fs_dtpref); ! 384: if (pref < nmp->nm_readdirsize) ! 385: nmp->nm_readdirsize = pref; ! 386: if (max < nmp->nm_readdirsize) { ! 387: nmp->nm_readdirsize = max; ! 388: } ! 389: nmp->nm_flag |= NFSMNT_GOTFSINFO; ! 390: } ! 391: nfsm_reqdone; ! 392: return (error); ! 393: } ! 394: ! 395: /* ! 396: * Mount a remote root fs via. nfs. This depends on the info in the ! 397: * nfs_diskless structure that has been filled in properly by some primary ! 398: * bootstrap. ! 399: * It goes something like this: ! 400: * - do enough of "ifconfig" by calling ifioctl() so that the system ! 401: * can talk to the server ! 402: * - If nfs_diskless.mygateway is filled in, use that address as ! 403: * a default gateway. ! 404: * - hand craft the swap nfs vnode hanging off a fake mount point ! 405: * if swdevt[0].sw_dev == NODEV ! 406: * - build the rootfs mount point and call mountnfs() to do the rest. ! 407: */ ! 408: int ! 409: nfs_mountroot() ! 410: { ! 411: struct nfs_diskless nd; ! 412: struct vattr attr; ! 413: struct mount *mp; ! 414: struct vnode *vp; ! 415: struct proc *procp; ! 416: long n; ! 417: int error; ! 418: #if !defined(NO_MOUNT_PRIVATE) ! 419: struct mount *mppriv; ! 420: struct vnode *vppriv; ! 421: #endif /* NO_MOUNT_PRIVATE */ ! 422: ! 423: procp = current_proc(); /* XXX */ ! 424: ! 425: /* ! 426: * Call nfs_boot_init() to fill in the nfs_diskless struct. ! 427: * Side effect: Finds and configures a network interface. ! 428: */ ! 429: bzero((caddr_t) &nd, sizeof(nd)); ! 430: nfs_boot_init(&nd, procp); ! 431: ! 432: /* ! 433: * Create the root mount point. ! 434: */ ! 435: #if !defined(NO_MOUNT_PRIVATE) ! 436: if ((error = nfs_mount_diskless(&nd.nd_root, "/", MNT_RDONLY, &vp, &mp))) { ! 437: #else ! 438: if (error = nfs_mount_diskless(&nd.nd_root, "/", NULL, &vp, &mp)) { ! 439: #endif /* NO_MOUNT_PRIVATE */ ! 440: return(error); ! 441: } ! 442: printf("root on %s\n", (char *)&nd.nd_root.ndm_host); ! 443: ! 444: simple_lock(&mountlist_slock); ! 445: CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); ! 446: simple_unlock(&mountlist_slock); ! 447: vfs_unbusy(mp, procp); ! 448: rootvp = vp; ! 449: ! 450: #if !defined(NO_MOUNT_PRIVATE) ! 451: if (nd.nd_private.ndm_saddr.sin_addr.s_addr) { ! 452: error = nfs_mount_diskless_private(&nd.nd_private, "/private", ! 453: NULL, &vppriv, &mppriv); ! 454: if (error) ! 455: return(error); ! 456: printf("private on %s\n", (char *)&nd.nd_private.ndm_host); ! 457: ! 458: simple_lock(&mountlist_slock); ! 459: CIRCLEQ_INSERT_TAIL(&mountlist, mppriv, mnt_list); ! 460: simple_unlock(&mountlist_slock); ! 461: vfs_unbusy(mppriv, procp); ! 462: } ! 463: ! 464: #endif /* NO_MOUNT_PRIVATE */ ! 465: ! 466: /* Get root attributes (for the time). */ ! 467: error = VOP_GETATTR(vp, &attr, procp->p_ucred, procp); ! 468: if (error) panic("nfs_mountroot: getattr for root"); ! 469: n = attr.va_mtime.tv_sec; ! 470: inittodr(n); ! 471: return (0); ! 472: } ! 473: ! 474: /* ! 475: * Internal version of mount system call for diskless setup. ! 476: */ ! 477: static int ! 478: nfs_mount_diskless(ndmntp, mntname, mntflag, vpp, mpp) ! 479: struct nfs_dlmount *ndmntp; ! 480: char *mntname; ! 481: int mntflag; ! 482: struct vnode **vpp; ! 483: struct mount **mpp; ! 484: { ! 485: struct nfs_args args; ! 486: struct mount *mp; ! 487: struct mbuf *m; ! 488: int error; ! 489: struct proc *procp; ! 490: ! 491: procp = current_proc(); /* XXX */ ! 492: ! 493: if ((error = vfs_rootmountalloc("nfs", ndmntp->ndm_host, &mp))) { ! 494: printf("nfs_mountroot: NFS not configured"); ! 495: return (error); ! 496: } ! 497: mp->mnt_flag = mntflag; ! 498: ! 499: /* Initialize mount args. */ ! 500: bzero((caddr_t) &args, sizeof(args)); ! 501: args.addr = (struct sockaddr *)&ndmntp->ndm_saddr; ! 502: args.addrlen = args.addr->sa_len; ! 503: args.sotype = SOCK_DGRAM; ! 504: args.fh = ndmntp->ndm_fh; ! 505: args.fhsize = NFSX_V2FH; ! 506: args.hostname = ndmntp->ndm_host; ! 507: args.flags = NFSMNT_RESVPORT; ! 508: ! 509: MGET(m, M_DONTWAIT, MT_SONAME); ! 510: bcopy((caddr_t)args.addr, mtod(m, caddr_t), ! 511: (m->m_len = args.addr->sa_len)); ! 512: if ((error = mountnfs(&args, mp, m, mntname, args.hostname, vpp))) { ! 513: printf("nfs_mountroot: mount %s failed: %d", mntname, error); ! 514: mp->mnt_vfc->vfc_refcount--; ! 515: vfs_unbusy(mp, procp); ! 516: _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); ! 517: return (error); ! 518: } ! 519: #if 0 /* Causes incorrect reporting of "mounted on" */ ! 520: (void) copystr(args.hostname, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); ! 521: #endif /* 0 */ ! 522: *mpp = mp; ! 523: return (0); ! 524: } ! 525: ! 526: #if !defined(NO_MOUNT_PRIVATE) ! 527: /* ! 528: * Internal version of mount system call to mount "/private" ! 529: * separately in diskless setup ! 530: */ ! 531: static int ! 532: nfs_mount_diskless_private(ndmntp, mntname, mntflag, vpp, mpp) ! 533: struct nfs_dlmount *ndmntp; ! 534: char *mntname; ! 535: int mntflag; ! 536: struct vnode **vpp; ! 537: struct mount **mpp; ! 538: { ! 539: struct nfs_args args; ! 540: struct mount *mp; ! 541: struct mbuf *m; ! 542: int error; ! 543: struct proc *procp; ! 544: struct vfsconf *vfsp; ! 545: struct nameidata nd; ! 546: struct vnode *vp; ! 547: ! 548: procp = current_proc(); /* XXX */ ! 549: ! 550: { ! 551: /* ! 552: * mimic main()!. Temporarily set up rootvnode and other stuff so ! 553: * that namei works. Need to undo this because main() does it, too ! 554: */ ! 555: struct filedesc *fdp; /* pointer to file descriptor state */ ! 556: fdp = procp->p_fd; ! 557: mountlist.cqh_first->mnt_flag |= MNT_ROOTFS; ! 558: ! 559: /* Get the vnode for '/'. Set fdp->fd_cdir to reference it. */ ! 560: if (VFS_ROOT(mountlist.cqh_first, &rootvnode)) ! 561: panic("cannot find root vnode"); ! 562: fdp->fd_cdir = rootvnode; ! 563: VREF(fdp->fd_cdir); ! 564: VOP_UNLOCK(rootvnode, 0, procp); ! 565: fdp->fd_rdir = NULL; ! 566: } ! 567: ! 568: /* ! 569: * Get vnode to be covered ! 570: */ ! 571: NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, ! 572: mntname, procp); ! 573: if ((error = namei(&nd))) { ! 574: printf("nfs_mountroot: private namei failed!"); ! 575: return (error); ! 576: } ! 577: { ! 578: /* undo VREF in mimic main()! */ ! 579: vrele(rootvnode); ! 580: } ! 581: vp = nd.ni_vp; ! 582: if ((error = vinvalbuf(vp, V_SAVE, procp->p_ucred, procp, 0, 0))) { ! 583: vput(vp); ! 584: return (error); ! 585: } ! 586: if (vp->v_type != VDIR) { ! 587: vput(vp); ! 588: return (ENOTDIR); ! 589: } ! 590: for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) ! 591: if (!strcmp(vfsp->vfc_name, "nfs")) ! 592: break; ! 593: if (vfsp == NULL) { ! 594: printf("nfs_mountroot: private NFS not configured"); ! 595: vput(vp); ! 596: return (ENODEV); ! 597: } ! 598: if (vp->v_mountedhere != NULL) { ! 599: vput(vp); ! 600: return (EBUSY); ! 601: } ! 602: ! 603: /* ! 604: * Allocate and initialize the filesystem. ! 605: */ ! 606: mp = _MALLOC_ZONE((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK); ! 607: lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); ! 608: (void)vfs_busy(mp, LK_NOWAIT, 0, procp); ! 609: LIST_INIT(&mp->mnt_vnodelist); ! 610: mp->mnt_op = vfsp->vfc_vfsops; ! 611: mp->mnt_vfc = vfsp; ! 612: vfsp->vfc_refcount++; ! 613: mp->mnt_stat.f_type = vfsp->vfc_typenum; ! 614: mp->mnt_flag = mntflag; ! 615: mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; ! 616: strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); ! 617: vp->v_mountedhere = mp; ! 618: mp->mnt_vnodecovered = vp; ! 619: mp->mnt_stat.f_owner = procp->p_ucred->cr_uid; ! 620: (void) copystr(mntname, mp->mnt_stat.f_mntonname, MNAMELEN - 1, 0); ! 621: (void) copystr(ndmntp->ndm_host, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, 0); ! 622: ! 623: /* Initialize mount args. */ ! 624: bzero((caddr_t) &args, sizeof(args)); ! 625: args.addr = (struct sockaddr *)&ndmntp->ndm_saddr; ! 626: args.addrlen = args.addr->sa_len; ! 627: args.sotype = SOCK_DGRAM; ! 628: args.fh = ndmntp->ndm_fh; ! 629: args.fhsize = NFSX_V2FH; ! 630: args.hostname = ndmntp->ndm_host; ! 631: args.flags = NFSMNT_RESVPORT; ! 632: ! 633: MGET(m, M_DONTWAIT, MT_SONAME); ! 634: bcopy((caddr_t)args.addr, mtod(m, caddr_t), ! 635: (m->m_len = args.addr->sa_len)); ! 636: if ((error = mountnfs(&args, mp, m, mntname, args.hostname, &vp))) { ! 637: printf("nfs_mountroot: mount %s failed: %d", mntname, error); ! 638: mp->mnt_vfc->vfc_refcount--; ! 639: vfs_unbusy(mp, procp); ! 640: _FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); ! 641: return (error); ! 642: } ! 643: ! 644: *mpp = mp; ! 645: *vpp = vp; ! 646: return (0); ! 647: } ! 648: #endif /* NO_MOUNT_PRIVATE */ ! 649: ! 650: /* ! 651: * VFS Operations. ! 652: * ! 653: * mount system call ! 654: * It seems a bit dumb to copyinstr() the host and path here and then ! 655: * bcopy() them in mountnfs(), but I wanted to detect errors before ! 656: * doing the sockargs() call because sockargs() allocates an mbuf and ! 657: * an error after that means that I have to release the mbuf. ! 658: */ ! 659: /* ARGSUSED */ ! 660: static int ! 661: nfs_mount(mp, path, data, ndp, p) ! 662: struct mount *mp; ! 663: char *path; ! 664: caddr_t data; ! 665: struct nameidata *ndp; ! 666: struct proc *p; ! 667: { ! 668: int error; ! 669: struct nfs_args args; ! 670: struct mbuf *nam; ! 671: struct vnode *vp; ! 672: char pth[MNAMELEN], hst[MNAMELEN]; ! 673: u_int len; ! 674: u_char nfh[NFSX_V3FHMAX]; ! 675: ! 676: error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args)); ! 677: if (error) ! 678: return (error); ! 679: if (args.version != NFS_ARGSVERSION) { ! 680: #ifndef NO_COMPAT_PRELITE2 ! 681: /* ! 682: * If the argument version is unknown, then assume the ! 683: * caller is a pre-lite2 4.4BSD client and convert its ! 684: * arguments. ! 685: */ ! 686: struct onfs_args oargs; ! 687: error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args)); ! 688: if (error) ! 689: return (error); ! 690: nfs_convert_oargs(&args,&oargs); ! 691: #else /* NO_COMPAT_PRELITE2 */ ! 692: return (EPROGMISMATCH); ! 693: #endif /* !NO_COMPAT_PRELITE2 */ ! 694: } ! 695: if (args.fhsize > NFSX_V3FHMAX) ! 696: return (EINVAL); ! 697: error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); ! 698: if (error) ! 699: return (error); ! 700: error = copyinstr(path, pth, MNAMELEN-1, &len); ! 701: if (error) ! 702: return (error); ! 703: bzero(&pth[len], MNAMELEN - len); ! 704: error = copyinstr(args.hostname, hst, MNAMELEN-1, &len); ! 705: if (error) ! 706: return (error); ! 707: bzero(&hst[len], MNAMELEN - len); ! 708: /* sockargs() call must be after above copyin() calls */ ! 709: error = sockargs(&nam, (caddr_t)args.addr, args.addrlen, MT_SONAME); ! 710: if (error) ! 711: return (error); ! 712: args.fh = nfh; ! 713: error = mountnfs(&args, mp, nam, pth, hst, &vp); ! 714: return (error); ! 715: } ! 716: ! 717: /* ! 718: * Common code for mount and mountroot ! 719: */ ! 720: static int ! 721: mountnfs(argp, mp, nam, pth, hst, vpp) ! 722: register struct nfs_args *argp; ! 723: register struct mount *mp; ! 724: struct mbuf *nam; ! 725: char *pth, *hst; ! 726: struct vnode **vpp; ! 727: { ! 728: register struct nfsmount *nmp; ! 729: struct nfsnode *np; ! 730: int error, maxio; ! 731: struct vattr attrs; ! 732: struct proc *curproc; ! 733: ! 734: if (mp->mnt_flag & MNT_UPDATE) { ! 735: nmp = VFSTONFS(mp); ! 736: /* update paths, file handles, etc, here XXX */ ! 737: m_freem(nam); ! 738: return (0); ! 739: } else { ! 740: MALLOC_ZONE(nmp, struct nfsmount *, ! 741: sizeof (struct nfsmount), M_NFSMNT, M_WAITOK); ! 742: bzero((caddr_t)nmp, sizeof (struct nfsmount)); ! 743: TAILQ_INIT(&nmp->nm_uidlruhead); ! 744: TAILQ_INIT(&nmp->nm_bufq); ! 745: mp->mnt_data = (qaddr_t)nmp; ! 746: } ! 747: vfs_getnewfsid(mp); ! 748: nmp->nm_mountp = mp; ! 749: nmp->nm_flag = argp->flags; ! 750: if (nmp->nm_flag & NFSMNT_NQNFS) ! 751: /* ! 752: * We have to set mnt_maxsymlink to a non-zero value so ! 753: * that COMPAT_43 routines will know that we are setting ! 754: * the d_type field in directories (and can zero it for ! 755: * unsuspecting binaries). ! 756: */ ! 757: mp->mnt_maxsymlinklen = 1; ! 758: nmp->nm_timeo = NFS_TIMEO; ! 759: nmp->nm_retry = NFS_RETRANS; ! 760: nmp->nm_wsize = NFS_WSIZE; ! 761: nmp->nm_rsize = NFS_RSIZE; ! 762: nmp->nm_readdirsize = NFS_READDIRSIZE; ! 763: nmp->nm_numgrps = NFS_MAXGRPS; ! 764: nmp->nm_readahead = NFS_DEFRAHEAD; ! 765: nmp->nm_leaseterm = NQ_DEFLEASE; ! 766: nmp->nm_deadthresh = NQ_DEADTHRESH; ! 767: CIRCLEQ_INIT(&nmp->nm_timerhead); ! 768: nmp->nm_inprog = NULLVP; ! 769: nmp->nm_fhsize = argp->fhsize; ! 770: bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize); ! 771: bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); ! 772: bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); ! 773: nmp->nm_nam = nam; ! 774: ! 775: /* ! 776: * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes ! 777: * no sense in that context. ! 778: */ ! 779: if (argp->sotype == SOCK_STREAM) ! 780: argp->flags &= ~NFSMNT_NOCONN; ! 781: ! 782: if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { ! 783: nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; ! 784: if (nmp->nm_timeo < NFS_MINTIMEO) ! 785: nmp->nm_timeo = NFS_MINTIMEO; ! 786: else if (nmp->nm_timeo > NFS_MAXTIMEO) ! 787: nmp->nm_timeo = NFS_MAXTIMEO; ! 788: } ! 789: ! 790: if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { ! 791: nmp->nm_retry = argp->retrans; ! 792: if (nmp->nm_retry > NFS_MAXREXMIT) ! 793: nmp->nm_retry = NFS_MAXREXMIT; ! 794: } ! 795: ! 796: if (argp->flags & NFSMNT_NFSV3) { ! 797: if (argp->sotype == SOCK_DGRAM) ! 798: maxio = NFS_MAXDGRAMDATA; ! 799: else ! 800: maxio = NFS_MAXDATA; ! 801: } else ! 802: maxio = NFS_V2MAXDATA; ! 803: ! 804: if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { ! 805: nmp->nm_wsize = argp->wsize; ! 806: /* Round down to multiple of blocksize */ ! 807: nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); ! 808: if (nmp->nm_wsize <= 0) ! 809: nmp->nm_wsize = NFS_FABLKSIZE; ! 810: } ! 811: if (nmp->nm_wsize > maxio) ! 812: nmp->nm_wsize = maxio; ! 813: if (nmp->nm_wsize > MAXBSIZE) ! 814: nmp->nm_wsize = MAXBSIZE; ! 815: ! 816: if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { ! 817: nmp->nm_rsize = argp->rsize; ! 818: /* Round down to multiple of blocksize */ ! 819: nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); ! 820: if (nmp->nm_rsize <= 0) ! 821: nmp->nm_rsize = NFS_FABLKSIZE; ! 822: } ! 823: if (nmp->nm_rsize > maxio) ! 824: nmp->nm_rsize = maxio; ! 825: if (nmp->nm_rsize > MAXBSIZE) ! 826: nmp->nm_rsize = MAXBSIZE; ! 827: ! 828: if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { ! 829: nmp->nm_readdirsize = argp->readdirsize; ! 830: } ! 831: if (nmp->nm_readdirsize > maxio) ! 832: nmp->nm_readdirsize = maxio; ! 833: if (nmp->nm_readdirsize > nmp->nm_rsize) ! 834: nmp->nm_readdirsize = nmp->nm_rsize; ! 835: ! 836: if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && ! 837: argp->maxgrouplist <= NFS_MAXGRPS) ! 838: nmp->nm_numgrps = argp->maxgrouplist; ! 839: if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && ! 840: argp->readahead <= NFS_MAXRAHEAD) ! 841: nmp->nm_readahead = argp->readahead; ! 842: if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && ! 843: argp->leaseterm <= NQ_MAXLEASE) ! 844: nmp->nm_leaseterm = argp->leaseterm; ! 845: if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && ! 846: argp->deadthresh <= NQ_NEVERDEAD) ! 847: nmp->nm_deadthresh = argp->deadthresh; ! 848: /* Set up the sockets and per-host congestion */ ! 849: nmp->nm_sotype = argp->sotype; ! 850: nmp->nm_soproto = argp->proto; ! 851: ! 852: /* ! 853: * For Connection based sockets (TCP,...) defer the connect until ! 854: * the first request, in case the server is not responding. ! 855: */ ! 856: if (nmp->nm_sotype == SOCK_DGRAM && ! 857: (error = nfs_connect(nmp, (struct nfsreq *)0))) ! 858: goto bad; ! 859: ! 860: /* ! 861: * This is silly, but it has to be set so that vinifod() works. ! 862: * We do not want to do an nfs_statfs() here since we can get ! 863: * stuck on a dead server and we are holding a lock on the mount ! 864: * point. ! 865: */ ! 866: mp->mnt_stat.f_iosize = nfs_iosize(nmp); ! 867: /* ! 868: * A reference count is needed on the nfsnode representing the ! 869: * remote root. If this object is not persistent, then backward ! 870: * traversals of the mount point (i.e. "..") will not work if ! 871: * the nfsnode gets flushed out of the cache. Ufs does not have ! 872: * this problem, because one can identify root inodes by their ! 873: * number == ROOTINO (2). ! 874: */ ! 875: error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); ! 876: if (error) ! 877: goto bad; ! 878: *vpp = NFSTOV(np); ! 879: ! 880: /* ! 881: * Get file attributes for the mountpoint. This has the side ! 882: * effect of filling in (*vpp)->v_type with the correct value. ! 883: */ ! 884: curproc = current_proc(); ! 885: VOP_GETATTR(*vpp, &attrs, curproc->p_ucred, curproc); ! 886: ! 887: /* ! 888: * Lose the lock but keep the ref. ! 889: */ ! 890: VOP_UNLOCK(*vpp, 0, curproc); ! 891: ! 892: return (0); ! 893: bad: ! 894: nfs_disconnect(nmp); ! 895: _FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT); ! 896: m_freem(nam); ! 897: return (error); ! 898: } ! 899: ! 900: /* ! 901: * unmount system call ! 902: */ ! 903: static int ! 904: nfs_unmount(mp, mntflags, p) ! 905: struct mount *mp; ! 906: int mntflags; ! 907: struct proc *p; ! 908: { ! 909: register struct nfsmount *nmp; ! 910: struct nfsnode *np; ! 911: struct vnode *vp; ! 912: int error, flags = 0; ! 913: ! 914: if (mntflags & MNT_FORCE) ! 915: flags |= FORCECLOSE; ! 916: nmp = VFSTONFS(mp); ! 917: /* ! 918: * Goes something like this.. ! 919: * - Check for activity on the root vnode (other than ourselves). ! 920: * - Call vflush() to clear out vnodes for this file system, ! 921: * except for the root vnode. ! 922: * - Decrement reference on the vnode representing remote root. ! 923: * - Close the socket ! 924: * - Free up the data structures ! 925: */ ! 926: /* ! 927: * We need to decrement the ref. count on the nfsnode representing ! 928: * the remote root. See comment in mountnfs(). The VFS unmount() ! 929: * has done vput on this vnode, otherwise we would get deadlock! ! 930: */ ! 931: error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); ! 932: if (error) ! 933: return(error); ! 934: vp = NFSTOV(np); ! 935: if (vp->v_usecount > 2) { ! 936: vput(vp); ! 937: return (EBUSY); ! 938: } ! 939: ! 940: /* ! 941: * Must handshake with nqnfs_clientd() if it is active. ! 942: */ ! 943: nmp->nm_flag |= NFSMNT_DISMINPROG; ! 944: while (nmp->nm_inprog != NULLVP) ! 945: (void) tsleep((caddr_t)&lbolt, PSOCK, "nfsdism", 0); ! 946: error = vflush(mp, vp, flags); ! 947: if (error) { ! 948: vput(vp); ! 949: nmp->nm_flag &= ~NFSMNT_DISMINPROG; ! 950: return (error); ! 951: } ! 952: ! 953: /* ! 954: * We are now committed to the unmount. ! 955: * For NQNFS, let the server daemon free the nfsmount structure. ! 956: */ ! 957: if (nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) ! 958: nmp->nm_flag |= NFSMNT_DISMNT; ! 959: ! 960: /* ! 961: * There are two reference counts and one lock to get rid of here. ! 962: */ ! 963: vput(vp); ! 964: vrele(vp); ! 965: vgone(vp); ! 966: nfs_disconnect(nmp); ! 967: m_freem(nmp->nm_nam); ! 968: ! 969: if ((nmp->nm_flag & (NFSMNT_NQNFS | NFSMNT_KERB)) == 0) { ! 970: register struct nfsreq *rp; ! 971: /* ! 972: * Loop through outstanding request list and remove dangling ! 973: * references to defunct nfsmount struct ! 974: */ ! 975: for (rp = nfs_reqq.tqh_first; rp; rp = rp->r_chain.tqe_next) ! 976: if (rp->r_nmp == nmp) ! 977: rp->r_nmp = (struct nfsmount *)0; ! 978: _FREE_ZONE((caddr_t)nmp, sizeof (struct nfsmount), M_NFSMNT); ! 979: } ! 980: return (0); ! 981: } ! 982: ! 983: /* ! 984: * Return root of a filesystem ! 985: */ ! 986: static int ! 987: nfs_root(mp, vpp) ! 988: struct mount *mp; ! 989: struct vnode **vpp; ! 990: { ! 991: register struct vnode *vp; ! 992: struct nfsmount *nmp; ! 993: struct nfsnode *np; ! 994: int error; ! 995: ! 996: nmp = VFSTONFS(mp); ! 997: error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np); ! 998: if (error) ! 999: return (error); ! 1000: vp = NFSTOV(np); ! 1001: if (vp->v_type == VNON) ! 1002: vp->v_type = VDIR; ! 1003: vp->v_flag = VROOT; ! 1004: *vpp = vp; ! 1005: return (0); ! 1006: } ! 1007: ! 1008: extern int syncprt; ! 1009: ! 1010: /* ! 1011: * Flush out the buffer cache ! 1012: */ ! 1013: /* ARGSUSED */ ! 1014: static int ! 1015: nfs_sync(mp, waitfor, cred, p) ! 1016: struct mount *mp; ! 1017: int waitfor; ! 1018: struct ucred *cred; ! 1019: struct proc *p; ! 1020: { ! 1021: register struct vnode *vp; ! 1022: int error, allerror = 0; ! 1023: ! 1024: /* ! 1025: * Force stale buffer cache information to be flushed. ! 1026: */ ! 1027: loop: ! 1028: for (vp = mp->mnt_vnodelist.lh_first; ! 1029: vp != NULL; ! 1030: vp = vp->v_mntvnodes.le_next) { ! 1031: /* ! 1032: * If the vnode that we are about to sync is no longer ! 1033: * associated with this mount point, start over. ! 1034: */ ! 1035: if (vp->v_mount != mp) ! 1036: goto loop; ! 1037: if (VOP_ISLOCKED(vp) || vp->v_dirtyblkhd.lh_first == NULL) ! 1038: continue; ! 1039: if (vget(vp, LK_EXCLUSIVE, p)) ! 1040: goto loop; ! 1041: error = VOP_FSYNC(vp, cred, waitfor, p); ! 1042: if (error) ! 1043: allerror = error; ! 1044: vput(vp); ! 1045: } ! 1046: return (allerror); ! 1047: } ! 1048: ! 1049: /* ! 1050: * NFS flat namespace lookup. ! 1051: * Currently unsupported. ! 1052: */ ! 1053: /* ARGSUSED */ ! 1054: static int ! 1055: nfs_vget(mp, ino, vpp) ! 1056: struct mount *mp; ! 1057: ino_t ino; ! 1058: struct vnode **vpp; ! 1059: { ! 1060: ! 1061: return (EOPNOTSUPP); ! 1062: } ! 1063: ! 1064: /* ! 1065: * At this point, this should never happen ! 1066: */ ! 1067: /* ARGSUSED */ ! 1068: static int ! 1069: nfs_fhtovp(mp, fhp, nam, vpp, exflagsp, credanonp) ! 1070: register struct mount *mp; ! 1071: struct fid *fhp; ! 1072: struct mbuf *nam; ! 1073: struct vnode **vpp; ! 1074: int *exflagsp; ! 1075: struct ucred **credanonp; ! 1076: { ! 1077: ! 1078: return (EINVAL); ! 1079: } ! 1080: ! 1081: /* ! 1082: * Vnode pointer to File handle, should never happen either ! 1083: */ ! 1084: /* ARGSUSED */ ! 1085: static int ! 1086: nfs_vptofh(vp, fhp) ! 1087: struct vnode *vp; ! 1088: struct fid *fhp; ! 1089: { ! 1090: ! 1091: return (EINVAL); ! 1092: } ! 1093: ! 1094: /* ! 1095: * Vfs start routine, a no-op. ! 1096: */ ! 1097: /* ARGSUSED */ ! 1098: static int ! 1099: nfs_start(mp, flags, p) ! 1100: struct mount *mp; ! 1101: int flags; ! 1102: struct proc *p; ! 1103: { ! 1104: ! 1105: return (0); ! 1106: } ! 1107: ! 1108: /* ! 1109: * Do operations associated with quotas, not supported ! 1110: */ ! 1111: /* ARGSUSED */ ! 1112: static int ! 1113: nfs_quotactl(mp, cmd, uid, arg, p) ! 1114: struct mount *mp; ! 1115: int cmd; ! 1116: uid_t uid; ! 1117: caddr_t arg; ! 1118: struct proc *p; ! 1119: { ! 1120: ! 1121: return (EOPNOTSUPP); ! 1122: } ! 1123: ! 1124: /* ! 1125: * Do that sysctl thang... ! 1126: */ ! 1127: static int ! 1128: nfs_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, ! 1129: size_t newlen, struct proc *p) ! 1130: { ! 1131: int rv; ! 1132: ! 1133: /* ! 1134: * All names at this level are terminal. ! 1135: */ ! 1136: if(namelen > 1) ! 1137: return ENOTDIR; /* overloaded */ ! 1138: ! 1139: switch(name[0]) { ! 1140: case NFS_NFSSTATS: ! 1141: if(!oldp) { ! 1142: *oldlenp = sizeof nfsstats; ! 1143: return 0; ! 1144: } ! 1145: ! 1146: if(*oldlenp < sizeof nfsstats) { ! 1147: *oldlenp = sizeof nfsstats; ! 1148: return ENOMEM; ! 1149: } ! 1150: ! 1151: rv = copyout(&nfsstats, oldp, sizeof nfsstats); ! 1152: if(rv) return rv; ! 1153: ! 1154: if(newp && newlen != sizeof nfsstats) ! 1155: return EINVAL; ! 1156: ! 1157: if(newp) { ! 1158: return copyin(newp, &nfsstats, sizeof nfsstats); ! 1159: } ! 1160: return 0; ! 1161: ! 1162: default: ! 1163: return EOPNOTSUPP; ! 1164: } ! 1165: } ! 1166:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.