Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 13 Apr 1997 13:58:59 +0900 (JST)
From:      kato@eclogite.eps.nagoya-u.ac.jp
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   kern/3271: deadlock problem in union_fsync
Message-ID:  <199704130458.NAA00314@marble.eps.nagoya-u.ac.jp>
Resent-Message-ID: <199704130500.WAA15842@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         3271
>Category:       kern
>Synopsis:       deadlock problem in union_fsync
>Confidential:   no
>Severity:       critical
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Apr 12 22:00:00 PDT 1997
>Last-Modified:
>Originator:     KATO Takenori
>Organization:
Dept. Earth Planet Sci, Nagoya Univ.
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

	

>Description:

The function union_fsync tries to lock overlaying vnode object when
dolock is not set (that is, targetvp == overlaying vnode object).
Current code use FIXUP macro to do this, and never unlocks overlaying
vnode object in union_fsync.  So, the vnode object will be locked
twice and never unlocked.

>How-To-Repeat:

	

>Fix:
---------- BEGIN ----------
*** union_vnops.c.ORIG	Sun Apr 13 13:43:15 1997
--- union_vnops.c	Sun Apr 13 13:43:29 1997
***************
*** 917,933 ****
  	int error = 0;
  	struct proc *p = ap->a_p;
  	struct vnode *targetvp = OTHERVP(ap->a_vp);
  
  	if (targetvp != NULLVP) {
  		int dolock = (targetvp == LOWERVP(ap->a_vp));
  
  		if (dolock)
  			vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
! 		else
! 			FIXUP(VTOUNION(ap->a_vp), p);
  		error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
  		if (dolock)
  			VOP_UNLOCK(targetvp, 0, p);
  	}
  
  	return (error);
--- 917,944 ----
  	int error = 0;
  	struct proc *p = ap->a_p;
  	struct vnode *targetvp = OTHERVP(ap->a_vp);
+ 	struct union_node *un;
+ 	int isupperlocked = 0;
  
  	if (targetvp != NULLVP) {
  		int dolock = (targetvp == LOWERVP(ap->a_vp));
  
+ 		un = VTOUNION(ap->a_vp);
  		if (dolock)
  			vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
! 		else if ((un->un_flags & UN_ULOCK) == 0 &&
! 				 VOP_ISLOCKED(targetvp) == 0) {
! 			isupperlocked = 1;
! 			vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
! 			un->un_flags |= UN_ULOCK;
! 		}
  		error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
  		if (dolock)
  			VOP_UNLOCK(targetvp, 0, p);
+ 		else if (isupperlocked) {
+ 			VOP_UNLOCK(targetvp, 0, p);
+ 			un->un_flags &= ~UN_ULOCK;
+ 		}
  	}
  
  	return (error);
---------- END ----------

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199704130458.NAA00314>