fs/btrfs/ref-verify.c

Source file repositories/reference/linux-study-clean/fs/btrfs/ref-verify.c

File Facts

System
Linux kernel
Corpus path
fs/btrfs/ref-verify.c
Extension
.c
Size
26215 bytes
Lines
1026
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 root_entry {
	u64 root_objectid;
	u64 num_refs;
	struct rb_node node;
};

/*
 * These are meant to represent what should exist in the extent tree, these can
 * be used to verify the extent tree is consistent as these should all match
 * what the extent tree says.
 */
struct ref_entry {
	u64 root_objectid;
	u64 parent;
	u64 owner;
	u64 offset;
	u64 num_refs;
	struct rb_node node;
};

#define MAX_TRACE	16

/*
 * Whenever we add/remove a reference we record the action.  The action maps
 * back to the delayed ref action.  We hold the ref we are changing in the
 * action so we can account for the history properly, and we record the root we
 * were called with since it could be different from ref_root.  We also store
 * stack traces because that's how I roll.
 */
struct ref_action {
	int action;
	u64 root;
	struct ref_entry ref;
	struct list_head list;
	unsigned long trace[MAX_TRACE];
	unsigned int trace_len;
};

/*
 * One of these for every block we reference, it holds the roots and references
 * to it as well as all of the ref actions that have occurred to it.  We never
 * free it until we unmount the file system in order to make sure re-allocations
 * are happening properly.
 */
struct block_entry {
	u64 bytenr;
	u64 len;
	u64 num_refs;
	int metadata;
	int from_disk;
	struct rb_root roots;
	struct rb_root refs;
	struct rb_node node;
	struct list_head actions;
};

static int block_entry_bytenr_key_cmp(const void *key, const struct rb_node *node)
{
	const u64 *bytenr = key;
	const struct block_entry *entry = rb_entry(node, struct block_entry, node);

	if (entry->bytenr < *bytenr)
		return 1;
	else if (entry->bytenr > *bytenr)
		return -1;

	return 0;
}

static int block_entry_bytenr_cmp(struct rb_node *new, const struct rb_node *existing)
{
	const struct block_entry *new_entry = rb_entry(new, struct block_entry, node);

	return block_entry_bytenr_key_cmp(&new_entry->bytenr, existing);
}

static struct block_entry *insert_block_entry(struct rb_root *root,
					      struct block_entry *be)
{
	struct rb_node *node;

	node = rb_find_add(&be->node, root, block_entry_bytenr_cmp);
	return rb_entry_safe(node, struct block_entry, node);
}

static struct block_entry *lookup_block_entry(struct rb_root *root, u64 bytenr)
{
	struct rb_node *node;

	node = rb_find(&bytenr, root, block_entry_bytenr_key_cmp);

Annotation

Implementation Notes