fs/xfs/libxfs/xfs_dir2_sf.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_dir2_sf.c
Extension
.c
Size
36543 bytes
Lines
1269
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 (!isdot && !isdotdot) {
			count++;
			namelen += dep->namelen + has_ftype;
		} else if (isdotdot)
			parent = be64_to_cpu(dep->inumber);
		/*
		 * Calculate the new size, see if we should give up yet.
		 */
		size = xfs_dir2_sf_hdr_size(i8count) +	/* header */
		       count * 3 * sizeof(u8) +		/* namelen + offset */
		       namelen +			/* name */
		       (i8count ?			/* inumber */
				count * XFS_INO64_SIZE :
				count * XFS_INO32_SIZE);
		if (size > xfs_inode_data_fork_size(dp))
			return size;		/* size value is a failure */
	}
	/*
	 * Create the output header, if it worked.
	 */
	sfhp->count = count;
	sfhp->i8count = i8count;
	xfs_dir2_sf_put_parent_ino(sfhp, parent);
	return size;
}

/*
 * Convert a block format directory to shortform.
 * Caller has already checked that it will fit, and built us a header.
 */
int						/* error */
xfs_dir2_block_to_sf(
	struct xfs_da_args	*args,		/* operation arguments */
	struct xfs_buf		*bp,
	int			size,		/* shortform directory size */
	struct xfs_dir2_sf_hdr	*sfhp)		/* shortform directory hdr */
{
	struct xfs_inode	*dp = args->dp;
	struct xfs_mount	*mp = dp->i_mount;
	int			error;		/* error return value */
	int			logflags;	/* inode logging flags */
	struct xfs_dir2_sf_entry *sfep;		/* shortform entry */
	struct xfs_dir2_sf_hdr	*sfp;		/* shortform directory header */
	unsigned int		offset = args->geo->data_entry_offset;
	unsigned int		end;

	trace_xfs_dir2_block_to_sf(args);

	/*
	 * Allocate a temporary destination buffer the size of the inode to
	 * format the data into.  Once we have formatted the data, we can free
	 * the block and copy the formatted data into the inode literal area.
	 */
	sfp = kmalloc(mp->m_sb.sb_inodesize, GFP_KERNEL | __GFP_NOFAIL);
	memcpy(sfp, sfhp, xfs_dir2_sf_hdr_size(sfhp->i8count));

	/*
	 * Loop over the active and unused entries.  Stop when we reach the
	 * leaf/tail portion of the block.
	 */
	end = xfs_dir3_data_end_offset(args->geo, bp->b_addr);
	sfep = xfs_dir2_sf_firstentry(sfp);
	while (offset < end) {
		struct xfs_dir2_data_unused	*dup = bp->b_addr + offset;
		struct xfs_dir2_data_entry	*dep = bp->b_addr + offset;

		/*
		 * If it's unused, just skip over it.
		 */
		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
			offset += be16_to_cpu(dup->length);
			continue;
		}

		/*
		 * Skip .
		 */
		if (dep->namelen == 1 && dep->name[0] == '.')
			ASSERT(be64_to_cpu(dep->inumber) == I_INO(dp));
		/*
		 * Skip .., but make sure the inode number is right.
		 */
		else if (dep->namelen == 2 &&
			 dep->name[0] == '.' && dep->name[1] == '.')
			ASSERT(be64_to_cpu(dep->inumber) ==
			       xfs_dir2_sf_get_parent_ino(sfp));
		/*
		 * Normal entry, copy it into shortform.
		 */
		else {

Annotation

Implementation Notes