fs/btrfs/extent-tree.c

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

File Facts

System
Linux kernel
Corpus path
fs/btrfs/extent-tree.c
Extension
.c
Size
197695 bytes
Lines
6937
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 {
	u64 refs[BTRFS_MAX_LEVEL];
	u64 flags[BTRFS_MAX_LEVEL];
	struct btrfs_key update_progress;
	struct btrfs_key drop_progress;
	int drop_level;
	int stage;
	int level;
	int shared_level;
	int update_ref;
	int keep_locks;
	int reada_slot;
	int reada_count;
	int restarted;
	/* Indicate that extent info needs to be looked up when walking the tree. */
	int lookup_info;
};

/*
 * This is our normal stage.  We are traversing blocks the current snapshot owns
 * and we are dropping any of our references to any children we are able to, and
 * then freeing the block once we've processed all of the children.
 */
#define DROP_REFERENCE	1

/*
 * We enter this stage when we have to walk into a child block (meaning we can't
 * simply drop our reference to it from our current parent node) and there are
 * more than one reference on it.  If we are the owner of any of the children
 * blocks from the current parent node then we have to do the FULL_BACKREF dance
 * on them in order to drop our normal ref and add the shared ref.
 */
#define UPDATE_BACKREF	2

/*
 * Decide if we need to walk down into this node to adjust the references.
 *
 * @root:	the root we are currently deleting
 * @wc:		the walk control for this deletion
 * @eb:		the parent eb that we're currently visiting
 * @flags:	the flags for wc->level - 1
 * @slot:	the slot in the eb that we're currently checking
 *
 * This is meant to be called when we're evaluating if a node we point to at
 * wc->level should be read and walked into, or if we can simply delete our
 * reference to it.  We return true if we should walk into the node, false if we
 * can skip it.
 *
 * We have assertions in here to make sure this is called correctly.  We assume
 * that sanity checking on the blocks read to this point has been done, so any
 * corrupted file systems must have been caught before calling this function.
 */
static bool visit_node_for_delete(struct btrfs_root *root, struct walk_control *wc,
				  struct extent_buffer *eb, u64 flags, int slot)
{
	struct btrfs_key key;
	u64 generation;
	int level = wc->level;

	ASSERT(level > 0);
	ASSERT(wc->refs[level - 1] > 0);

	/*
	 * The update backref stage we only want to skip if we already have
	 * FULL_BACKREF set, otherwise we need to read.
	 */
	if (wc->stage == UPDATE_BACKREF) {
		if (level == 1 && flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)
			return false;
		return true;
	}

	/*
	 * We're the last ref on this block, we must walk into it and process
	 * any refs it's pointing at.
	 */
	if (wc->refs[level - 1] == 1)
		return true;

	/*
	 * If we're already FULL_BACKREF then we know we can just drop our
	 * current reference.
	 */
	if (level == 1 && flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)
		return false;

	/*
	 * This block is older than our creation generation, we can drop our
	 * reference to it.
	 */

Annotation

Implementation Notes