fs/ntfs3/attrlist.c

Source file repositories/reference/linux-study-clean/fs/ntfs3/attrlist.c

File Facts

System
Linux kernel
Corpus path
fs/ntfs3/attrlist.c
Extension
.c
Size
8786 bytes
Lines
429
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 (!lsize) {
			err = -EINVAL;
			goto out;
		}

		/* attr is resident: lsize < record_size (1K or 4K) */
		le = kvmalloc(al_aligned(lsize), GFP_KERNEL);
		if (!le) {
			err = -ENOMEM;
			goto out;
		}
		memcpy(le, resident_data(attr), lsize);
	} else if (attr->nres.svcn) {
		err = -EINVAL;
		goto out;
	} else {
		u16 run_off = le16_to_cpu(attr->nres.run_off);

		lsize = le64_to_cpu(attr->nres.data_size);
		if (!lsize) {
			err = -EINVAL;
			goto out;
		}

		run_init(&ni->attr_list.run);

		if (run_off > le32_to_cpu(attr->size)) {
			err = -EINVAL;
			goto out;
		}

		err = run_unpack_ex(&ni->attr_list.run, ni->mi.sbi, ni->mi.rno,
				    0, le64_to_cpu(attr->nres.evcn), 0,
				    Add2Ptr(attr, run_off),
				    le32_to_cpu(attr->size) - run_off);
		if (err < 0)
			goto out;

		/* attr is nonresident.
		 * The worst case:
		 * 1T (2^40) extremely fragmented file.
		 * cluster = 4K (2^12) => 2^28 fragments
		 * 2^9 fragments per one record => 2^19 records
		 * 2^5 bytes of ATTR_LIST_ENTRY per one record => 2^24 bytes.
		 *
		 * the result is 16M bytes per attribute list.
		 * Use kvmalloc to allocate in range [several Kbytes - dozen Mbytes]
		 */
		le = kvmalloc(al_aligned(lsize), GFP_KERNEL);
		if (!le) {
			err = -ENOMEM;
			goto out;
		}

		err = ntfs_read_run_nb(ni->mi.sbi, &ni->attr_list.run, 0, le,
				       lsize, NULL);
		if (err)
			goto out;
	}

	ni->attr_list.size = lsize;
	ni->attr_list.le = le;

	return 0;

out:
	ni->attr_list.le = le;
	al_destroy(ni);

	return err;
}

/*
 * al_enumerate
 *
 * Return:
 * * The next list le.
 * * If @le is NULL then return the first le.
 */
struct ATTR_LIST_ENTRY *al_enumerate(struct ntfs_inode *ni,
				     struct ATTR_LIST_ENTRY *le)
{
	size_t off;
	u16 sz;
	const unsigned le_min_size = le_size(0);

	if (!le) {
		le = ni->attr_list.le;
	} else {
		sz = le16_to_cpu(le->size);

Annotation

Implementation Notes