Enhancements from Matthias Drochner:
- Try V3 first for diskless booting. Fall back to V2 if V3 fails. - optionally (option NFS_BOOT_TCP) try a TCP mount first for diskless booting. Fall back to UDP if it fails. - Enable switching between UDP and TCP for remounts.
This commit is contained in:
parent
7133ecf2ca
commit
735944405b
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: krpc.h,v 1.4 1995/12/19 23:07:11 cgd Exp $ */
|
||||
/* $NetBSD: krpc.h,v 1.5 1996/10/20 13:13:22 fvdl Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
|
@ -7,7 +7,7 @@ int krpc_call __P((struct sockaddr_in *sin,
|
|||
struct mbuf **data, struct mbuf **from));
|
||||
|
||||
int krpc_portmap __P((struct sockaddr_in *sin,
|
||||
u_int prog, u_int vers, u_int16_t *portp));
|
||||
u_int prog, u_int vers, u_int proto, u_int16_t *portp));
|
||||
|
||||
struct mbuf *xdr_string_encode __P((char *str, int len));
|
||||
struct mbuf *xdr_string_decode __P((struct mbuf *m, char *str, int *len_p));
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: krpc_subr.c,v 1.18 1996/10/13 01:39:03 christos Exp $ */
|
||||
/* $NetBSD: krpc_subr.c,v 1.19 1996/10/20 13:13:24 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Gordon Ross, Adam Glass
|
||||
|
@ -126,9 +126,9 @@ struct rpc_reply {
|
|||
* Returns non-zero error on failure.
|
||||
*/
|
||||
int
|
||||
krpc_portmap(sin, prog, vers, portp)
|
||||
krpc_portmap(sin, prog, vers, proto, portp)
|
||||
struct sockaddr_in *sin; /* server address */
|
||||
u_int prog, vers; /* host order */
|
||||
u_int prog, vers, proto; /* host order */
|
||||
u_int16_t *portp; /* network order */
|
||||
{
|
||||
struct sdata {
|
||||
|
@ -157,7 +157,7 @@ krpc_portmap(sin, prog, vers, portp)
|
|||
/* Do the RPC to get it. */
|
||||
sdata->prog = txdr_unsigned(prog);
|
||||
sdata->vers = txdr_unsigned(vers);
|
||||
sdata->proto = txdr_unsigned(IPPROTO_UDP);
|
||||
sdata->proto = txdr_unsigned(proto);
|
||||
sdata->port = 0;
|
||||
|
||||
sin->sin_port = htons(PMAPPORT);
|
||||
|
@ -381,7 +381,9 @@ krpc_call(sa, prog, vers, func, data, from_p)
|
|||
/* Did the call succeed? */
|
||||
if (reply->rp_status != 0) {
|
||||
error = fxdr_unsigned(u_int32_t, reply->rp_status);
|
||||
printf("rpc denied, status=%d\n", error);
|
||||
if (error == RPC_PROGMISMATCH)
|
||||
goto out;
|
||||
printf("rpc failed, status=%d\n", error);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nfs_boot.c,v 1.28 1996/10/13 01:39:05 christos Exp $ */
|
||||
/* $NetBSD: nfs_boot.c,v 1.29 1996/10/20 13:13:25 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995 Adam Glass, Gordon Ross
|
||||
|
@ -102,7 +102,7 @@ static int bp_getfile __P((struct sockaddr_in *bpsin, char *key,
|
|||
|
||||
/* mountd RPC */
|
||||
static int md_mount __P((struct sockaddr_in *mdsin, char *path,
|
||||
u_char *fh));
|
||||
struct nfs_args *argp));
|
||||
|
||||
char *nfsbootdevname;
|
||||
|
||||
|
@ -256,12 +256,42 @@ nfs_boot_getfh(bpsin, key, ndmntp)
|
|||
char *key; /* root or swap */
|
||||
struct nfs_dlmount *ndmntp; /* output */
|
||||
{
|
||||
struct nfs_args *args;
|
||||
char pathname[MAXPATHLEN];
|
||||
char *sp, *dp, *endp;
|
||||
struct sockaddr_in *sin;
|
||||
int error;
|
||||
|
||||
sin = &ndmntp->ndm_saddr;
|
||||
args = &ndmntp->ndm_args;
|
||||
|
||||
/* Initialize mount args. */
|
||||
bzero((caddr_t) args, sizeof(*args));
|
||||
args->addr = &ndmntp->ndm_saddr;
|
||||
args->addrlen = args->addr->sa_len;
|
||||
#ifdef NFS_BOOT_TCP
|
||||
args->sotype = SOCK_STREAM;
|
||||
#else
|
||||
args->sotype = SOCK_DGRAM;
|
||||
#endif
|
||||
args->fh = ndmntp->ndm_fh;
|
||||
args->hostname = ndmntp->ndm_host;
|
||||
args->flags = NFSMNT_RESVPORT | NFSMNT_NFSV3;
|
||||
|
||||
#ifdef NFS_BOOT_OPTIONS
|
||||
args->flags |= NFS_BOOT_OPTIONS;
|
||||
#endif
|
||||
#ifdef NFS_BOOT_RWSIZE
|
||||
/*
|
||||
* Reduce rsize,wsize for interfaces that consistently
|
||||
* drop fragments of long UDP messages. (i.e. wd8003).
|
||||
* You can always change these later via remount.
|
||||
*/
|
||||
args->flags |= NFSMNT_WSIZE | NFSMNT_RSIZE;
|
||||
args->wsize = NFS_BOOT_RWSIZE;
|
||||
args->rsize = NFS_BOOT_RWSIZE;
|
||||
#endif
|
||||
|
||||
sin = (void*)&ndmntp->ndm_saddr;
|
||||
|
||||
/*
|
||||
* Get server:pathname for "key" (root or swap)
|
||||
|
@ -275,15 +305,29 @@ nfs_boot_getfh(bpsin, key, ndmntp)
|
|||
* Get file handle for "key" (root or swap)
|
||||
* using RPC to mountd/mount
|
||||
*/
|
||||
error = md_mount(sin, pathname, ndmntp->ndm_fh);
|
||||
error = md_mount(sin, pathname, args);
|
||||
if (error)
|
||||
panic("nfs_boot: mountd %s, error=%d", key, error);
|
||||
|
||||
/* Set port number for NFS use. */
|
||||
/* XXX: NFS port is always 2049, right? */
|
||||
error = krpc_portmap(sin, NFS_PROG, NFS_VER2, &sin->sin_port);
|
||||
if (error)
|
||||
panic("nfs_boot: portmap NFS/v2, error=%d", error);
|
||||
#ifdef NFS_BOOT_TCP
|
||||
retry:
|
||||
#endif
|
||||
error = krpc_portmap(sin, NFS_PROG,
|
||||
(args->flags & NFSMNT_NFSV3) ? NFS_VER3 : NFS_VER2,
|
||||
(args->sotype == SOCK_STREAM) ? IPPROTO_TCP : IPPROTO_UDP,
|
||||
&sin->sin_port);
|
||||
|
||||
if (error || (sin->sin_port == htons(0))) {
|
||||
#ifdef NFS_BOOT_TCP
|
||||
if (args->sotype == SOCK_STREAM) {
|
||||
args->sotype = SOCK_DGRAM;
|
||||
goto retry;
|
||||
}
|
||||
#endif
|
||||
panic("nfs_boot: portmap NFS, error=%d", error);
|
||||
}
|
||||
|
||||
/* Construct remote path (for getmntinfo(3)) */
|
||||
dp = ndmntp->ndm_host;
|
||||
|
@ -500,33 +544,48 @@ out:
|
|||
* Also, sets sin->sin_port to the NFS service port.
|
||||
*/
|
||||
static int
|
||||
md_mount(mdsin, path, fhp)
|
||||
md_mount(mdsin, path, argp)
|
||||
struct sockaddr_in *mdsin; /* mountd server address */
|
||||
char *path;
|
||||
u_char *fhp;
|
||||
struct nfs_args *argp;
|
||||
{
|
||||
/* The RPC structures */
|
||||
struct rdata {
|
||||
u_int32_t errno;
|
||||
u_int8_t fh[NFSX_V2FH];
|
||||
union {
|
||||
u_int8_t v2fh[NFSX_V2FH];
|
||||
struct {
|
||||
u_int32_t fhlen;
|
||||
u_int8_t fh[1];
|
||||
} v3fh;
|
||||
} fh;
|
||||
} *rdata;
|
||||
struct mbuf *m;
|
||||
int error;
|
||||
u_int8_t *fh;
|
||||
int minlen, error;
|
||||
|
||||
retry:
|
||||
/* Get port number for MOUNTD. */
|
||||
error = krpc_portmap(mdsin, RPCPROG_MNT, RPCMNT_VER1,
|
||||
&mdsin->sin_port);
|
||||
if (error) return error;
|
||||
error = krpc_portmap(mdsin, RPCPROG_MNT,
|
||||
(argp->flags & NFSMNT_NFSV3) ? RPCMNT_VER3 : RPCMNT_VER1,
|
||||
IPPROTO_UDP, &mdsin->sin_port);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
m = xdr_string_encode(path, strlen(path));
|
||||
if (m == NULL)
|
||||
return ENOMEM;
|
||||
|
||||
/* Do RPC to mountd. */
|
||||
error = krpc_call(mdsin, RPCPROG_MNT, RPCMNT_VER1,
|
||||
RPCMNT_MOUNT, &m, NULL);
|
||||
if (error)
|
||||
error = krpc_call(mdsin, RPCPROG_MNT, (argp->flags & NFSMNT_NFSV3) ?
|
||||
RPCMNT_VER3 : RPCMNT_VER1, RPCMNT_MOUNT, &m, NULL);
|
||||
if (error) {
|
||||
if ((error==RPC_PROGMISMATCH) && (argp->flags & NFSMNT_NFSV3)) {
|
||||
argp->flags &= ~NFSMNT_NFSV3;
|
||||
goto retry;
|
||||
}
|
||||
return error; /* message already freed */
|
||||
}
|
||||
|
||||
/* The reply might have only the errno. */
|
||||
if (m->m_len < 4)
|
||||
|
@ -538,13 +597,26 @@ md_mount(mdsin, path, fhp)
|
|||
goto out;
|
||||
|
||||
/* Have errno==0, so the fh must be there. */
|
||||
if (m->m_len < sizeof(*rdata)) {
|
||||
m = m_pullup(m, sizeof(*rdata));
|
||||
if (m == NULL)
|
||||
if (argp->flags & NFSMNT_NFSV3){
|
||||
argp->fhsize = fxdr_unsigned(u_int32_t, rdata->fh.v3fh.fhlen);
|
||||
if (argp->fhsize > NFSX_V3FHMAX)
|
||||
goto bad;
|
||||
minlen = 2 * sizeof(u_int32_t) + argp->fhsize;
|
||||
} else {
|
||||
argp->fhsize = NFSX_V2FH;
|
||||
minlen = sizeof(u_int32_t) + argp->fhsize;
|
||||
}
|
||||
|
||||
if (m->m_len < minlen) {
|
||||
m = m_pullup(m, minlen);
|
||||
if (m == NULL)
|
||||
return(EBADRPC);
|
||||
rdata = mtod(m, struct rdata *);
|
||||
}
|
||||
bcopy(rdata->fh, fhp, NFSX_V2FH);
|
||||
|
||||
fh = (argp->flags & NFSMNT_NFSV3) ? rdata->fh.v3fh.fh : rdata->fh.v2fh;
|
||||
bcopy(fh, argp->fh, argp->fhsize);
|
||||
|
||||
goto out;
|
||||
|
||||
bad:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nfs_vfsops.c,v 1.51 1996/10/13 01:39:10 christos Exp $ */
|
||||
/* $NetBSD: nfs_vfsops.c,v 1.52 1996/10/20 13:13:26 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993, 1995
|
||||
|
@ -394,7 +394,6 @@ nfs_mount_diskless(ndmntp, mntname, mntflag, vpp)
|
|||
int mntflag;
|
||||
struct vnode **vpp;
|
||||
{
|
||||
struct nfs_args args;
|
||||
struct mount *mp;
|
||||
struct mbuf *m;
|
||||
int error;
|
||||
|
@ -405,43 +404,20 @@ nfs_mount_diskless(ndmntp, mntname, mntflag, vpp)
|
|||
/* Create the mount point. */
|
||||
mp = (struct mount *)malloc((u_long)sizeof(struct mount),
|
||||
M_MOUNT, M_WAITOK);
|
||||
if (mp == NULL)
|
||||
panic("nfs_mountroot: malloc mount for %s", mntname);
|
||||
bzero((char *)mp, (u_long)sizeof(struct mount));
|
||||
#endif
|
||||
mp->mnt_op = &nfs_vfsops;
|
||||
mp->mnt_flag = mntflag;
|
||||
|
||||
/* Initialize mount args. */
|
||||
bzero((caddr_t) &args, sizeof(args));
|
||||
args.addr = (struct sockaddr *)&ndmntp->ndm_saddr;
|
||||
args.addrlen = args.addr->sa_len;
|
||||
args.sotype = SOCK_DGRAM;
|
||||
args.fh = ndmntp->ndm_fh;
|
||||
args.fhsize = NFSX_V2FH;
|
||||
args.hostname = ndmntp->ndm_host;
|
||||
args.flags = NFSMNT_RESVPORT;
|
||||
|
||||
#ifdef NFS_BOOT_OPTIONS
|
||||
args.flags |= NFS_BOOT_OPTIONS;
|
||||
#endif
|
||||
#ifdef NFS_BOOT_RWSIZE
|
||||
/*
|
||||
* Reduce rsize,wsize for interfaces that consistently
|
||||
* drop fragments of long UDP messages. (i.e. wd8003).
|
||||
* You can always change these later via remount.
|
||||
*/
|
||||
args.flags |= NFSMNT_WSIZE | NFSMNT_RSIZE;
|
||||
args.wsize = NFS_BOOT_RWSIZE;
|
||||
args.rsize = NFS_BOOT_RWSIZE;
|
||||
#endif
|
||||
|
||||
/* Get mbuf for server sockaddr. */
|
||||
m = m_get(M_WAIT, MT_SONAME);
|
||||
bcopy((caddr_t)args.addr, mtod(m, caddr_t),
|
||||
(m->m_len = args.addr->sa_len));
|
||||
if (m == NULL)
|
||||
panic("nfs_mountroot: mget soname for %s", mntname);
|
||||
bcopy((caddr_t)ndmntp->ndm_args.addr, mtod(m, caddr_t),
|
||||
(m->m_len = ndmntp->ndm_args.addr->sa_len));
|
||||
|
||||
error = mountnfs(&args, mp, m, mntname, args.hostname, vpp);
|
||||
error = mountnfs(&ndmntp->ndm_args, mp, m, mntname,
|
||||
ndmntp->ndm_args.hostname, vpp);
|
||||
if (error)
|
||||
panic("nfs_mountroot: mount %s failed: %d", mntname, error);
|
||||
|
||||
|
@ -543,6 +519,11 @@ nfs_decode_args(nmp, argp)
|
|||
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_disconnect(nmp);
|
||||
if (nmp->nm_sotype == SOCK_DGRAM)
|
||||
|
@ -683,12 +664,13 @@ 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;
|
||||
nfs_decode_args(nmp, argp);
|
||||
|
||||
/* 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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: nfsdiskless.h,v 1.9 1996/02/18 11:54:00 fvdl Exp $ */
|
||||
/* $NetBSD: nfsdiskless.h,v 1.10 1996/10/20 13:13:28 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
|
@ -50,9 +50,10 @@
|
|||
* client/server byte ordering differences.
|
||||
*/
|
||||
struct nfs_dlmount {
|
||||
struct sockaddr_in ndm_saddr; /* Address of file server */
|
||||
struct nfs_args ndm_args;
|
||||
struct sockaddr ndm_saddr; /* Address of file server */
|
||||
char ndm_host[MNAMELEN]; /* Host name for mount pt */
|
||||
u_char ndm_fh[NFSX_V2FH]; /* The file's file handle */
|
||||
u_char ndm_fh[NFSX_V3FHMAX]; /* The file's file handle */
|
||||
};
|
||||
struct nfs_diskless {
|
||||
struct sockaddr_in nd_boot; /* Address of boot server */
|
||||
|
|
Loading…
Reference in New Issue