fs/btrfs/qgroup.c

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

File Facts

System
Linux kernel
Corpus path
fs/btrfs/qgroup.c
Extension
.c
Size
139049 bytes
Lines
4990
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

if (list->group == parent) {
			list_del(&list->next_group);
			list_del(&list->next_member);
			kfree(list);
			return 0;
		}
	}
	return -ENOENT;
}

#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
int btrfs_verify_qgroup_counts(const struct btrfs_fs_info *fs_info, u64 qgroupid,
			       u64 rfer, u64 excl)
{
	struct btrfs_qgroup *qgroup;

	qgroup = find_qgroup_rb(fs_info, qgroupid);
	if (!qgroup)
		return -EINVAL;
	if (qgroup->rfer != rfer || qgroup->excl != excl)
		return -EINVAL;
	return 0;
}
#endif

static bool squota_check_parent_usage(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *parent)
{
	u64 excl_sum = 0;
	u64 rfer_sum = 0;
	u64 excl_cmpr_sum = 0;
	u64 rfer_cmpr_sum = 0;
	struct btrfs_qgroup_list *glist;
	int nr_members = 0;
	bool mismatch;

	if (btrfs_qgroup_mode(fs_info) != BTRFS_QGROUP_MODE_SIMPLE)
		return false;
	if (btrfs_qgroup_level(parent->qgroupid) == 0)
		return false;

	/* Eligible parent qgroup. Squota; level > 0; empty members list. */
	list_for_each_entry(glist, &parent->members, next_member) {
		excl_sum += glist->member->excl;
		rfer_sum += glist->member->rfer;
		excl_cmpr_sum += glist->member->excl_cmpr;
		rfer_cmpr_sum += glist->member->rfer_cmpr;
		nr_members++;
	}
	mismatch = (parent->excl != excl_sum || parent->rfer != rfer_sum ||
		    parent->excl_cmpr != excl_cmpr_sum || parent->rfer_cmpr != rfer_cmpr_sum);

	WARN(mismatch,
	     "parent squota qgroup " BTRFS_QGROUP_FMT " has mismatched usage from its %d members. "
	     "%llu %llu %llu %llu vs %llu %llu %llu %llu\n",
	     BTRFS_QGROUP_FMT_VALUE(parent), nr_members, parent->excl,
	     parent->rfer, parent->excl_cmpr, parent->rfer_cmpr, excl_sum,
	     rfer_sum, excl_cmpr_sum, rfer_cmpr_sum);
	return mismatch;
}

__printf(2, 3)
static void qgroup_mark_inconsistent(struct btrfs_fs_info *fs_info, const char *fmt, ...)
{
	const u64 old_flags = fs_info->qgroup_flags;

	if (btrfs_qgroup_mode(fs_info) == BTRFS_QGROUP_MODE_SIMPLE)
		return;
	fs_info->qgroup_flags |= (BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT |
				  BTRFS_QGROUP_RUNTIME_FLAG_CANCEL_RESCAN |
				  BTRFS_QGROUP_RUNTIME_FLAG_NO_ACCOUNTING);
	if (!(old_flags & BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT)) {
		struct va_format vaf;
		va_list args;

		va_start(args, fmt);
		vaf.fmt = fmt;
		vaf.va = &args;

		btrfs_warn_rl(fs_info, "qgroup marked inconsistent, %pV", &vaf);
		va_end(args);
	}
}

static void qgroup_read_enable_gen(struct btrfs_fs_info *fs_info,
				   struct extent_buffer *leaf, int slot,
				   struct btrfs_qgroup_status_item *ptr)
{
	ASSERT(btrfs_fs_incompat(fs_info, SIMPLE_QUOTA));
	ASSERT(btrfs_item_size(leaf, slot) >= sizeof(*ptr));
	fs_info->qgroup_enable_gen = btrfs_qgroup_status_enable_gen(leaf, ptr);

Annotation

Implementation Notes