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

📄 jfs_imap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
				 * 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, bool 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)		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, bool 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, RDWRLOCK_IMAP);	/* 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) * * FUNCTION:	add a new extent of free inodes to an iag, allocating *		an inode from this extent to satisfy the current allocation *		request. * *		this routine first tries to find an existing iag with free *		extents through the ag free extent list.  if list is not *		empty, the head of the list will be selected as the home *		of the new extent of free inodes.  otherwise (the list is *		empty), a new iag will be allocated for the ag to contain *		the extent. * *		once an iag has been selected, the free extent summary map *		is used to locate a free extent within the iag and diNewExt() *		is called to initialize the extent, with initialization *		including the allocation of the first inode of the extent *		for the purpose of satisfying this request. * * PARAMETERS: *	imap	- pointer to inode map control structure. *	agno	- allocation group number. *	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 diAllocExt(struct inomap * imap, int agno, struct inode *ip){	int rem, iagno, sword, extno, rc;	struct metapage *mp;	struct iag *iagp;	/* check if the ag has any iags with free extents.  if not,	 * allocate a new iag for the ag.	 */	if ((iagno = imap->im_agctl[agno].extfree) < 0) {		/* If successful, diNewIAG will obtain the read lock on the		 * imap inode.		 */		if ((rc = diNewIAG(imap, &iagno, agno, &mp))) {			return (rc);		}

⌨️ 快捷键说明

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