DBG_DIFREE(imap, inum); 
int diFree(struct inode *ip){	int rc;	ino_t inum = ip->i_ino;	struct iag *iagp, *aiagp, *biagp, *ciagp, *diagp;	struct metapage *mp, *amp, *bmp, *cmp, *dmp;	int iagno, ino, extno, bitno, sword, agno;	int back, fwd;	u32 bitmap, mask;	struct inode *ipimap = JFS_SBI(ip->i_sb)->ipimap;	struct inomap *imap = JFS_IP(ipimap)->i_imap;	pxd_t freepxd;	tid_t tid;	struct inode *iplist[3];	struct tlock *tlck;	struct pxd_lock *pxdlock;	/*	 * This is just to suppress compiler warnings.  The same logic that	 * references these variables is used to initialize them.	 */	aiagp = biagp = ciagp = diagp = NULL;	/* get the iag number containing the inode.	 */	iagno = INOTOIAG(inum);	/* make sure that the iag is contained within 	 * the map.	 */	if (iagno >= imap->im_nextiag) {		dump_mem("imap", imap, 32);		jfs_error(ip->i_sb,			  "diFree: inum = %d, iagno = %d, nextiag = %d",			  (uint) inum, iagno, imap->im_nextiag);		return -EIO;	}	/* get the allocation group for this ino.	 */	agno = JFS_IP(ip)->agno;	/* Lock the AG specific inode map information	 */	AG_LOCK(imap, agno);	/* Obtain read lock in imap inode.  Don't release it until we have	 * read all of the IAG's that we are going to.	 */	IREAD_LOCK(ipimap);	/* read the iag.	 */	if ((rc = diIAGRead(imap, iagno, &mp))) {		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		return (rc);	}	iagp = (struct iag *) mp->data;	/* get the inode number and extent number of the inode within	 * the iag and the inode number within the extent.	 */	ino = inum & (INOSPERIAG - 1);	extno = ino >> L2INOSPEREXT;	bitno = ino & (INOSPEREXT - 1);	mask = HIGHORDER >> bitno;	if (!(le32_to_cpu(iagp->wmap[extno]) & mask)) {		jfs_error(ip->i_sb,			  "diFree: wmap shows inode already free");	}	if (!addressPXD(&iagp->inoext[extno])) {		release_metapage(mp);		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		jfs_error(ip->i_sb, "diFree: invalid inoext");		return -EIO;	}	/* compute the bitmap for the extent reflecting the freed inode.	 */	bitmap = le32_to_cpu(iagp->wmap[extno]) & ~mask;	if (imap->im_agctl[agno].numfree > imap->im_agctl[agno].numinos) {		release_metapage(mp);		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		jfs_error(ip->i_sb, "diFree: numfree > numinos");		return -EIO;	}	/*	 *      inode extent still has some inodes or below low water mark:	 *      keep the inode extent;	 */	if (bitmap ||	    imap->im_agctl[agno].numfree < 96 ||	    (imap->im_agctl[agno].numfree < 288 &&	     (((imap->im_agctl[agno].numfree * 100) /	       imap->im_agctl[agno].numinos) <= 25))) {		/* if the iag currently has no free inodes (i.e.,		 * the inode being freed is the first free inode of iag),		 * insert the iag at head of the inode free list for the ag.		 */		if (iagp->nfreeinos == 0) {			/* check if there are any iags on the ag inode			 * free list.  if so, read the first one so that			 * we can link the current iag onto the list at			 * the head.			 */			if ((fwd = imap->im_agctl[agno].inofree) >= 0) {				/* read the iag that currently is the head				 * of the list.				 */				if ((rc = diIAGRead(imap, fwd, &amp))) {					IREAD_UNLOCK(ipimap);					AG_UNLOCK(imap, agno);					release_metapage(mp);					return (rc);				}				aiagp = (struct iag *) amp->data;				/* make current head point back to the iag.				 */				aiagp->inofreeback = cpu_to_le32(iagno);				write_metapage(amp);			}			/* iag points forward to current head and iag			 * becomes the new head of the list.			 */			iagp->inofreefwd =			    cpu_to_le32(imap->im_agctl[agno].inofree);			iagp->inofreeback = cpu_to_le32(-1);			imap->im_agctl[agno].inofree = iagno;		}		IREAD_UNLOCK(ipimap);		/* update the free inode summary map for the extent if		 * freeing the inode means the extent will now have free		 * inodes (i.e., the inode being freed is the first free 		 * inode of extent),		 */		if (iagp->wmap[extno] == cpu_to_le32(ONES)) {			sword = extno >> L2EXTSPERSUM;			bitno = extno & (EXTSPERSUM - 1);			iagp->inosmap[sword] &=			    cpu_to_le32(~(HIGHORDER >> bitno));		}		/* update the bitmap.		 */		iagp->wmap[extno] = cpu_to_le32(bitmap);		DBG_DIFREE(imap, inum);		/* update the free inode counts at the iag, ag and		 * map level.		 */		iagp->nfreeinos =		    cpu_to_le32(le32_to_cpu(iagp->nfreeinos) + 1);		imap->im_agctl[agno].numfree += 1;		atomic_inc(&imap->im_numfree);		/* release the AG inode map lock		 */		AG_UNLOCK(imap, agno);		/* write the iag */		write_metapage(mp);		return (0);	}	/*	 *      inode extent has become free and above low water mark:	 *      free the inode extent;	 */	/*	 *      prepare to update iag list(s) (careful update step 1)	 */	amp = bmp = cmp = dmp = NULL;	fwd = back = -1;	/* check if the iag currently has no free extents.  if so,	 * it will be placed on the head of the ag extent free list.	 */	if (iagp->nfreeexts == 0) {		/* check if the ag extent free list has any iags.		 * if so, read the iag at the head of the list now.		 * this (head) iag will be updated later to reflect		 * the addition of the current iag at the head of		 * the list.		 */		if ((fwd = imap->im_agctl[agno].extfree) >= 0) {			if ((rc = diIAGRead(imap, fwd, &amp)))				goto error_out;			aiagp = (struct iag *) amp->data;		}	} else {		/* iag has free extents. check if the addition of a free		 * extent will cause all extents to be free within this		 * iag.  if so, the iag will be removed from the ag extent		 * free list and placed on the inode map's free iag list.		 */		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) {			/* in preparation for removing the iag from the			 * ag extent free list, read the iags preceeding			 * and following the iag on the ag extent free			 * list.			 */			if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) {				if ((rc = diIAGRead(imap, fwd, &amp)))					goto error_out;				aiagp = (struct iag *) amp->data;			}			if ((back = le32_to_cpu(iagp->extfreeback)) >= 0) {				if ((rc = diIAGRead(imap, back, &bmp)))					goto error_out;				biagp = (struct iag *) bmp->data;			}		}	}	/* remove the iag from the ag inode free list if freeing	 * this extent cause the iag to have no free inodes.	 */	if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) {		int inofreeback = le32_to_cpu(iagp->inofreeback);		int inofreefwd = le32_to_cpu(iagp->inofreefwd);		/* in preparation for removing the iag from the		 * ag inode free list, read the iags preceeding		 * and following the iag on the ag inode free		 * list.  before reading these iags, we must make		 * sure that we already don't have them in hand		 * from up above, since re-reading an iag (buffer)		 * we are currently holding would cause a deadlock.		 */		if (inofreefwd >= 0) {			if (inofreefwd == fwd)				ciagp = (struct iag *) amp->data;			else if (inofreefwd == back)				ciagp = (struct iag *) bmp->data;			else {				if ((rc =				     diIAGRead(imap, inofreefwd, &cmp)))					goto error_out;				ciagp = (struct iag *) cmp->data;			}			assert(ciagp != NULL);		}		if (inofreeback >= 0) {			if (inofreeback == fwd)				diagp = (struct iag *) amp->data;			else if (inofreeback == back)				diagp = (struct iag *) bmp->data;			else {				if ((rc =				     diIAGRead(imap, inofreeback, &dmp)))					goto error_out;				diagp = (struct iag *) dmp->data;			}			assert(diagp != NULL);		}	}	IREAD_UNLOCK(ipimap);	/*	 * invalidate any page of the inode extent freed from buffer cache;	 */	freepxd = iagp->inoext[extno];	invalidate_pxd_metapages(ip, freepxd);	/*	 *      update iag list(s) (careful update step 2)	 */	/* add the iag to the ag extent free list if this is the	 * first free extent for the iag.	 */	if (iagp->nfreeexts == 0) {		if (fwd >= 0)			aiagp->extfreeback = cpu_to_le32(iagno);		iagp->extfreefwd =		    cpu_to_le32(imap->im_agctl[agno].extfree);		iagp->extfreeback = cpu_to_le32(-1);		imap->im_agctl[agno].extfree = iagno;	} else {		/* remove the iag from the ag extent list if all extents		 * are now free and place it on the inode map iag free list.		 */		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG - 1)) {			if (fwd >= 0)				aiagp->extfreeback = iagp->extfreeback;			if (back >= 0)				biagp->extfreefwd = iagp->extfreefwd;			else				imap->im_agctl[agno].extfree =				    le32_to_cpu(iagp->extfreefwd);			iagp->extfreefwd = iagp->extfreeback = cpu_to_le32(-1);			IAGFREE_LOCK(imap);			iagp->iagfree = cpu_to_le32(imap->im_freeiag);			imap->im_freeiag = iagno;			IAGFREE_UNLOCK(imap);		}	}	/* remove the iag from the ag inode free list if freeing	 * this extent causes the iag to have no free inodes.	 */	if (iagp->nfreeinos == cpu_to_le32(INOSPEREXT - 1)) {		if ((int) le32_to_cpu(iagp->inofreefwd) >= 0)			ciagp->inofreeback = iagp->inofreeback;		if ((int) le32_to_cpu(iagp->inofreeback) >= 0)			diagp->inofreefwd = iagp->inofreefwd;		else			imap->im_agctl[agno].inofree =			    le32_to_cpu(iagp->inofreefwd);		iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);	}	/* update the inode extent address and working map 	 * to reflect the free extent.	 * the permanent map should have been updated already 	 * for the inode being freed.	 */	if (iagp->pmap[extno] != 0) {		jfs_error(ip->i_sb, "diFree: the pmap does not show inode free");	}	iagp->wmap[extno] = 0;	DBG_DIFREE(imap, inum);	PXDlength(&iagp->inoext[extno], 0);	PXDaddress(&iagp->inoext[extno], 0);	/* update the free extent and free inode summary maps	 * to reflect the freed extent.	 * the inode summary map is marked to indicate no inodes 	 * available for the freed extent.	 */	sword = extno >> L2EXTSPERSUM;	bitno = extno & (EXTSPERSUM - 1);	mask = HIGHORDER >> bitno;	iagp->inosmap[sword] |= cpu_to_le32(mask);	iagp->extsmap[sword] &= cpu_to_le32(~mask);	/* update the number of free inodes and number of free extents	 * for the iag.	 */	iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) -				      (INOSPEREXT - 1));	iagp->nfreeexts = cpu_to_le32(le32_to_cpu(iagp->nfreeexts) + 1);	/* update the number of free inodes and backed inodes	 * at the ag and inode map level.	 */	imap->im_agctl[agno].numfree -= (INOSPEREXT - 1);	imap->im_agctl[agno].numinos -= INOSPEREXT;	atomic_sub(INOSPEREXT - 1, &imap->im_numfree);	atomic_sub(INOSPEREXT, &imap->im_numinos);	if (amp)		write_metapage(amp);	if (bmp)		write_metapage(bmp);	if (cmp)		write_metapage(cmp);	if (dmp)		write_metapage(dmp);	/*	 * start transaction to update block allocation map	 * for the inode extent freed;	 *	 * N.B. AG_LOCK is released and iag will be released below, and 	 * other thread may allocate inode from/reusing the ixad freed	 * BUT with new/different backing inode extent from the extent 	 * to be freed by the transaction;  	 */	tid = txBegin(ipimap->i_sb, COMMIT_FORCE);	down(&JFS_IP(ipimap)->commit_sem);	/* acquire tlock of the iag page of the freed ixad 	 * to force the page NOHOMEOK (even though no data is	 * logged from the iag page) until NOREDOPAGE|FREEXTENT log 	 * for the free of the extent is committed;	 * write FREEXTENT|NOREDOPAGE log record	 * N.B. linelock is overlaid as freed extent descriptor;	 */	tlck = txLock(tid, ipimap, mp, tlckINODE | tlckFREE);	pxdlock = (struct pxd_lock *) & tlck->lock;	pxdlock->flag = mlckFREEPXD;	pxdlock->pxd = freepxd;	pxdlock->index = 1;	write_metapage(mp);	iplist[0] = ipimap;	/*	 * logredo needs the IAG number and IAG extent index in order	 * to ensure that the IMap is consistent.  The least disruptive	 * way to pass these values through  to the transaction manager	 * is in the iplist array.  	 * 	 * It's not pretty, but it works.	 */	iplist[1] = (struct inode *) (size_t)iagno;	iplist[2] = (struct inode *) (size_t)extno;	rc = txCommit(tid, 1, &iplist[0], COMMIT_FORCE);	txEnd(tid);	up(&JFS_IP(ipimap)->commit_sem);	/* unlock the AG inode map information */	AG_UNLOCK(imap, agno);	return (0);      error_out:	IREAD_UNLOCK(ipimap);	if (amp)		release_metapage(amp);	if (bmp)		release_metapage(bmp);	if (cmp)		release_metapage(cmp);	if (dmp)		release_metapage(dmp);	AG_UNLOCK(imap, agno);	release_metapage(mp);	return (rc);}
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/b38a3ab3d1bb0dc3288f73903d4dc4672b5cd2d0/jfs_imap.c/buggy/fs/jfs/jfs_imap.c