fs/ntfs/mft.c

Source file repositories/reference/linux-study-clean/fs/ntfs/mft.c

File Facts

System
Linux kernel
Corpus path
fs/ntfs/mft.c
Extension
.c
Size
93674 bytes
Lines
2842
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

le16_to_cpu(m->usa_ofs) + le16_to_cpu(m->usa_count) * 2 > vol->mft_record_size) {
		ntfs_error(sb, "Record %llu has corrupt fix-up values fields\n",
				mft_no);
		goto err_out;
	}

	if (le32_to_cpu(m->bytes_allocated) != vol->mft_record_size) {
		ntfs_error(sb, "Record %llu has corrupt allocation size (%u <> %u)\n",
				mft_no, vol->mft_record_size,
				le32_to_cpu(m->bytes_allocated));
		goto err_out;
	}

	if (le32_to_cpu(m->bytes_in_use) > vol->mft_record_size) {
		ntfs_error(sb, "Record %llu has corrupt in-use size (%u > %u)\n",
				mft_no, le32_to_cpu(m->bytes_in_use),
				vol->mft_record_size);
		goto err_out;
	}

	if (le16_to_cpu(m->attrs_offset) & 7) {
		ntfs_error(sb, "Attributes badly aligned in record %llu\n",
				mft_no);
		goto err_out;
	}

	attrs_offset = le16_to_cpu(m->attrs_offset);
	bytes_in_use = le32_to_cpu(m->bytes_in_use);

	if (attrs_offset > bytes_in_use ||
	    bytes_in_use - attrs_offset < sizeof_field(struct attr_record, type)) {
		ntfs_error(sb, "Record %llu has corrupt attribute offset\n", mft_no);
		goto err_out;
	}

	a = (struct attr_record *)((char *)m + attrs_offset);
	if ((char *)a < (char *)m || (char *)a > (char *)m + vol->mft_record_size) {
		ntfs_error(sb, "Record %llu is corrupt\n", mft_no);
		goto err_out;
	}

	return 0;

err_out:
	return -EIO;
}

/*
 * map_mft_record_folio - map the folio in which a specific mft record resides
 * @ni:		ntfs inode whose mft record page to map
 *
 * This maps the folio in which the mft record of the ntfs inode @ni is
 * situated.
 *
 * This allocates a new buffer (@ni->mrec), copies the MFT record data from
 * the mapped folio into this buffer, and applies the MST (Multi Sector
 * Transfer) fixups on the copy.
 *
 * The folio is pinned (referenced) in @ni->folio to ensure the data remains
 * valid in the page cache, but the returned pointer is the allocated copy.
 *
 * Return: A pointer to the allocated and fixed-up mft record (@ni->mrec).
 * The return value needs to be checked with IS_ERR(). If it is true,
 * PTR_ERR() contains the negative error code.
 */
static inline struct mft_record *map_mft_record_folio(struct ntfs_inode *ni)
{
	loff_t i_size;
	struct ntfs_volume *vol = ni->vol;
	struct inode *mft_vi = vol->mft_ino;
	struct folio *folio;
	unsigned long index, end_index;
	unsigned int ofs;

	WARN_ON(ni->folio);
	/*
	 * The index into the page cache and the offset within the page cache
	 * page of the wanted mft record.
	 */
	index = NTFS_MFT_NR_TO_PIDX(vol, ni->mft_no);
	ofs = NTFS_MFT_NR_TO_POFS(vol, ni->mft_no);

	i_size = i_size_read(mft_vi);
	/* The maximum valid index into the page cache for $MFT's data. */
	end_index = i_size >> PAGE_SHIFT;

	/* If the wanted index is out of bounds the mft record doesn't exist. */
	if (unlikely(index >= end_index)) {
		if (index > end_index || (i_size & ~PAGE_MASK) < ofs +
				vol->mft_record_size) {

Annotation

Implementation Notes