Subject: kern/1512: vnode device driver fails to lock properly, causing union failures
To: None <gnats-bugs@gnats.netbsd.org>
From: John Kohl <jtk@kolvir.arlington.ma.us>
List: netbsd-bugs
Date: 09/26/1995 00:01:21
>Number:         1512
>Category:       kern
>Synopsis:       vnode device driver fails to lock properly, causing union failures
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Sep 26 00:50:01 1995
>Last-Modified:
>Originator:     John Kohl
>Organization:
NetBSD Kernel Hackers `R` Us
>Release:        NetBSD-current as of about 1995/09/22
>Environment:
	
System: NetBSD pattern 1.0A NetBSD 1.0A (PATTERN) #131: Mon Sep 25 23:51:33 EDT 1995 jtk@pattern:/u1/NetBSD-current/src/sys/arch/i386/compile/PATTERN i386


>Description:
	The union filesystem requires its callers to properly
lock/unlock before calling VOP_* which use locked arguments.  the vnode
driver code doesn't do that.
>How-To-Repeat:
	On a DIAGNOSTIC kernel, mount a union FS over /usr/src, go to
/usr/src/distrib/i386/floppies/inst and make inst-10A.fs.
Then try to unmount the union FS and watch it panic with a locking error
(the locking process will no longer exist).

>Fix:
This seems to do the trick.  I found another locking violation inside
vnd.c at the same time.

===================================================================
RCS file: RCS/vnd.c,v
retrieving revision 1.1
diff -c -r1.1 vnd.c
*** vnd.c	1995/09/26 03:49:05	1.1
--- sys/dev/vnd.c	1995/09/26 03:51:02
***************
*** 228,234 ****
--- 228,236 ----
  		int off, s, nra;
  
  		nra = 0;
+ 		VOP_LOCK(vnd->sc_vp);
  		error = VOP_BMAP(vnd->sc_vp, bn / bsize, &vp, &nbn, &nra);
+ 		VOP_UNLOCK(vnd->sc_vp);
  		if (error == 0 && (long)nbn == -1)
  			error = EIO;
  #ifdef DEBUG
***************
*** 508,514 ****
--- 510,518 ----
  	auio.uio_rw = UIO_READ;
  	auio.uio_segflg = UIO_SYSSPACE;
  	auio.uio_resid = aiov.iov_len;
+ 	VOP_LOCK(vnd->sc_vp);
  	error = VOP_READ(vnd->sc_vp, &auio, 0, vnd->sc_cred);
+ 	VOP_UNLOCK(vnd->sc_vp);
  
  	free(tmpbuf, M_TEMP);
  	return (error);

>Audit-Trail:
>Unformatted: