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

📄 xfs_bmap.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		xfs_bmbt_set_blockcount(ep,			PREV.br_blockcount - new->br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx,			XFS_DATA_FORK);		xfs_bmbt_set_allf(xfs_iext_get_ext(ifp, idx + 1),			new->br_startoff, new->br_startblock,			new->br_blockcount + RIGHT.br_blockcount, newext);		XFS_BMAP_TRACE_POST_UPDATE("RF|RC", ip, idx + 1,			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,				PREV.br_startblock,				PREV.br_blockcount - new->br_blockcount,				oldext)))				goto done;			if ((error = xfs_bmbt_increment(cur, 0, &i)))				goto done;			if ((error = xfs_bmbt_update(cur, new->br_startoff,				new->br_startblock,				new->br_blockcount + RIGHT.br_blockcount,				newext)))				goto done;		}		/* DELTA: The boundary between two in-core extents moved. */		temp = PREV.br_startoff;		temp2 = PREV.br_blockcount +			RIGHT.br_blockcount;		break;	case MASK(RIGHT_FILLING):		/*		 * Setting the last part of a previous oldext extent to newext.		 * The right neighbor is not contiguous.		 */		XFS_BMAP_TRACE_PRE_UPDATE("RF", ip, idx, XFS_DATA_FORK);		xfs_bmbt_set_blockcount(ep,			PREV.br_blockcount - new->br_blockcount);		XFS_BMAP_TRACE_POST_UPDATE("RF", ip, idx, XFS_DATA_FORK);		XFS_BMAP_TRACE_INSERT("RF", ip, idx + 1, 1, new, NULL,			XFS_DATA_FORK);		xfs_iext_insert(ifp, idx + 1, 1, new);		ip->i_df.if_lastex = 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_update(cur, PREV.br_startoff,				PREV.br_startblock,				PREV.br_blockcount - new->br_blockcount,				oldext)))				goto done;			if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff,					new->br_startblock, new->br_blockcount,					&i)))				goto done;			ASSERT(i == 0);			cur->bc_rec.b.br_state = XFS_EXT_NORM;			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 0:		/*		 * Setting the middle part of a previous oldext extent to		 * newext.  Contiguity is impossible here.		 * One extent becomes three extents.		 */		XFS_BMAP_TRACE_PRE_UPDATE("0", ip, idx, XFS_DATA_FORK);		xfs_bmbt_set_blockcount(ep,			new->br_startoff - PREV.br_startoff);		XFS_BMAP_TRACE_POST_UPDATE("0", ip, idx, XFS_DATA_FORK);		r[0] = *new;		r[1].br_startoff = new_endoff;		r[1].br_blockcount =			PREV.br_startoff + PREV.br_blockcount - new_endoff;		r[1].br_startblock = new->br_startblock + new->br_blockcount;		r[1].br_state = oldext;		XFS_BMAP_TRACE_INSERT("0", ip, idx + 1, 2, &r[0], &r[1],			XFS_DATA_FORK);		xfs_iext_insert(ifp, idx + 1, 2, &r[0]);		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, PREV.br_startoff,					PREV.br_startblock, PREV.br_blockcount,					&i)))				goto done;			ASSERT(i == 1);			/* new right extent - oldext */			if ((error = xfs_bmbt_update(cur, r[1].br_startoff,				r[1].br_startblock, r[1].br_blockcount,				r[1].br_state)))				goto done;			/* new left extent - oldext */			PREV.br_blockcount =				new->br_startoff - PREV.br_startoff;			cur->bc_rec.b = PREV;			if ((error = xfs_bmbt_insert(cur, &i)))				goto done;			ASSERT(i == 1);			if ((error = xfs_bmbt_increment(cur, 0, &i)))				goto done;			ASSERT(i == 1);			/* new middle extent - newext */			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 three. */		temp = PREV.br_startoff;		temp2 = PREV.br_blockcount;		break;	case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):	case MASK3(RIGHT_FILLING, LEFT_CONTIG, RIGHT_CONTIG):	case MASK2(LEFT_FILLING, RIGHT_CONTIG):	case MASK2(RIGHT_FILLING, LEFT_CONTIG):	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):	case MASK(LEFT_CONTIG):	case MASK(RIGHT_CONTIG):		/*		 * These cases are all impossible.		 */		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 a hole * to a delayed allocation. *//*ARGSUSED*/STATIC int				/* error */xfs_bmap_add_extent_hole_delay(	xfs_inode_t		*ip,	/* incore inode pointer */	xfs_extnum_t		idx,	/* extent number to update/insert */	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 */	int			rsvd)		/* OK to allocate reserved blocks */{	xfs_bmbt_rec_host_t	*ep;	/* extent record for idx */	xfs_ifork_t		*ifp;	/* inode fork pointer */	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */	xfs_filblks_t		newlen=0;	/* new indirect size */	xfs_filblks_t		oldlen=0;	/* old indirect size */	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */	int			state;  /* state bits, accessed thru macros */	xfs_filblks_t		temp=0;	/* temp for indirect calculations */	xfs_filblks_t		temp2=0;	enum {				/* bit number definitions for state */		LEFT_CONTIG,	RIGHT_CONTIG,		LEFT_DELAY,	RIGHT_DELAY,		LEFT_VALID,	RIGHT_VALID	};#define	MASK(b)			(1 << (b))#define	MASK2(a,b)		(MASK(a) | MASK(b))#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 & MASK2(LEFT_CONTIG, RIGHT_CONTIG))	ifp = XFS_IFORK_PTR(ip, XFS_DATA_FORK);	ep = xfs_iext_get_ext(ifp, idx);	state = 0;	ASSERT(ISNULLSTARTBLOCK(new->br_startblock));	/*	 * Check and set flags if this segment has a left neighbor	 */	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));	}	/*	 * Check and set flags if the current (right) segment exists.	 * If it doesn't exist, we're converting the hole at end-of-file.	 */	if (STATE_SET_TEST(RIGHT_VALID,			   idx <			   ip->i_df.if_bytes / (uint)sizeof(xfs_bmbt_rec_t))) {		xfs_bmbt_get_all(ep, &right);		STATE_SET(RIGHT_DELAY, ISNULLSTARTBLOCK(right.br_startblock));	}	/*	 * Set contiguity flags on the left and right neighbors.	 * Don't let extents get too large, even if the pieces are contiguous.	 */	STATE_SET(LEFT_CONTIG,		STATE_TEST(LEFT_VALID) && STATE_TEST(LEFT_DELAY) &&		left.br_startoff + left.br_blockcount == new->br_startoff &&		left.br_blockcount + new->br_blockcount <= MAXEXTLEN);	STATE_SET(RIGHT_CONTIG,		STATE_TEST(RIGHT_VALID) && STATE_TEST(RIGHT_DELAY) &&		new->br_startoff + new->br_blockcount == right.br_startoff &&		new->br_blockcount + right.br_blockcount <= MAXEXTLEN &&		(!STATE_TEST(LEFT_CONTIG) ||		 (left.br_blockcount + new->br_blockcount +		     right.br_blockcount <= MAXEXTLEN)));	/*	 * Switch out based on the contiguity flags.	 */	switch (SWITCH_STATE) {	case MASK2(LEFT_CONTIG, RIGHT_CONTIG):		/*		 * New allocation is contiguous with delayed allocations		 * on the left and on the right.		 * Merge all three into a single extent record.		 */		temp = left.br_blockcount + new->br_blockcount +			right.br_blockcount;		XFS_BMAP_TRACE_PRE_UPDATE("LC|RC", ip, idx - 1,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);		oldlen = STARTBLOCKVAL(left.br_startblock) +			STARTBLOCKVAL(new->br_startblock) +			STARTBLOCKVAL(right.br_startblock);		newlen = xfs_bmap_worst_indlen(ip, temp);		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),			NULLSTARTBLOCK((int)newlen));		XFS_BMAP_TRACE_POST_UPDATE("LC|RC", ip, idx - 1,			XFS_DATA_FORK);		XFS_BMAP_TRACE_DELETE("LC|RC", ip, idx, 1, XFS_DATA_FORK);		xfs_iext_remove(ifp, idx, 1);		ip->i_df.if_lastex = idx - 1;		/* DELTA: Two in-core extents were replaced by one. */		temp2 = temp;		temp = left.br_startoff;		break;	case MASK(LEFT_CONTIG):		/*		 * New allocation is contiguous with a delayed allocation		 * on the left.		 * Merge the new allocation with the left neighbor.		 */		temp = left.br_blockcount + new->br_blockcount;		XFS_BMAP_TRACE_PRE_UPDATE("LC", ip, idx - 1,			XFS_DATA_FORK);		xfs_bmbt_set_blockcount(xfs_iext_get_ext(ifp, idx - 1), temp);		oldlen = STARTBLOCKVAL(left.br_startblock) +			STARTBLOCKVAL(new->br_startblock);		newlen = xfs_bmap_worst_indlen(ip, temp);		xfs_bmbt_set_startblock(xfs_iext_get_ext(ifp, idx - 1),			NULLSTARTBLOCK((int)newlen));		XFS_BMAP_TRACE_POST_UPDATE("LC", ip, idx - 1,			XFS_DATA_FORK);		ip->i_df.if_lastex = idx - 1;		/* DELTA: One in-core extent grew into a hole. */		temp2 = temp;		temp = left.br_startoff;		break;	case MASK(RIGHT_CONTIG):		/*		 * New allocation is contiguous with a delayed allocation		 * on the right.		 * Merge the new allocation with the right neighbor.		 */		XFS_BMAP_TRACE_PRE_UPDATE("RC", ip, idx, XFS_DATA_FORK);		temp = new->br_blockcount + right.br_blockcount;		oldlen = STARTBLOCKVAL(new->br_startblock) +			STARTBLOCKVAL(right.br_startblock);		newlen = xfs_bmap_worst_indlen(ip, temp);		xfs_bmbt_set_allf(ep, new->br_startoff,			NULLSTARTBLOCK((int)newlen), temp, right.br_state);		XFS_BMAP_TRACE_POST_UPDATE("RC", ip, idx, XFS_DATA_FORK);		ip->i_df.if_lastex = idx;		/* DELTA: One in-core extent grew into a hole. */		temp2 = temp;		temp = new->br_startoff;		break;	case 0:		/*		 * New allocation is not contiguous with another		 * delayed allocation.		 * Insert a new entry.		 */		oldlen = newlen = 0;		XFS_BMAP_TRACE_INSERT("0", ip, idx, 1, new, NULL,			XFS_DATA_FORK);		xfs_iext_insert(ifp, idx, 1, new);		ip->i_df.if_lastex = idx;		/* DELTA: A new in-core extent was added in a hole. */		temp2 = new->br_blockcount;		temp = new->br_startoff;		break;	}	if (oldlen != newlen) {		ASSERT(oldlen > newlen);		xfs_mod_incore_sb(ip->i_mount, XFS_SBS_FDBLOCKS,			(int64_t)(oldlen - newlen), rsvd);		/*		 * Nothing to do for disk quota accounting here.		 */	}	if (delta) {		temp2 += temp;		if (delta->xed_startoff > temp)			delta->xed_startoff = temp;		if (delta->xed_blockcount < temp2)			delta->xed_blockcount = temp2;	}	*logflagsp = 0;	return 0;#undef	MASK#undef	MASK2#undef	STATE_SET#undef	STATE_TEST#undef	STATE_SET_TEST#undef	SWITCH_STATE}/* * Called by xfs_bmap_add_extent to handle cases converting a hole * to a real allocation. */STATIC int				/* error */xfs_bmap_add_extent_hole_real(	xfs_inode_t		*ip,	/* incore inode pointer */	xfs_extnum_t		idx,	/* extent number to update/insert */	xfs_btree_cur_t		*cur,	/* if 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 */	int			whichfork) /* data or attr fork */{	xfs_bmbt_rec_host_t	*ep;	/* pointer to extent entry ins. point */	int			error;	/* error return value */	int			i;	/* temp state */	xfs_ifork_t		*ifp;	/* inode fork pointer */	xfs_bmbt_irec_t		left;	/* left neighbor extent entry */	xfs_bmbt_irec_t		right;	/* right neighbor extent entry */	int			rval=0;	/* return value (logging flags) */	int			state;	/* 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_DELAY,	RIGHT_DELAY,		LEFT_VALID,	RIGHT_VALID	};#define	MASK(b)			(1 << (b))#define	MASK2(a,b)		(MASK(a) | MASK(b))#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 & MASK2(LEFT_CONTIG, RIGHT_CONTIG))	ifp = XFS_IFORK_PTR(ip, whichfork);	ASSERT(idx <= ifp->if_bytes / (uint)sizeof(xfs_bmbt_rec_t));	ep = xfs_iext_get_ext(ifp, idx);	state = 0;	/*	 * Check and set flags if this segment has a left neighbor

⌨️ 快捷键说明

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