diff options
author | peter <peter@FreeBSD.org> | 1998-05-31 19:49:31 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1998-05-31 19:49:31 +0000 |
commit | 401c250cc40de5fcfc5f53856a8194793ba32667 (patch) | |
tree | 77292b0fb6150895d044dedafa84184c95243d2e /sys/nfs | |
parent | 5080277e0ee6d3017bdd8ac4e416ccef13a15697 (diff) | |
download | FreeBSD-src-401c250cc40de5fcfc5f53856a8194793ba32667.zip FreeBSD-src-401c250cc40de5fcfc5f53856a8194793ba32667.tar.gz |
Support 'mount -u' remounts. This may require disconnecting and rebinding
the socket. Certain mode changes are not allowed.
Obtained from: NetBSD
Diffstat (limited to 'sys/nfs')
-rw-r--r-- | sys/nfs/nfs.h | 3 | ||||
-rw-r--r-- | sys/nfs/nfs_socket.c | 15 | ||||
-rw-r--r-- | sys/nfs/nfs_vfsops.c | 260 |
3 files changed, 174 insertions, 104 deletions
diff --git a/sys/nfs/nfs.h b/sys/nfs/nfs.h index ec0d530..a9fa37e 100644 --- a/sys/nfs/nfs.h +++ b/sys/nfs/nfs.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs.h 8.4 (Berkeley) 5/1/95 - * $Id: nfs.h,v 1.37 1998/05/31 17:27:45 peter Exp $ + * $Id: nfs.h,v 1.38 1998/05/31 17:48:03 peter Exp $ */ #ifndef _NFS_NFS_H_ @@ -639,6 +639,7 @@ void nfsrv_updatecache __P((struct nfsrv_descript *, int, struct mbuf *)); void nfsrv_cleancache __P((void)); int nfs_connect __P((struct nfsmount *, struct nfsreq *)); void nfs_disconnect __P((struct nfsmount *)); +void nfs_safedisconnect __P((struct nfsmount *)); int nfs_getattrcache __P((struct vnode *, struct vattr *)); int nfsm_strtmbuf __P((struct mbuf **, char **, const char *, long)); int nfs_bioread __P((struct vnode *, struct uio *, int, struct ucred *, diff --git a/sys/nfs/nfs_socket.c b/sys/nfs/nfs_socket.c index 45f2b61..8fcefeb 100644 --- a/sys/nfs/nfs_socket.c +++ b/sys/nfs/nfs_socket.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_socket.c 8.5 (Berkeley) 3/30/95 - * $Id: nfs_socket.c,v 1.37 1998/05/31 18:06:07 peter Exp $ + * $Id: nfs_socket.c,v 1.38 1998/05/31 18:08:09 peter Exp $ */ /* @@ -371,6 +371,19 @@ nfs_disconnect(nmp) } } +void +nfs_safedisconnect(nmp) + struct nfsmount *nmp; +{ + struct nfsreq dummyreq; + + bzero(&dummyreq, sizeof(dummyreq)); + dummyreq.r_nmp = nmp; + nfs_rcvlock(&dummyreq); + nfs_disconnect(nmp); + nfs_rcvunlock(&nmp->nm_flag, &nmp->nm_state); +} + /* * This is the nfs send routine. For connection based socket types, it * must be called with an nfs_sndlock() on the socket. diff --git a/sys/nfs/nfs_vfsops.c b/sys/nfs/nfs_vfsops.c index 167e6c9..d7bb8e2 100644 --- a/sys/nfs/nfs_vfsops.c +++ b/sys/nfs/nfs_vfsops.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)nfs_vfsops.c 8.12 (Berkeley) 5/20/95 - * $Id: nfs_vfsops.c,v 1.66 1998/05/31 18:19:43 peter Exp $ + * $Id: nfs_vfsops.c,v 1.67 1998/05/31 19:20:44 peter Exp $ */ #include <sys/param.h> @@ -93,6 +93,8 @@ SYSCTL_INT(_vfs_nfs, OID_AUTO, debug, CTLFLAG_RW, &nfs_debug, 0, ""); #endif static int nfs_iosize __P((struct nfsmount *nmp)); +static void nfs_decode_args __P((struct nfsmount *nmp, + struct nfs_args *argp)); static int mountnfs __P((struct nfs_args *,struct mount *, struct sockaddr *,char *,char *,struct vnode **)); static int nfs_mount __P(( struct mount *mp, char *path, caddr_t data, @@ -589,6 +591,142 @@ nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp) return (0); } +static void +nfs_decode_args(nmp, argp) + struct nfsmount *nmp; + struct nfs_args *argp; +{ + int s; + int adjsock; + int maxio; + + s = splnet(); + /* + * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes + * no sense in that context. + */ + if (argp->sotype == SOCK_STREAM) + nmp->nm_flag &= ~NFSMNT_NOCONN; + + /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */ + if ((argp->flags & NFSMNT_NFSV3) == 0) + nmp->nm_flag &= ~NFSMNT_RDIRPLUS; + + /* Re-bind if rsrvd port requested and wasn't on one */ + adjsock = !(nmp->nm_flag & NFSMNT_RESVPORT) + && (argp->flags & NFSMNT_RESVPORT); + /* Also re-bind if we're switching to/from a connected UDP socket */ + adjsock |= ((nmp->nm_flag & NFSMNT_NOCONN) != + (argp->flags & NFSMNT_NOCONN)); + + /* Update flags atomically. Don't change the lock bits. */ + nmp->nm_flag = argp->flags | nmp->nm_flag; + splx(s); + + if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { + nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; + if (nmp->nm_timeo < NFS_MINTIMEO) + nmp->nm_timeo = NFS_MINTIMEO; + else if (nmp->nm_timeo > NFS_MAXTIMEO) + nmp->nm_timeo = NFS_MAXTIMEO; + } + + if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { + nmp->nm_retry = argp->retrans; + if (nmp->nm_retry > NFS_MAXREXMIT) + nmp->nm_retry = NFS_MAXREXMIT; + } + + if (argp->flags & NFSMNT_NFSV3) { + if (argp->sotype == SOCK_DGRAM) + maxio = NFS_MAXDGRAMDATA; + else + maxio = NFS_MAXDATA; + } else + maxio = NFS_V2MAXDATA; + + if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { + nmp->nm_wsize = argp->wsize; + /* Round down to multiple of blocksize */ + nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); + if (nmp->nm_wsize <= 0) + nmp->nm_wsize = NFS_FABLKSIZE; + } + if (nmp->nm_wsize > maxio) + nmp->nm_wsize = maxio; + if (nmp->nm_wsize > MAXBSIZE) + nmp->nm_wsize = MAXBSIZE; + + if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { + nmp->nm_rsize = argp->rsize; + /* Round down to multiple of blocksize */ + nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); + if (nmp->nm_rsize <= 0) + nmp->nm_rsize = NFS_FABLKSIZE; + } + if (nmp->nm_rsize > maxio) + nmp->nm_rsize = maxio; + if (nmp->nm_rsize > MAXBSIZE) + nmp->nm_rsize = MAXBSIZE; + + if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { + nmp->nm_readdirsize = argp->readdirsize; + } + if (nmp->nm_readdirsize > maxio) + nmp->nm_readdirsize = maxio; + if (nmp->nm_readdirsize > nmp->nm_rsize) + nmp->nm_readdirsize = nmp->nm_rsize; + + if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) + nmp->nm_acregmin = argp->acregmin; + else + nmp->nm_acregmin = NFS_MINATTRTIMO; + if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) + nmp->nm_acregmax = argp->acregmax; + else + nmp->nm_acregmax = NFS_MAXATTRTIMO; + if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) + nmp->nm_acdirmin = argp->acdirmin; + else + nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; + if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) + nmp->nm_acdirmax = argp->acdirmax; + else + nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; + if (nmp->nm_acdirmin > nmp->nm_acdirmax) + nmp->nm_acdirmin = nmp->nm_acdirmax; + if (nmp->nm_acregmin > nmp->nm_acregmax) + nmp->nm_acregmin = nmp->nm_acregmax; + + if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && + argp->maxgrouplist <= NFS_MAXGRPS) + nmp->nm_numgrps = argp->maxgrouplist; + if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && + argp->readahead <= NFS_MAXRAHEAD) + nmp->nm_readahead = argp->readahead; + if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && + argp->leaseterm <= NQ_MAXLEASE) + nmp->nm_leaseterm = argp->leaseterm; + if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && + argp->deadthresh <= NQ_NEVERDEAD) + nmp->nm_deadthresh = argp->deadthresh; + + adjsock |= ((nmp->nm_sotype != argp->sotype) || + (nmp->nm_soproto != argp->proto)); + nmp->nm_sotype = argp->sotype; + nmp->nm_soproto = argp->proto; + + if (nmp->nm_so && adjsock) { + nfs_safedisconnect(nmp); + if (nmp->nm_sotype == SOCK_DGRAM) + while (nfs_connect(nmp, (struct nfsreq *)0)) { + printf("nfs_args: retrying connect\n"); + (void) tsleep((caddr_t)&lbolt, + PSOCK, "nfscon", 0); + } + } +} + /* * VFS Operations. * @@ -638,6 +776,22 @@ nfs_mount(mp, path, data, ndp, p) return (EPROGMISMATCH); #endif /* !NO_COMPAT_PRELITE2 */ } + if (mp->mnt_flag & MNT_UPDATE) { + register struct nfsmount *nmp = VFSTONFS(mp); + + if (nmp == NULL) + return (EIO); + /* + * When doing an update, we can't change from or to + * v3 and/or nqnfs, or change cookie translation + */ + args.flags = (args.flags & + ~(NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)) | + (nmp->nm_flag & + (NFSMNT_NFSV3|NFSMNT_NQNFS /*|NFSMNT_XLATECOOKIE*/)); + nfs_decode_args(nmp, &args); + return (0); + } error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize); if (error) return (error); @@ -688,8 +842,7 @@ mountnfs(argp, mp, nam, pth, hst, vpp) } vfs_getnewfsid(mp); nmp->nm_mountp = mp; - nmp->nm_flag = argp->flags; - if (nmp->nm_flag & NFSMNT_NQNFS) + if (argp->flags & NFSMNT_NQNFS) /* * We have to set mnt_maxsymlink to a non-zero value so * that COMPAT_43 routines will know that we are setting @@ -721,109 +874,12 @@ mountnfs(argp, mp, nam, pth, hst, vpp) bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN); bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN); nmp->nm_nam = nam; - - /* - * Silently clear NFSMNT_NOCONN if it's a TCP mount, it makes - * no sense in that context. - */ - if (argp->sotype == SOCK_STREAM) - nmp->nm_flag &= ~NFSMNT_NOCONN; - - /* Also clear RDIRPLUS if not NFSv3, it crashes some servers */ - if ((argp->flags & NFSMNT_NFSV3) == 0) - nmp->nm_flag &= ~NFSMNT_RDIRPLUS; - - if ((argp->flags & NFSMNT_TIMEO) && argp->timeo > 0) { - nmp->nm_timeo = (argp->timeo * NFS_HZ + 5) / 10; - if (nmp->nm_timeo < NFS_MINTIMEO) - nmp->nm_timeo = NFS_MINTIMEO; - else if (nmp->nm_timeo > NFS_MAXTIMEO) - nmp->nm_timeo = NFS_MAXTIMEO; - } - - if ((argp->flags & NFSMNT_RETRANS) && argp->retrans > 1) { - nmp->nm_retry = argp->retrans; - if (nmp->nm_retry > NFS_MAXREXMIT) - nmp->nm_retry = NFS_MAXREXMIT; - } - - if (argp->flags & NFSMNT_NFSV3) { - if (argp->sotype == SOCK_DGRAM) - maxio = NFS_MAXDGRAMDATA; - else - maxio = NFS_MAXDATA; - } else - maxio = NFS_V2MAXDATA; - - if ((argp->flags & NFSMNT_WSIZE) && argp->wsize > 0) { - nmp->nm_wsize = argp->wsize; - /* Round down to multiple of blocksize */ - nmp->nm_wsize &= ~(NFS_FABLKSIZE - 1); - if (nmp->nm_wsize <= 0) - nmp->nm_wsize = NFS_FABLKSIZE; - } - if (nmp->nm_wsize > maxio) - nmp->nm_wsize = maxio; - if (nmp->nm_wsize > MAXBSIZE) - nmp->nm_wsize = MAXBSIZE; - - if ((argp->flags & NFSMNT_RSIZE) && argp->rsize > 0) { - nmp->nm_rsize = argp->rsize; - /* Round down to multiple of blocksize */ - nmp->nm_rsize &= ~(NFS_FABLKSIZE - 1); - if (nmp->nm_rsize <= 0) - nmp->nm_rsize = NFS_FABLKSIZE; - } - if (nmp->nm_rsize > maxio) - nmp->nm_rsize = maxio; - if (nmp->nm_rsize > MAXBSIZE) - nmp->nm_rsize = MAXBSIZE; - - if ((argp->flags & NFSMNT_READDIRSIZE) && argp->readdirsize > 0) { - nmp->nm_readdirsize = argp->readdirsize; - } - if (nmp->nm_readdirsize > maxio) - nmp->nm_readdirsize = maxio; - if (nmp->nm_readdirsize > nmp->nm_rsize) - nmp->nm_readdirsize = nmp->nm_rsize; - - if ((argp->flags & NFSMNT_ACREGMIN) && argp->acregmin >= 0) - nmp->nm_acregmin = argp->acregmin; - else - nmp->nm_acregmin = NFS_MINATTRTIMO; - if ((argp->flags & NFSMNT_ACREGMAX) && argp->acregmax >= 0) - nmp->nm_acregmax = argp->acregmax; - else - nmp->nm_acregmax = NFS_MAXATTRTIMO; - if ((argp->flags & NFSMNT_ACDIRMIN) && argp->acdirmin >= 0) - nmp->nm_acdirmin = argp->acdirmin; - else - nmp->nm_acdirmin = NFS_MINDIRATTRTIMO; - if ((argp->flags & NFSMNT_ACDIRMAX) && argp->acdirmax >= 0) - nmp->nm_acdirmax = argp->acdirmax; - else - nmp->nm_acdirmax = NFS_MAXDIRATTRTIMO; - if (nmp->nm_acdirmin > nmp->nm_acdirmax) - nmp->nm_acdirmin = nmp->nm_acdirmax; - if (nmp->nm_acregmin > nmp->nm_acregmax) - nmp->nm_acregmin = nmp->nm_acregmax; - - if ((argp->flags & NFSMNT_MAXGRPS) && argp->maxgrouplist >= 0 && - argp->maxgrouplist <= NFS_MAXGRPS) - nmp->nm_numgrps = argp->maxgrouplist; - if ((argp->flags & NFSMNT_READAHEAD) && argp->readahead >= 0 && - argp->readahead <= NFS_MAXRAHEAD) - nmp->nm_readahead = argp->readahead; - if ((argp->flags & NFSMNT_LEASETERM) && argp->leaseterm >= 2 && - argp->leaseterm <= NQ_MAXLEASE) - nmp->nm_leaseterm = argp->leaseterm; - if ((argp->flags & NFSMNT_DEADTHRESH) && argp->deadthresh >= 1 && - argp->deadthresh <= NQ_NEVERDEAD) - nmp->nm_deadthresh = argp->deadthresh; /* Set up the sockets and per-host congestion */ nmp->nm_sotype = argp->sotype; nmp->nm_soproto = argp->proto; + nfs_decode_args(nmp, argp); + /* * For Connection based sockets (TCP,...) defer the connect until * the first request, in case the server is not responding. |