|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1989 The Regents of the University of California. ! 3: * 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 is only permitted until one year after the first shipment ! 9: * of 4.4BSD by the Regents. Otherwise, redistribution and use in source and ! 10: * binary forms are permitted provided that: (1) source distributions retain ! 11: * this entire copyright notice and comment, and (2) distributions including ! 12: * binaries display the following acknowledgement: This product includes ! 13: * software developed by the University of California, Berkeley and its ! 14: * contributors'' in the documentation or other materials provided with the ! 15: * distribution and in all advertising materials mentioning features or use ! 16: * of this software. Neither the name of the University nor the names of ! 17: * its contributors may be used to endorse or promote products derived from ! 18: * this software without specific prior written permission. ! 19: * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 20: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 21: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 22: * ! 23: * @(#)nfs_vfsops.c 7.24 (Berkeley) 6/28/90 ! 24: */ ! 25: ! 26: #include "param.h" ! 27: #include "signal.h" ! 28: #include "user.h" ! 29: #include "proc.h" ! 30: #include "vnode.h" ! 31: #include "mount.h" ! 32: #include "errno.h" ! 33: #include "buf.h" ! 34: #include "mbuf.h" ! 35: #include "socket.h" ! 36: #include "systm.h" ! 37: #include "nfsv2.h" ! 38: #include "nfsnode.h" ! 39: #include "nfsmount.h" ! 40: #include "nfs.h" ! 41: #include "xdr_subs.h" ! 42: #include "nfsm_subs.h" ! 43: ! 44: /* ! 45: * nfs vfs operations. ! 46: */ ! 47: int nfs_mount(); ! 48: int nfs_start(); ! 49: int nfs_unmount(); ! 50: int nfs_root(); ! 51: int nfs_quotactl(); ! 52: int nfs_statfs(); ! 53: int nfs_sync(); ! 54: int nfs_fhtovp(); ! 55: int nfs_vptofh(); ! 56: int nfs_init(); ! 57: ! 58: struct vfsops nfs_vfsops = { ! 59: nfs_mount, ! 60: nfs_start, ! 61: nfs_unmount, ! 62: nfs_root, ! 63: nfs_quotactl, ! 64: nfs_statfs, ! 65: nfs_sync, ! 66: nfs_fhtovp, ! 67: nfs_vptofh, ! 68: nfs_init, ! 69: }; ! 70: ! 71: static u_char nfs_mntid; ! 72: extern u_long nfs_procids[NFS_NPROCS]; ! 73: extern u_long nfs_prog, nfs_vers; ! 74: void nfs_disconnect(); ! 75: ! 76: #define TRUE 1 ! 77: #define FALSE 0 ! 78: ! 79: /* ! 80: * nfs statfs call ! 81: */ ! 82: nfs_statfs(mp, sbp) ! 83: struct mount *mp; ! 84: register struct statfs *sbp; ! 85: { ! 86: register struct vnode *vp; ! 87: register struct nfsv2_statfs *sfp; ! 88: register caddr_t cp; ! 89: register long t1; ! 90: caddr_t bpos, dpos, cp2; ! 91: u_long xid; ! 92: int error = 0; ! 93: struct mbuf *mreq, *mrep, *md, *mb, *mb2; ! 94: struct nfsmount *nmp; ! 95: struct ucred *cred; ! 96: struct nfsnode *np; ! 97: ! 98: nmp = VFSTONFS(mp); ! 99: if (error = nfs_nget(mp, &nmp->nm_fh, &np)) ! 100: return (error); ! 101: vp = NFSTOV(np); ! 102: nfsstats.rpccnt[NFSPROC_STATFS]++; ! 103: cred = crget(); ! 104: cred->cr_ngroups = 1; ! 105: nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH); ! 106: nfsm_fhtom(vp); ! 107: nfsm_request(vp, NFSPROC_STATFS, u.u_procp, 0); ! 108: nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS); ! 109: sbp->f_type = MOUNT_NFS; ! 110: sbp->f_flags = nmp->nm_flag; ! 111: sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize); ! 112: sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize); ! 113: sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); ! 114: sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); ! 115: sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); ! 116: sbp->f_files = 0; ! 117: sbp->f_ffree = 0; ! 118: if (sbp != &mp->mnt_stat) { ! 119: bcopy(mp->mnt_stat.f_mntonname, sbp->f_mntonname, MNAMELEN); ! 120: bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); ! 121: } ! 122: nfsm_reqdone; ! 123: nfs_nput(vp); ! 124: crfree(cred); ! 125: return (error); ! 126: } ! 127: ! 128: /* ! 129: * Called by vfs_mountroot when nfs is going to be mounted as root ! 130: * Not Yet (By a LONG shot) ! 131: */ ! 132: nfs_mountroot() ! 133: { ! 134: return (ENODEV); ! 135: } ! 136: ! 137: /* ! 138: * VFS Operations. ! 139: * ! 140: * mount system call ! 141: * It seems a bit dumb to copyinstr() the host and path here and then ! 142: * bcopy() them in mountnfs(), but I wanted to detect errors before ! 143: * doing the sockargs() call because sockargs() allocates an mbuf and ! 144: * an error after that means that I have to release the mbuf. ! 145: */ ! 146: /* ARGSUSED */ ! 147: nfs_mount(mp, path, data, ndp) ! 148: struct mount *mp; ! 149: char *path; ! 150: caddr_t data; ! 151: struct nameidata *ndp; ! 152: { ! 153: int error; ! 154: struct nfs_args args; ! 155: struct mbuf *nam; ! 156: char pth[MNAMELEN], hst[MNAMELEN]; ! 157: int len; ! 158: nfsv2fh_t nfh; ! 159: ! 160: if (mp->mnt_flag & MNT_UPDATE) ! 161: return (0); ! 162: if (error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args))) ! 163: return (error); ! 164: if (error=copyin((caddr_t)args.fh, (caddr_t)&nfh, sizeof (nfsv2fh_t))) ! 165: return (error); ! 166: if (error = copyinstr(path, pth, MNAMELEN-1, &len)) ! 167: return (error); ! 168: bzero(&pth[len], MNAMELEN-len); ! 169: if (error = copyinstr(args.hostname, hst, MNAMELEN-1, &len)) ! 170: return (error); ! 171: bzero(&hst[len], MNAMELEN-len); ! 172: /* sockargs() call must be after above copyin() calls */ ! 173: if (error = sockargs(&nam, (caddr_t)args.addr, ! 174: sizeof (struct sockaddr), MT_SONAME)) ! 175: return (error); ! 176: args.fh = &nfh; ! 177: error = mountnfs(&args, mp, nam, pth, hst); ! 178: return (error); ! 179: } ! 180: ! 181: /* ! 182: * Common code for mount and mountroot ! 183: */ ! 184: mountnfs(argp, mp, nam, pth, hst) ! 185: register struct nfs_args *argp; ! 186: register struct mount *mp; ! 187: struct mbuf *nam; ! 188: char *pth, *hst; ! 189: { ! 190: register struct nfsmount *nmp; ! 191: struct nfsnode *np; ! 192: int error; ! 193: fsid_t tfsid; ! 194: ! 195: MALLOC(nmp, struct nfsmount *, sizeof *nmp, M_NFSMNT, M_WAITOK); ! 196: bzero((caddr_t)nmp, sizeof *nmp); ! 197: mp->mnt_data = (qaddr_t)nmp; ! 198: /* ! 199: * Generate a unique nfs mount id. The problem is that a dev number ! 200: * is not unique across multiple systems. The techique is as follows: ! 201: * 1) Set to nblkdev,0 which will never be used otherwise ! 202: * 2) Generate a first guess as nblkdev,nfs_mntid where nfs_mntid is ! 203: * NOT 0 ! 204: * 3) Loop searching the mount list for another one with same id ! 205: * If a match, increment val[0] and try again ! 206: * NB: I increment val[0] { a long } instead of nfs_mntid { a u_char } ! 207: * so that nfs is not limited to 255 mount points ! 208: * Incrementing the high order bits does no real harm, since it ! 209: * simply makes the major dev number tick up. The upper bound is ! 210: * set to major dev 127 to avoid any sign extention problems ! 211: */ ! 212: mp->mnt_stat.f_fsid.val[0] = makedev(nblkdev, 0); ! 213: mp->mnt_stat.f_fsid.val[1] = MOUNT_NFS; ! 214: if (++nfs_mntid == 0) ! 215: ++nfs_mntid; ! 216: tfsid.val[0] = makedev(nblkdev, nfs_mntid); ! 217: tfsid.val[1] = MOUNT_NFS; ! 218: while (getvfs(&tfsid)) { ! 219: tfsid.val[0]++; ! 220: nfs_mntid++; ! 221: } ! 222: if (major(tfsid.val[0]) > 127) { ! 223: error = ENOENT; ! 224: goto bad; ! 225: } ! 226: mp->mnt_stat.f_fsid.val[0] = tfsid.val[0]; ! 227: nmp->nm_mountp = mp; ! 228: nmp->nm_flag = argp->flags; ! 229: nmp->nm_rto = NFS_TIMEO; ! 230: nmp->nm_rtt = -1; ! 231: nmp->nm_rttvar = nmp->nm_rto << 1; ! 232: nmp->nm_retry = NFS_RETRANS; ! 233: nmp->nm_wsize = NFS_WSIZE; ! 234: nmp->nm_rsize = NFS_RSIZE; ! 235: bcopy((caddr_t)argp->fh, (caddr_t)&nmp->nm_fh, sizeof(nfsv2fh_t)); ! 236: bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); ! 237: bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); ! 238: nmp->nm_nam = nam; ! 239: ! 240: if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { ! 241: nmp->nm_rto = argp->timeo; ! 242: /* NFS timeouts are specified in 1/10 sec. */ ! 243: nmp->nm_rto = (nmp->nm_rto * 10) / NFS_HZ; ! 244: if (nmp->nm_rto < NFS_MINTIMEO) ! 245: nmp->nm_rto = NFS_MINTIMEO; ! 246: else if (nmp->nm_rto > NFS_MAXTIMEO) ! 247: nmp->nm_rto = NFS_MAXTIMEO; ! 248: nmp->nm_rttvar = nmp->nm_rto << 1; ! 249: } ! 250: ! 251: if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { ! 252: nmp->nm_retry = argp->retrans; ! 253: if (nmp->nm_retry > NFS_MAXREXMIT) ! 254: nmp->nm_retry = NFS_MAXREXMIT; ! 255: } ! 256: ! 257: if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { ! 258: nmp->nm_wsize = argp->wsize; ! 259: /* Round down to multiple of blocksize */ ! 260: nmp->nm_wsize &= ~0x1ff; ! 261: if (nmp->nm_wsize <= 0) ! 262: nmp->nm_wsize = 512; ! 263: else if (nmp->nm_wsize > NFS_MAXDATA) ! 264: nmp->nm_wsize = NFS_MAXDATA; ! 265: } ! 266: if (nmp->nm_wsize > MAXBSIZE) ! 267: nmp->nm_wsize = MAXBSIZE; ! 268: ! 269: if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { ! 270: nmp->nm_rsize = argp->rsize; ! 271: /* Round down to multiple of blocksize */ ! 272: nmp->nm_rsize &= ~0x1ff; ! 273: if (nmp->nm_rsize <= 0) ! 274: nmp->nm_rsize = 512; ! 275: else if (nmp->nm_rsize > NFS_MAXDATA) ! 276: nmp->nm_rsize = NFS_MAXDATA; ! 277: } ! 278: if (nmp->nm_rsize > MAXBSIZE) ! 279: nmp->nm_rsize = MAXBSIZE; ! 280: /* Set up the sockets and per-host congestion */ ! 281: nmp->nm_sotype = argp->sotype; ! 282: nmp->nm_soproto = argp->proto; ! 283: if (error = nfs_connect(nmp)) ! 284: goto bad; ! 285: ! 286: if (error = nfs_statfs(mp, &mp->mnt_stat)) ! 287: goto bad; ! 288: /* ! 289: * A reference count is needed on the nfsnode representing the ! 290: * remote root. If this object is not persistent, then backward ! 291: * traversals of the mount point (i.e. "..") will not work if ! 292: * the nfsnode gets flushed out of the cache. Ufs does not have ! 293: * this problem, because one can identify root inodes by their ! 294: * number == ROOTINO (2). ! 295: */ ! 296: if (error = nfs_nget(mp, &nmp->nm_fh, &np)) ! 297: goto bad; ! 298: /* ! 299: * Unlock it, but keep the reference count. ! 300: */ ! 301: nfs_unlock(NFSTOV(np)); ! 302: ! 303: return (0); ! 304: bad: ! 305: nfs_disconnect(nmp); ! 306: FREE(nmp, M_NFSMNT); ! 307: m_freem(nam); ! 308: return (error); ! 309: } ! 310: ! 311: /* ! 312: * unmount system call ! 313: */ ! 314: nfs_unmount(mp, mntflags) ! 315: struct mount *mp; ! 316: int mntflags; ! 317: { ! 318: register struct nfsmount *nmp; ! 319: struct nfsnode *np; ! 320: struct vnode *vp; ! 321: int flags = 0; ! 322: int error; ! 323: ! 324: if (mntflags & MNT_FORCE) ! 325: return (EINVAL); ! 326: if (mntflags & MNT_FORCE) ! 327: flags |= FORCECLOSE; ! 328: nmp = VFSTONFS(mp); ! 329: /* ! 330: * Clear out the buffer cache ! 331: */ ! 332: mntflushbuf(mp, 0); ! 333: if (mntinvalbuf(mp)) ! 334: return (EBUSY); ! 335: /* ! 336: * Goes something like this.. ! 337: * - Check for activity on the root vnode (other than ourselves). ! 338: * - Call vflush() to clear out vnodes for this file system, ! 339: * except for the root vnode. ! 340: * - Decrement reference on the vnode representing remote root. ! 341: * - Close the socket ! 342: * - Free up the data structures ! 343: */ ! 344: /* ! 345: * We need to decrement the ref. count on the nfsnode representing ! 346: * the remote root. See comment in mountnfs(). The VFS unmount() ! 347: * has done vput on this vnode, otherwise we would get deadlock! ! 348: */ ! 349: if (error = nfs_nget(mp, &nmp->nm_fh, &np)) ! 350: return(error); ! 351: vp = NFSTOV(np); ! 352: if (vp->v_usecount > 2) { ! 353: vput(vp); ! 354: return (EBUSY); ! 355: } ! 356: if (error = vflush(mp, vp, flags)) { ! 357: vput(vp); ! 358: return (error); ! 359: } ! 360: /* ! 361: * Get rid of two reference counts, and unlock it on the second. ! 362: */ ! 363: vrele(vp); ! 364: vput(vp); ! 365: nfs_disconnect(nmp); ! 366: m_freem(nmp->nm_nam); ! 367: free((caddr_t)nmp, M_NFSMNT); ! 368: return (0); ! 369: } ! 370: ! 371: /* ! 372: * Return root of a filesystem ! 373: */ ! 374: nfs_root(mp, vpp) ! 375: struct mount *mp; ! 376: struct vnode **vpp; ! 377: { ! 378: register struct vnode *vp; ! 379: struct nfsmount *nmp; ! 380: struct nfsnode *np; ! 381: int error; ! 382: ! 383: nmp = VFSTONFS(mp); ! 384: if (error = nfs_nget(mp, &nmp->nm_fh, &np)) ! 385: return (error); ! 386: vp = NFSTOV(np); ! 387: vp->v_type = VDIR; ! 388: vp->v_flag = VROOT; ! 389: *vpp = vp; ! 390: return (0); ! 391: } ! 392: ! 393: extern int syncprt; ! 394: ! 395: /* ! 396: * Flush out the buffer cache ! 397: */ ! 398: /* ARGSUSED */ ! 399: nfs_sync(mp, waitfor) ! 400: struct mount *mp; ! 401: int waitfor; ! 402: { ! 403: if (syncprt) ! 404: bufstats(); ! 405: /* ! 406: * Force stale buffer cache information to be flushed. ! 407: */ ! 408: mntflushbuf(mp, waitfor == MNT_WAIT ? B_SYNC : 0); ! 409: return (0); ! 410: } ! 411: ! 412: /* ! 413: * At this point, this should never happen ! 414: */ ! 415: /* ARGSUSED */ ! 416: nfs_fhtovp(mp, fhp, vpp) ! 417: struct mount *mp; ! 418: struct fid *fhp; ! 419: struct vnode **vpp; ! 420: { ! 421: ! 422: return (EINVAL); ! 423: } ! 424: ! 425: /* ! 426: * Vnode pointer to File handle, should never happen either ! 427: */ ! 428: /* ARGSUSED */ ! 429: nfs_vptofh(mp, fhp, vpp) ! 430: struct mount *mp; ! 431: struct fid *fhp; ! 432: struct vnode **vpp; ! 433: { ! 434: ! 435: return (EINVAL); ! 436: } ! 437: ! 438: /* ! 439: * Vfs start routine, a no-op. ! 440: */ ! 441: /* ARGSUSED */ ! 442: nfs_start(mp, flags) ! 443: struct mount *mp; ! 444: int flags; ! 445: { ! 446: ! 447: return (0); ! 448: } ! 449: ! 450: /* ! 451: * Do operations associated with quotas, not supported ! 452: */ ! 453: nfs_quotactl(mp, cmd, uid, arg) ! 454: struct mount *mp; ! 455: int cmd; ! 456: uid_t uid; ! 457: caddr_t arg; ! 458: { ! 459: #ifdef lint ! 460: mp = mp; cmd = cmd; uid = uid; arg = arg; ! 461: #endif /* lint */ ! 462: return (EOPNOTSUPP); ! 463: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.