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:
fvdl 1996-10-20 13:13:22 +00:00
parent 7133ecf2ca
commit 735944405b
5 changed files with 120 additions and 63 deletions

View File

@ -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));

View File

@ -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;
}

View File

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

View File

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

View File

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