aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2013-05-21 04:02:02 -0400
committerBen Myers <bpm@sgi.com>2013-05-23 18:31:20 -0400
commit913e96bc292e1bb248854686c79d6545ef3ee720 (patch)
treeb8d11a6eb3fea7343b4a7f264bd5fdbfe04fcfea /fs
parent90253cf142469a40f89f989904abf0a1e500e1a6 (diff)
xfs: remote attribute read too short
Reading a maximally size remote attribute fails when CRCs are enabled with this verification error: XFS (vdb): remote attribute header does not match required off/len/owner) There are two reasons for this, the first being that the length of the buffer being read is determined from the args->rmtblkcnt which doesn't take into account CRC headers. Hence the mapped length ends up being too short and so we need to calculate it directly from the value length. The second is that the byte count of valid data within a buffer is capped by the length of the data and so doesn't take into account that the buffer might be longer due to headers. Hence we need to calculate the data space in the buffer first before calculating the actual byte count of data. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_attr_remote.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/fs/xfs/xfs_attr_remote.c b/fs/xfs/xfs_attr_remote.c
index aad95b08e76b..bcdc07c4e8f4 100644
--- a/fs/xfs/xfs_attr_remote.c
+++ b/fs/xfs/xfs_attr_remote.c
@@ -52,9 +52,11 @@ xfs_attr3_rmt_blocks(
52 struct xfs_mount *mp, 52 struct xfs_mount *mp,
53 int attrlen) 53 int attrlen)
54{ 54{
55 int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, 55 if (xfs_sb_version_hascrc(&mp->m_sb)) {
56 mp->m_sb.sb_blocksize); 56 int buflen = XFS_ATTR3_RMT_BUF_SPACE(mp, mp->m_sb.sb_blocksize);
57 return (attrlen + buflen - 1) / buflen; 57 return (attrlen + buflen - 1) / buflen;
58 }
59 return XFS_B_TO_FSB(mp, attrlen);
58} 60}
59 61
60static bool 62static bool
@@ -206,8 +208,9 @@ xfs_attr_rmtval_get(
206 208
207 while (valuelen > 0) { 209 while (valuelen > 0) {
208 nmap = ATTR_RMTVALUE_MAPSIZE; 210 nmap = ATTR_RMTVALUE_MAPSIZE;
211 blkcnt = xfs_attr3_rmt_blocks(mp, valuelen);
209 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno, 212 error = xfs_bmapi_read(args->dp, (xfs_fileoff_t)lblkno,
210 args->rmtblkcnt, map, &nmap, 213 blkcnt, map, &nmap,
211 XFS_BMAPI_ATTRFORK); 214 XFS_BMAPI_ATTRFORK);
212 if (error) 215 if (error)
213 return error; 216 return error;
@@ -227,8 +230,8 @@ xfs_attr_rmtval_get(
227 if (error) 230 if (error)
228 return error; 231 return error;
229 232
230 byte_cnt = min_t(int, valuelen, BBTOB(bp->b_length)); 233 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, BBTOB(bp->b_length));
231 byte_cnt = XFS_ATTR3_RMT_BUF_SPACE(mp, byte_cnt); 234 byte_cnt = min_t(int, valuelen, byte_cnt);
232 235
233 src = bp->b_addr; 236 src = bp->b_addr;
234 if (xfs_sb_version_hascrc(&mp->m_sb)) { 237 if (xfs_sb_version_hascrc(&mp->m_sb)) {