mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	xfs: add bmapi nodiscard flag
Freed extents are unconditionally discarded when online discard is enabled. Define XFS_BMAPI_NODISCARD to allow callers to bypass discards when unnecessary. For example, this will be useful for eofblocks trimming. This patch does not change behavior. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
		
							parent
							
								
									e6631f8554
								
							
						
					
					
						commit
						fcb762f5de
					
				
					 7 changed files with 87 additions and 18 deletions
				
			
		| 
						 | 
				
			
			@ -3009,18 +3009,20 @@ xfs_free_extent_fix_freelist(
 | 
			
		|||
 * after fixing up the freelist.
 | 
			
		||||
 */
 | 
			
		||||
int				/* error */
 | 
			
		||||
xfs_free_extent(
 | 
			
		||||
__xfs_free_extent(
 | 
			
		||||
	struct xfs_trans	*tp,	/* transaction pointer */
 | 
			
		||||
	xfs_fsblock_t		bno,	/* starting block number of extent */
 | 
			
		||||
	xfs_extlen_t		len,	/* length of extent */
 | 
			
		||||
	struct xfs_owner_info	*oinfo,	/* extent owner */
 | 
			
		||||
	enum xfs_ag_resv_type	type)	/* block reservation type */
 | 
			
		||||
	enum xfs_ag_resv_type	type,	/* block reservation type */
 | 
			
		||||
	bool			skip_discard)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_mount	*mp = tp->t_mountp;
 | 
			
		||||
	struct xfs_buf		*agbp;
 | 
			
		||||
	xfs_agnumber_t		agno = XFS_FSB_TO_AGNO(mp, bno);
 | 
			
		||||
	xfs_agblock_t		agbno = XFS_FSB_TO_AGBNO(mp, bno);
 | 
			
		||||
	int			error;
 | 
			
		||||
	unsigned int		busy_flags = 0;
 | 
			
		||||
 | 
			
		||||
	ASSERT(len != 0);
 | 
			
		||||
	ASSERT(type != XFS_AG_RESV_AGFL);
 | 
			
		||||
| 
						 | 
				
			
			@ -3044,7 +3046,9 @@ xfs_free_extent(
 | 
			
		|||
	if (error)
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
	xfs_extent_busy_insert(tp, agno, agbno, len, 0);
 | 
			
		||||
	if (skip_discard)
 | 
			
		||||
		busy_flags |= XFS_EXTENT_BUSY_SKIP_DISCARD;
 | 
			
		||||
	xfs_extent_busy_insert(tp, agno, agbno, len, busy_flags);
 | 
			
		||||
	return 0;
 | 
			
		||||
 | 
			
		||||
err:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -191,12 +191,35 @@ xfs_alloc_vextent(
 | 
			
		|||
 * Free an extent.
 | 
			
		||||
 */
 | 
			
		||||
int				/* error */
 | 
			
		||||
xfs_free_extent(
 | 
			
		||||
__xfs_free_extent(
 | 
			
		||||
	struct xfs_trans	*tp,	/* transaction pointer */
 | 
			
		||||
	xfs_fsblock_t		bno,	/* starting block number of extent */
 | 
			
		||||
	xfs_extlen_t		len,	/* length of extent */
 | 
			
		||||
	struct xfs_owner_info	*oinfo,	/* extent owner */
 | 
			
		||||
	enum xfs_ag_resv_type	type);	/* block reservation type */
 | 
			
		||||
	enum xfs_ag_resv_type	type,	/* block reservation type */
 | 
			
		||||
	bool			skip_discard);
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
xfs_free_extent(
 | 
			
		||||
	struct xfs_trans	*tp,
 | 
			
		||||
	xfs_fsblock_t		bno,
 | 
			
		||||
	xfs_extlen_t		len,
 | 
			
		||||
	struct xfs_owner_info	*oinfo,
 | 
			
		||||
	enum xfs_ag_resv_type	type)
 | 
			
		||||
{
 | 
			
		||||
	return __xfs_free_extent(tp, bno, len, oinfo, type, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline int
 | 
			
		||||
xfs_free_extent_nodiscard(
 | 
			
		||||
	struct xfs_trans	*tp,
 | 
			
		||||
	xfs_fsblock_t		bno,
 | 
			
		||||
	xfs_extlen_t		len,
 | 
			
		||||
	struct xfs_owner_info	*oinfo,
 | 
			
		||||
	enum xfs_ag_resv_type	type)
 | 
			
		||||
{
 | 
			
		||||
	return __xfs_free_extent(tp, bno, len, oinfo, type, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int				/* error */
 | 
			
		||||
xfs_alloc_lookup_le(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -544,12 +544,13 @@ xfs_bmap_validate_ret(
 | 
			
		|||
 * The list is maintained sorted (by block number).
 | 
			
		||||
 */
 | 
			
		||||
void
 | 
			
		||||
xfs_bmap_add_free(
 | 
			
		||||
__xfs_bmap_add_free(
 | 
			
		||||
	struct xfs_mount		*mp,
 | 
			
		||||
	struct xfs_defer_ops		*dfops,
 | 
			
		||||
	xfs_fsblock_t			bno,
 | 
			
		||||
	xfs_filblks_t			len,
 | 
			
		||||
	struct xfs_owner_info		*oinfo)
 | 
			
		||||
	struct xfs_owner_info		*oinfo,
 | 
			
		||||
	bool				skip_discard)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_extent_free_item	*new;		/* new element */
 | 
			
		||||
#ifdef DEBUG
 | 
			
		||||
| 
						 | 
				
			
			@ -576,6 +577,7 @@ xfs_bmap_add_free(
 | 
			
		|||
		new->xefi_oinfo = *oinfo;
 | 
			
		||||
	else
 | 
			
		||||
		xfs_rmap_skip_owner_update(&new->xefi_oinfo);
 | 
			
		||||
	new->xefi_skip_discard = skip_discard;
 | 
			
		||||
	trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
 | 
			
		||||
			XFS_FSB_TO_AGBNO(mp, bno), len);
 | 
			
		||||
	xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
 | 
			
		||||
| 
						 | 
				
			
			@ -5106,9 +5108,16 @@ xfs_bmap_del_extent_real(
 | 
			
		|||
			error = xfs_refcount_decrease_extent(mp, dfops, del);
 | 
			
		||||
			if (error)
 | 
			
		||||
				goto done;
 | 
			
		||||
		} else
 | 
			
		||||
			xfs_bmap_add_free(mp, dfops, del->br_startblock,
 | 
			
		||||
		} else {
 | 
			
		||||
			if (bflags & XFS_BMAPI_NODISCARD) {
 | 
			
		||||
				xfs_bmap_add_free_nodiscard(mp, dfops,
 | 
			
		||||
					del->br_startblock, del->br_blockcount,
 | 
			
		||||
					NULL);
 | 
			
		||||
			} else {
 | 
			
		||||
				xfs_bmap_add_free(mp, dfops, del->br_startblock,
 | 
			
		||||
					del->br_blockcount, NULL);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,7 @@ struct xfs_extent_free_item
 | 
			
		|||
	xfs_extlen_t		xefi_blockcount;/* number of blocks in extent */
 | 
			
		||||
	struct list_head	xefi_list;
 | 
			
		||||
	struct xfs_owner_info	xefi_oinfo;	/* extent owner */
 | 
			
		||||
	bool			xefi_skip_discard;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define	XFS_BMAP_MAX_NMAP	4
 | 
			
		||||
| 
						 | 
				
			
			@ -116,6 +117,9 @@ struct xfs_extent_free_item
 | 
			
		|||
/* Only convert unwritten extents, don't allocate new blocks */
 | 
			
		||||
#define XFS_BMAPI_CONVERT_ONLY	0x800
 | 
			
		||||
 | 
			
		||||
/* Skip online discard of freed extents */
 | 
			
		||||
#define XFS_BMAPI_NODISCARD	0x1000
 | 
			
		||||
 | 
			
		||||
#define XFS_BMAPI_FLAGS \
 | 
			
		||||
	{ XFS_BMAPI_ENTIRE,	"ENTIRE" }, \
 | 
			
		||||
	{ XFS_BMAPI_METADATA,	"METADATA" }, \
 | 
			
		||||
| 
						 | 
				
			
			@ -128,7 +132,8 @@ struct xfs_extent_free_item
 | 
			
		|||
	{ XFS_BMAPI_REMAP,	"REMAP" }, \
 | 
			
		||||
	{ XFS_BMAPI_COWFORK,	"COWFORK" }, \
 | 
			
		||||
	{ XFS_BMAPI_DELALLOC,	"DELALLOC" }, \
 | 
			
		||||
	{ XFS_BMAPI_CONVERT_ONLY, "CONVERT_ONLY" }
 | 
			
		||||
	{ XFS_BMAPI_CONVERT_ONLY, "CONVERT_ONLY" }, \
 | 
			
		||||
	{ XFS_BMAPI_NODISCARD,	"NODISCARD" }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static inline int xfs_bmapi_aflag(int w)
 | 
			
		||||
| 
						 | 
				
			
			@ -192,9 +197,9 @@ void	xfs_trim_extent(struct xfs_bmbt_irec *irec, xfs_fileoff_t bno,
 | 
			
		|||
void	xfs_trim_extent_eof(struct xfs_bmbt_irec *, struct xfs_inode *);
 | 
			
		||||
int	xfs_bmap_add_attrfork(struct xfs_inode *ip, int size, int rsvd);
 | 
			
		||||
void	xfs_bmap_local_to_extents_empty(struct xfs_inode *ip, int whichfork);
 | 
			
		||||
void	xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 | 
			
		||||
void	__xfs_bmap_add_free(struct xfs_mount *mp, struct xfs_defer_ops *dfops,
 | 
			
		||||
			  xfs_fsblock_t bno, xfs_filblks_t len,
 | 
			
		||||
			  struct xfs_owner_info *oinfo);
 | 
			
		||||
			  struct xfs_owner_info *oinfo, bool skip_discard);
 | 
			
		||||
void	xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
 | 
			
		||||
int	xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
 | 
			
		||||
		xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
 | 
			
		||||
| 
						 | 
				
			
			@ -240,6 +245,28 @@ int	xfs_bmapi_reserve_delalloc(struct xfs_inode *ip, int whichfork,
 | 
			
		|||
		struct xfs_bmbt_irec *got, struct xfs_iext_cursor *cur,
 | 
			
		||||
		int eof);
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xfs_bmap_add_free(
 | 
			
		||||
	struct xfs_mount		*mp,
 | 
			
		||||
	struct xfs_defer_ops		*dfops,
 | 
			
		||||
	xfs_fsblock_t			bno,
 | 
			
		||||
	xfs_filblks_t			len,
 | 
			
		||||
	struct xfs_owner_info		*oinfo)
 | 
			
		||||
{
 | 
			
		||||
	__xfs_bmap_add_free(mp, dfops, bno, len, oinfo, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
xfs_bmap_add_free_nodiscard(
 | 
			
		||||
	struct xfs_mount		*mp,
 | 
			
		||||
	struct xfs_defer_ops		*dfops,
 | 
			
		||||
	xfs_fsblock_t			bno,
 | 
			
		||||
	xfs_filblks_t			len,
 | 
			
		||||
	struct xfs_owner_info		*oinfo)
 | 
			
		||||
{
 | 
			
		||||
	__xfs_bmap_add_free(mp, dfops, bno, len, oinfo, true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
enum xfs_bmap_intent_type {
 | 
			
		||||
	XFS_BMAP_MAP = 1,
 | 
			
		||||
	XFS_BMAP_UNMAP,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -542,7 +542,7 @@ xfs_efi_recover(
 | 
			
		|||
	for (i = 0; i < efip->efi_format.efi_nextents; i++) {
 | 
			
		||||
		extp = &efip->efi_format.efi_extents[i];
 | 
			
		||||
		error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
 | 
			
		||||
					      extp->ext_len, &oinfo);
 | 
			
		||||
					      extp->ext_len, &oinfo, false);
 | 
			
		||||
		if (error)
 | 
			
		||||
			goto abort_error;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -235,7 +235,8 @@ struct xfs_efd_log_item	*xfs_trans_get_efd(struct xfs_trans *,
 | 
			
		|||
				  uint);
 | 
			
		||||
int		xfs_trans_free_extent(struct xfs_trans *,
 | 
			
		||||
				      struct xfs_efd_log_item *, xfs_fsblock_t,
 | 
			
		||||
				      xfs_extlen_t, struct xfs_owner_info *);
 | 
			
		||||
				      xfs_extlen_t, struct xfs_owner_info *,
 | 
			
		||||
				      bool);
 | 
			
		||||
int		xfs_trans_commit(struct xfs_trans *);
 | 
			
		||||
int		xfs_trans_roll(struct xfs_trans **);
 | 
			
		||||
int		xfs_trans_roll_inode(struct xfs_trans **, struct xfs_inode *);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,7 +68,8 @@ xfs_trans_free_extent(
 | 
			
		|||
	struct xfs_efd_log_item	*efdp,
 | 
			
		||||
	xfs_fsblock_t		start_block,
 | 
			
		||||
	xfs_extlen_t		ext_len,
 | 
			
		||||
	struct xfs_owner_info	*oinfo)
 | 
			
		||||
	struct xfs_owner_info	*oinfo,
 | 
			
		||||
	bool			skip_discard)
 | 
			
		||||
{
 | 
			
		||||
	struct xfs_mount	*mp = tp->t_mountp;
 | 
			
		||||
	uint			next_extent;
 | 
			
		||||
| 
						 | 
				
			
			@ -79,8 +80,12 @@ xfs_trans_free_extent(
 | 
			
		|||
 | 
			
		||||
	trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
 | 
			
		||||
 | 
			
		||||
	error = xfs_free_extent(tp, start_block, ext_len, oinfo,
 | 
			
		||||
			XFS_AG_RESV_NONE);
 | 
			
		||||
	if (skip_discard)
 | 
			
		||||
		error = xfs_free_extent_nodiscard(tp, start_block, ext_len,
 | 
			
		||||
						  oinfo, XFS_AG_RESV_NONE);
 | 
			
		||||
	else
 | 
			
		||||
		error = xfs_free_extent(tp, start_block, ext_len, oinfo,
 | 
			
		||||
					XFS_AG_RESV_NONE);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * Mark the transaction dirty, even on error. This ensures the
 | 
			
		||||
| 
						 | 
				
			
			@ -195,7 +200,7 @@ xfs_extent_free_finish_item(
 | 
			
		|||
	error = xfs_trans_free_extent(tp, done_item,
 | 
			
		||||
			free->xefi_startblock,
 | 
			
		||||
			free->xefi_blockcount,
 | 
			
		||||
			&free->xefi_oinfo);
 | 
			
		||||
			&free->xefi_oinfo, free->xefi_skip_discard);
 | 
			
		||||
	kmem_free(free);
 | 
			
		||||
	return error;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue