fs/exfat/balloc.c

Source file repositories/reference/linux-study-clean/fs/exfat/balloc.c

File Facts

System
Linux kernel
Corpus path
fs/exfat/balloc.c
Extension
.c
Size
9965 bytes
Lines
400
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 (clu_mask > 0) {
			bitval |= cpu_to_lel(clu_mask);
			clu_mask = 0;
		}
		if (lel_to_cpu(bitval) != ULONG_MAX) {
			clu_bits = lel_to_cpu(bitval);
			clu_free = clu_base + ffz(clu_bits);
			if (clu_free < sbi->num_clusters)
				return clu_free;
		}
		clu_base += BITS_PER_LONG;
		map_b += sizeof(long);

		if (map_b >= sb->s_blocksize ||
		    clu_base >= sbi->num_clusters) {
			if (++map_i >= sbi->map_sectors) {
				clu_base = EXFAT_FIRST_CLUSTER;
				map_i = 0;
			}
			map_b = 0;
		}
	}

	return EXFAT_EOF_CLUSTER;
}

int exfat_count_used_clusters(struct super_block *sb, unsigned int *ret_count)
{
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	unsigned int count = 0;
	unsigned int i, map_i = 0, map_b = 0;
	unsigned int total_clus = EXFAT_DATA_CLUSTER_COUNT(sbi);
	unsigned int last_mask = total_clus & (BITS_PER_LONG - 1);
	unsigned long *bitmap, clu_bits;

	total_clus &= ~last_mask;
	for (i = 0; i < total_clus; i += BITS_PER_LONG) {
		bitmap = (void *)(sbi->vol_amap[map_i]->b_data + map_b);
		count += hweight_long(*bitmap);
		map_b += sizeof(long);
		if (map_b >= (unsigned int)sb->s_blocksize) {
			map_i++;
			map_b = 0;
		}
	}

	if (last_mask) {
		bitmap = (void *)(sbi->vol_amap[map_i]->b_data + map_b);
		clu_bits = lel_to_cpu(*(__le_long *)bitmap);
		count += hweight_long(clu_bits & BITMAP_LAST_WORD_MASK(last_mask));
	}

	*ret_count = count;
	return 0;
}

int exfat_trim_fs(struct inode *inode, struct fstrim_range *range)
{
	unsigned int trim_begin, trim_end, count, next_free_clu;
	u64 clu_start, clu_end, trim_minlen, trimmed_total = 0;
	struct super_block *sb = inode->i_sb;
	struct exfat_sb_info *sbi = EXFAT_SB(sb);
	int err = 0;

	clu_start = max_t(u64, range->start >> sbi->cluster_size_bits,
				EXFAT_FIRST_CLUSTER);
	clu_end = clu_start + (range->len >> sbi->cluster_size_bits) - 1;
	trim_minlen = range->minlen >> sbi->cluster_size_bits;

	if (clu_start >= sbi->num_clusters || range->len < sbi->cluster_size)
		return -EINVAL;

	if (clu_end >= sbi->num_clusters)
		clu_end = sbi->num_clusters - 1;

	mutex_lock(&sbi->bitmap_lock);

	trim_begin = trim_end = exfat_find_free_bitmap(sb, clu_start);
	if (trim_begin == EXFAT_EOF_CLUSTER)
		goto unlock;

	next_free_clu = exfat_find_free_bitmap(sb, trim_end + 1);
	if (next_free_clu == EXFAT_EOF_CLUSTER)
		goto unlock;

	do {
		if (next_free_clu == trim_end + 1) {
			/* extend trim range for continuous free cluster */
			trim_end++;
		} else {

Annotation

Implementation Notes