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

📄 jfs_imap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		iagp = (struct iag *) mp->data;		/* set the ag number if this a brand new iag		 */		iagp->agstart =		    cpu_to_le64(AGTOBLK(agno, imap->im_ipimap));	} else {		/* read the iag.		 */		IREAD_LOCK(imap->im_ipimap, RDWRLOCK_IMAP);		if ((rc = diIAGRead(imap, iagno, &mp))) {			IREAD_UNLOCK(imap->im_ipimap);			jfs_error(ip->i_sb, "diAllocExt: error reading iag");			return rc;		}		iagp = (struct iag *) mp->data;	}	/* using the free extent summary map, find a free extent.	 */	for (sword = 0;; sword++) {		if (sword >= SMAPSZ) {			release_metapage(mp);			IREAD_UNLOCK(imap->im_ipimap);			jfs_error(ip->i_sb,				  "diAllocExt: free ext summary map not found");			return -EIO;		}		if (~iagp->extsmap[sword])			break;	}	/* determine the extent number of the free extent.	 */	rem = diFindFree(le32_to_cpu(iagp->extsmap[sword]), 0);	if (rem >= EXTSPERSUM) {		release_metapage(mp);		IREAD_UNLOCK(imap->im_ipimap);		jfs_error(ip->i_sb, "diAllocExt: free extent not found");		return -EIO;	}	extno = (sword << L2EXTSPERSUM) + rem;	/* initialize the new extent.	 */	rc = diNewExt(imap, iagp, extno);	IREAD_UNLOCK(imap->im_ipimap);	if (rc) {		/* something bad happened.  if a new iag was allocated,		 * place it back on the inode map's iag free list, and		 * clear the ag number information.		 */		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {			IAGFREE_LOCK(imap);			iagp->iagfree = cpu_to_le32(imap->im_freeiag);			imap->im_freeiag = iagno;			IAGFREE_UNLOCK(imap);		}		write_metapage(mp);		return (rc);	}	/* set the results of the allocation and write the iag.	 */	diInitInode(ip, iagno, extno << L2INOSPEREXT, extno, iagp);	write_metapage(mp);	return (0);}/* * NAME:	diAllocBit(imap,iagp,ino) * * FUNCTION:	allocate a backed inode from an iag. * *		this routine performs the mechanics of allocating a *		specified inode from a backed extent. * *		if the inode to be allocated represents the last free *		inode within the iag, the iag will be removed from the *		ag free inode list. * *		a careful update approach is used to provide consistency *		in the face of updates to multiple buffers.  under this *		approach, all required buffers are obtained before making *		any updates and are held all are updates are complete. * * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on *	this AG.  Must have read lock on imap inode. * * PARAMETERS: *	imap	- pointer to inode map control structure. *	iagp	- pointer to iag. *	ino	- inode number to be allocated within the iag. * * RETURN VALUES: *	0	- success. *	-ENOSPC	- insufficient disk resources. *	-EIO	- i/o error. */static int diAllocBit(struct inomap * imap, struct iag * iagp, int ino){	int extno, bitno, agno, sword, rc;	struct metapage *amp = NULL, *bmp = NULL;	struct iag *aiagp = NULL, *biagp = NULL;	u32 mask;	/* check if this is the last free inode within the iag.	 * if so, it will have to be removed from the ag free	 * inode list, so get the iags preceeding and following	 * it on the list.	 */	if (iagp->nfreeinos == cpu_to_le32(1)) {		if ((int) le32_to_cpu(iagp->inofreefwd) >= 0) {			if ((rc =			     diIAGRead(imap, le32_to_cpu(iagp->inofreefwd),				       &amp)))				return (rc);			aiagp = (struct iag *) amp->data;		}		if ((int) le32_to_cpu(iagp->inofreeback) >= 0) {			if ((rc =			     diIAGRead(imap,				       le32_to_cpu(iagp->inofreeback),				       &bmp))) {				if (amp)					release_metapage(amp);				return (rc);			}			biagp = (struct iag *) bmp->data;		}	}	/* get the ag number, extent number, inode number within	 * the extent.	 */	agno = BLKTOAG(le64_to_cpu(iagp->agstart), JFS_SBI(imap->im_ipimap->i_sb));	extno = ino >> L2INOSPEREXT;	bitno = ino & (INOSPEREXT - 1);	/* compute the mask for setting the map.	 */	mask = HIGHORDER >> bitno;	/* the inode should be free and backed.	 */	if (((le32_to_cpu(iagp->pmap[extno]) & mask) != 0) ||	    ((le32_to_cpu(iagp->wmap[extno]) & mask) != 0) ||	    (addressPXD(&iagp->inoext[extno]) == 0)) {		if (amp)			release_metapage(amp);		if (bmp)			release_metapage(bmp);		jfs_error(imap->im_ipimap->i_sb,			  "diAllocBit: iag inconsistent");		return -EIO;	}	/* mark the inode as allocated in the working map.	 */	iagp->wmap[extno] |= cpu_to_le32(mask);	/* check if all inodes within the extent are now	 * allocated.  if so, update the free inode summary	 * map to reflect this.	 */	if (iagp->wmap[extno] == cpu_to_le32(ONES)) {		sword = extno >> L2EXTSPERSUM;		bitno = extno & (EXTSPERSUM - 1);		iagp->inosmap[sword] |= cpu_to_le32(HIGHORDER >> bitno);	}	/* if this was the last free inode in the iag, remove the	 * iag from the ag free inode list.	 */	if (iagp->nfreeinos == cpu_to_le32(1)) {		if (amp) {			aiagp->inofreeback = iagp->inofreeback;			write_metapage(amp);		}		if (bmp) {			biagp->inofreefwd = iagp->inofreefwd;			write_metapage(bmp);		} else {			imap->im_agctl[agno].inofree =			    le32_to_cpu(iagp->inofreefwd);		}		iagp->inofreefwd = iagp->inofreeback = cpu_to_le32(-1);	}	/* update the free inode count at the iag, ag, inode	 * map levels.	 */	iagp->nfreeinos = cpu_to_le32(le32_to_cpu(iagp->nfreeinos) - 1);	imap->im_agctl[agno].numfree -= 1;	atomic_dec(&imap->im_numfree);	return (0);}/* * NAME:	diNewExt(imap,iagp,extno) * * FUNCTION:	initialize a new extent of inodes for an iag, allocating *		the first inode of the extent for use for the current *		allocation request. * *		disk resources are allocated for the new extent of inodes *		and the inodes themselves are initialized to reflect their *		existence within the extent (i.e. their inode numbers and *		inode extent addresses are set) and their initial state *		(mode and link count are set to zero). * *		if the iag is new, it is not yet on an ag extent free list *		but will now be placed on this list. * *		if the allocation of the new extent causes the iag to *		have no free extent, the iag will be removed from the *		ag extent free list. * *		if the iag has no free backed inodes, it will be placed *		on the ag free inode list, since the addition of the new *		extent will now cause it to have free inodes. * *		a careful update approach is used to provide consistency *		(i.e. list consistency) in the face of updates to multiple *		buffers.  under this approach, all required buffers are *		obtained before making any updates and are held until all *		updates are complete. * * PRE CONDITION: Already have buffer lock on iagp.  Already have AG lock on *	this AG.  Must have read lock on imap inode. * * PARAMETERS: *	imap	- pointer to inode map control structure. *	iagp	- pointer to iag. *	extno	- extent number. * * RETURN VALUES: *	0	- success. *	-ENOSPC	- insufficient disk resources. *	-EIO	- i/o error. */static int diNewExt(struct inomap * imap, struct iag * iagp, int extno){	int agno, iagno, fwd, back, freei = 0, sword, rc;	struct iag *aiagp = NULL, *biagp = NULL, *ciagp = NULL;	struct metapage *amp, *bmp, *cmp, *dmp;	struct inode *ipimap;	s64 blkno, hint;	int i, j;	u32 mask;	ino_t ino;	struct dinode *dp;	struct jfs_sb_info *sbi;	/* better have free extents.	 */	if (!iagp->nfreeexts) {		jfs_error(imap->im_ipimap->i_sb, "diNewExt: no free extents");		return -EIO;	}	/* get the inode map inode.	 */	ipimap = imap->im_ipimap;	sbi = JFS_SBI(ipimap->i_sb);	amp = bmp = cmp = NULL;	/* get the ag and iag numbers for this iag.	 */	agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi);	iagno = le32_to_cpu(iagp->iagnum);	/* check if this is the last free extent within the	 * iag.  if so, the iag must be removed from the ag	 * free extent list, so get the iags preceeding and	 * following the iag on this list.	 */	if (iagp->nfreeexts == cpu_to_le32(1)) {		if ((fwd = le32_to_cpu(iagp->extfreefwd)) >= 0) {			if ((rc = diIAGRead(imap, fwd, &amp)))				return (rc);			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;		}	} else {		/* the iag has free extents.  if all extents are free		 * (as is the case for a newly allocated iag), the iag		 * must be added to the ag free extent list, so get		 * the iag at the head of the list in preparation for		 * adding this iag to this list.		 */		fwd = back = -1;		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {			if ((fwd = imap->im_agctl[agno].extfree) >= 0) {				if ((rc = diIAGRead(imap, fwd, &amp)))					goto error_out;				aiagp = (struct iag *) amp->data;			}		}	}	/* check if the iag has no free inodes.  if so, the iag	 * will have to be added to the ag free inode list, so get	 * the iag at the head of the list in preparation for	 * adding this iag to this list.  in doing this, we must	 * check if we already have the iag at the head of	 * the list in hand.	 */	if (iagp->nfreeinos == 0) {		freei = imap->im_agctl[agno].inofree;		if (freei >= 0) {			if (freei == fwd) {				ciagp = aiagp;			} else if (freei == back) {				ciagp = biagp;			} else {				if ((rc = diIAGRead(imap, freei, &cmp)))					goto error_out;				ciagp = (struct iag *) cmp->data;			}			if (ciagp == NULL) {				jfs_error(imap->im_ipimap->i_sb,					  "diNewExt: ciagp == NULL");				rc = -EIO;				goto error_out;			}		}	}	/* allocate disk space for the inode extent.	 */	if ((extno == 0) || (addressPXD(&iagp->inoext[extno - 1]) == 0))		hint = ((s64) agno << sbi->bmap->db_agl2size) - 1;	else		hint = addressPXD(&iagp->inoext[extno - 1]) +		    lengthPXD(&iagp->inoext[extno - 1]) - 1;	if ((rc = dbAlloc(ipimap, hint, (s64) imap->im_nbperiext, &blkno)))		goto error_out;	/* compute the inode number of the first inode within the	 * extent.	 */	ino = (iagno << L2INOSPERIAG) + (extno << L2INOSPEREXT);	/* initialize the inodes within the newly allocated extent a	 * page at a time.	 */	for (i = 0; i < imap->im_nbperiext; i += sbi->nbperpage) {		/* get a buffer for this page of disk inodes.		 */		dmp = get_metapage(ipimap, blkno + i, PSIZE, 1);		if (dmp == NULL) {			rc = -EIO;			goto error_out;		}		dp = (struct dinode *) dmp->data;		/* initialize the inode number, mode, link count and		 * inode extent address.		 */		for (j = 0; j < INOSPERPAGE; j++, dp++, ino++) {			dp->di_inostamp = cpu_to_le32(sbi->inostamp);			dp->di_number = cpu_to_le32(ino);			dp->di_fileset = cpu_to_le32(FILESYSTEM_I);			dp->di_mode = 0;			dp->di_nlink = 0;			PXDaddress(&(dp->di_ixpxd), blkno);			PXDlength(&(dp->di_ixpxd), imap->im_nbperiext);		}		write_metapage(dmp);	}	/* if this is the last free extent within the iag, remove the	 * iag from the ag free extent list.	 */	if (iagp->nfreeexts == cpu_to_le32(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);	} else {		/* if the iag has all free extents (newly allocated iag),		 * add the iag to the ag free extent list.		 */		if (iagp->nfreeexts == cpu_to_le32(EXTSPERIAG)) {			if (fwd >= 0)				aiagp->extfreeback = cpu_to_le32(iagno);			iagp->extfreefwd = cpu_to_le32(fwd);			iagp->extfreeback = cpu_to_le32(-1);			imap->im_agctl[agno].extfree = iagno;		}	}	/* if the iag has no free inodes, add the iag to the	 * ag free inode list.	 */	if (iagp->nfreeinos == 0) {		if (freei >= 0)			ciagp->inofreeback = cpu_to_le32(iagno);		iagp->inofreefwd =		    cpu_to_le32(imap->im_agctl[agno].inofree);		iagp->inofreeback = cpu_to_le32(-1);		imap->im_agctl[agno].inofree = iagno;	}	/* initialize the extent descriptor of the extent. */	PXDlength(&iagp->inoext[extno], imap->im_nbperiext);	PXDaddress(&iagp->inoext[extno], blkno);	/* initialize the working and persistent map of the extent.	 * the working map will be initialized such that	 * it indicates the first inode of the extent is allocated.	 */	iagp->wmap[extno] = cpu_to_le32(HIGHORDER);	iagp->pmap[extno] = 0;	/* update the free inode and free extent summary maps	 * for the extent to indicate the extent has free inodes	 * and no longer represents a free extent.	 */	sword = extno >> L2EXTSPERSUM;	mask = HIGHORDER >> (extno & (EXTSPERSUM - 1));	iagp->extsmap[sword] |= cpu_to_le32(mask);	iagp->inosmap[sword] &= cpu_to_le32(~mask);	/* update the free inode and free extent counts 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 free and backed inode counts for the ag.	 */	imap->im_agctl[agno].numfree += (INOSPEREXT - 1);	imap->im_agctl[agno].numinos += INOSPEREXT;	/* update the free and backed inode counts for the inode map.	 */	atomic_add(INOSPEREXT - 1, &imap->im_numfree);	atomic_add(INOSPEREXT, &imap->im_numinos);	/* write the iags.	 */	if (amp)		write_metapage(amp);	if (bmp)		write_metapage(bmp);	if (cmp)		write_metapage(cmp);	return (0); 

⌨️ 快捷键说明

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