fs/exfat/iomap.c

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

File Facts

System
Linux kernel
Corpus path
fs/exfat/iomap.c
Extension
.c
Size
7755 bytes
Lines
272
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 (i_size_read(inode) <= offset) {
			iomap->type = IOMAP_HOLE;
			iomap->addr = IOMAP_NULL_ADDR;
			iomap->offset = offset;
			iomap->length = length;
			return 0;
		}

		/* Clamp length if the requested range goes beyond i_size */
		if (offset + length > i_size_read(inode))
			length = round_up(i_size_read(inode),
					  i_blocksize(inode)) - offset;
	}

	num_clusters = exfat_bytes_to_cluster_round_up(sbi,
			offset + length) - exfat_bytes_to_cluster(sbi, offset);

	mutex_lock(&sbi->s_lock);
	iomap->bdev = inode->i_sb->s_bdev;
	iomap->offset = offset;

	err = exfat_map_cluster(inode, exfat_bytes_to_cluster(sbi, offset),
			&cluster, &num_clusters, may_alloc, &balloc);
	if (err)
		goto out;

	cluster_offset = exfat_cluster_offset(sbi, offset);
	cluster_length = exfat_cluster_to_bytes(sbi, num_clusters);

	iomap->length = min_t(loff_t, length, cluster_length - cluster_offset);
	iomap->addr = exfat_cluster_to_phys_bytes(sbi, cluster) + cluster_offset;
	iomap->type = IOMAP_MAPPED;
	iomap->flags = IOMAP_F_MERGED;

	if (may_alloc || flags & IOMAP_ZERO) {
		if (balloc)
			iomap->flags |= IOMAP_F_NEW;
		else if (iomap->offset + iomap->length >= ei->valid_size) {
			/*
			 * This is a write that starts at or extends beyond
			 * the current valid_size. The region between the old
			 * valid_size and the end of this write needs to be
			 * zeroed in the page cache to prevent stale data
			 * exposure (see IOMAP_F_ZERO_TAIL handling in
			 * __iomap_write_begin()).
			 */
			iomap->flags |= IOMAP_F_ZERO_TAIL;
		}
	} else {
		/*
		 * valid_size is tracked in byte granularity and
		 * marks the exact boundary between valid data and
		 * holes (or unwritten space).
		 *
		 * When IOMAP_REPORT is set (used by lseek(SEEK_HOLE)
		 * and SEEK_DATA), we return IOMAP_HOLE. This allows
		 * iomap_seek_hole_iter() to directly return the
		 * precise byte position.
		 *
		 * For normal I/O paths (without IOMAP_REPORT) we
		 * return IOMAP_UNWRITTEN so the write path can
		 * distinguish it from a real hole.
		 */
		if (offset >= ei->valid_size) {
			iomap->type = flags & IOMAP_REPORT ?
				IOMAP_HOLE : IOMAP_UNWRITTEN;
		} else if (offset + iomap->length > ei->valid_size) {
			if (flags & IOMAP_REPORT) {
				/*
				 * For SEEK_HOLE/SEEK_DATA, clip the length
				 * to the exact byte boundary (valid_size).
				 * This ensures the caller gets the precise
				 * hole position in byte units.
				 */
				iomap->length = ei->valid_size - iomap->offset;
			} else
				iomap->length = round_up(ei->valid_size,
							 i_blocksize(inode)) -
								iomap->offset;
		}
	}

	iomap->flags |= IOMAP_F_MERGED;
out:
	mutex_unlock(&sbi->s_lock);
	return err;
}

static int exfat_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
		unsigned int flags, struct iomap *iomap, struct iomap *srcmap)

Annotation

Implementation Notes