fs/xfs/libxfs/xfs_symlink_remote.c

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

File Facts

System
Linux kernel
Corpus path
fs/xfs/libxfs/xfs_symlink_remote.c
Extension
.c
Size
9988 bytes
Lines
433
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 (xfs_has_crc(mp)) {
			if (!xfs_symlink_hdr_ok(I_INO(ip), offset,
							byte_cnt, bp)) {
				xfs_inode_mark_sick(ip, XFS_SICK_INO_SYMLINK);
				error = -EFSCORRUPTED;
				xfs_alert(mp,
"symlink header does not match required off/len/owner (0x%x/0x%x,0x%llx)",
					offset, byte_cnt, I_INO(ip));
				xfs_buf_relse(bp);
				goto out;

			}

			cur_chunk += sizeof(struct xfs_dsymlink_hdr);
		}

		memcpy(link + offset, cur_chunk, byte_cnt);

		pathlen -= byte_cnt;
		offset += byte_cnt;

		xfs_buf_relse(bp);
	}
	ASSERT(pathlen == 0);

	link[ip->i_disk_size] = '\0';
	error = 0;

 out:
	return error;
}

/* Write the symlink target into the inode. */
int
xfs_symlink_write_target(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	xfs_ino_t		owner,
	const char		*target_path,
	int			pathlen,
	xfs_fsblock_t		fs_blocks,
	uint			resblks)
{
	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
	struct xfs_mount	*mp = tp->t_mountp;
	const char		*cur_chunk;
	struct xfs_buf		*bp;
	xfs_daddr_t		d;
	int			byte_cnt;
	int			nmaps;
	int			offset = 0;
	int			n;
	int			error;

	/*
	 * If the symlink will fit into the inode, write it inline.
	 */
	if (pathlen <= xfs_inode_data_fork_size(ip)) {
		xfs_init_local_fork(ip, XFS_DATA_FORK, target_path, pathlen);

		ip->i_disk_size = pathlen;
		ip->i_df.if_format = XFS_DINODE_FMT_LOCAL;
		xfs_trans_log_inode(tp, ip, XFS_ILOG_DDATA | XFS_ILOG_CORE);
		return 0;
	}

	nmaps = XFS_SYMLINK_MAPS;
	error = xfs_bmapi_write(tp, ip, 0, fs_blocks, XFS_BMAPI_METADATA,
			resblks, mval, &nmaps);
	if (error)
		return error;

	ip->i_disk_size = pathlen;
	xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);

	cur_chunk = target_path;
	offset = 0;
	for (n = 0; n < nmaps; n++) {
		char	*buf;

		d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
		byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
		error = xfs_trans_get_buf(tp, mp->m_ddev_targp, d,
				BTOBB(byte_cnt), 0, &bp);
		if (error)
			return error;
		bp->b_ops = &xfs_symlink_buf_ops;

		byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
		byte_cnt = min(byte_cnt, pathlen);

Annotation

Implementation Notes