Subject: kern/1780: kernel w/NFSSERVER but w/o NFSCLIENT crashes
To: None <gnats-bugs@gnats.netbsd.org>
From: Chris G. Demetriou <cgd@NetBSD.ORG>
List: netbsd-bugs
Date: 11/22/1995 18:43:45
>Number: 1780
>Category: kern
>Synopsis: NFSSERVER option won't work w/o NFSCLIENT option.
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: kern-bug-people (Kernel Bug People)
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Nov 22 19:05:04 1995
>Last-Modified:
>Originator: Chris G. Demetriou
>Organization:
Kernel Hackers 'r' Us
>Release: NetBSD-current (trunk) 11/22/95
>Environment:
System: NetBSD sun-lamp.pc.cs.cmu.edu 1.0A NetBSD 1.0A (SUN_LAMP) #9: Wed Nov 22 16:05:06 EST 1995 cgd@sun-lamp.pc.cs.cmu.edu:/usr/src/sys/arch/i386/compile/SUN_LAMP i386
>Description:
A kernel compiled with 'options NFSSERVER' but without
'options NFSCLIENT' will crash rather quickly on boot.
This has been a problem with the NetBSD source tree
for a Long Time.
The problem is that the NFS data structures that
are used exclusively the NFS server, or that are
shared between the server and the client are
initialized only in the nfs_init() function. however,
nfs_init() is the NFS vfs's VFS "init" operation,
which is only invoked if NFSCLIENT is defined.
Because some of its (important) data structures
are uninitialized, the NFSSERVER code crashes
pretty quickly.
>How-To-Repeat:
Compile a kernel with 'options NFSSERVER', but
WITHOUT 'options NFSCLIENT'. Boot it. It should
crash while loading /sbin/init or soon afterward.
>Fix:
The diff included below solves the problem. (I'm
sending it as a PR, because it fixes the problem
but i'm not sure i like the method i used to fix
it, and don't care to argue for it...)
The diff does the following:
(1) invokes the nfs_init() function
in main() in init_main.c before
vfsinit(), if NFSSERVER or NFSCLIENT
is defined.
(2) moves client-specific init code
into nfs_vfs_init(), and makes
that the NFS VFS "init" function.
nfs_init() initializes the data structures
shared by the client and the server, and the
server-specific data structures. nfs_vfs_init()
is invoked by the vfs initialization process
to do the NFS client (VFS) data structures.
Index: kern/init_main.c
===================================================================
RCS file: /a/cvsroot/src/sys/kern/init_main.c,v
retrieving revision 1.78
diff -c -r1.78 init_main.c
*** init_main.c 1995/10/07 06:28:05 1.78
--- init_main.c 1995/11/22 23:33:37
***************
*** 72,77 ****
--- 72,81 ----
#include <vm/vm.h>
+ #if defined(NFSSERVER) || defined(NFSCLIENT)
+ #include <nfs/nfsmount.h> /* proto for nfs_init() */
+ #endif
+
char copyright[] =
"Copyright (c) 1982, 1986, 1989, 1991, 1993\n\tThe Regents of the University of California. All rights reserved.\n\n";
***************
*** 242,247 ****
--- 246,254 ----
vm_init_limits(p);
/* Initialize the file systems. */
+ #if defined(NFSSERVER) || defined(NFSCLIENT)
+ nfs_init(); /* initialize server/shared data */
+ #endif
vfsinit();
/* Start real time and statistics clocks. */
Index: nfs/nfs_subs.c
===================================================================
RCS file: /a/cvsroot/src/sys/nfs/nfs_subs.c,v
retrieving revision 1.21
diff -c -r1.21 nfs_subs.c
*** nfs_subs.c 1995/09/08 13:52:23 1.21
--- nfs_subs.c 1995/11/22 23:33:39
***************
*** 578,585 ****
}
/*
! * Called once to initialize data structures...
*/
nfs_init()
{
register int i;
--- 578,587 ----
}
/*
! * Called once before VFS init to initialize shared and
! * server-specific data structures.
*/
+ void
nfs_init()
{
register int i;
***************
*** 603,619 ****
/* Loop thru nfs procids */
for (i = 0; i < NFS_NPROCS; i++)
nfs_procids[i] = txdr_unsigned(i);
- #ifdef NFSCLIENT
- /* Ensure async daemons disabled */
- for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
- nfs_iodwant[i] = (struct proc *)0;
- TAILQ_INIT(&nfs_bufq);
- nfs_nhinit(); /* Init the nfsnode table */
- #endif /* NFSCLIENT */
#ifdef NFSSERVER
nfsrv_init(0); /* Init server data structures */
nfsrv_initcache(); /* Init the server request cache */
- #endif /* NFSSERVER */
/*
* Initialize the nqnfs server stuff.
--- 605,613 ----
***************
*** 627,632 ****
--- 621,627 ----
CIRCLEQ_INIT(&nqtimerhead);
nqfhhashtbl = hashinit(NQLCHSZ, M_NQLEASE, &nqfhhash);
}
+ #endif /* NFSSERVER */
/*
* Initialize reply list and start timer
***************
*** 636,641 ****
--- 631,651 ----
}
#ifdef NFSCLIENT
+ /*
+ * Called once at VFS init to initialize client-specific data structures.
+ */
+ void
+ nfs_vfs_init()
+ {
+ register int i;
+
+ /* Ensure async daemons disabled */
+ for (i = 0; i < NFS_MAXASYNCDAEMON; i++)
+ nfs_iodwant[i] = (struct proc *)0;
+ TAILQ_INIT(&nfs_bufq);
+ nfs_nhinit(); /* Init the nfsnode table */
+ }
+
/*
* Attribute cache routines.
* nfs_loadattrcache() - loads or updates the cache contents from attributes
Index: nfs/nfs_vfsops.c
===================================================================
RCS file: /a/cvsroot/src/sys/nfs/nfs_vfsops.c,v
retrieving revision 1.38
diff -c -r1.38 nfs_vfsops.c
*** nfs_vfsops.c 1995/08/13 00:00:08 1.38
--- nfs_vfsops.c 1995/11/22 23:33:45
***************
*** 81,87 ****
nfs_vget,
nfs_fhtovp,
nfs_vptofh,
! nfs_init,
};
extern u_long nfs_procids[NFS_NPROCS];
--- 81,87 ----
nfs_vget,
nfs_fhtovp,
nfs_vptofh,
! nfs_vfs_init,
};
extern u_long nfs_procids[NFS_NPROCS];
Index: nfs/nfsmount.h
===================================================================
RCS file: /a/cvsroot/src/sys/nfs/nfsmount.h,v
retrieving revision 1.8
diff -c -r1.8 nfsmount.h
*** nfsmount.h 1995/03/26 20:37:31 1.8
--- nfsmount.h 1995/11/22 23:33:45
***************
*** 125,128 ****
int nfs_vptofh __P((
struct vnode *vp,
struct fid *fhp));
! int nfs_init __P(());
--- 125,133 ----
int nfs_vptofh __P((
struct vnode *vp,
struct fid *fhp));
! int nfs_vfs_init __P((void));
!
! /*
! * Prototypes for miscellaneous exported NFS functions.
! */
! void nfs_init __P((void));
>Audit-Trail:
>Unformatted: