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: