diff options
Diffstat (limited to 'fs/xfs/libxfs')
| -rw-r--r-- | fs/xfs/libxfs/xfs_alloc.c | 4 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr.c | 20 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.c | 9 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_attr_leaf.h | 3 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_bmap.c | 8 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.c | 39 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_defer.h | 5 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.c | 10 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_ialloc.h | 1 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_iext_tree.c | 4 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_refcount.c | 52 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_rmap.c | 99 | ||||
| -rw-r--r-- | fs/xfs/libxfs/xfs_rmap.h | 16 | 
13 files changed, 185 insertions, 85 deletions
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c index 0da80019a917..83ed7715f856 100644 --- a/fs/xfs/libxfs/xfs_alloc.c +++ b/fs/xfs/libxfs/xfs_alloc.c @@ -702,7 +702,7 @@ xfs_alloc_ag_vextent(  	ASSERT(args->agbno % args->alignment == 0);  	/* if not file data, insert new block into the reverse map btree */ -	if (args->oinfo.oi_owner != XFS_RMAP_OWN_UNKNOWN) { +	if (!xfs_rmap_should_skip_owner_update(&args->oinfo)) {  		error = xfs_rmap_alloc(args->tp, args->agbp, args->agno,  				       args->agbno, args->len, &args->oinfo);  		if (error) @@ -1682,7 +1682,7 @@ xfs_free_ag_extent(  	bno_cur = cnt_cur = NULL;  	mp = tp->t_mountp; -	if (oinfo->oi_owner != XFS_RMAP_OWN_UNKNOWN) { +	if (!xfs_rmap_should_skip_owner_update(oinfo)) {  		error = xfs_rmap_free(tp, agbp, agno, bno, len, oinfo);  		if (error)  			goto error0; diff --git a/fs/xfs/libxfs/xfs_attr.c b/fs/xfs/libxfs/xfs_attr.c index 6249c92671de..a76914db72ef 100644 --- a/fs/xfs/libxfs/xfs_attr.c +++ b/fs/xfs/libxfs/xfs_attr.c @@ -212,6 +212,7 @@ xfs_attr_set(  	int			flags)  {  	struct xfs_mount	*mp = dp->i_mount; +	struct xfs_buf		*leaf_bp = NULL;  	struct xfs_da_args	args;  	struct xfs_defer_ops	dfops;  	struct xfs_trans_res	tres; @@ -327,9 +328,16 @@ xfs_attr_set(  		 * GROT: another possible req'mt for a double-split btree op.  		 */  		xfs_defer_init(args.dfops, args.firstblock); -		error = xfs_attr_shortform_to_leaf(&args); +		error = xfs_attr_shortform_to_leaf(&args, &leaf_bp);  		if (error)  			goto out_defer_cancel; +		/* +		 * Prevent the leaf buffer from being unlocked so that a +		 * concurrent AIL push cannot grab the half-baked leaf +		 * buffer and run into problems with the write verifier. +		 */ +		xfs_trans_bhold(args.trans, leaf_bp); +		xfs_defer_bjoin(args.dfops, leaf_bp);  		xfs_defer_ijoin(args.dfops, dp);  		error = xfs_defer_finish(&args.trans, args.dfops);  		if (error) @@ -337,13 +345,14 @@ xfs_attr_set(  		/*  		 * Commit the leaf transformation.  We'll need another (linked) -		 * transaction to add the new attribute to the leaf. +		 * transaction to add the new attribute to the leaf, which +		 * means that we have to hold & join the leaf buffer here too.  		 */ -  		error = xfs_trans_roll_inode(&args.trans, dp);  		if (error)  			goto out; - +		xfs_trans_bjoin(args.trans, leaf_bp); +		leaf_bp = NULL;  	}  	if (xfs_bmap_one_block(dp, XFS_ATTR_FORK)) @@ -374,8 +383,9 @@ xfs_attr_set(  out_defer_cancel:  	xfs_defer_cancel(&dfops); -	args.trans = NULL;  out: +	if (leaf_bp) +		xfs_trans_brelse(args.trans, leaf_bp);  	if (args.trans)  		xfs_trans_cancel(args.trans);  	xfs_iunlock(dp, XFS_ILOCK_EXCL); diff --git a/fs/xfs/libxfs/xfs_attr_leaf.c b/fs/xfs/libxfs/xfs_attr_leaf.c index 53cc8b986eac..601eaa36f1ad 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.c +++ b/fs/xfs/libxfs/xfs_attr_leaf.c @@ -735,10 +735,13 @@ xfs_attr_shortform_getvalue(xfs_da_args_t *args)  }  /* - * Convert from using the shortform to the leaf. + * Convert from using the shortform to the leaf.  On success, return the + * buffer so that we can keep it locked until we're totally done with it.   */  int -xfs_attr_shortform_to_leaf(xfs_da_args_t *args) +xfs_attr_shortform_to_leaf( +	struct xfs_da_args	*args, +	struct xfs_buf		**leaf_bp)  {  	xfs_inode_t *dp;  	xfs_attr_shortform_t *sf; @@ -818,7 +821,7 @@ xfs_attr_shortform_to_leaf(xfs_da_args_t *args)  		sfe = XFS_ATTR_SF_NEXTENTRY(sfe);  	}  	error = 0; - +	*leaf_bp = bp;  out:  	kmem_free(tmpbuffer);  	return error; diff --git a/fs/xfs/libxfs/xfs_attr_leaf.h b/fs/xfs/libxfs/xfs_attr_leaf.h index f7dda0c237b0..894124efb421 100644 --- a/fs/xfs/libxfs/xfs_attr_leaf.h +++ b/fs/xfs/libxfs/xfs_attr_leaf.h @@ -48,7 +48,8 @@ void	xfs_attr_shortform_create(struct xfs_da_args *args);  void	xfs_attr_shortform_add(struct xfs_da_args *args, int forkoff);  int	xfs_attr_shortform_lookup(struct xfs_da_args *args);  int	xfs_attr_shortform_getvalue(struct xfs_da_args *args); -int	xfs_attr_shortform_to_leaf(struct xfs_da_args *args); +int	xfs_attr_shortform_to_leaf(struct xfs_da_args *args, +			struct xfs_buf **leaf_bp);  int	xfs_attr_shortform_remove(struct xfs_da_args *args);  int	xfs_attr_shortform_allfit(struct xfs_buf *bp, struct xfs_inode *dp);  int	xfs_attr_shortform_bytesfit(struct xfs_inode *dp, int bytes); diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 08df809e2315..1bddbba6b80c 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5136,7 +5136,7 @@ __xfs_bunmapi(  	 * blowing out the transaction with a mix of EFIs and reflink  	 * adjustments.  	 */ -	if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) +	if (tp && xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK)  		max_len = min(len, xfs_refcount_max_unmap(tp->t_log_res));  	else  		max_len = len; @@ -5662,7 +5662,8 @@ xfs_bmap_collapse_extents(  		*done = true;  		goto del_cursor;  	} -	XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); +	XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock), +				del_cursor);  	new_startoff = got.br_startoff - offset_shift_fsb;  	if (xfs_iext_peek_prev_extent(ifp, &icur, &prev)) { @@ -5767,7 +5768,8 @@ xfs_bmap_insert_extents(  			goto del_cursor;  		}  	} -	XFS_WANT_CORRUPTED_RETURN(mp, !isnullstartblock(got.br_startblock)); +	XFS_WANT_CORRUPTED_GOTO(mp, !isnullstartblock(got.br_startblock), +				del_cursor);  	if (stop_fsb >= got.br_startoff + got.br_blockcount) {  		error = -EIO; diff --git a/fs/xfs/libxfs/xfs_defer.c b/fs/xfs/libxfs/xfs_defer.c index 072ebfe1d6ae..087fea02c389 100644 --- a/fs/xfs/libxfs/xfs_defer.c +++ b/fs/xfs/libxfs/xfs_defer.c @@ -249,6 +249,10 @@ xfs_defer_trans_roll(  	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)  		xfs_trans_log_inode(*tp, dop->dop_inodes[i], XFS_ILOG_CORE); +	/* Hold the (previously bjoin'd) buffer locked across the roll. */ +	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) +		xfs_trans_dirty_buf(*tp, dop->dop_bufs[i]); +  	trace_xfs_defer_trans_roll((*tp)->t_mountp, dop);  	/* Roll the transaction. */ @@ -264,6 +268,12 @@ xfs_defer_trans_roll(  	for (i = 0; i < XFS_DEFER_OPS_NR_INODES && dop->dop_inodes[i]; i++)  		xfs_trans_ijoin(*tp, dop->dop_inodes[i], 0); +	/* Rejoin the buffers and dirty them so the log moves forward. */ +	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS && dop->dop_bufs[i]; i++) { +		xfs_trans_bjoin(*tp, dop->dop_bufs[i]); +		xfs_trans_bhold(*tp, dop->dop_bufs[i]); +	} +  	return error;  } @@ -295,6 +305,31 @@ xfs_defer_ijoin(  		}  	} +	ASSERT(0); +	return -EFSCORRUPTED; +} + +/* + * Add this buffer to the deferred op.  Each joined buffer is relogged + * each time we roll the transaction. + */ +int +xfs_defer_bjoin( +	struct xfs_defer_ops		*dop, +	struct xfs_buf			*bp) +{ +	int				i; + +	for (i = 0; i < XFS_DEFER_OPS_NR_BUFS; i++) { +		if (dop->dop_bufs[i] == bp) +			return 0; +		else if (dop->dop_bufs[i] == NULL) { +			dop->dop_bufs[i] = bp; +			return 0; +		} +	} + +	ASSERT(0);  	return -EFSCORRUPTED;  } @@ -493,9 +528,7 @@ xfs_defer_init(  	struct xfs_defer_ops		*dop,  	xfs_fsblock_t			*fbp)  { -	dop->dop_committed = false; -	dop->dop_low = false; -	memset(&dop->dop_inodes, 0, sizeof(dop->dop_inodes)); +	memset(dop, 0, sizeof(struct xfs_defer_ops));  	*fbp = NULLFSBLOCK;  	INIT_LIST_HEAD(&dop->dop_intake);  	INIT_LIST_HEAD(&dop->dop_pending); diff --git a/fs/xfs/libxfs/xfs_defer.h b/fs/xfs/libxfs/xfs_defer.h index d4f046dd44bd..045beacdd37d 100644 --- a/fs/xfs/libxfs/xfs_defer.h +++ b/fs/xfs/libxfs/xfs_defer.h @@ -59,6 +59,7 @@ enum xfs_defer_ops_type {  };  #define XFS_DEFER_OPS_NR_INODES	2	/* join up to two inodes */ +#define XFS_DEFER_OPS_NR_BUFS	2	/* join up to two buffers */  struct xfs_defer_ops {  	bool			dop_committed;	/* did any trans commit? */ @@ -66,8 +67,9 @@ struct xfs_defer_ops {  	struct list_head	dop_intake;	/* unlogged pending work */  	struct list_head	dop_pending;	/* logged pending work */ -	/* relog these inodes with each roll */ +	/* relog these with each roll */  	struct xfs_inode	*dop_inodes[XFS_DEFER_OPS_NR_INODES]; +	struct xfs_buf		*dop_bufs[XFS_DEFER_OPS_NR_BUFS];  };  void xfs_defer_add(struct xfs_defer_ops *dop, enum xfs_defer_ops_type type, @@ -77,6 +79,7 @@ void xfs_defer_cancel(struct xfs_defer_ops *dop);  void xfs_defer_init(struct xfs_defer_ops *dop, xfs_fsblock_t *fbp);  bool xfs_defer_has_unfinished_work(struct xfs_defer_ops *dop);  int xfs_defer_ijoin(struct xfs_defer_ops *dop, struct xfs_inode *ip); +int xfs_defer_bjoin(struct xfs_defer_ops *dop, struct xfs_buf *bp);  /* Description of a deferred type. */  struct xfs_defer_op_type { diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c index de3f04a98656..3b57ef0f2f76 100644 --- a/fs/xfs/libxfs/xfs_ialloc.c +++ b/fs/xfs/libxfs/xfs_ialloc.c @@ -920,8 +920,7 @@ STATIC xfs_agnumber_t  xfs_ialloc_ag_select(  	xfs_trans_t	*tp,		/* transaction pointer */  	xfs_ino_t	parent,		/* parent directory inode number */ -	umode_t		mode,		/* bits set to indicate file type */ -	int		okalloc)	/* ok to allocate more space */ +	umode_t		mode)		/* bits set to indicate file type */  {  	xfs_agnumber_t	agcount;	/* number of ag's in the filesystem */  	xfs_agnumber_t	agno;		/* current ag number */ @@ -978,9 +977,6 @@ xfs_ialloc_ag_select(  			return agno;  		} -		if (!okalloc) -			goto nextag; -  		if (!pag->pagf_init) {  			error = xfs_alloc_pagf_init(mp, tp, agno, flags);  			if (error) @@ -1680,7 +1676,6 @@ xfs_dialloc(  	struct xfs_trans	*tp,  	xfs_ino_t		parent,  	umode_t			mode, -	int			okalloc,  	struct xfs_buf		**IO_agbp,  	xfs_ino_t		*inop)  { @@ -1692,6 +1687,7 @@ xfs_dialloc(  	int			noroom = 0;  	xfs_agnumber_t		start_agno;  	struct xfs_perag	*pag; +	int			okalloc = 1;  	if (*IO_agbp) {  		/* @@ -1707,7 +1703,7 @@ xfs_dialloc(  	 * We do not have an agbp, so select an initial allocation  	 * group for inode allocation.  	 */ -	start_agno = xfs_ialloc_ag_select(tp, parent, mode, okalloc); +	start_agno = xfs_ialloc_ag_select(tp, parent, mode);  	if (start_agno == NULLAGNUMBER) {  		*inop = NULLFSINO;  		return 0; diff --git a/fs/xfs/libxfs/xfs_ialloc.h b/fs/xfs/libxfs/xfs_ialloc.h index d2bdcd5e7312..66a8de0b1caa 100644 --- a/fs/xfs/libxfs/xfs_ialloc.h +++ b/fs/xfs/libxfs/xfs_ialloc.h @@ -81,7 +81,6 @@ xfs_dialloc(  	struct xfs_trans *tp,		/* transaction pointer */  	xfs_ino_t	parent,		/* parent inode (directory) */  	umode_t		mode,		/* mode bits for new inode */ -	int		okalloc,	/* ok to allocate more space */  	struct xfs_buf	**agbp,		/* buf for a.g. inode header */  	xfs_ino_t	*inop);		/* inode number allocated */ diff --git a/fs/xfs/libxfs/xfs_iext_tree.c b/fs/xfs/libxfs/xfs_iext_tree.c index 89bf16b4d937..b0f31791c7e6 100644 --- a/fs/xfs/libxfs/xfs_iext_tree.c +++ b/fs/xfs/libxfs/xfs_iext_tree.c @@ -632,8 +632,6 @@ xfs_iext_insert(  	struct xfs_iext_leaf	*new = NULL;  	int			nr_entries, i; -	trace_xfs_iext_insert(ip, cur, state, _RET_IP_); -  	if (ifp->if_height == 0)  		xfs_iext_alloc_root(ifp, cur);  	else if (ifp->if_height == 1) @@ -661,6 +659,8 @@ xfs_iext_insert(  	xfs_iext_set(cur_rec(cur), irec);  	ifp->if_bytes += sizeof(struct xfs_iext_rec); +	trace_xfs_iext_insert(ip, cur, state, _RET_IP_); +  	if (new)  		xfs_iext_insert_node(ifp, xfs_iext_leaf_key(new, 0), new, 2);  } diff --git a/fs/xfs/libxfs/xfs_refcount.c b/fs/xfs/libxfs/xfs_refcount.c index 585b35d34142..c40d26763075 100644 --- a/fs/xfs/libxfs/xfs_refcount.c +++ b/fs/xfs/libxfs/xfs_refcount.c @@ -1488,27 +1488,12 @@ __xfs_refcount_cow_alloc(  	xfs_extlen_t		aglen,  	struct xfs_defer_ops	*dfops)  { -	int			error; -  	trace_xfs_refcount_cow_increase(rcur->bc_mp, rcur->bc_private.a.agno,  			agbno, aglen);  	/* Add refcount btree reservation */ -	error = xfs_refcount_adjust_cow(rcur, agbno, aglen, +	return xfs_refcount_adjust_cow(rcur, agbno, aglen,  			XFS_REFCOUNT_ADJUST_COW_ALLOC, dfops); -	if (error) -		return error; - -	/* Add rmap entry */ -	if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { -		error = xfs_rmap_alloc_extent(rcur->bc_mp, dfops, -				rcur->bc_private.a.agno, -				agbno, aglen, XFS_RMAP_OWN_COW); -		if (error) -			return error; -	} - -	return error;  }  /* @@ -1521,27 +1506,12 @@ __xfs_refcount_cow_free(  	xfs_extlen_t		aglen,  	struct xfs_defer_ops	*dfops)  { -	int			error; -  	trace_xfs_refcount_cow_decrease(rcur->bc_mp, rcur->bc_private.a.agno,  			agbno, aglen);  	/* Remove refcount btree reservation */ -	error = xfs_refcount_adjust_cow(rcur, agbno, aglen, +	return xfs_refcount_adjust_cow(rcur, agbno, aglen,  			XFS_REFCOUNT_ADJUST_COW_FREE, dfops); -	if (error) -		return error; - -	/* Remove rmap entry */ -	if (xfs_sb_version_hasrmapbt(&rcur->bc_mp->m_sb)) { -		error = xfs_rmap_free_extent(rcur->bc_mp, dfops, -				rcur->bc_private.a.agno, -				agbno, aglen, XFS_RMAP_OWN_COW); -		if (error) -			return error; -	} - -	return error;  }  /* Record a CoW staging extent in the refcount btree. */ @@ -1552,11 +1522,19 @@ xfs_refcount_alloc_cow_extent(  	xfs_fsblock_t			fsb,  	xfs_extlen_t			len)  { +	int				error; +  	if (!xfs_sb_version_hasreflink(&mp->m_sb))  		return 0; -	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW, +	error = __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_ALLOC_COW,  			fsb, len); +	if (error) +		return error; + +	/* Add rmap entry */ +	return xfs_rmap_alloc_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb), +			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW);  }  /* Forget a CoW staging event in the refcount btree. */ @@ -1567,9 +1545,17 @@ xfs_refcount_free_cow_extent(  	xfs_fsblock_t			fsb,  	xfs_extlen_t			len)  { +	int				error; +  	if (!xfs_sb_version_hasreflink(&mp->m_sb))  		return 0; +	/* Remove rmap entry */ +	error = xfs_rmap_free_extent(mp, dfops, XFS_FSB_TO_AGNO(mp, fsb), +			XFS_FSB_TO_AGBNO(mp, fsb), len, XFS_RMAP_OWN_COW); +	if (error) +		return error; +  	return __xfs_refcount_add(mp, dfops, XFS_REFCOUNT_FREE_COW,  			fsb, len);  } diff --git a/fs/xfs/libxfs/xfs_rmap.c b/fs/xfs/libxfs/xfs_rmap.c index dd019cee1b3b..50db920ceeeb 100644 --- a/fs/xfs/libxfs/xfs_rmap.c +++ b/fs/xfs/libxfs/xfs_rmap.c @@ -368,6 +368,51 @@ xfs_rmap_lookup_le_range(  }  /* + * Perform all the relevant owner checks for a removal op.  If we're doing an + * unknown-owner removal then we have no owner information to check. + */ +static int +xfs_rmap_free_check_owner( +	struct xfs_mount	*mp, +	uint64_t		ltoff, +	struct xfs_rmap_irec	*rec, +	xfs_fsblock_t		bno, +	xfs_filblks_t		len, +	uint64_t		owner, +	uint64_t		offset, +	unsigned int		flags) +{ +	int			error = 0; + +	if (owner == XFS_RMAP_OWN_UNKNOWN) +		return 0; + +	/* Make sure the unwritten flag matches. */ +	XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == +			(rec->rm_flags & XFS_RMAP_UNWRITTEN), out); + +	/* Make sure the owner matches what we expect to find in the tree. */ +	XFS_WANT_CORRUPTED_GOTO(mp, owner == rec->rm_owner, out); + +	/* Check the offset, if necessary. */ +	if (XFS_RMAP_NON_INODE_OWNER(owner)) +		goto out; + +	if (flags & XFS_RMAP_BMBT_BLOCK) { +		XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_flags & XFS_RMAP_BMBT_BLOCK, +				out); +	} else { +		XFS_WANT_CORRUPTED_GOTO(mp, rec->rm_offset <= offset, out); +		XFS_WANT_CORRUPTED_GOTO(mp, +				ltoff + rec->rm_blockcount >= offset + len, +				out); +	} + +out: +	return error; +} + +/*   * Find the extent in the rmap btree and remove it.   *   * The record we find should always be an exact match for the extent that we're @@ -444,33 +489,40 @@ xfs_rmap_unmap(  		goto out_done;  	} -	/* Make sure the unwritten flag matches. */ -	XFS_WANT_CORRUPTED_GOTO(mp, (flags & XFS_RMAP_UNWRITTEN) == -			(ltrec.rm_flags & XFS_RMAP_UNWRITTEN), out_error); +	/* +	 * If we're doing an unknown-owner removal for EFI recovery, we expect +	 * to find the full range in the rmapbt or nothing at all.  If we +	 * don't find any rmaps overlapping either end of the range, we're +	 * done.  Hopefully this means that the EFI creator already queued +	 * (and finished) a RUI to remove the rmap. +	 */ +	if (owner == XFS_RMAP_OWN_UNKNOWN && +	    ltrec.rm_startblock + ltrec.rm_blockcount <= bno) { +		struct xfs_rmap_irec    rtrec; + +		error = xfs_btree_increment(cur, 0, &i); +		if (error) +			goto out_error; +		if (i == 0) +			goto out_done; +		error = xfs_rmap_get_rec(cur, &rtrec, &i); +		if (error) +			goto out_error; +		XFS_WANT_CORRUPTED_GOTO(mp, i == 1, out_error); +		if (rtrec.rm_startblock >= bno + len) +			goto out_done; +	}  	/* Make sure the extent we found covers the entire freeing range. */  	XFS_WANT_CORRUPTED_GOTO(mp, ltrec.rm_startblock <= bno && -		ltrec.rm_startblock + ltrec.rm_blockcount >= -		bno + len, out_error); +			ltrec.rm_startblock + ltrec.rm_blockcount >= +			bno + len, out_error); -	/* Make sure the owner matches what we expect to find in the tree. */ -	XFS_WANT_CORRUPTED_GOTO(mp, owner == ltrec.rm_owner || -				    XFS_RMAP_NON_INODE_OWNER(owner), out_error); - -	/* Check the offset, if necessary. */ -	if (!XFS_RMAP_NON_INODE_OWNER(owner)) { -		if (flags & XFS_RMAP_BMBT_BLOCK) { -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltrec.rm_flags & XFS_RMAP_BMBT_BLOCK, -					out_error); -		} else { -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltrec.rm_offset <= offset, out_error); -			XFS_WANT_CORRUPTED_GOTO(mp, -					ltoff + ltrec.rm_blockcount >= offset + len, -					out_error); -		} -	} +	/* Check owner information. */ +	error = xfs_rmap_free_check_owner(mp, ltoff, <rec, bno, len, owner, +			offset, flags); +	if (error) +		goto out_error;  	if (ltrec.rm_startblock == bno && ltrec.rm_blockcount == len) {  		/* exact match, simply remove the record from rmap tree */ @@ -664,6 +716,7 @@ xfs_rmap_map(  		flags |= XFS_RMAP_UNWRITTEN;  	trace_xfs_rmap_map(mp, cur->bc_private.a.agno, bno, len,  			unwritten, oinfo); +	ASSERT(!xfs_rmap_should_skip_owner_update(oinfo));  	/*  	 * For the initial lookup, look for an exact match or the left-adjacent diff --git a/fs/xfs/libxfs/xfs_rmap.h b/fs/xfs/libxfs/xfs_rmap.h index 466ede637080..0fcd5b1ba729 100644 --- a/fs/xfs/libxfs/xfs_rmap.h +++ b/fs/xfs/libxfs/xfs_rmap.h @@ -61,7 +61,21 @@ static inline void  xfs_rmap_skip_owner_update(  	struct xfs_owner_info	*oi)  { -	oi->oi_owner = XFS_RMAP_OWN_UNKNOWN; +	xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_NULL); +} + +static inline bool +xfs_rmap_should_skip_owner_update( +	struct xfs_owner_info	*oi) +{ +	return oi->oi_owner == XFS_RMAP_OWN_NULL; +} + +static inline void +xfs_rmap_any_owner_update( +	struct xfs_owner_info	*oi) +{ +	xfs_rmap_ag_owner(oi, XFS_RMAP_OWN_UNKNOWN);  }  /* Reverse mapping functions. */  | 
