[net.bugs.4bsd] flock bug report with fix

robin@gatech.CSNET (Robin Cutshaw) (02/20/86)

Program: /sys/sys/sys_inode.c
Severity: major
Releases:  BSD4.2, BRL 3.0, Ultrix 1.1

Description:
  The flock system call invokes ino_lock() in /sys/sys/sys_inode.c.
Ino_lock() loops waiting for release of an exclusive lock and then
loops waiting for release of shared locks if the request is an
exclusive lock.  When all shared locks release, any AND ALL exclusive
lock requests will be granted (yes more than one exclusive lock will
pass).

Repeat-By:
  Crank up a process that will request a shared lock and wait for a
few seconds, then release.  After the shared lock process has locked
but before it releases, crank up multiple processes requesting
exclusive locks.  When the shared lock clears, all of the exclusive
requests will succeed simultaneously.

Fix:
  In vanilla 4.2 :

*** sys_inode.c.4.2	Fri Jul 29 10:07:21 1983
--- sys_inode.c.4.2.rkc	Wed Feb 19 12:08:35 1986
***************
*** 390,395
  		/*
  		 * Must wait for any shared locks to finish
  		 * before we try to apply a exclusive lock.
  		 */
  		while (ip->i_flag & ISHLOCK) {
  			if (cmd & LOCK_NB)

--- 390,398 -----
  		/*
  		 * Must wait for any shared locks to finish
  		 * before we try to apply a exclusive lock.
+                  *
+                  * We must also wait if an exclusive lock
+                  * was applied during our last wait. (gatech!robin)
  		 */
  		while (ip->i_flag & ISHLOCK) {
  			if (cmd & LOCK_NB)
***************
*** 404,409
  			}
  			ip->i_flag |= ILWAIT;
  			sleep((caddr_t)&ip->i_shlockc, PLOCK);
  		}
  	}
  	if (fp->f_flag & (FSHLOCK|FEXLOCK))

--- 407,414 -----
  			}
  			ip->i_flag |= ILWAIT;
  			sleep((caddr_t)&ip->i_shlockc, PLOCK);
+ 			if (ip->i_flag & IEXLOCK)
+ 				goto again;
  		}
  	}
  	if (fp->f_flag & (FSHLOCK|FEXLOCK))
====================================================================
  In BRL unix :

*** sys_inode.c.brl	Thu May  2 16:47:31 1985
--- sys_inode.c.brl.rkc	Wed Feb 19 10:56:14 1986
***************
*** 400,405
  		/*
  		 * Must wait for any shared locks to finish
  		 * before we try to apply a exclusive lock.
  		 */
  		while (ip->i_flag & ISHLOCK) {
  			/*

--- 400,408 -----
  		/*
  		 * Must wait for any shared locks to finish
  		 * before we try to apply a exclusive lock.
+                  *
+                  * We must also wait if an exclusive lock
+                  * was applied during our last wait. (gatech!robin)
  		 */
  		while (ip->i_flag & ISHLOCK) {
  			/*
***************
*** 414,419
  				return (EWOULDBLOCK);
  			ip->i_flag |= ILWAIT;
  			csleep((caddr_t)&ip->i_shlockc, PLOCK, "EXCL OPEN");
  		}
  	}
  	if (fp->f_flag & (FSHLOCK|FEXLOCK))

--- 417,424 -----
  				return (EWOULDBLOCK);
  			ip->i_flag |= ILWAIT;
  			csleep((caddr_t)&ip->i_shlockc, PLOCK, "EXCL OPEN");
+ 			if (ip->i_flag & IEXLOCK)
+ 				goto again;
  		}
  	}
  	if (fp->f_flag & (FSHLOCK|FEXLOCK))
====================================================================
-- 
Robin K. Cutshaw
School of Information & Computer Science, Georgia Tech, Atlanta GA 30332
CSNet:  robin @ GATech		ARPA:  robin%GATech.CSNet @ CSNet-Relay.ARPA
uucp:  ...!{akgua,allegra,amd,hplabs,ihnp4,seismo,ut-ngp}!gatech!robin

robin@gatech.CSNET (Robin Cutshaw) (02/22/86)

Note that for vanilla bsd4.2 this bug does not exist due to the
ILWAIT bit being checked.  In derivative systems (and probably 4.3)
the ILWAIT check was removed, thereby causing the bug.  This bug
does exist in Ultrix 1.1 and BRL version 3.0.

robin
-- 
Robin K. Cutshaw
School of Information & Computer Science, Georgia Tech, Atlanta GA 30332
CSNet:  robin @ GATech		ARPA:  robin%GATech.CSNet @ CSNet-Relay.ARPA
uucp:  ...!{akgua,allegra,amd,hplabs,ihnp4,seismo,ut-ngp}!gatech!robin