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

📄 xfs_bmap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		ASSERT(0);	}	*curp = cur;	if (delta) {		temp2 += temp;		if (delta->xed_startoff > temp)			delta->xed_startoff = temp;		if (delta->xed_blockcount < temp2)			delta->xed_blockcount = temp2;	}done:	*logflagsp = rval;	return error;#undef	LEFT#undef	RIGHT#undef	PREV#undef	MASK#undef	MASK2#undef	MASK3#undef	MASK4#undef	STATE_SET#undef	STATE_TEST#undef	STATE_SET_TEST#undef	SWITCH_STATE}/* * Called by xfs_bmap_add_extent to handle cases converting an unwritten * allocation to a real allocation or vice versa. */STATIC int				/* error */xfs_bmap_add_extent_unwritten_real(	xfs_inode_t		*ip,	/* incore inode pointer */	xfs_extnum_t		idx,	/* extent number to update/insert */	xfs_btree_cur_t		**curp,	/* if *curp is null, not a btree */	xfs_bmbt_irec_t		*new,	/* new data to add to file extents */	int			*logflagsp, /* inode logging flags */	xfs_extdelta_t		*delta) /* Change made to incore extents */{	xfs_btree_cur_t		*cur;	/* btree cursor */	xfs_bmbt_rec_host_t	*ep;	/* extent entry for idx */	int			error;	/* error return value */	int			i;	/* temp state */	xfs_ifork_t		*ifp;	/* inode fork pointer */	xfs_fileoff_t		new_endoff;	/* end offset of new entry */	xfs_exntst_t		newext;	/* new extent state */	xfs_exntst_t		oldext;	/* old extent state */	xfs_bmbt_irec_t		r[3];	/* neighbor extent entries */					/* left is 0, right is 1, prev is 2 */	int			rval=0;	/* return value (logging flags) */	int			state = 0;/* state bits, accessed thru macros */	xfs_filblks_t		temp=0;	xfs_filblks_t		temp2=0;	enum {				/* bit number definitions for state */		LEFT_CONTIG,	RIGHT_CONTIG,		LEFT_FILLING,	RIGHT_FILLING,		LEFT_DELAY,	RIGHT_DELAY,		LEFT_VALID,	RIGHT_VALID	};#define	LEFT		r[0]#define	RIGHT		r[1]#define	PREV		r[2]#define	MASK(b)		(1 << (b))#define	MASK2(a,b)	(MASK(a) | MASK(b))#define	MASK3(a,b,c)	(MASK2(a,b) | MASK(c))#define	MASK4(a,b,c,d)	(MASK3(a,b,c) | MASK(d))#define	STATE_SET(b,v)	((v) ? (state |= MASK(b)) : (state &= ~MASK(b)))#define	STATE_TEST(b)	(state & MASK(b))#define	STATE_SET_TEST(b,v)	((v) ? ((state |= MASK(b)), 1) : \				       ((state &= ~MASK(b)), 0))#define	SWITCH_STATE		\	(state & MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG))	/*	 * Set up a bunch of variables to make the tests simpler.	 */	error = 0;	cur = *curp;	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);	ep = xfs_iext_get_ext(ifp, idx);	xfs_bmbt_get_all(ep, &PREV);	newext = new->br_state;	oldext = (newext == XFS_EXT_UNWRITTEN) ?		XFS_EXT_NORM : XFS_EXT_UNWRITTEN;	ASSERT(PREV.br_state == oldext);	new_endoff = new->br_startoff + new->br_blockcount;	ASSERT(PREV.br_startoff <= new->br_startoff);	ASSERT(PREV.br_startoff + PREV.br_blockcount >= new_endoff);	/*	 * Set flags determining what part of the previous oldext allocation	 * extent is being replaced by a newext allocation.	 */	STATE_SET(LEFT_FILLING, PREV.br_startoff == new->br_startoff);	STATE_SET(RIGHT_FILLING,		PREV.br_startoff + PREV.br_blockcount == new_endoff);	/*	 * Check and set flags if this segment has a left neighbor.	 * Don't set contiguous if the combined extent would be too large.	 */	if (STATE_SET_TEST(LEFT_VALID, idx > 0)) {		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx - 1), &LEFT);		STATE_SET(LEFT_DELAY, ISNULLSTARTBLOCK(LEFT.br_startblock));	}	STATE_SET(LEFT_CONTIG,		STATE_TEST(LEFT_VALID) && !STATE_TEST(LEFT_DELAY) &&		LEFT.br_startoff + LEFT.br_blockcount == new->br_startoff &&		LEFT.br_startblock + LEFT.br_blockcount == new->br_startblock &&		LEFT.br_state == newext &&		LEFT.br_blockcount + new->br_blockcount <= MAXEXTLEN);	/*	 * Check and set flags if this segment has a right neighbor.	 * Don't set contiguous if the combined extent would be too large.	 * Also check for all-three-contiguous being too large.	 */	if (STATE_SET_TEST(RIGHT_VALID,			idx <			ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t) - 1)) {		xfs_bmbt_get_all(xfs_iext_get_ext(ifp, idx + 1), &RIGHT);		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(RIGHT.br_startblock));	}	STATE_SET(RIGHT_CONTIG,		STATE_TEST(RIGHT_VALID) && !STATE_TEST(RIGHT_DELAY) &&		new_endoff == RIGHT.br_startoff &&		new->br_startblock + new->br_blockcount ==		    RIGHT.br_startblock &&		newext == RIGHT.br_state &&		new->br_blockcount + RIGHT.br_blockcount <= MAXEXTLEN &&		((state & MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING)) !=		  MASK3(LEFT_CONTIG, LEFT_FILLING, RIGHT_FILLING) ||		 LEFT.br_blockcount + new->br_blockcount + RIGHT.br_blockcount		     <= MAXEXTLEN));	/*	 * Switch out based on the FILLING and CONTIG state bits.	 */	switch (SWITCH_STATE) {	case MASK4(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):		/*		 * Setting all of a previous oldext extent to newext.		 * The left and right neighbors are both contiguous with new.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC|RC", ip, idx - 1,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),			LEFT.br_blockcount + PREV.br_blockcount +			RIGHT.br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC|RC", ip, idx - 1,			XFS_DATA_FORK);		XFS_BMAP_TRACE_DELETE("LF|RF|LC|RC", ip, idx, 2, XFS_DATA_FORK);		xfs_iext_remove(ifp, idx, 2);		ip->i_df.if_lastex = idx - 1;		ip->i_d.di_nextents -= 2;		if (cur == NULL)			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;		else {			rval = XFS_ILOG_CORE;			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,					RIGHT.br_startblock,					RIGHT.br_blockcount, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_delete(cur, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_decrement(cur, 0, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_delete(cur, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_decrement(cur, 0, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,				LEFT.br_startblock,				LEFT.br_blockcount + PREV.br_blockcount +				RIGHT.br_blockcount, LEFT.br_state)))				goto done;		}		/* DELTA: Three in-core extents are replaced by one. */		temp = LEFT.br_startoff;		temp2 = LEFT.br_blockcount +			PREV.br_blockcount +			RIGHT.br_blockcount;		break;	case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG):		/*		 * Setting all of a previous oldext extent to newext.		 * The left neighbor is contiguous, the right is not.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|LC", ip, idx - 1,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),			LEFT.br_blockcount + PREV.br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|LC", ip, idx - 1,			XFS_DATA_FORK);		ip->i_df.if_lastex = idx - 1;		XFS_BMAP_TRACE_DELETE("LF|RF|LC", ip, idx, 1, XFS_DATA_FORK);		xfs_iext_remove(ifp, idx, 1);		ip->i_d.di_nextents--;		if (cur == NULL)			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;		else {			rval = XFS_ILOG_CORE;			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,					PREV.br_startblock, PREV.br_blockcount,					&i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_delete(cur, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_decrement(cur, 0, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur, LEFT.br_startoff,				LEFT.br_startblock,				LEFT.br_blockcount + PREV.br_blockcount,				LEFT.br_state)))				goto done;		}		/* DELTA: Two in-core extents are replaced by one. */		temp = LEFT.br_startoff;		temp2 = LEFT.br_blockcount +			PREV.br_blockcount;		break;	case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG):		/*		 * Setting all of a previous oldext extent to newext.		 * The right neighbor is contiguous, the left is not.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF|RC", ip, idx,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(ep,			PREV.br_blockcount + RIGHT.br_blockcount);		xfs_bmbt_set_state(ep, newext);		XFS_BMAP_TRACE_POST_UPDATE("LF|RF|RC", ip, idx,			XFS_DATA_FORK);		ip->i_df.if_lastex = idx;		XFS_BMAP_TRACE_DELETE("LF|RF|RC", ip, idx + 1, 1, XFS_DATA_FORK);		xfs_iext_remove(ifp, idx + 1, 1);		ip->i_d.di_nextents--;		if (cur == NULL)			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;		else {			rval = XFS_ILOG_CORE;			if ((error = xfs_bmbt_lookup_eq(cur, RIGHT.br_startoff,					RIGHT.br_startblock,					RIGHT.br_blockcount, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_delete(cur, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_decrement(cur, 0, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur, new->br_startoff,				new->br_startblock,				new->br_blockcount + RIGHT.br_blockcount,				newext)))				goto done;		}		/* DELTA: Two in-core extents are replaced by one. */		temp = PREV.br_startoff;		temp2 = PREV.br_blockcount +			RIGHT.br_blockcount;		break;	case MASK2(LEFT_FILLING, RIGHT_FILLING):		/*		 * Setting all of a previous oldext extent to newext.		 * Neither the left nor right neighbors are contiguous with		 * the new one.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF|RF", ip, idx,			XFS_DATA_FORK);		xfs_bmbt_set_state(ep, newext);		XFS_BMAP_TRACE_POST_UPDATE("LF|RF", ip, idx,			XFS_DATA_FORK);		ip->i_df.if_lastex = idx;		if (cur == NULL)			rval = XFS_ILOG_DEXT;		else {			rval = 0;			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,					new->br_startblock, new->br_blockcount,					&i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur, new->br_startoff,				new->br_startblock, new->br_blockcount,				newext)))				goto done;		}		/* DELTA: The in-core extent described by new changed type. */		temp = new->br_startoff;		temp2 = new->br_blockcount;		break;	case MASK2(LEFT_FILLING, LEFT_CONTIG):		/*		 * Setting the first part of a previous oldext extent to newext.		 * The left neighbor is contiguous.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx - 1,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1),			LEFT.br_blockcount + new->br_blockcount);		xfs_bmbt_set_startoff(ep,			PREV.br_startoff + new->br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx - 1,			XFS_DATA_FORK);		XFS_BMAP_TRACE_PRE_UPDATE("LF|LC", ip, idx,			XFS_DATA_FORK);		xfs_bmbt_set_startblock(ep,			new->br_startblock + new->br_blockcount);		xfs_bmbt_set_blockcount(ep,			PREV.br_blockcount - new->br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("LF|LC", ip, idx,			XFS_DATA_FORK);		ip->i_df.if_lastex = idx - 1;		if (cur == NULL)			rval = XFS_ILOG_DEXT;		else {			rval = 0;			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,					PREV.br_startblock, PREV.br_blockcount,					&i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur,				PREV.br_startoff + new->br_blockcount,				PREV.br_startblock + new->br_blockcount,				PREV.br_blockcount - new->br_blockcount,				oldext)))				goto done;			if ((error = xfs_bmbt_decrement(cur, 0, &i)))				goto done;			if (xfs_bmbt_update(cur, LEFT.br_startoff,				LEFT.br_startblock,				LEFT.br_blockcount + new->br_blockcount,				LEFT.br_state))				goto done;		}		/* DELTA: The boundary between two in-core extents moved. */		temp = LEFT.br_startoff;		temp2 = LEFT.br_blockcount +			PREV.br_blockcount;		break;	case MASK(LEFT_FILLING):		/*		 * Setting the first part of a previous oldext extent to newext.		 * The left neighbor is not contiguous.		 */		XFS_BMAP_TRACE_PRE_UPDATE("LF", ip, idx, XFS_DATA_FORK);		ASSERT(ep && xfs_bmbt_get_state(ep) == oldext);		xfs_bmbt_set_startoff(ep, new_endoff);		xfs_bmbt_set_blockcount(ep,			PREV.br_blockcount - new->br_blockcount);		xfs_bmbt_set_startblock(ep,			new->br_startblock + new->br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("LF", ip, idx, XFS_DATA_FORK);		XFS_BMAP_TRACE_INSERT("LF", ip, idx, 1, new, NULL,			XFS_DATA_FORK);		xfs_iext_insert(ifp, idx, 1, new);		ip->i_df.if_lastex = idx;		ip->i_d.di_nextents++;		if (cur == NULL)			rval = XFS_ILOG_CORE | XFS_ILOG_DEXT;		else {			rval = XFS_ILOG_CORE;			if ((error = xfs_bmbt_lookup_eq(cur, PREV.br_startoff,					PREV.br_startblock, PREV.br_blockcount,					&i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_update(cur,				PREV.br_startoff + new->br_blockcount,				PREV.br_startblock + new->br_blockcount,				PREV.br_blockcount - new->br_blockcount,				oldext)))				goto done;			cur->bc_rec.b = *new;			if ((error = xfs_bmbt_insert(cur, &i)))				goto done;			ASSERT(i == 1);		}		/* DELTA: One in-core extent is split in two. */		temp = PREV.br_startoff;		temp2 = PREV.br_blockcount;		break;	case MASK2(RIGHT_FILLING, RIGHT_CONTIG):		/*		 * Setting the last part of a previous oldext extent to newext.		 * The right neighbor is contiguous with the new allocation.		 */		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx,			XFS_DATA_FORK);		XFS_BMAP_TRACE_PRE_UPDATE("RF|RC", ip, idx + 1,			XFS_DATA_FORK);

⌨️ 快捷键说明

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