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

📄 xfs_ialloc.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
			"xfs_difree: agno >= mp->m_sb.sb_agcount (%d >= %d) on %s.  Returning EINVAL.",			agno, mp->m_sb.sb_agcount, mp->m_fsname);		ASSERT(0);		return XFS_ERROR(EINVAL);	}	agino = XFS_INO_TO_AGINO(mp, inode);	if (inode != XFS_AGINO_TO_INO(mp, agno, agino))  {		cmn_err(CE_WARN,			"xfs_difree: inode != XFS_AGINO_TO_INO() "			"(%llu != %llu) on %s.  Returning EINVAL.",			(unsigned long long)inode,			(unsigned long long)XFS_AGINO_TO_INO(mp, agno, agino),			mp->m_fsname);		ASSERT(0);		return XFS_ERROR(EINVAL);	}	agbno = XFS_AGINO_TO_AGBNO(mp, agino);	if (agbno >= mp->m_sb.sb_agblocks)  {		cmn_err(CE_WARN,			"xfs_difree: agbno >= mp->m_sb.sb_agblocks (%d >= %d) on %s.  Returning EINVAL.",			agbno, mp->m_sb.sb_agblocks, mp->m_fsname);		ASSERT(0);		return XFS_ERROR(EINVAL);	}	/*	 * Get the allocation group header.	 */	down_read(&mp->m_peraglock);	error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);	up_read(&mp->m_peraglock);	if (error) {		cmn_err(CE_WARN,			"xfs_difree: xfs_ialloc_read_agi() returned an error %d on %s.  Returning error.",			error, mp->m_fsname);		return error;	}	agi = XFS_BUF_TO_AGI(agbp);	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);	ASSERT(agbno < be32_to_cpu(agi->agi_length));	/*	 * Initialize the cursor.	 */	cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO,		(xfs_inode_t *)0, 0);#ifdef DEBUG	if (cur->bc_nlevels == 1) {		int freecount = 0;		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))			goto error0;		do {			if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino,					&rec.ir_freecount, &rec.ir_free, &i)))				goto error0;			if (i) {				freecount += rec.ir_freecount;				if ((error = xfs_inobt_increment(cur, 0, &i)))					goto error0;			}		} while (i == 1);		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||		       XFS_FORCED_SHUTDOWN(mp));	}#endif	/*	 * Look for the entry describing this inode.	 */	if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {		cmn_err(CE_WARN,			"xfs_difree: xfs_inobt_lookup_le returned()  an error %d on %s.  Returning error.",			error, mp->m_fsname);		goto error0;	}	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);	if ((error = xfs_inobt_get_rec(cur, &rec.ir_startino, &rec.ir_freecount,			&rec.ir_free, &i))) {		cmn_err(CE_WARN,			"xfs_difree: xfs_inobt_get_rec()  returned an error %d on %s.  Returning error.",			error, mp->m_fsname);		goto error0;	}	XFS_WANT_CORRUPTED_GOTO(i == 1, error0);	/*	 * Get the offset in the inode chunk.	 */	off = agino - rec.ir_startino;	ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK);	ASSERT(!XFS_INOBT_IS_FREE(&rec, off));	/*	 * Mark the inode free & increment the count.	 */	XFS_INOBT_SET_FREE(&rec, off);	rec.ir_freecount++;	/*	 * When an inode cluster is free, it becomes eligible for removal	 */	if ((mp->m_flags & XFS_MOUNT_IDELETE) &&	    (rec.ir_freecount == XFS_IALLOC_INODES(mp))) {		*delete = 1;		*first_ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino);		/*		 * Remove the inode cluster from the AGI B+Tree, adjust the		 * AGI and Superblock inode counts, and mark the disk space		 * to be freed when the transaction is committed.		 */		ilen = XFS_IALLOC_INODES(mp);		be32_add(&agi->agi_count, -ilen);		be32_add(&agi->agi_freecount, -(ilen - 1));		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_COUNT | XFS_AGI_FREECOUNT);		down_read(&mp->m_peraglock);		mp->m_perag[agno].pagi_freecount -= ilen - 1;		up_read(&mp->m_peraglock);		xfs_trans_mod_sb(tp, XFS_TRANS_SB_ICOUNT, -ilen);		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, -(ilen - 1));		if ((error = xfs_inobt_delete(cur, &i))) {			cmn_err(CE_WARN, "xfs_difree: xfs_inobt_delete returned an error %d on %s.\n",				error, mp->m_fsname);			goto error0;		}		xfs_bmap_add_free(XFS_AGB_TO_FSB(mp,				agno, XFS_INO_TO_AGBNO(mp,rec.ir_startino)),				XFS_IALLOC_BLOCKS(mp), flist, mp);	} else {		*delete = 0;		if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, rec.ir_free))) {			cmn_err(CE_WARN,				"xfs_difree: xfs_inobt_update()  returned an error %d on %s.  Returning error.",				error, mp->m_fsname);			goto error0;		}		/* 		 * Change the inode free counts and log the ag/sb changes.		 */		be32_add(&agi->agi_freecount, 1);		xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREECOUNT);		down_read(&mp->m_peraglock);		mp->m_perag[agno].pagi_freecount++;		up_read(&mp->m_peraglock);		xfs_trans_mod_sb(tp, XFS_TRANS_SB_IFREE, 1);	}#ifdef DEBUG	if (cur->bc_nlevels == 1) {		int freecount = 0;		if ((error = xfs_inobt_lookup_ge(cur, 0, 0, 0, &i)))			goto error0;		do {			if ((error = xfs_inobt_get_rec(cur,					&rec.ir_startino,					&rec.ir_freecount,					&rec.ir_free, &i)))				goto error0;			if (i) {				freecount += rec.ir_freecount;				if ((error = xfs_inobt_increment(cur, 0, &i)))					goto error0;			}		} while (i == 1);		ASSERT(freecount == be32_to_cpu(agi->agi_freecount) ||		       XFS_FORCED_SHUTDOWN(mp));	}#endif	xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);	return 0;error0:	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);	return error;}/* * Return the location of the inode in bno/off, for mapping it into a buffer. *//*ARGSUSED*/intxfs_dilocate(	xfs_mount_t	*mp,	/* file system mount structure */	xfs_trans_t	*tp,	/* transaction pointer */	xfs_ino_t	ino,	/* inode to locate */	xfs_fsblock_t	*bno,	/* output: block containing inode */	int		*len,	/* output: num blocks in inode cluster */	int		*off,	/* output: index in block of inode */	uint		flags)	/* flags concerning inode lookup */{	xfs_agblock_t	agbno;	/* block number of inode in the alloc group */	xfs_buf_t	*agbp;	/* agi buffer */	xfs_agino_t	agino;	/* inode number within alloc group */	xfs_agnumber_t	agno;	/* allocation group number */	int		blks_per_cluster; /* num blocks per inode cluster */	xfs_agblock_t	chunk_agbno;	/* first block in inode chunk */	xfs_agino_t	chunk_agino;	/* first agino in inode chunk */	__int32_t	chunk_cnt;	/* count of free inodes in chunk */	xfs_inofree_t	chunk_free;	/* mask of free inodes in chunk */	xfs_agblock_t	cluster_agbno;	/* first block in inode cluster */	xfs_btree_cur_t	*cur;	/* inode btree cursor */	int		error;	/* error code */	int		i;	/* temp state */	int		offset;	/* index of inode in its buffer */	int		offset_agbno;	/* blks from chunk start to inode */	ASSERT(ino != NULLFSINO);	/*	 * Split up the inode number into its parts.	 */	agno = XFS_INO_TO_AGNO(mp, ino);	agino = XFS_INO_TO_AGINO(mp, ino);	agbno = XFS_AGINO_TO_AGBNO(mp, agino);	if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks ||	    ino != XFS_AGINO_TO_INO(mp, agno, agino)) {#ifdef DEBUG		/* no diagnostics for bulkstat, ino comes from userspace */		if (flags & XFS_IMAP_BULKSTAT)			return XFS_ERROR(EINVAL);		if (agno >= mp->m_sb.sb_agcount) {			xfs_fs_cmn_err(CE_ALERT, mp,					"xfs_dilocate: agno (%d) >= "					"mp->m_sb.sb_agcount (%d)",					agno,  mp->m_sb.sb_agcount);		}		if (agbno >= mp->m_sb.sb_agblocks) {			xfs_fs_cmn_err(CE_ALERT, mp,					"xfs_dilocate: agbno (0x%llx) >= "					"mp->m_sb.sb_agblocks (0x%lx)",					(unsigned long long) agbno,					(unsigned long) mp->m_sb.sb_agblocks);		}		if (ino != XFS_AGINO_TO_INO(mp, agno, agino)) {			xfs_fs_cmn_err(CE_ALERT, mp,					"xfs_dilocate: ino (0x%llx) != "					"XFS_AGINO_TO_INO(mp, agno, agino) "					"(0x%llx)",					ino, XFS_AGINO_TO_INO(mp, agno, agino));		}		xfs_stack_trace();#endif /* DEBUG */		return XFS_ERROR(EINVAL);	}	if ((mp->m_sb.sb_blocksize >= XFS_INODE_CLUSTER_SIZE(mp)) ||	    !(flags & XFS_IMAP_LOOKUP)) {		offset = XFS_INO_TO_OFFSET(mp, ino);		ASSERT(offset < mp->m_sb.sb_inopblock);		*bno = XFS_AGB_TO_FSB(mp, agno, agbno);		*off = offset;		*len = 1;		return 0;	}	blks_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_blocklog;	if (*bno != NULLFSBLOCK) {		offset = XFS_INO_TO_OFFSET(mp, ino);		ASSERT(offset < mp->m_sb.sb_inopblock);		cluster_agbno = XFS_FSB_TO_AGBNO(mp, *bno);		*off = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +			offset;		*len = blks_per_cluster;		return 0;	}	if (mp->m_inoalign_mask) {		offset_agbno = agbno & mp->m_inoalign_mask;		chunk_agbno = agbno - offset_agbno;	} else {		down_read(&mp->m_peraglock);		error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);		up_read(&mp->m_peraglock);		if (error) {#ifdef DEBUG			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "					"xfs_ialloc_read_agi() returned "					"error %d, agno %d",					error, agno);#endif /* DEBUG */			return error;		}		cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO,			(xfs_inode_t *)0, 0);		if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {#ifdef DEBUG			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "					"xfs_inobt_lookup_le() failed");#endif /* DEBUG */			goto error0;		}		if ((error = xfs_inobt_get_rec(cur, &chunk_agino, &chunk_cnt,				&chunk_free, &i))) {#ifdef DEBUG			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "					"xfs_inobt_get_rec() failed");#endif /* DEBUG */			goto error0;		}		if (i == 0) {#ifdef DEBUG			xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "					"xfs_inobt_get_rec() failed");#endif /* DEBUG */			error = XFS_ERROR(EINVAL);		}		xfs_trans_brelse(tp, agbp);		xfs_btree_del_cursor(cur, XFS_BTREE_NOERROR);		if (error)			return error;		chunk_agbno = XFS_AGINO_TO_AGBNO(mp, chunk_agino);		offset_agbno = agbno - chunk_agbno;	}	ASSERT(agbno >= chunk_agbno);	cluster_agbno = chunk_agbno +		((offset_agbno / blks_per_cluster) * blks_per_cluster);	offset = ((agbno - cluster_agbno) * mp->m_sb.sb_inopblock) +		XFS_INO_TO_OFFSET(mp, ino);	*bno = XFS_AGB_TO_FSB(mp, agno, cluster_agbno);	*off = offset;	*len = blks_per_cluster;	return 0;error0:	xfs_trans_brelse(tp, agbp);	xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);	return error;}/* * Compute and fill in value of m_in_maxlevels. */voidxfs_ialloc_compute_maxlevels(	xfs_mount_t	*mp)		/* file system mount structure */{	int		level;	uint		maxblocks;	uint		maxleafents;	int		minleafrecs;	int		minnoderecs;	maxleafents = (1LL << XFS_INO_AGINO_BITS(mp)) >>		XFS_INODES_PER_CHUNK_LOG;	minleafrecs = mp->m_alloc_mnr[0];	minnoderecs = mp->m_alloc_mnr[1];	maxblocks = (maxleafents + minleafrecs - 1) / minleafrecs;	for (level = 1; maxblocks > 1; level++)		maxblocks = (maxblocks + minnoderecs - 1) / minnoderecs;	mp->m_in_maxlevels = level;}/* * Log specified fields for the ag hdr (inode section) */voidxfs_ialloc_log_agi(	xfs_trans_t	*tp,		/* transaction pointer */	xfs_buf_t	*bp,		/* allocation group header buffer */	int		fields)		/* bitmask of fields to log */{	int			first;		/* first byte number */	int			last;		/* last byte number */	static const short	offsets[] = {	/* field starting offsets */					/* keep in sync with bit definitions */		offsetof(xfs_agi_t, agi_magicnum),		offsetof(xfs_agi_t, agi_versionnum),		offsetof(xfs_agi_t, agi_seqno),		offsetof(xfs_agi_t, agi_length),		offsetof(xfs_agi_t, agi_count),		offsetof(xfs_agi_t, agi_root),		offsetof(xfs_agi_t, agi_level),		offsetof(xfs_agi_t, agi_freecount),		offsetof(xfs_agi_t, agi_newino),		offsetof(xfs_agi_t, agi_dirino),		offsetof(xfs_agi_t, agi_unlinked),		sizeof(xfs_agi_t)	};#ifdef DEBUG	xfs_agi_t		*agi;	/* allocation group header */	agi = XFS_BUF_TO_AGI(bp);	ASSERT(be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC);#endif	/*	 * Compute byte offsets for the first and last fields.	 */	xfs_btree_offsets(fields, offsets, XFS_AGI_NUM_BITS, &first, &last);	/*	 * Log the allocation group inode header buffer.	 */	xfs_trans_log_buf(tp, bp, first, last);}/* * Read in the allocation group header (inode allocation section) */intxfs_ialloc_read_agi(	xfs_mount_t	*mp,		/* file system mount structure */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_agnumber_t	agno,		/* allocation group number */	xfs_buf_t	**bpp)		/* allocation group hdr buf */{	xfs_agi_t	*agi;		/* allocation group header */	int		agi_ok;		/* agi is consistent */	xfs_buf_t	*bp;		/* allocation group hdr buf */	xfs_perag_t	*pag;		/* per allocation group data */	int		error;	ASSERT(agno != NULLAGNUMBER);	error = xfs_trans_read_buf(			mp, tp, mp->m_ddev_targp,			XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),			XFS_FSS_TO_BB(mp, 1), 0, &bp);	if (error)		return error;	ASSERT(bp && !XFS_BUF_GETERROR(bp));	/*	 * Validate the magic number of the agi block.	 */	agi = XFS_BUF_TO_AGI(bp);	agi_ok =		be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&		XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));	if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,			XFS_RANDOM_IALLOC_READ_AGI))) {		XFS_CORRUPTION_ERROR("xfs_ialloc_read_agi", XFS_ERRLEVEL_LOW,				     mp, agi);		xfs_trans_brelse(tp, bp);		return XFS_ERROR(EFSCORRUPTED);	}	pag = &mp->m_perag[agno];	if (!pag->pagi_init) {		pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);		pag->pagi_count = be32_to_cpu(agi->agi_count);		pag->pagi_init = 1;	} else {		/*		 * It's possible for these to be out of sync if		 * we are in the middle of a forced shutdown.		 */		ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||			XFS_FORCED_SHUTDOWN(mp));	}#ifdef DEBUG	{		int	i;		for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)			ASSERT(agi->agi_unlinked[i]);	}#endif	XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGI, XFS_AGI_REF);	*bpp = bp;	return 0;}/* * Read in the agi to initialise the per-ag data in the mount structure */intxfs_ialloc_pagi_init(	xfs_mount_t	*mp,		/* file system mount structure */	xfs_trans_t	*tp,		/* transaction pointer */	xfs_agnumber_t	agno)		/* allocation group number */{	xfs_buf_t	*bp = NULL;	int		error;	error = xfs_ialloc_read_agi(mp, tp, agno, &bp);	if (error)		return error;	if (bp)		xfs_trans_brelse(tp, bp);	return 0;}

⌨️ 快捷键说明

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