linux/fs/xfs/xfs_buf_item_recover.c

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (c) 2000-2006 Silicon Graphics, Inc.
 * All Rights Reserved.
 */
#include "xfs.h"
#include "xfs_fs.h"
#include "xfs_shared.h"
#include "xfs_format.h"
#include "xfs_log_format.h"
#include "xfs_trans_resv.h"
#include "xfs_bit.h"
#include "xfs_mount.h"
#include "xfs_trans.h"
#include "xfs_buf_item.h"
#include "xfs_trans_priv.h"
#include "xfs_trace.h"
#include "xfs_log.h"
#include "xfs_log_priv.h"
#include "xfs_log_recover.h"
#include "xfs_error.h"
#include "xfs_inode.h"
#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

#define XLOG_BUF_CANCEL_BUCKET(log, blkno)

/*
 * This structure is used during recovery to record the buf log items which
 * have been canceled and should not be replayed.
 */
struct xfs_buf_cancel {};

static struct xfs_buf_cancel *
xlog_find_buffer_cancelled(
	struct xlog		*log,
	xfs_daddr_t		blkno,
	uint			len)
{}

static bool
xlog_add_buffer_cancelled(
	struct xlog		*log,
	xfs_daddr_t		blkno,
	uint			len)
{}

/*
 * Check if there is and entry for blkno, len in the buffer cancel record table.
 */
bool
xlog_is_buffer_cancelled(
	struct xlog		*log,
	xfs_daddr_t		blkno,
	uint			len)
{}

/*
 * Check if there is and entry for blkno, len in the buffer cancel record table,
 * and decremented the reference count on it if there is one.
 *
 * Remove the cancel record once the refcount hits zero, so that if the same
 * buffer is re-used again after its last cancellation we actually replay the
 * changes made at that point.
 */
static bool
xlog_put_buffer_cancelled(
	struct xlog		*log,
	xfs_daddr_t		blkno,
	uint			len)
{}

/* log buffer item recovery */

/*
 * Sort buffer items for log recovery.  Most buffer items should end up on the
 * buffer list and are recovered first, with the following exceptions:
 *
 * 1. XFS_BLF_CANCEL buffers must be processed last because some log items
 *    might depend on the incor ecancellation record, and replaying a cancelled
 *    buffer item can remove the incore record.
 *
 * 2. XFS_BLF_INODE_BUF buffers are handled after most regular items so that
 *    we replay di_next_unlinked only after flushing the inode 'free' state
 *    to the inode buffer.
 *
 * See xlog_recover_reorder_trans for more details.
 */
STATIC enum xlog_recover_reorder
xlog_recover_buf_reorder(
	struct xlog_recover_item	*item)
{}

STATIC void
xlog_recover_buf_ra_pass2(
	struct xlog                     *log,
	struct xlog_recover_item        *item)
{}

/*
 * Build up the table of buf cancel records so that we don't replay cancelled
 * data in the second pass.
 */
static int
xlog_recover_buf_commit_pass1(
	struct xlog			*log,
	struct xlog_recover_item	*item)
{}

/*
 * Validate the recovered buffer is of the correct type and attach the
 * appropriate buffer operations to them for writeback. Magic numbers are in a
 * few places:
 *	the first 16 bits of the buffer (inode buffer, dquot buffer),
 *	the first 32 bits of the buffer (most blocks),
 *	inside a struct xfs_da_blkinfo at the start of the buffer.
 */
static void
xlog_recover_validate_buf_type(
	struct xfs_mount		*mp,
	struct xfs_buf			*bp,
	struct xfs_buf_log_format	*buf_f,
	xfs_lsn_t			current_lsn)
{}

/*
 * Perform a 'normal' buffer recovery.  Each logged region of the
 * buffer should be copied over the corresponding region in the
 * given buffer.  The bitmap in the buf log format structure indicates
 * where to place the logged data.
 */
STATIC void
xlog_recover_do_reg_buffer(
	struct xfs_mount		*mp,
	struct xlog_recover_item	*item,
	struct xfs_buf			*bp,
	struct xfs_buf_log_format	*buf_f,
	xfs_lsn_t			current_lsn)
{}

