⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jfs_imap.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 = -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] == 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 = -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 = -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 = -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);}/* * There are several places in the diAlloc* routines where we initialize * the inode. */static inline voiddiInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp){	struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb);	struct jfs_inode_info *jfs_ip = JFS_IP(ip);	ip->i_ino = (iagno << L2INOSPERIAG) + ino;	DBG_DIALLOC(JFS_IP(ipimap)->i_imap, ip->i_ino);	jfs_ip->ixpxd = iagp->inoext[extno];	jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);	jfs_ip->active_ag = -1;}/* * NAME:        diAlloc(pip,dir,ip) * * FUNCTION:    allocate a disk inode from the inode working map  *		for a fileset or aggregate. * * PARAMETERS: *      pip  	- pointer to incore inode for the parent inode. *      dir  	- TRUE if the new disk inode is for a directory. *      ip  	- pointer to a new inode * * RETURN VALUES: *      0       - success. *      -ENOSPC	- insufficient disk resources. *      -EIO  	- i/o error. */int diAlloc(struct inode *pip, boolean_t dir, struct inode *ip){	int rc, ino, iagno, addext, extno, bitno, sword;	int nwords, rem, i, agno;	u32 mask, inosmap, extsmap;	struct inode *ipimap;	struct metapage *mp;	ino_t inum;	struct iag *iagp;	struct inomap *imap;	/* get the pointers to the inode map inode and the	 * corresponding imap control structure.	 */	ipimap = JFS_SBI(pip->i_sb)->ipimap;	imap = JFS_IP(ipimap)->i_imap;	JFS_IP(ip)->ipimap = ipimap;	JFS_IP(ip)->fileset = FILESYSTEM_I;	/* for a directory, the allocation policy is to start 	 * at the ag level using the preferred ag.	 */	if (dir == TRUE) {		agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);		AG_LOCK(imap, agno);		goto tryag;	}	/* for files, the policy starts off by trying to allocate from	 * the same iag containing the parent disk inode:	 * try to allocate the new disk inode close to the parent disk	 * inode, using parent disk inode number + 1 as the allocation	 * hint.  (we use a left-to-right policy to attempt to avoid	 * moving backward on the disk.)  compute the hint within the	 * file system and the iag.	 */	/* get the ag number of this iag */	agno = JFS_IP(pip)->agno;	if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) {		/*		 * There is an open file actively growing.  We want to		 * allocate new inodes from a different ag to avoid		 * fragmentation problems.		 */		agno = dbNextAG(JFS_SBI(pip->i_sb)->ipbmap);		AG_LOCK(imap, agno);		goto tryag;	}	inum = pip->i_ino + 1;	ino = inum & (INOSPERIAG - 1);	/* back off the the hint if it is outside of the iag */	if (ino == 0)		inum = pip->i_ino;	/* lock the AG inode map information */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -