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

📄 jfs_imap.c

📁 jfs-2.4-1.1.7.tar.gz jfs 2.4-1.1.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
 * 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);		}		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);		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, *bmp;	struct iag *aiagp = 0, *biagp = 0;	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)) {		amp = bmp = NULL;		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] == 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 = -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 = 0, *biagp = 0, *ciagp = 0;	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 = -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 = -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 = -1;		imap->im_agctl[agno].inofree = iagno;	}	/* initialize the extent descriptor of the extent. */	PXDlength(&ia

⌨️ 快捷键说明

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