fs/btrfs/tree-log.c

Source file repositories/reference/linux-study-clean/fs/btrfs/tree-log.c

File Facts

System
Linux kernel
Corpus path
fs/btrfs/tree-log.c
Extension
.c
Size
243852 bytes
Lines
8223
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

struct walk_control {
	/*
	 * Signal that we are freeing the metadata extents of a log tree.
	 * This is used at transaction commit time while freeing a log tree.
	 */
	bool free;

	/*
	 * Signal that we are pinning the metadata extents of a log tree and the
	 * data extents its leaves point to (if using mixed block groups).
	 * This happens in the first stage of log replay to ensure that during
	 * replay, while we are modifying subvolume trees, we don't overwrite
	 * the metadata extents of log trees.
	 */
	bool pin;

	/* What stage of the replay code we're currently in. */
	int stage;

	/*
	 * Ignore any items from the inode currently being processed. Needs
	 * to be set every time we find a BTRFS_INODE_ITEM_KEY.
	 */
	bool ignore_cur_inode;

	/*
	 * The root we are currently replaying to. This is NULL for the replay
	 * stage LOG_WALK_PIN_ONLY.
	 */
	struct btrfs_root *root;

	/* The log tree we are currently processing (not NULL for any stage). */
	struct btrfs_root *log;

	/* The transaction handle used for replaying all log trees. */
	struct btrfs_trans_handle *trans;

	/*
	 * The function that gets used to process blocks we find in the tree.
	 * Note the extent_buffer might not be up to date when it is passed in,
	 * and it must be checked or read if you need the data inside it.
	 */
	int (*process_func)(struct extent_buffer *eb,
			    struct walk_control *wc, u64 gen, int level);

	/*
	 * The following are used only when stage is >= LOG_WALK_REPLAY_INODES
	 * and by the replay_one_buffer() callback.
	 */

	/* The current log leaf being processed. */
	struct extent_buffer *log_leaf;
	/* The key being processed of the current log leaf. */
	struct btrfs_key log_key;
	/* The slot being processed of the current log leaf. */
	int log_slot;

	/* A path used for searches and modifications to subvolume trees. */
	struct btrfs_path *subvol_path;
};

static void do_abort_log_replay(struct walk_control *wc, const char *function,
				unsigned int line, int error, const char *fmt, ...)
{
	struct btrfs_fs_info *fs_info = wc->trans->fs_info;
	struct va_format vaf;
	va_list args;

	/*
	 * Do nothing if we already aborted, to avoid dumping leaves again which
	 * can be verbose. Further more, only the first call is useful since it
	 * is where we have a problem. Note that we do not use the flag
	 * BTRFS_FS_STATE_TRANS_ABORTED because log replay calls functions that
	 * are outside of tree-log.c that can abort transactions (such as
	 * btrfs_add_link() for example), so if that happens we still want to
	 * dump all log replay specific information below.
	 */
	if (test_and_set_bit(BTRFS_FS_STATE_LOG_REPLAY_ABORTED, &fs_info->fs_state))
		return;

	btrfs_abort_transaction(wc->trans, error);

	if (wc->subvol_path && wc->subvol_path->nodes[0]) {
		btrfs_crit(fs_info,
			   "subvolume (root %llu) leaf currently being processed:",
			   btrfs_root_id(wc->root));
		btrfs_print_leaf(wc->subvol_path->nodes[0]);
	}

	if (wc->log_leaf) {

Annotation

Implementation Notes