Skip to content

Commit

Permalink
xfs: refactor buffer cancellation table allocation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Darrick J. Wong authored and Dave Chinner committed May 27, 2022
1 parent ab6a8d3 commit 2723234
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 32 deletions.
14 changes: 8 additions & 6 deletions fs/xfs/libxfs/xfs_log_recover.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,6 @@ struct xlog_recover {

#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_PASS1 1
#define XLOG_RECOVER_PASS2 2
Expand All @@ -128,5 +122,13 @@ int xlog_recover_iget(struct xfs_mount *mp, xfs_ino_t ino,
struct xfs_inode **ipp);
void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type,
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__ */
47 changes: 47 additions & 0 deletions fs/xfs/xfs_buf_item_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@
#include "xfs_dir2.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
* have been canceled and should not be replayed.
Expand Down Expand Up @@ -993,3 +1002,41 @@ const struct xlog_recover_item_ops xlog_buf_item_ops = {
.commit_pass1 = xlog_recover_buf_commit_pass1,
.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;
}
3 changes: 0 additions & 3 deletions fs/xfs/xfs_log_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -428,9 +428,6 @@ struct xlog {
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
*/
Expand Down
32 changes: 9 additions & 23 deletions fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -3223,45 +3223,31 @@ xlog_do_log_recovery(
xfs_daddr_t head_blk,
xfs_daddr_t tail_blk)
{
int error, i;
int error;

ASSERT(head_blk != tail_blk);

/*
* 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.
*/
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]);
xlog_alloc_buf_cancel_table(log);

error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS1, NULL);
if (error != 0) {
kmem_free(log->l_buf_cancel_table);
log->l_buf_cancel_table = NULL;
return error;
}
if (error != 0)
goto out_cancel;

/*
* Then do a second pass to actually recover the items in the log.
* When it is complete free the table of buf cancel items.
*/
error = xlog_do_recovery_pass(log, head_blk, tail_blk,
XLOG_RECOVER_PASS2, NULL);
#ifdef DEBUG
if (!error) {
int i;

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;

if (!error)
xlog_check_buf_cancel_table(log);
out_cancel:
xlog_free_buf_cancel_table(log);
return error;
}

Expand Down

0 comments on commit 2723234

Please sign in to comment.