Commit 97d3ac75 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Alex Elder

xfs: exact busy extent tracking

Update the extent tree in case we have to reuse a busy extent, so that it
always is kept uptodate.  This is done by replacing the busy list searches
with a new xfs_alloc_busy_reuse helper, which updates the busy extent tree
in case of a reuse.  This allows us to allow reusing metadata extents
unconditionally, and thus avoid log forces especially for allocation btree
blocks.
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarAlex Elder <aelder@sgi.com>
parent e26f0501
...@@ -1151,44 +1151,7 @@ TRACE_EVENT(xfs_bunmap, ...@@ -1151,44 +1151,7 @@ TRACE_EVENT(xfs_bunmap,
); );
#define XFS_BUSY_SYNC \ DECLARE_EVENT_CLASS(xfs_busy_class,
{ 0, "async" }, \
{ 1, "sync" }
TRACE_EVENT(xfs_alloc_busy,
TP_PROTO(struct xfs_trans *trans, xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_extlen_t len, int sync),
TP_ARGS(trans, agno, agbno, len, sync),
TP_STRUCT__entry(
__field(dev_t, dev)
__field(struct xfs_trans *, tp)
__field(int, tid)
__field(xfs_agnumber_t, agno)
__field(xfs_agblock_t, agbno)
__field(xfs_extlen_t, len)
__field(int, sync)
),
TP_fast_assign(
__entry->dev = trans->t_mountp->m_super->s_dev;
__entry->tp = trans;
__entry->tid = trans->t_ticket->t_tid;
__entry->agno = agno;
__entry->agbno = agbno;
__entry->len = len;
__entry->sync = sync;
),
TP_printk("dev %d:%d trans 0x%p tid 0x%x agno %u agbno %u len %u %s",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->tp,
__entry->tid,
__entry->agno,
__entry->agbno,
__entry->len,
__print_symbolic(__entry->sync, XFS_BUSY_SYNC))
);
TRACE_EVENT(xfs_alloc_unbusy,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t agbno, xfs_extlen_t len), xfs_agblock_t agbno, xfs_extlen_t len),
TP_ARGS(mp, agno, agbno, len), TP_ARGS(mp, agno, agbno, len),
...@@ -1210,36 +1173,16 @@ TRACE_EVENT(xfs_alloc_unbusy, ...@@ -1210,36 +1173,16 @@ TRACE_EVENT(xfs_alloc_unbusy,
__entry->agbno, __entry->agbno,
__entry->len) __entry->len)
); );
#define DEFINE_BUSY_EVENT(name) \
#define XFS_BUSY_STATES \ DEFINE_EVENT(xfs_busy_class, name, \
{ 0, "missing" }, \ TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, \
{ 1, "found" } xfs_agblock_t agbno, xfs_extlen_t len), \
TP_ARGS(mp, agno, agbno, len))
TRACE_EVENT(xfs_alloc_busysearch, DEFINE_BUSY_EVENT(xfs_alloc_busy);
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, DEFINE_BUSY_EVENT(xfs_alloc_busy_enomem);
xfs_agblock_t agbno, xfs_extlen_t len, int found), DEFINE_BUSY_EVENT(xfs_alloc_busy_force);
TP_ARGS(mp, agno, agbno, len, found), DEFINE_BUSY_EVENT(xfs_alloc_busy_reuse);
TP_STRUCT__entry( DEFINE_BUSY_EVENT(xfs_alloc_busy_clear);
__field(dev_t, dev)
__field(xfs_agnumber_t, agno)
__field(xfs_agblock_t, agbno)
__field(xfs_extlen_t, len)
__field(int, found)
),
TP_fast_assign(
__entry->dev = mp->m_super->s_dev;
__entry->agno = agno;
__entry->agbno = agbno;
__entry->len = len;
__entry->found = found;
),
TP_printk("dev %d:%d agno %u agbno %u len %u %s",
MAJOR(__entry->dev), MINOR(__entry->dev),
__entry->agno,
__entry->agbno,
__entry->len,
__print_symbolic(__entry->found, XFS_BUSY_STATES))
);
TRACE_EVENT(xfs_alloc_busy_trim, TRACE_EVENT(xfs_alloc_busy_trim,
TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno, TP_PROTO(struct xfs_mount *mp, xfs_agnumber_t agno,
......
...@@ -187,7 +187,6 @@ struct xfs_busy_extent { ...@@ -187,7 +187,6 @@ struct xfs_busy_extent {
xfs_agnumber_t agno; xfs_agnumber_t agno;
xfs_agblock_t bno; xfs_agblock_t bno;
xfs_extlen_t length; xfs_extlen_t length;
xlog_tid_t tid; /* transaction that created this */
}; };
/* /*
......
This diff is collapsed.
...@@ -145,6 +145,10 @@ xfs_alloc_busy_clear(struct xfs_mount *mp, struct xfs_busy_extent *busyp); ...@@ -145,6 +145,10 @@ xfs_alloc_busy_clear(struct xfs_mount *mp, struct xfs_busy_extent *busyp);
int int
xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno, xfs_alloc_busy_search(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t bno, xfs_extlen_t len); xfs_agblock_t bno, xfs_extlen_t len);
void
xfs_alloc_busy_reuse(struct xfs_mount *mp, xfs_agnumber_t agno,
xfs_agblock_t fbno, xfs_extlen_t flen, bool userdata);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
/* /*
......
...@@ -94,8 +94,8 @@ xfs_allocbt_alloc_block( ...@@ -94,8 +94,8 @@ xfs_allocbt_alloc_block(
*stat = 0; *stat = 0;
return 0; return 0;
} }
if (xfs_alloc_busy_search(cur->bc_mp, cur->bc_private.a.agno, bno, 1))
xfs_trans_set_sync(cur->bc_tp); xfs_alloc_busy_reuse(cur->bc_mp, cur->bc_private.a.agno, bno, 1, false);
xfs_trans_agbtree_delta(cur->bc_tp, 1); xfs_trans_agbtree_delta(cur->bc_tp, 1);
new->s = cpu_to_be32(bno); new->s = cpu_to_be32(bno);
...@@ -120,17 +120,6 @@ xfs_allocbt_free_block( ...@@ -120,17 +120,6 @@ xfs_allocbt_free_block(
if (error) if (error)
return error; return error;
/*
* Since blocks move to the free list without the coordination used in
* xfs_bmap_finish, we can't allow block to be available for
* reallocation and non-transaction writing (user data) until we know
* that the transaction that moved it to the free list is permanently
* on disk. We track the blocks by declaring these blocks as "busy";
* the busy list is maintained on a per-ag basis and each transaction
* records which entries should be removed when the iclog commits to
* disk. If a busy block is allocated, the iclog is pushed up to the
* LSN that freed the block.
*/
xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1); xfs_alloc_busy_insert(cur->bc_tp, be32_to_cpu(agf->agf_seqno), bno, 1);
xfs_trans_agbtree_delta(cur->bc_tp, -1); xfs_trans_agbtree_delta(cur->bc_tp, -1);
return 0; return 0;
......
...@@ -3248,13 +3248,6 @@ xfs_log_ticket_get( ...@@ -3248,13 +3248,6 @@ xfs_log_ticket_get(
return ticket; return ticket;
} }
xlog_tid_t
xfs_log_get_trans_ident(
struct xfs_trans *tp)
{
return tp->t_ticket->t_tid;
}
/* /*
* Allocate and initialise a new log ticket. * Allocate and initialise a new log ticket.
*/ */
......
...@@ -189,8 +189,6 @@ void xlog_iodone(struct xfs_buf *); ...@@ -189,8 +189,6 @@ void xlog_iodone(struct xfs_buf *);
struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket); struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
void xfs_log_ticket_put(struct xlog_ticket *ticket); void xfs_log_ticket_put(struct xlog_ticket *ticket);
xlog_tid_t xfs_log_get_trans_ident(struct xfs_trans *tp);
void xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp, void xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
struct xfs_log_vec *log_vector, struct xfs_log_vec *log_vector,
xfs_lsn_t *commit_lsn, int flags); xfs_lsn_t *commit_lsn, int flags);
......
...@@ -146,6 +146,8 @@ static inline uint xlog_get_client_id(__be32 i) ...@@ -146,6 +146,8 @@ static inline uint xlog_get_client_id(__be32 i)
shutdown */ shutdown */
#define XLOG_TAIL_WARN 0x10 /* log tail verify warning issued */ #define XLOG_TAIL_WARN 0x10 /* log tail verify warning issued */
typedef __uint32_t xlog_tid_t;
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*
* Below are states for covering allocation transactions. * Below are states for covering allocation transactions.
......
...@@ -73,8 +73,6 @@ typedef __int32_t xfs_tid_t; /* transaction identifier */ ...@@ -73,8 +73,6 @@ typedef __int32_t xfs_tid_t; /* transaction identifier */
typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */ typedef __uint32_t xfs_dablk_t; /* dir/attr block number (in file) */
typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */ typedef __uint32_t xfs_dahash_t; /* dir/attr hash value */
typedef __uint32_t xlog_tid_t; /* transaction ID type */
/* /*
* These types are 64 bits on disk but are either 32 or 64 bits in memory. * These types are 64 bits on disk but are either 32 or 64 bits in memory.
* Disk based types: * Disk based types:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment