Subject: kern/3215: NFS getdirentries(2) result is truncated (with fix)
To: None <gnats-bugs@gnats.netbsd.org>
From: None <soda@sra.co.jp>
List: netbsd-bugs
Date: 02/13/1997 00:31:48
>Number:         3215
>Category:       kern
>Synopsis:       NFS getdirentries(2) result is truncated
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed Feb 12 07:50:00 1997
>Last-Modified:
>Originator:     Hiroshi Tezuka <tezuka@trc.rwcp.or.jp>
>Organization:
Real World Computing Partnership.
>Release:        1.2 and 1.2C (-current Feb 10, 1997)
>Environment:

System: NetBSD mpspc5.trc.rwcp.or.jp 1.2C NetBSD 1.2C (MPSPC) #1: Tue Feb 11 20:51:40 JST 1997 soda@mpspc7.trc.rwcp.or.jp:/amd/u56/mnt5/mpsoft/work/soda.i386/src.netpower/netbsd-19970210/sys/arch/i386/compile/MPSPC i386

>Description:

	Sometimes, getdirentries(2) returns incorrect result
	(not all entries are returned), when the directory is big
	and NFS mounted.

	For example,
	    normal case:
		% /bin/ls -af /home/ | wc
		     857     857    6562 
	    illegal case:
		% /bin/ls -af /home/ | wc
		     294     294    2211 

	    normal case:
		% cd /home/tezuka
		% /bin/pwd
		/amd/sh1/afs/rwcp.or.jp/home/tezuka
	    illegal case:
		% /bin/pwd
		pwd: No such file or directory

	Note, the directory "/home" is not modified during operation.

>How-To-Repeat:

	Assume "/home" is big and NFS mounted.

	% /bin/ls -af /home/ | wc
	     857     857    6562 
		--- reading big directory
	% cd /home/arita
		--- change directory to first entry of /home
	% cat /bin/* /usr/bin/* > /dev/null
		--- clear buffer cache
	% pwd
	/amd/sh1/afs/rwcp.or.jp/home/arita
		--- read to first entry on the /home direcotry
	% /bin/ls -af /home/ | wc
	     294     294    2211 
		--- TRUNCATED !!!
	% cat /bin/* /usr/bin/* > /dev/null
		--- clear buffer cache
	% /bin/ls -af /home/ | wc
	     857     857    6562 
		--- recovered

>Fix:

	Investigating the reason and making fix are done by
	Mr. Hiroshi Tezuka <tezuka@trc.rwcp.or.jp>.

Reason:
	- `n_sillyrename' member and `n_cookie' member in struct nfsnode
	   share same memory. (because they are in same union `n_un3').

	- nfs_inactive() in nfs_node.c makes `n_sillyrename' NULL,
	  even if the vnode is directory, so that `n_cookie' is broken 
	  by accident.

Fix:
	DO NOT break `n_cookie' member, if the vnode is directory.

------------------------------------------------------------------------
Index: nfs_node.c
===================================================================
RCS file: /usr/trc/project/mpsoft/cvs/netbsd/sys/nfs/nfs_node.c,v
retrieving revision 1.1
diff -c -r1.1 nfs_node.c
*** nfs_node.c	1996/08/20 07:46:16	1.1
--- nfs_node.c	1997/02/12 14:47:06
***************
*** 173,183 ****
  	np = VTONFS(ap->a_vp);
  	if (prtactive && ap->a_vp->v_usecount != 0)
  		vprint("nfs_inactive: pushing active", ap->a_vp);
! 	if (ap->a_vp->v_type != VDIR)
  		sp = np->n_sillyrename;
! 	else
  		sp = (struct sillyrename *)0;
- 	np->n_sillyrename = (struct sillyrename *)0;
  	if (sp) {
  		/*
  		 * Remove the silly file that was rename'd earlier
--- 173,183 ----
  	np = VTONFS(ap->a_vp);
  	if (prtactive && ap->a_vp->v_usecount != 0)
  		vprint("nfs_inactive: pushing active", ap->a_vp);
! 	if (ap->a_vp->v_type != VDIR) {
  		sp = np->n_sillyrename;
! 		np->n_sillyrename = (struct sillyrename *)0;
! 	} else
  		sp = (struct sillyrename *)0;
  	if (sp) {
  		/*
  		 * Remove the silly file that was rename'd earlier
------------------------------------------------------------------------
--
soda@sra.co.jp		Software Research Associates, Inc., Japan
(Noriyuki Soda)		   software tools and technology group
>Audit-Trail:
>Unformatted: