aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2012-03-27 16:40:26 -0400
committerBen Myers <bpm@sgi.com>2013-06-20 14:26:09 -0400
commit427d9fe233ccec3a293be4bcf07f9bac12463a99 (patch)
treefa4fe5c810a10785d8a11f8f80c6e27c7e20d375
parent39a45d8463d98ea57347b871641136be64b216a9 (diff)
xfs: check on-disk (not incore) btree root size in dfrag.c
xfs_swap_extents_check_format() contains checks to make sure that original and the temporary files during defrag are compatible; Gabriel VLASIU ran into a case where xfs_fsr returned EINVAL because the tests found the btree root to be of size 120, while the fork offset was only 104; IOW, they overlapped. However, this is just due to an error in the xfs_swap_extents_check_format() tests, because it is checking the in-memory btree root size against the on-disk fork offset. We should be checking the on-disk sizes in both cases. This patch adds a new macro to calculate this size, and uses it in the tests. With this change, the filesystem image provided by Gabriel allows for proper file degragmentation. Reported-by: Gabriel VLASIU <gabriel@vlasiu.net> Signed-off-by: Eric Sandeen <sandeen@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_bmap_btree.h2
-rw-r--r--fs/xfs/xfs_dfrag.c8
2 files changed, 7 insertions, 3 deletions
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index 70c43d9f72c1..1b726d626941 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -196,6 +196,8 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
196#define XFS_BMDR_SPACE_CALC(nrecs) \ 196#define XFS_BMDR_SPACE_CALC(nrecs) \
197 (int)(sizeof(xfs_bmdr_block_t) + \ 197 (int)(sizeof(xfs_bmdr_block_t) + \
198 ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) 198 ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
199#define XFS_BMAP_BMDR_SPACE(bb) \
200 (XFS_BMDR_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
199 201
200/* 202/*
201 * Maximum number of bmap btree levels. 203 * Maximum number of bmap btree levels.
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index c407e1ccff43..e36445ceaf80 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -24,6 +24,9 @@
24#include "xfs_ag.h" 24#include "xfs_ag.h"
25#include "xfs_mount.h" 25#include "xfs_mount.h"
26#include "xfs_bmap_btree.h" 26#include "xfs_bmap_btree.h"
27#include "xfs_alloc_btree.h"
28#include "xfs_ialloc_btree.h"
29#include "xfs_btree.h"
27#include "xfs_dinode.h" 30#include "xfs_dinode.h"
28#include "xfs_inode.h" 31#include "xfs_inode.h"
29#include "xfs_inode_item.h" 32#include "xfs_inode_item.h"
@@ -182,7 +185,7 @@ xfs_swap_extents_check_format(
182 */ 185 */
183 if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) { 186 if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
184 if (XFS_IFORK_BOFF(ip) && 187 if (XFS_IFORK_BOFF(ip) &&
185 tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip)) 188 XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
186 return EINVAL; 189 return EINVAL;
187 if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <= 190 if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
188 XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK)) 191 XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
@@ -192,9 +195,8 @@ xfs_swap_extents_check_format(
192 /* Reciprocal target->temp btree format checks */ 195 /* Reciprocal target->temp btree format checks */
193 if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) { 196 if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
194 if (XFS_IFORK_BOFF(tip) && 197 if (XFS_IFORK_BOFF(tip) &&
195 ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip)) 198 XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
196 return EINVAL; 199 return EINVAL;
197
198 if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <= 200 if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
199 XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK)) 201 XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
200 return EINVAL; 202 return EINVAL;