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

📄 jfs_imap.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	AG_LOCK(imap, agno);	/* Get read lock on imap inode */	IREAD_LOCK(ipimap);	/* get the iag number and read the iag */	iagno = INOTOIAG(inum);	if ((rc = diIAGRead(imap, iagno, &mp))) {		IREAD_UNLOCK(ipimap);		AG_UNLOCK(imap, agno);		return (rc);	}	iagp = (struct iag *) mp->data;	/* determine if new inode extent is allowed to be added to the iag.	 * new inode extent can be added to the iag if the ag	 * has less than 32 free disk inodes and the iag has free extents.	 */	addext = (imap->im_agctl[agno].numfree < 32 && iagp->nfreeexts);	/*	 *      try to allocate from the IAG	 */	/* check if the inode may be allocated from the iag 	 * (i.e. the inode has free inodes or new extent can be added).	 */	if (iagp->nfreeinos || addext) {		/* determine the extent number of the hint.		 */		extno = ino >> L2INOSPEREXT;		/* check if the extent containing the hint has backed		 * inodes.  if so, try to allocate within this extent.		 */		if (addressPXD(&iagp->inoext[extno])) {			bitno = ino & (INOSPEREXT - 1);			if ((bitno =			     diFindFree(le32_to_cpu(iagp->wmap[extno]),					bitno))			    < INOSPEREXT) {				ino = (extno << L2INOSPEREXT) + bitno;				/* a free inode (bit) was found within this				 * extent, so allocate it.				 */				rc = diAllocBit(imap, iagp, ino);				IREAD_UNLOCK(ipimap);				if (rc) {					assert(rc == -EIO);				} else {					/* set the results of the allocation					 * and write the iag.					 */					diInitInode(ip, iagno, ino, extno,						    iagp);					mark_metapage_dirty(mp);				}				release_metapage(mp);				/* free the AG lock and return.				 */				AG_UNLOCK(imap, agno);				return (rc);			}			if (!addext)				extno =				    (extno ==				     EXTSPERIAG - 1) ? 0 : extno + 1;		}		/*		 * no free inodes within the extent containing the hint.		 *		 * try to allocate from the backed extents following		 * hint or, if appropriate (i.e. addext is true), allocate		 * an extent of free inodes at or following the extent		 * containing the hint.		 * 		 * the free inode and free extent summary maps are used		 * here, so determine the starting summary map position		 * and the number of words we'll have to examine.  again,		 * the approach is to allocate following the hint, so we		 * might have to initially ignore prior bits of the summary		 * map that represent extents prior to the extent containing		 * the hint and later revisit these bits.		 */		bitno = extno & (EXTSPERSUM - 1);		nwords = (bitno == 0) ? SMAPSZ : SMAPSZ + 1;		sword = extno >> L2EXTSPERSUM;		/* mask any prior bits for the starting words of the		 * summary map.		 */		mask = ONES << (EXTSPERSUM - bitno);		inosmap = le32_to_cpu(iagp->inosmap[sword]) | mask;		extsmap = le32_to_cpu(iagp->extsmap[sword]) | mask;		/* scan the free inode and free extent summary maps for		 * free resources.		 */		for (i = 0; i < nwords; i++) {			/* check if this word of the free inode summary			 * map describes an extent with free inodes.			 */			if (~inosmap) {				/* an extent with free inodes has been				 * found. determine the extent number				 * and the inode number within the extent.				 */				rem = diFindFree(inosmap, 0);				extno = (sword << L2EXTSPERSUM) + rem;				rem = diFindFree(le32_to_cpu(iagp->wmap[extno]),						 0);				if (rem >= INOSPEREXT) {					IREAD_UNLOCK(ipimap);					release_metapage(mp);					AG_UNLOCK(imap, agno);					jfs_error(ip->i_sb,						  "diAlloc: can't find free bit "						  "in wmap");					return EIO;				}				/* determine the inode number within the				 * iag and allocate the inode from the				 * map.				 */				ino = (extno << L2INOSPEREXT) + rem;				rc = diAllocBit(imap, iagp, ino);				IREAD_UNLOCK(ipimap);				if (rc)					assert(rc == -EIO);				else {					/* set the results of the allocation					 * and write the iag.					 */					diInitInode(ip, iagno, ino, extno,						    iagp);					mark_metapage_dirty(mp);				}				release_metapage(mp);				/* free the AG lock and return.				 */				AG_UNLOCK(imap, agno);				return (rc);			}			/* check if we may allocate an extent of free			 * inodes and whether this word of the free			 * extents summary map describes a free extent.			 */			if (addext && ~extsmap) {				/* a free extent has been found.  determine				 * the extent number.				 */				rem = diFindFree(extsmap, 0);				extno = (sword << L2EXTSPERSUM) + rem;				/* allocate an extent of free inodes.				 */				if ((rc = diNewExt(imap, iagp, extno))) {					/* if there is no disk space for a					 * new extent, try to allocate the					 * disk inode from somewhere else.					 */					if (rc == -ENOSPC)						break;					assert(rc == -EIO);				} else {					/* set the results of the allocation					 * and write the iag.					 */					diInitInode(ip, iagno,						    extno << L2INOSPEREXT,						    extno, iagp);					mark_metapage_dirty(mp);				}				release_metapage(mp);				/* free the imap inode & the AG lock & return.				 */				IREAD_UNLOCK(ipimap);				AG_UNLOCK(imap, agno);				return (rc);			}			/* move on to the next set of summary map words.			 */			sword = (sword == SMAPSZ - 1) ? 0 : sword + 1;			inosmap = le32_to_cpu(iagp->inosmap[sword]);			extsmap = le32_to_cpu(iagp->extsmap[sword]);		}	}	/* unlock imap inode */	IREAD_UNLOCK(ipimap);	/* nothing doing in this iag, so release it. */	release_metapage(mp);      tryag:	/*	 * try to allocate anywhere within the same AG as the parent inode.	 */	rc = diAllocAG(imap, agno, dir, ip);	AG_UNLOCK(imap, agno);	if (rc != -ENOSPC)		return (rc);	/*	 * try to allocate in any AG.	 */	return (diAllocAny(imap, agno, dir, ip));}/* * NAME:        diAllocAG(imap,agno,dir,ip) * * FUNCTION:    allocate a disk inode from the allocation group. * *		this routine first determines if a new extent of free *		inodes should be added for the allocation group, with *		the current request satisfied from this extent. if this *		is the case, an attempt will be made to do just that.  if *		this attempt fails or it has been determined that a new  *		extent should not be added, an attempt is made to satisfy *		the request by allocating an existing (backed) free inode *		from the allocation group. * * PRE CONDITION: Already have the AG lock for this AG. * * PARAMETERS: *      imap  	- pointer to inode map control structure. *      agno  	- allocation group to allocate from. *      dir  	- TRUE if the new disk inode is for a directory. *      ip  	- pointer to the new inode to be filled in on successful return *		  with the disk inode number allocated, its extent address *		  and the start of the ag. * * RETURN VALUES: *      0       - success. *      -ENOSPC	- insufficient disk resources. *      -EIO  	- i/o error. */static intdiAllocAG(struct inomap * imap, int agno, boolean_t dir, struct inode *ip){	int rc, addext, numfree, numinos;	/* get the number of free and the number of backed disk 	 * inodes currently within the ag.	 */	numfree = imap->im_agctl[agno].numfree;	numinos = imap->im_agctl[agno].numinos;	if (numfree > numinos) {		jfs_error(ip->i_sb, "diAllocAG: numfree > numinos");		return -EIO;	}	/* determine if we should allocate a new extent of free inodes	 * within the ag: for directory inodes, add a new extent	 * if there are a small number of free inodes or number of free	 * inodes is a small percentage of the number of backed inodes.	 */	if (dir == TRUE)		addext = (numfree < 64 ||			  (numfree < 256			   && ((numfree * 100) / numinos) <= 20));	else		addext = (numfree == 0);	/*	 * try to allocate a new extent of free inodes.	 */	if (addext) {		/* if free space is not avaliable for this new extent, try		 * below to allocate a free and existing (already backed)		 * inode from the ag.		 */		if ((rc = diAllocExt(imap, agno, ip)) != -ENOSPC)			return (rc);	}	/*	 * try to allocate an existing free inode from the ag.	 */	return (diAllocIno(imap, agno, ip));}/* * NAME:        diAllocAny(imap,agno,dir,iap) * * FUNCTION:    allocate a disk inode from any other allocation group. * *		this routine is called when an allocation attempt within *		the primary allocation group has failed. if attempts to *		allocate an inode from any allocation group other than the *		specified primary group. * * PARAMETERS: *      imap  	- pointer to inode map control structure. *      agno  	- primary allocation group (to avoid). *      dir  	- TRUE if the new disk inode is for a directory. *      ip  	- pointer to a new inode to be filled in on successful return *		  with the disk inode number allocated, its extent address *		  and the start of the ag. * * RETURN VALUES: *      0       - success. *      -ENOSPC	- insufficient disk resources. *      -EIO  	- i/o error. */static intdiAllocAny(struct inomap * imap, int agno, boolean_t dir, struct inode *ip){	int ag, rc;	int maxag = JFS_SBI(imap->im_ipimap->i_sb)->bmap->db_maxag;	/* try to allocate from the ags following agno up to 	 * the maximum ag number.	 */	for (ag = agno + 1; ag <= maxag; ag++) {		AG_LOCK(imap, ag);		rc = diAllocAG(imap, ag, dir, ip);		AG_UNLOCK(imap, ag);		if (rc != -ENOSPC)			return (rc);	}	/* try to allocate from the ags in front of agno.	 */	for (ag = 0; ag < agno; ag++) {		AG_LOCK(imap, ag);		rc = diAllocAG(imap, ag, dir, ip);		AG_UNLOCK(imap, ag);		if (rc != -ENOSPC)			return (rc);	}	/* no free disk inodes.	 */	return -ENOSPC;}/* * NAME:        diAllocIno(imap,agno,ip) * * FUNCTION:    allocate a disk inode from the allocation group's free *		inode list, returning an error if this free list is *		empty (i.e. no iags on the list). * *		allocation occurs from the first iag on the list using *		the iag's free inode summary map to find the leftmost *		free inode in the iag.  *		 * PRE CONDITION: Already have AG lock for this AG. *		 * PARAMETERS: *      imap  	- pointer to inode map control structure. *      agno  	- allocation group. *      ip  	- pointer to new inode to be filled in on successful return *		  with the disk inode number allocated, its extent address *		  and the start of the ag. * * RETURN VALUES: *      0       - success. *      -ENOSPC	- insufficient disk resources. *      -EIO  	- i/o error. */static int diAllocIno(struct inomap * imap, int agno, struct inode *ip){	int iagno, ino, rc, rem, extno, sword;	struct metapage *mp;	struct iag *iagp;	/* check if there are iags on the ag's free inode list.	 */	if ((iagno = imap->im_agctl[agno].inofree) < 0)		return -ENOSPC;	/* obtain read lock on imap inode */	IREAD_LOCK(imap->im_ipimap);	/* read the iag at the head of the list.	 */	if ((rc = diIAGRead(imap, iagno, &mp))) {		IREAD_UNLOCK(imap->im_ipimap);		return (rc);	}	iagp = (struct iag *) mp->data;	/* better be free inodes in this iag if it is on the	 * list.	 */	if (!iagp->nfreeinos) {		IREAD_UNLOCK(imap->im_ipimap);		release_metapage(mp);		jfs_error(ip->i_sb,			  "diAllocIno: nfreeinos = 0, but iag on freelist");		return -EIO;	}	/* scan the free inode summary map to find an extent	 * with free inodes.	 */	for (sword = 0;; sword++) {		if (sword >= SMAPSZ) {			IREAD_UNLOCK(imap->im_ipimap);			release_metapage(mp);			jfs_error(ip->i_sb,				  "diAllocIno: free inode not found in summary map");			return -EIO;		}		if (~iagp->inosmap[sword])			break;	}	/* found a extent with free inodes. determine	 * the extent number.	 */	rem = diFindFree(le32_to_cpu(iagp->inosmap[sword]), 0);	if (rem >= EXTSPERSUM) {		IREAD_UNLOCK(imap->im_ipimap);		release_metapage(mp);		jfs_error(ip->i_sb, "diAllocIno: no free extent found");		return -EIO;	}	extno = (sword << L2EXTSPERSUM) + rem;	/* find the first free inode in the extent.	 */	rem = diFindFree(le32_to_cpu(iagp->wmap[extno]), 0);	if (rem >= INOSPEREXT) {		IREAD_UNLOCK(imap->im_ipimap);		release_metapage(mp);		jfs_error(ip->i_sb, "diAllocIno: free inode not found");		return -EIO;	}	/* compute the inode number within the iag. 	 */	ino = (extno << L2INOSPEREXT) + rem;	/* allocate the inode.	 */	rc = diAllocBit(imap, iagp, ino);	IREAD_UNLOCK(imap->im_ipimap);	if (rc) {		release_metapage(mp);		return (rc);	}	/* set the results of the allocation and write the iag.	 */	diInitInode(ip, iagno, ino, extno, iagp);	write_metapage(mp);	return (0);}/* * NAME:        diAllocExt(imap,agno,ip) *

⌨️ 快捷键说明

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