fs/xfs/libxfs/xfs_dir2_data.c

Source file repositories/reference/linux-study-clean/fs/xfs/libxfs/xfs_dir2_data.c

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_dir2_data.c
Extension
.c
Size
34598 bytes
Lines
1256
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 (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
			xfs_failaddr_t	fa;

			reclen = xfs_dir2_data_unusedsize(
					be16_to_cpu(dup->length));
			if (lastfree != 0)
				return __this_address;
			if (be16_to_cpu(dup->length) != reclen)
				return __this_address;
			if (offset + reclen > end)
				return __this_address;
			if (be16_to_cpu(*xfs_dir2_data_unused_tag_p(dup)) !=
			    offset)
				return __this_address;
			fa = xfs_dir2_data_freefind_verify(hdr, bf, dup, &dfp);
			if (fa)
				return fa;
			if (dfp) {
				i = (int)(dfp - bf);
				if ((freeseen & (1 << i)) != 0)
					return __this_address;
				freeseen |= 1 << i;
			} else {
				if (be16_to_cpu(dup->length) >
				    be16_to_cpu(bf[2].length))
					return __this_address;
			}
			offset += reclen;
			lastfree = 1;
			continue;
		}

		/*
		 * This is not an unused entry. Are the remaining bytes
		 * large enough for a dirent with a single-byte name?
		 */
		if (offset > end - xfs_dir2_data_entsize(mp, 1))
			return __this_address;

		/*
		 * It's a real entry.  Validate the fields.
		 * If this is a block directory then make sure it's
		 * in the leaf section of the block.
		 * The linear search is crude but this is DEBUG code.
		 */
		if (dep->namelen == 0)
			return __this_address;
		reclen = xfs_dir2_data_entsize(mp, dep->namelen);
		if (offset + reclen > end)
			return __this_address;
		if (!xfs_verify_dir_ino(mp, be64_to_cpu(dep->inumber)))
			return __this_address;
		if (be16_to_cpu(*xfs_dir2_data_entry_tag_p(mp, dep)) != offset)
			return __this_address;
		if (xfs_dir2_data_get_ftype(mp, dep) >= XFS_DIR3_FT_MAX)
			return __this_address;
		count++;
		lastfree = 0;
		if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
		    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
			addr = xfs_dir2_db_off_to_dataptr(geo, geo->datablk,
						(xfs_dir2_data_aoff_t)
						((char *)dep - (char *)hdr));
			name.name = dep->name;
			name.len = dep->namelen;
			hash = xfs_dir2_hashname(mp, &name);
			for (i = 0; i < be32_to_cpu(btp->count); i++) {
				if (be32_to_cpu(lep[i].address) == addr &&
				    be32_to_cpu(lep[i].hashval) == hash)
					break;
			}
			if (i >= be32_to_cpu(btp->count))
				return __this_address;
		}
		offset += reclen;
	}
	/*
	 * Need to have seen all the entries and all the bestfree slots.
	 */
	if (freeseen != 7)
		return __this_address;
	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
	    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
		for (i = stale = 0; i < be32_to_cpu(btp->count); i++) {
			if (lep[i].address ==
			    cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
				stale++;
			if (i > 0 && be32_to_cpu(lep[i].hashval) <
				     be32_to_cpu(lep[i - 1].hashval))
				return __this_address;

Annotation

Implementation Notes