Skip to content

Commit

Permalink
xfs: fix incorrect remote symlink block count
Browse files Browse the repository at this point in the history
When CRCs are enabled, the number of blocks needed to hold a remote
symlink on a 1k block size filesystem may be 2 instead of 1. The
transaction reservation for the allocated blocks was not taking this
into account and only allocating one block. Hence when trying to
read or invalidate such symlinks, we are mapping a hole where there
should be a block and things go bad at that point.

Fix the reservation to use the correct block count, clean up the
block count calculation similar to the remote attribute calculation,
and add a debug guard to detect when we don't write the entire
symlink to disk.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Ben Myers <bpm@sgi.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
Signed-off-by: Ben Myers <bpm@sgi.com>

(cherry picked from commit 321a958)
  • Loading branch information
Dave Chinner authored and Ben Myers committed May 30, 2013
1 parent 7d2ffe8 commit 1de09d1
Showing 1 changed file with 6 additions and 14 deletions.
20 changes: 6 additions & 14 deletions fs/xfs/xfs_symlink.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,9 @@ xfs_symlink_blocks(
struct xfs_mount *mp,
int pathlen)
{
int fsblocks = 0;
int len = pathlen;
int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);

do {
fsblocks++;
len -= XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
} while (len > 0);

ASSERT(fsblocks <= XFS_SYMLINK_MAPS);
return fsblocks;
return (pathlen + buflen - 1) / buflen;
}

static int
Expand Down Expand Up @@ -405,7 +398,7 @@ xfs_symlink(
if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version))
fs_blocks = 0;
else
fs_blocks = XFS_B_TO_FSB(mp, pathlen);
fs_blocks = xfs_symlink_blocks(mp, pathlen);
resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks);
error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0,
XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT);
Expand Down Expand Up @@ -512,7 +505,7 @@ xfs_symlink(
cur_chunk = target_path;
offset = 0;
for (n = 0; n < nmaps; n++) {
char *buf;
char *buf;

d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock);
byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount);
Expand All @@ -525,9 +518,7 @@ xfs_symlink(
bp->b_ops = &xfs_symlink_buf_ops;

byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt);
if (pathlen < byte_cnt) {
byte_cnt = pathlen;
}
byte_cnt = min(byte_cnt, pathlen);

buf = bp->b_addr;
buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset,
Expand All @@ -542,6 +533,7 @@ xfs_symlink(
xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) -
(char *)bp->b_addr);
}
ASSERT(pathlen == 0);
}

/*
Expand Down

0 comments on commit 1de09d1

Please sign in to comment.