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>
This commit is contained in:
@@ -196,6 +196,8 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;
|
|||||||
#define XFS_BMDR_SPACE_CALC(nrecs) \
|
#define XFS_BMDR_SPACE_CALC(nrecs) \
|
||||||
(int)(sizeof(xfs_bmdr_block_t) + \
|
(int)(sizeof(xfs_bmdr_block_t) + \
|
||||||
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
|
((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t))))
|
||||||
|
#define XFS_BMAP_BMDR_SPACE(bb) \
|
||||||
|
(XFS_BMDR_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Maximum number of bmap btree levels.
|
* Maximum number of bmap btree levels.
|
||||||
|
@@ -24,6 +24,9 @@
|
|||||||
#include "xfs_ag.h"
|
#include "xfs_ag.h"
|
||||||
#include "xfs_mount.h"
|
#include "xfs_mount.h"
|
||||||
#include "xfs_bmap_btree.h"
|
#include "xfs_bmap_btree.h"
|
||||||
|
#include "xfs_alloc_btree.h"
|
||||||
|
#include "xfs_ialloc_btree.h"
|
||||||
|
#include "xfs_btree.h"
|
||||||
#include "xfs_dinode.h"
|
#include "xfs_dinode.h"
|
||||||
#include "xfs_inode.h"
|
#include "xfs_inode.h"
|
||||||
#include "xfs_inode_item.h"
|
#include "xfs_inode_item.h"
|
||||||
@@ -182,7 +185,7 @@ xfs_swap_extents_check_format(
|
|||||||
*/
|
*/
|
||||||
if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
if (tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
||||||
if (XFS_IFORK_BOFF(ip) &&
|
if (XFS_IFORK_BOFF(ip) &&
|
||||||
tip->i_df.if_broot_bytes > XFS_IFORK_BOFF(ip))
|
XFS_BMAP_BMDR_SPACE(tip->i_df.if_broot) > XFS_IFORK_BOFF(ip))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
|
if (XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK) <=
|
||||||
XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
|
XFS_IFORK_MAXEXT(ip, XFS_DATA_FORK))
|
||||||
@@ -192,9 +195,8 @@ xfs_swap_extents_check_format(
|
|||||||
/* Reciprocal target->temp btree format checks */
|
/* Reciprocal target->temp btree format checks */
|
||||||
if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
if (ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
||||||
if (XFS_IFORK_BOFF(tip) &&
|
if (XFS_IFORK_BOFF(tip) &&
|
||||||
ip->i_df.if_broot_bytes > XFS_IFORK_BOFF(tip))
|
XFS_BMAP_BMDR_SPACE(ip->i_df.if_broot) > XFS_IFORK_BOFF(tip))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
|
if (XFS_IFORK_NEXTENTS(ip, XFS_DATA_FORK) <=
|
||||||
XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
|
XFS_IFORK_MAXEXT(tip, XFS_DATA_FORK))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
Reference in New Issue
Block a user