Support 'mount -u' remounts. This may require disconnecting and rebinding

the socket.  Certain mode changes are not allowed.

Obtained from:  NetBSD
This commit is contained in:
Peter Wemm 1998-05-31 19:49:31 +00:00
parent 261114d95c
commit 75c6892c16
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=36540
11 changed files with 430 additions and 273 deletions

View File

@ -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 *,

View File

@ -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.

View File

@ -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,139 +591,16 @@ nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
return (0);
}
/*
* VFS Operations.
*
* mount system call
* It seems a bit dumb to copyinstr() the host and path here and then
* bcopy() them in mountnfs(), but I wanted to detect errors before
* doing the sockargs() call because sockargs() allocates an mbuf and
* an error after that means that I have to release the mbuf.
*/
/* ARGSUSED */
static int
nfs_mount(mp, path, data, ndp, p)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
static void
nfs_decode_args(nmp, argp)
struct nfsmount *nmp;
struct nfs_args *argp;
{
int error;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
u_char nfh[NFSX_V3FHMAX];
if (path == NULL) {
nfs_mountroot(mp);
return (0);
}
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
if (args.version != NFS_ARGSVERSION) {
#ifndef NO_COMPAT_PRELITE2
/*
* If the argument version is unknown, then assume the
* caller is a pre-lite2 4.4BSD client and convert its
* arguments.
*/
struct onfs_args oargs;
error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
if (error)
return (error);
nfs_convert_oargs(&args,&oargs);
#else /* NO_COMPAT_PRELITE2 */
return (EPROGMISMATCH);
#endif /* !NO_COMPAT_PRELITE2 */
}
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
error = copyinstr(path, pth, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&pth[len], MNAMELEN - len);
error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&hst[len], MNAMELEN - len);
/* sockargs() call must be after above copyin() calls */
error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
if (error)
return (error);
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
/*
* Common code for mount and mountroot
*/
static int
mountnfs(argp, mp, nam, pth, hst, vpp)
register struct nfs_args *argp;
register struct mount *mp;
struct sockaddr *nam;
char *pth, *hst;
struct vnode **vpp;
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error, maxio;
struct vattr attrs;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
/* update paths, file handles, etc, here XXX */
FREE(nam, M_SONAME);
return (0);
} else {
nmp = zalloc(nfsmount_zone);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if (nmp->nm_flag & NFSMNT_NQNFS)
/*
* We have to set mnt_maxsymlink to a non-zero value so
* that COMPAT_43 routines will know that we are setting
* the d_type field in directories (and can zero it for
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
if ((argp->flags & NFSMNT_NFSV3) == 0)
/*
* V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
* will fill this in.
*/
nmp->nm_maxfilesize = 0xffffffffLL;
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
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.
@ -733,6 +612,17 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
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)
@ -820,10 +710,176 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
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.
*
* mount system call
* It seems a bit dumb to copyinstr() the host and path here and then
* bcopy() them in mountnfs(), but I wanted to detect errors before
* doing the sockargs() call because sockargs() allocates an mbuf and
* an error after that means that I have to release the mbuf.
*/
/* ARGSUSED */
static int
nfs_mount(mp, path, data, ndp, p)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
{
int error;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
u_char nfh[NFSX_V3FHMAX];
if (path == NULL) {
nfs_mountroot(mp);
return (0);
}
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
if (args.version != NFS_ARGSVERSION) {
#ifndef NO_COMPAT_PRELITE2
/*
* If the argument version is unknown, then assume the
* caller is a pre-lite2 4.4BSD client and convert its
* arguments.
*/
struct onfs_args oargs;
error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
if (error)
return (error);
nfs_convert_oargs(&args,&oargs);
#else /* NO_COMPAT_PRELITE2 */
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);
error = copyinstr(path, pth, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&pth[len], MNAMELEN - len);
error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&hst[len], MNAMELEN - len);
/* sockargs() call must be after above copyin() calls */
error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
if (error)
return (error);
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
/*
* Common code for mount and mountroot
*/
static int
mountnfs(argp, mp, nam, pth, hst, vpp)
register struct nfs_args *argp;
register struct mount *mp;
struct sockaddr *nam;
char *pth, *hst;
struct vnode **vpp;
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error, maxio;
struct vattr attrs;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
/* update paths, file handles, etc, here XXX */
FREE(nam, M_SONAME);
return (0);
} else {
nmp = zalloc(nfsmount_zone);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
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
* the d_type field in directories (and can zero it for
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
if ((argp->flags & NFSMNT_NFSV3) == 0)
/*
* V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
* will fill this in.
*/
nmp->nm_maxfilesize = 0xffffffffLL;
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
/* 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.

View File

@ -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 *,

View File

@ -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.

View File

@ -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,139 +591,16 @@ nfs_mountdiskless(path, which, mountflag, sin, args, p, vpp, mpp)
return (0);
}
/*
* VFS Operations.
*
* mount system call
* It seems a bit dumb to copyinstr() the host and path here and then
* bcopy() them in mountnfs(), but I wanted to detect errors before
* doing the sockargs() call because sockargs() allocates an mbuf and
* an error after that means that I have to release the mbuf.
*/
/* ARGSUSED */
static int
nfs_mount(mp, path, data, ndp, p)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
static void
nfs_decode_args(nmp, argp)
struct nfsmount *nmp;
struct nfs_args *argp;
{
int error;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
u_char nfh[NFSX_V3FHMAX];
if (path == NULL) {
nfs_mountroot(mp);
return (0);
}
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
if (args.version != NFS_ARGSVERSION) {
#ifndef NO_COMPAT_PRELITE2
/*
* If the argument version is unknown, then assume the
* caller is a pre-lite2 4.4BSD client and convert its
* arguments.
*/
struct onfs_args oargs;
error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
if (error)
return (error);
nfs_convert_oargs(&args,&oargs);
#else /* NO_COMPAT_PRELITE2 */
return (EPROGMISMATCH);
#endif /* !NO_COMPAT_PRELITE2 */
}
error = copyin((caddr_t)args.fh, (caddr_t)nfh, args.fhsize);
if (error)
return (error);
error = copyinstr(path, pth, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&pth[len], MNAMELEN - len);
error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&hst[len], MNAMELEN - len);
/* sockargs() call must be after above copyin() calls */
error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
if (error)
return (error);
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
/*
* Common code for mount and mountroot
*/
static int
mountnfs(argp, mp, nam, pth, hst, vpp)
register struct nfs_args *argp;
register struct mount *mp;
struct sockaddr *nam;
char *pth, *hst;
struct vnode **vpp;
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error, maxio;
struct vattr attrs;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
/* update paths, file handles, etc, here XXX */
FREE(nam, M_SONAME);
return (0);
} else {
nmp = zalloc(nfsmount_zone);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
nmp->nm_flag = argp->flags;
if (nmp->nm_flag & NFSMNT_NQNFS)
/*
* We have to set mnt_maxsymlink to a non-zero value so
* that COMPAT_43 routines will know that we are setting
* the d_type field in directories (and can zero it for
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
if ((argp->flags & NFSMNT_NFSV3) == 0)
/*
* V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
* will fill this in.
*/
nmp->nm_maxfilesize = 0xffffffffLL;
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
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.
@ -733,6 +612,17 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
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)
@ -820,10 +710,176 @@ mountnfs(argp, mp, nam, pth, hst, vpp)
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.
*
* mount system call
* It seems a bit dumb to copyinstr() the host and path here and then
* bcopy() them in mountnfs(), but I wanted to detect errors before
* doing the sockargs() call because sockargs() allocates an mbuf and
* an error after that means that I have to release the mbuf.
*/
/* ARGSUSED */
static int
nfs_mount(mp, path, data, ndp, p)
struct mount *mp;
char *path;
caddr_t data;
struct nameidata *ndp;
struct proc *p;
{
int error;
struct nfs_args args;
struct sockaddr *nam;
struct vnode *vp;
char pth[MNAMELEN], hst[MNAMELEN];
u_int len;
u_char nfh[NFSX_V3FHMAX];
if (path == NULL) {
nfs_mountroot(mp);
return (0);
}
error = copyin(data, (caddr_t)&args, sizeof (struct nfs_args));
if (error)
return (error);
if (args.version != NFS_ARGSVERSION) {
#ifndef NO_COMPAT_PRELITE2
/*
* If the argument version is unknown, then assume the
* caller is a pre-lite2 4.4BSD client and convert its
* arguments.
*/
struct onfs_args oargs;
error = copyin(data, (caddr_t)&oargs, sizeof (struct onfs_args));
if (error)
return (error);
nfs_convert_oargs(&args,&oargs);
#else /* NO_COMPAT_PRELITE2 */
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);
error = copyinstr(path, pth, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&pth[len], MNAMELEN - len);
error = copyinstr(args.hostname, hst, MNAMELEN-1, &len);
if (error)
return (error);
bzero(&hst[len], MNAMELEN - len);
/* sockargs() call must be after above copyin() calls */
error = getsockaddr(&nam, (caddr_t)args.addr, args.addrlen);
if (error)
return (error);
args.fh = nfh;
error = mountnfs(&args, mp, nam, pth, hst, &vp);
return (error);
}
/*
* Common code for mount and mountroot
*/
static int
mountnfs(argp, mp, nam, pth, hst, vpp)
register struct nfs_args *argp;
register struct mount *mp;
struct sockaddr *nam;
char *pth, *hst;
struct vnode **vpp;
{
register struct nfsmount *nmp;
struct nfsnode *np;
int error, maxio;
struct vattr attrs;
if (mp->mnt_flag & MNT_UPDATE) {
nmp = VFSTONFS(mp);
/* update paths, file handles, etc, here XXX */
FREE(nam, M_SONAME);
return (0);
} else {
nmp = zalloc(nfsmount_zone);
bzero((caddr_t)nmp, sizeof (struct nfsmount));
TAILQ_INIT(&nmp->nm_uidlruhead);
TAILQ_INIT(&nmp->nm_bufq);
mp->mnt_data = (qaddr_t)nmp;
}
vfs_getnewfsid(mp);
nmp->nm_mountp = mp;
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
* the d_type field in directories (and can zero it for
* unsuspecting binaries).
*/
mp->mnt_maxsymlinklen = 1;
if ((argp->flags & NFSMNT_NFSV3) == 0)
/*
* V2 can only handle 32 bit filesizes. For v3, nfs_fsinfo
* will fill this in.
*/
nmp->nm_maxfilesize = 0xffffffffLL;
nmp->nm_timeo = NFS_TIMEO;
nmp->nm_retry = NFS_RETRANS;
nmp->nm_wsize = NFS_WSIZE;
nmp->nm_rsize = NFS_RSIZE;
nmp->nm_readdirsize = NFS_READDIRSIZE;
nmp->nm_numgrps = NFS_MAXGRPS;
nmp->nm_readahead = NFS_DEFRAHEAD;
nmp->nm_leaseterm = NQ_DEFLEASE;
nmp->nm_deadthresh = NQ_DEADTHRESH;
CIRCLEQ_INIT(&nmp->nm_timerhead);
nmp->nm_inprog = NULLVP;
nmp->nm_fhsize = argp->fhsize;
bcopy((caddr_t)argp->fh, (caddr_t)nmp->nm_fh, argp->fhsize);
bcopy(hst, mp->mnt_stat.f_mntfromname, MNAMELEN);
bcopy(pth, mp->mnt_stat.f_mntonname, MNAMELEN);
nmp->nm_nam = nam;
/* 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.

View File

@ -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 *,

View File

@ -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 *,

View File

@ -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 *,

View File

@ -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.

View File

@ -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 *,