Commit b8102b61 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: move symlink target write function to libxfs



Move xfs_symlink_write_target to xfs_symlink_remote.c so that kernel and
mkfs can share the same function.

Signed-off-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent 376b4f05
Loading
Loading
Loading
Loading
+76 −0
Original line number Diff line number Diff line
@@ -304,3 +304,79 @@ xfs_symlink_remote_read(
 out:
	return error;
}

/* Write the symlink target into the inode. */
int
xfs_symlink_write_target(
	struct xfs_trans	*tp,
	struct xfs_inode	*ip,
	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);

		buf = bp->b_addr;
		buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, byte_cnt,
				bp);

		memcpy(buf, cur_chunk, byte_cnt);

		cur_chunk += byte_cnt;
		pathlen -= byte_cnt;
		offset += byte_cnt;

		xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
		xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
						(char *)bp->b_addr);
	}
	ASSERT(pathlen == 0);
	return 0;
}
+3 −0
Original line number Diff line number Diff line
@@ -19,5 +19,8 @@ void xfs_symlink_local_to_remote(struct xfs_trans *tp, struct xfs_buf *bp,
				 struct xfs_inode *ip, struct xfs_ifork *ifp);
xfs_failaddr_t xfs_symlink_shortform_verify(void *sfp, int64_t size);
int xfs_symlink_remote_read(struct xfs_inode *ip, char *link);
int xfs_symlink_write_target(struct xfs_trans *tp, struct xfs_inode *ip,
		const char *target_path, int pathlen, xfs_fsblock_t fs_blocks,
		uint resblks);

#endif /* __XFS_SYMLINK_REMOTE_H */
+5 −64
Original line number Diff line number Diff line
@@ -93,15 +93,7 @@ xfs_symlink(
	int			error = 0;
	int			pathlen;
	bool                    unlock_dp_on_error = false;
	xfs_fileoff_t		first_fsb;
	xfs_filblks_t		fs_blocks;
	int			nmaps;
	struct xfs_bmbt_irec	mval[XFS_SYMLINK_MAPS];
	xfs_daddr_t		d;
	const char		*cur_chunk;
	int			byte_cnt;
	int			n;
	struct xfs_buf		*bp;
	prid_t			prid;
	struct xfs_dquot	*udqp = NULL;
	struct xfs_dquot	*gdqp = NULL;
@@ -189,62 +181,11 @@ xfs_symlink(
	xfs_qm_vop_create_dqattach(tp, ip, udqp, gdqp, pdqp);

	resblks -= XFS_IALLOC_SPACE_RES(mp);
	/*
	 * 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);
	} else {
		int	offset;

		first_fsb = 0;
		nmaps = XFS_SYMLINK_MAPS;

		error = xfs_bmapi_write(tp, ip, first_fsb, fs_blocks,
				  XFS_BMAPI_METADATA, resblks, mval, &nmaps);
	error = xfs_symlink_write_target(tp, ip, target_path, pathlen,
			fs_blocks, resblks);
	if (error)
		goto out_trans_cancel;

	resblks -= fs_blocks;
		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)
				goto out_trans_cancel;
			bp->b_ops = &xfs_symlink_buf_ops;

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

			buf = bp->b_addr;
			buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
						   byte_cnt, bp);

			memcpy(buf, cur_chunk, byte_cnt);

			cur_chunk += byte_cnt;
			pathlen -= byte_cnt;
			offset += byte_cnt;

			xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SYMLINK_BUF);
			xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
							(char *)bp->b_addr);
		}
		ASSERT(pathlen == 0);
	}
	i_size_write(VFS_I(ip), ip->i_disk_size);

	/*