fs/btrfs/defrag.c

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

File Facts

System
Linux kernel
Corpus path
fs/btrfs/defrag.c
Extension
.c
Size
41058 bytes
Lines
1500
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 inode_defrag {
	struct rb_node rb_node;
	/* Inode number */
	u64 ino;
	/*
	 * Transid where the defrag was added, we search for extents newer than
	 * this.
	 */
	u64 transid;

	/* Root objectid */
	u64 root;

	/*
	 * The extent size threshold for autodefrag.
	 *
	 * This value is different for compressed/non-compressed extents, thus
	 * needs to be passed from higher layer.
	 * (aka, inode_should_defrag())
	 */
	u32 extent_thresh;
};

static int compare_inode_defrag(const struct inode_defrag *defrag1,
				const struct inode_defrag *defrag2)
{
	if (defrag1->root > defrag2->root)
		return 1;
	else if (defrag1->root < defrag2->root)
		return -1;
	else if (defrag1->ino > defrag2->ino)
		return 1;
	else if (defrag1->ino < defrag2->ino)
		return -1;
	else
		return 0;
}

static int inode_defrag_cmp(struct rb_node *new, const struct rb_node *existing)
{
	const struct inode_defrag *new_defrag = rb_entry(new, struct inode_defrag, rb_node);
	const struct inode_defrag *existing_defrag = rb_entry(existing, struct inode_defrag, rb_node);

	return compare_inode_defrag(new_defrag, existing_defrag);
}

/*
 * Insert a record for an inode into the defrag tree.  The lock must be held
 * already.
 *
 * If you're inserting a record for an older transid than an existing record,
 * the transid already in the tree is lowered.
 */
static int btrfs_insert_inode_defrag(struct btrfs_inode *inode,
				     struct inode_defrag *defrag)
{
	struct btrfs_fs_info *fs_info = inode->root->fs_info;
	struct rb_node *node;

	node = rb_find_add(&defrag->rb_node, &fs_info->defrag_inodes, inode_defrag_cmp);
	if (node) {
		struct inode_defrag *entry;

		entry = rb_entry(node, struct inode_defrag, rb_node);
		/*
		 * If we're reinserting an entry for an old defrag run, make
		 * sure to lower the transid of our existing record.
		 */
		if (defrag->transid < entry->transid)
			entry->transid = defrag->transid;
		entry->extent_thresh = min(defrag->extent_thresh, entry->extent_thresh);
		return -EEXIST;
	}
	set_bit(BTRFS_INODE_IN_DEFRAG, &inode->runtime_flags);
	return 0;
}

static inline bool need_auto_defrag(struct btrfs_fs_info *fs_info)
{
	if (!btrfs_test_opt(fs_info, AUTO_DEFRAG))
		return false;

	if (btrfs_fs_closing(fs_info))
		return false;

	return true;
}

/*
 * Insert a defrag record for this inode if auto defrag is enabled. No errors

Annotation

Implementation Notes