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