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: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
376b4f0522
commit
b8102b61f7
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
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);
|
||||
}
|
||||
error = xfs_symlink_write_target(tp, ip, target_path, pathlen,
|
||||
fs_blocks, resblks);
|
||||
if (error)
|
||||
goto out_trans_cancel;
|
||||
resblks -= fs_blocks;
|
||||
i_size_write(VFS_I(ip), ip->i_disk_size);
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user