xfs: refactor buffer cancellation table allocation

Move the code that allocates and frees the buffer cancellation tables
used by log recovery into the file that actually uses the tables.  This
is a precursor to some cleanups and a memory leak fix.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Darrick J. Wong 2022-05-27 10:26:17 +10:00 committed by Dave Chinner
parent ab6a8d3f1a
commit 2723234923
4 changed files with 64 additions and 32 deletions

View File

@ -110,12 +110,6 @@ struct xlog_recover {
#define ITEM_TYPE(i) (*(unsigned short *)(i)->ri_buf[0].i_addr) #define ITEM_TYPE(i) (*(unsigned short *)(i)->ri_buf[0].i_addr)
/*
* This is the number of entries in the l_buf_cancel_table used during
* recovery.
*/
#define XLOG_BC_TABLE_SIZE 64
#define XLOG_RECOVER_CRCPASS 0 #define XLOG_RECOVER_CRCPASS 0
#define XLOG_RECOVER_PASS1 1 #define XLOG_RECOVER_PASS1 1
#define XLOG_RECOVER_PASS2 2 #define XLOG_RECOVER_PASS2 2
@ -128,5 +122,13 @@ int xlog_recover_iget(struct xfs_mount *mp, xfs_ino_t ino,
struct xfs_inode **ipp); struct xfs_inode **ipp);
void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type, void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type,
uint64_t intent_id); uint64_t intent_id);
void xlog_alloc_buf_cancel_table(struct xlog *log);
void xlog_free_buf_cancel_table(struct xlog *log);
#ifdef DEBUG
void xlog_check_buf_cancel_table(struct xlog *log);
#else
#define xlog_check_buf_cancel_table(log) do { } while (0)
#endif
#endif /* __XFS_LOG_RECOVER_H__ */ #endif /* __XFS_LOG_RECOVER_H__ */

View File

@ -23,6 +23,15 @@
#include "xfs_dir2.h" #include "xfs_dir2.h"
#include "xfs_quota.h" #include "xfs_quota.h"
/*
* This is the number of entries in the l_buf_cancel_table used during
* recovery.
*/
#define XLOG_BC_TABLE_SIZE 64
#define XLOG_BUF_CANCEL_BUCKET(log, blkno) \
((log)->l_buf_cancel_table + ((uint64_t)blkno % XLOG_BC_TABLE_SIZE))
/* /*
* This structure is used during recovery to record the buf log items which * This structure is used during recovery to record the buf log items which
* have been canceled and should not be replayed. * have been canceled and should not be replayed.
@ -993,3 +1002,41 @@ const struct xlog_recover_item_ops xlog_buf_item_ops = {
.commit_pass1 = xlog_recover_buf_commit_pass1, .commit_pass1 = xlog_recover_buf_commit_pass1,
.commit_pass2 = xlog_recover_buf_commit_pass2, .commit_pass2 = xlog_recover_buf_commit_pass2,
}; };
#ifdef DEBUG
void
xlog_check_buf_cancel_table(
struct xlog *log)
{
int i;
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
ASSERT(list_empty(&log->l_buf_cancel_table[i]));
}
#endif
void
xlog_alloc_buf_cancel_table(
struct xlog *log)
{
int i;
ASSERT(log->l_buf_cancel_table == NULL);
log->l_buf_cancel_table = kmem_zalloc(XLOG_BC_TABLE_SIZE *
sizeof(struct list_head),
0);
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
INIT_LIST_HEAD(&log->l_buf_cancel_table[i]);
}
void
xlog_free_buf_cancel_table(
struct xlog *log)
{
if (!log->l_buf_cancel_table)
return;
kmem_free(log->l_buf_cancel_table);
log->l_buf_cancel_table = NULL;
}

View File

@ -428,9 +428,6 @@ struct xlog {
struct rw_semaphore l_incompat_users; struct rw_semaphore l_incompat_users;
}; };
#define XLOG_BUF_CANCEL_BUCKET(log, blkno) \
((log)->l_buf_cancel_table + ((uint64_t)blkno % XLOG_BC_TABLE_SIZE))
/* /*
* Bits for operational state * Bits for operational state
*/ */

View File

@ -3223,7 +3223,7 @@ xlog_do_log_recovery(
xfs_daddr_t head_blk, xfs_daddr_t head_blk,
xfs_daddr_t tail_blk) xfs_daddr_t tail_blk)
{ {
int error, i; int error;
ASSERT(head_blk != tail_blk); ASSERT(head_blk != tail_blk);
@ -3231,37 +3231,23 @@ xlog_do_log_recovery(
* First do a pass to find all of the cancelled buf log items. * First do a pass to find all of the cancelled buf log items.
* Store them in the buf_cancel_table for use in the second pass. * Store them in the buf_cancel_table for use in the second pass.
*/ */
log->l_buf_cancel_table = kmem_zalloc(XLOG_BC_TABLE_SIZE * xlog_alloc_buf_cancel_table(log);
sizeof(struct list_head),
0);
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
INIT_LIST_HEAD(&log->l_buf_cancel_table[i]);
error = xlog_do_recovery_pass(log, head_blk, tail_blk, error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS1, NULL); XLOG_RECOVER_PASS1, NULL);
if (error != 0) { if (error != 0)
kmem_free(log->l_buf_cancel_table); goto out_cancel;
log->l_buf_cancel_table = NULL;
return error;
}
/* /*
* Then do a second pass to actually recover the items in the log. * Then do a second pass to actually recover the items in the log.
* When it is complete free the table of buf cancel items. * When it is complete free the table of buf cancel items.
*/ */
error = xlog_do_recovery_pass(log, head_blk, tail_blk, error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS2, NULL); XLOG_RECOVER_PASS2, NULL);
#ifdef DEBUG if (!error)
if (!error) { xlog_check_buf_cancel_table(log);
int i; out_cancel:
xlog_free_buf_cancel_table(log);
for (i = 0; i < XLOG_BC_TABLE_SIZE; i++)
ASSERT(list_empty(&log->l_buf_cancel_table[i]));
}
#endif /* DEBUG */
kmem_free(log->l_buf_cancel_table);
log->l_buf_cancel_table = NULL;
return error; return error;
} }