Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Jul 1997 04:29:18 -0700 (PDT)
From:      yamagata@nwgpc.kek.jp
To:        freebsd-gnats-submit@FreeBSD.ORG
Subject:   kern/4011: GNU grep on CDROM causes panic
Message-ID:  <199707021129.EAA29117@hub.freebsd.org>
Resent-Message-ID: <199707021130.EAA29169@hub.freebsd.org>

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

>Number:         4011
>Category:       kern
>Synopsis:       GNU grep on CDROM causes panic
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul  2 04:30:00 PDT 1997
>Last-Modified:
>Originator:     yamagata
>Organization:
KEK , Tsukuba , Japan
>Release:        2.2.1-RELEASE
>Environment:
FreeBSD kekhw2.kek.jp 2.2.1-RELEASE FreeBSD 2.2.1-RELEASE #1: Tue Jun 17 12:04:24 JST 1997
>Description:
When GNU grep (maked with option -DHAVE_WORKING_MMAP=1) access files on CDROM,
system will panic, saying "locking against myself".
MSDOS FS seems to have same problem.
>How-To-Repeat:
1) make GNU grep by typing just only "./configure ; make". configure will set the option "-DHAVE_WORKING_MMAP=1".
2) apply grep to files on CDROM, "./grep xxx /cdrom/*"
3) system will panic

if set the option HAVE_WORKING_MMAP 0, panic will not happen.
>Fix:
apply this patch, but this is for FreeBSD-2.1.5.
this patch is contributed by Okamura Yoshihito <okamura@bardot.rim.or.jp>



*** cd9660_node.c.orig	Wed Jun 12 12:41:35 1996
--- cd9660_node.c	Sun Nov 17 17:36:34 1996
*************** iso_ilock(ip)
*** 420,428 ****
  {
  
  	while (ip->i_flag & ILOCKED) {
  		ip->i_flag |= IWANT;
- 		if (ip->i_spare0 == curproc->p_pid)
- 			panic("locking against myself");
  		ip->i_spare1 = curproc->p_pid;
  		(void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
  	}
--- 420,435 ----
  {
  
  	while (ip->i_flag & ILOCKED) {
+ 		if (ip->i_spare0 == curproc->p_pid) {
+ 			if((ip->i_flag & IRECURSE) == 0)
+ 				panic("locking against myself");
+ 			else {
+ 				++ip->i_lockcount;
+ 				return(0);
+ 			}
+ 				
+ 		}
  		ip->i_flag |= IWANT;
  		ip->i_spare1 = curproc->p_pid;
  		(void) tsleep((caddr_t)ip, PINOD, "isoilk", 0);
  	}
*************** iso_iunlock(ip)
*** 440,449 ****
  	register struct iso_node *ip;
  {
  
  	if ((ip->i_flag & ILOCKED) == 0)
  		vprint("iso_iunlock: unlocked inode", ITOV(ip));
  	ip->i_spare0 = 0;
! 	ip->i_flag &= ~ILOCKED;
  	if (ip->i_flag&IWANT) {
  		ip->i_flag &= ~IWANT;
  		wakeup((caddr_t)ip);
--- 447,460 ----
  	register struct iso_node *ip;
  {
  
+ 	if(ip->i_lockcount > 0) {
+ 		--ip->i_lockcount;
+ 		return(0);
+ 	}
  	if ((ip->i_flag & ILOCKED) == 0)
  		vprint("iso_iunlock: unlocked inode", ITOV(ip));
  	ip->i_spare0 = 0;
! 	ip->i_flag &= ~(ILOCKED|IRECURSE);
  	if (ip->i_flag&IWANT) {
  		ip->i_flag &= ~IWANT;
  		wakeup((caddr_t)ip);

*** cd9660_node.h.orig	Fri Mar 17 03:12:16 1995
--- cd9660_node.h	Sun Nov 17 17:11:29 1996
*************** struct iso_node {
*** 95,100 ****
--- 95,101 ----
  	long iso_start;		/* actual start of data of file (may be different */
  				/* from iso_extent, if file has extended attributes) */
  	ISO_RRIP_INODE	inode;
+ 	int		i_lockcount; /* Process lock count (recursion) */
  };
  
  #define	i_forw		i_chain[0]
*************** struct iso_node {
*** 104,109 ****
--- 105,111 ----
  #define	ILOCKED		0x0001		/* inode is locked */
  #define	IWANT		0x0002		/* some process waiting on lock */
  #define	IACC		0x0020		/* inode access time to be updated */
+ #define	IRECURSE	0x0400		/* Recursion expected */
  
  #define VTOI(vp) ((struct iso_node *)(vp)->v_data)
  #define ITOV(ip) ((ip)->i_vnode)

*** cd9660_vnops.c.org	Wed Jun 26 03:30:21 1996
--- cd9660_vnops.c	Sun Nov 17 17:14:38 1996
*************** cd9660_read(ap)
*** 331,337 ****
--- 331,341 ----
  			return (error);
  		}
  
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			ip->i_flag |= IRECURSE;
  		error = uiomove(bp->b_un.b_addr + on, (int)n, uio);
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			ip->i_flag &= ~IRECURSE;
  		brelse(bp);
  	} while (error == 0 && uio->uio_resid > 0 && n != 0);
  	return (error);

*** denode.h.org	Tue May 30 17:07:32 1995
--- denode.h	Sun Nov 17 17:48:48 1996
*************** struct denode {
*** 159,164 ****
--- 159,165 ----
  	u_short de_StartCluster; /* starting cluster of file */
  	u_long de_FileSize;	/* size of file in bytes */
  	struct fatcache de_fc[FC_SIZE];	/* fat cache */
+ 	int	de_lockcount;	/* Process lock count (recursion) */
  };
  
  /*
*************** struct denode {
*** 169,174 ****
--- 170,176 ----
  #define	DE_UPDATE	0x0004	/* modification time update request */
  #define	DE_MODIFIED	0x0080	/* denode has been modified, but DE_UPDATE
  				 * isn't set */
+ #define DE_RECURSE	0x0400	/* Recursion expected */
  
  /*
   * Transfer directory entries between internal and external form.

*** msdosfs_vnops.c.org	Wed Jul  3 03:40:22 1996
--- msdosfs_vnops.c	Sun Nov 17 17:56:08 1996
*************** msdosfs_read(ap)
*** 535,541 ****
--- 535,545 ----
  			brelse(bp);
  			return error;
  		}
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			dep->de_flag |= DE_RECURSE;
  		error = uiomove(bp->b_data + on, (int) n, uio);
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			dep->de_flag &= ~DE_RECURSE;
  		/*
  		 * If we have read everything from this block or have read
  		 * to end of file then we are done with this block.  Mark
*************** msdosfs_write(ap)
*** 728,734 ****
--- 732,742 ----
  		/*
  		 * Copy the data from user space into the buf header.
  		 */
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			dep->de_flag |= DE_RECURSE;
  		error = uiomove(bp->b_data + croffset, n, uio);
+ 		if (uio->uio_segflg != UIO_NOCOPY)
+ 			dep->de_flag &= ~DE_RECURSE;
  
  		/*
  		 * If they want this synchronous then write it and wait for
*************** msdosfs_lock(ap)
*** 1757,1765 ****
  	struct denode *dep = VTODE(ap->a_vp);
  
  	while (dep->de_flag & DE_LOCKED) {
  		dep->de_flag |= DE_WANTED;
- 		if (dep->de_lockholder == curproc->p_pid)
- 			panic("msdosfs_lock: locking against myself");
  		dep->de_lockwaiter = curproc->p_pid;
  		(void) tsleep((caddr_t) dep, PINOD, "msdlck", 0);
  	}
--- 1765,1779 ----
  	struct denode *dep = VTODE(ap->a_vp);
  
  	while (dep->de_flag & DE_LOCKED) {
+ 		if (dep->de_lockholder == curproc->p_pid) {
+ 			if ((dep->de_flag & DE_RECURSE) == 0)
+ 				panic("msdosfs_lock: locking against myself");
+ 			else {
+ 				++dep->de_lockcount;
+ 				return 0;
+ 			}
+ 		}
  		dep->de_flag |= DE_WANTED;
  		dep->de_lockwaiter = curproc->p_pid;
  		(void) tsleep((caddr_t) dep, PINOD, "msdlck", 0);
  	}
*************** msdosfs_unlock(ap)
*** 1777,1786 ****
  {
  	struct denode *dep = VTODE(ap->a_vp);
  
  	if (!(dep->de_flag & DE_LOCKED))
  		panic("msdosfs_unlock: denode not locked");
  	dep->de_lockholder = 0;
! 	dep->de_flag &= ~DE_LOCKED;
  	if (dep->de_flag & DE_WANTED) {
  		dep->de_flag &= ~DE_WANTED;
  		wakeup((caddr_t) dep);
--- 1791,1804 ----
  {
  	struct denode *dep = VTODE(ap->a_vp);
  
+ 	if(dep->de_lockcount > 0) {
+ 		--dep->de_lockcount;
+ 		return 0;
+ 	}
  	if (!(dep->de_flag & DE_LOCKED))
  		panic("msdosfs_unlock: denode not locked");
  	dep->de_lockholder = 0;
! 	dep->de_flag &= ~(DE_LOCKED|DE_RECURSE);
  	if (dep->de_flag & DE_WANTED) {
  		dep->de_flag &= ~DE_WANTED;
  		wakeup((caddr_t) dep);


>Audit-Trail:
>Unformatted:



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