/*
 * Perform a dquot buffer recovery.
 * Simple algorithm: if we have found a QUOTAOFF log item of the same type
 * (ie. USR or GRP), then just toss this buffer away; don't recover it.
 * Else, treat it as a regular buffer and do recovery.
 *
 * Return false if the buffer was tossed and true if we recovered the buffer to
 * indicate to the caller if the buffer needs writing.
 */
STATIC bool
xlog_recover_do_dquot_buffer(
	struct xfs_mount		*mp,
	struct xlog			*log,
	struct xlog_recover_item	*item,
	struct xfs_buf			*bp,
	struct xfs_buf_log_format	*buf_f)
{}

/*
 * Perform recovery for a buffer full of inodes.  In these buffers, the only
 * data which should be recovered is that which corresponds to the
 * di_next_unlinked pointers in the on disk inode structures.  The rest of the
 * data for the inodes is always logged through the inodes themselves rather
 * than the inode buffer and is recovered in xlog_recover_inode_pass2().
 *
 * The only time when buffers full of inodes are fully recovered is when the
 * buffer is full of newly allocated inodes.  In this case the buffer will
 * not be marked as an inode buffer and so will be sent to
 * xlog_recover_do_reg_buffer() below during recovery.
 */
STATIC int
xlog_recover_do_inode_buffer(
	struct xfs_mount		*mp,
	struct xlog_recover_item	*item,
	struct xfs_buf			*bp,
	struct xfs_buf_log_format	*buf_f)
{}

/*
 * V5 filesystems know the age of the buffer on disk being recovered. We can
 * have newer objects on disk than we are replaying, and so for these cases we
 * don't want to replay the current change as that will make the buffer contents
 * temporarily invalid on disk.
 *
 * The magic number might not match the buffer type we are going to recover
 * (e.g. reallocated blocks), so we ignore the xfs_buf_log_format flags.  Hence
 * extract the LSN of the existing object in the buffer based on it's current
 * magic number.  If we don't recognise the magic number in the buffer, then
 * return a LSN of -1 so that the caller knows it was an unrecognised block and
 * so can recover the buffer.
 *
 * Note: we cannot rely solely on magic number matches to determine that the
 * buffer has a valid LSN - we also need to verify that it belongs to this
 * filesystem, so we need to extract the object's LSN and compare it to that
 * which we read from the superblock. If the UUIDs don't match, then we've got a
 * stale metadata block from an old filesystem instance that we need to recover
 * over the top of.
 */
static xfs_lsn_t
xlog_recover_get_buf_lsn(
	struct xfs_mount	*mp,
	struct xfs_buf		*bp,
	struct xfs_buf_log_format *buf_f)
{}

/*
 * This routine replays a modification made to a buffer at runtime.
 * There are actually two types of buffer, regular and inode, which
 * are handled differently.  Inode buffers are handled differently
 * in that we only recover a specific set of data from them, namely
 * the inode di_next_unlinked fields.  This is because all other inode
 * data is actually logged via inode records and any data we replay
 * here which overlaps that may be stale.
 *
 * When meta-data buffers are freed at run time we log a buffer item
 * with the XFS_BLF_CANCEL bit set to indicate that previous copies
 * of the buffer in the log should not be replayed at recovery time.
 * This is so that if the blocks covered by the buffer are reused for
 * file data before we crash we don't end up replaying old, freed
 * meta-data into a user's file.
 *
 * To handle the cancellation of buffer log items, we make two passes
 * over the log during recovery.  During the first we build a table of
 * those buffers which have been cancelled, and during the second we
 * only replay those buffers which do not have corresponding cancel
 * records in the table.  See xlog_recover_buf_pass[1,2] above
 * for more details on the implementation of the table of cancel records.
 */
STATIC int
xlog_recover_buf_commit_pass2(
	struct xlog			*log,
	struct list_head		*buffer_list,
	struct xlog_recover_item	*item,
	xfs_lsn_t			current_lsn)
{}

const struct xlog_recover_item_ops xlog_buf_item_ops =;

#ifdef DEBUG
void
xlog_check_buf_cancel_table(
	struct xlog	*log)
{}
#endif

int
xlog_alloc_buf_cancel_table(
	struct xlog	*log)
{}

void
xlog_free_buf_cancel_table(
	struct xlog	*log)
{}