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
|
@ -3009,18 +3009,20 @@ out:
|
||||||
* after fixing up the freelist.
|
* after fixing up the freelist.
|
||||||
*/
|
*/
|
||||||
int /* error */
|
int /* error */
|
||||||
xfs_free_extent(
|
__xfs_free_extent(
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
struct xfs_trans *tp, /* transaction pointer */
|
||||||
xfs_fsblock_t bno, /* starting block number of extent */
|
xfs_fsblock_t bno, /* starting block number of extent */
|
||||||
xfs_extlen_t len, /* length of extent */
|
xfs_extlen_t len, /* length of extent */
|
||||||
struct xfs_owner_info *oinfo, /* extent owner */
|
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_mount *mp = tp->t_mountp;
|
||||||
struct xfs_buf *agbp;
|
struct xfs_buf *agbp;
|
||||||
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
xfs_agnumber_t agno = XFS_FSB_TO_AGNO(mp, bno);
|
||||||
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno);
|
||||||
int error;
|
int error;
|
||||||
|
unsigned int busy_flags = 0;
|
||||||
|
|
||||||
ASSERT(len != 0);
|
ASSERT(len != 0);
|
||||||
ASSERT(type != XFS_AG_RESV_AGFL);
|
ASSERT(type != XFS_AG_RESV_AGFL);
|
||||||
|
@ -3044,7 +3046,9 @@ xfs_free_extent(
|
||||||
if (error)
|
if (error)
|
||||||
goto err;
|
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;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
|
|
@ -191,12 +191,35 @@ xfs_alloc_vextent(
|
||||||
* Free an extent.
|
* Free an extent.
|
||||||
*/
|
*/
|
||||||
int /* error */
|
int /* error */
|
||||||
xfs_free_extent(
|
__xfs_free_extent(
|
||||||
struct xfs_trans *tp, /* transaction pointer */
|
struct xfs_trans *tp, /* transaction pointer */
|
||||||
xfs_fsblock_t bno, /* starting block number of extent */
|
xfs_fsblock_t bno, /* starting block number of extent */
|
||||||
xfs_extlen_t len, /* length of extent */
|
xfs_extlen_t len, /* length of extent */
|
||||||
struct xfs_owner_info *oinfo, /* extent owner */
|
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 */
|
int /* error */
|
||||||
xfs_alloc_lookup_le(
|
xfs_alloc_lookup_le(
|
||||||
|
|
|
@ -544,12 +544,13 @@ xfs_bmap_validate_ret(
|
||||||
* The list is maintained sorted (by block number).
|
* The list is maintained sorted (by block number).
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
xfs_bmap_add_free(
|
__xfs_bmap_add_free(
|
||||||
struct xfs_mount *mp,
|
struct xfs_mount *mp,
|
||||||
struct xfs_defer_ops *dfops,
|
struct xfs_defer_ops *dfops,
|
||||||
xfs_fsblock_t bno,
|
xfs_fsblock_t bno,
|
||||||
xfs_filblks_t len,
|
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 */
|
struct xfs_extent_free_item *new; /* new element */
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -576,6 +577,7 @@ xfs_bmap_add_free(
|
||||||
new->xefi_oinfo = *oinfo;
|
new->xefi_oinfo = *oinfo;
|
||||||
else
|
else
|
||||||
xfs_rmap_skip_owner_update(&new->xefi_oinfo);
|
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,
|
trace_xfs_bmap_free_defer(mp, XFS_FSB_TO_AGNO(mp, bno), 0,
|
||||||
XFS_FSB_TO_AGBNO(mp, bno), len);
|
XFS_FSB_TO_AGBNO(mp, bno), len);
|
||||||
xfs_defer_add(dfops, XFS_DEFER_OPS_TYPE_FREE, &new->xefi_list);
|
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);
|
error = xfs_refcount_decrease_extent(mp, dfops, del);
|
||||||
if (error)
|
if (error)
|
||||||
goto done;
|
goto done;
|
||||||
} else
|
} else {
|
||||||
xfs_bmap_add_free(mp, dfops, del->br_startblock,
|
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);
|
del->br_blockcount, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -68,6 +68,7 @@ struct xfs_extent_free_item
|
||||||
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
|
xfs_extlen_t xefi_blockcount;/* number of blocks in extent */
|
||||||
struct list_head xefi_list;
|
struct list_head xefi_list;
|
||||||
struct xfs_owner_info xefi_oinfo; /* extent owner */
|
struct xfs_owner_info xefi_oinfo; /* extent owner */
|
||||||
|
bool xefi_skip_discard;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define XFS_BMAP_MAX_NMAP 4
|
#define XFS_BMAP_MAX_NMAP 4
|
||||||
|
@ -116,6 +117,9 @@ struct xfs_extent_free_item
|
||||||
/* Only convert unwritten extents, don't allocate new blocks */
|
/* Only convert unwritten extents, don't allocate new blocks */
|
||||||
#define XFS_BMAPI_CONVERT_ONLY 0x800
|
#define XFS_BMAPI_CONVERT_ONLY 0x800
|
||||||
|
|
||||||
|
/* Skip online discard of freed extents */
|
||||||
|
#define XFS_BMAPI_NODISCARD 0x1000
|
||||||
|
|
||||||
#define XFS_BMAPI_FLAGS \
|
#define XFS_BMAPI_FLAGS \
|
||||||
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
||||||
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
||||||
|
@ -128,7 +132,8 @@ struct xfs_extent_free_item
|
||||||
{ XFS_BMAPI_REMAP, "REMAP" }, \
|
{ XFS_BMAPI_REMAP, "REMAP" }, \
|
||||||
{ XFS_BMAPI_COWFORK, "COWFORK" }, \
|
{ XFS_BMAPI_COWFORK, "COWFORK" }, \
|
||||||
{ XFS_BMAPI_DELALLOC, "DELALLOC" }, \
|
{ 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)
|
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 *);
|
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);
|
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_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,
|
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);
|
void xfs_bmap_compute_maxlevels(struct xfs_mount *mp, int whichfork);
|
||||||
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
|
int xfs_bmap_first_unused(struct xfs_trans *tp, struct xfs_inode *ip,
|
||||||
xfs_extlen_t len, xfs_fileoff_t *unused, int whichfork);
|
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,
|
struct xfs_bmbt_irec *got, struct xfs_iext_cursor *cur,
|
||||||
int eof);
|
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 {
|
enum xfs_bmap_intent_type {
|
||||||
XFS_BMAP_MAP = 1,
|
XFS_BMAP_MAP = 1,
|
||||||
XFS_BMAP_UNMAP,
|
XFS_BMAP_UNMAP,
|
||||||
|
|
|
@ -542,7 +542,7 @@ xfs_efi_recover(
|
||||||
for (i = 0; i < efip->efi_format.efi_nextents; i++) {
|
for (i = 0; i < efip->efi_format.efi_nextents; i++) {
|
||||||
extp = &efip->efi_format.efi_extents[i];
|
extp = &efip->efi_format.efi_extents[i];
|
||||||
error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
|
error = xfs_trans_free_extent(tp, efdp, extp->ext_start,
|
||||||
extp->ext_len, &oinfo);
|
extp->ext_len, &oinfo, false);
|
||||||
if (error)
|
if (error)
|
||||||
goto abort_error;
|
goto abort_error;
|
||||||
|
|
||||||
|
|
|
@ -235,7 +235,8 @@ struct xfs_efd_log_item *xfs_trans_get_efd(struct xfs_trans *,
|
||||||
uint);
|
uint);
|
||||||
int xfs_trans_free_extent(struct xfs_trans *,
|
int xfs_trans_free_extent(struct xfs_trans *,
|
||||||
struct xfs_efd_log_item *, xfs_fsblock_t,
|
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_commit(struct xfs_trans *);
|
||||||
int xfs_trans_roll(struct xfs_trans **);
|
int xfs_trans_roll(struct xfs_trans **);
|
||||||
int xfs_trans_roll_inode(struct xfs_trans **, struct xfs_inode *);
|
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,
|
struct xfs_efd_log_item *efdp,
|
||||||
xfs_fsblock_t start_block,
|
xfs_fsblock_t start_block,
|
||||||
xfs_extlen_t ext_len,
|
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;
|
struct xfs_mount *mp = tp->t_mountp;
|
||||||
uint next_extent;
|
uint next_extent;
|
||||||
|
@ -79,8 +80,12 @@ xfs_trans_free_extent(
|
||||||
|
|
||||||
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
|
trace_xfs_bmap_free_deferred(tp->t_mountp, agno, 0, agbno, ext_len);
|
||||||
|
|
||||||
error = xfs_free_extent(tp, start_block, ext_len, oinfo,
|
if (skip_discard)
|
||||||
XFS_AG_RESV_NONE);
|
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
|
* 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,
|
error = xfs_trans_free_extent(tp, done_item,
|
||||||
free->xefi_startblock,
|
free->xefi_startblock,
|
||||||
free->xefi_blockcount,
|
free->xefi_blockcount,
|
||||||
&free->xefi_oinfo);
|
&free->xefi_oinfo, free->xefi_skip_discard);
|
||||||
kmem_free(free);
|
kmem_free(free);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue