xfs: check on-disk (not incore) btree root size in dfrag.c
PATCH 1/1 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.
---
fs/xfs/xfs_bmap_btree.h +3 -1
@@ -189,12 +189,14 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;#define XFS_BMAP_BROOT_SPACE_CALC (nrecs) \ (int)(XFS_BTREE_LBLOCK_LEN + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) -#define XFS_BMAP_BROOT_SPACE (bb) \ (XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) +#define XFS_BMDR_SPACE_CALC (nrecs) \ (int)(sizeof(xfs_bmdr_block_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.
fs/xfs/xfs_dfrag.c +5 -3
@@ -26,6 +26,9 @@#include "xfs_ag.h" #include "xfs_mount.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_inode.h" #include "xfs_inode_item.h"
@@ -184,7 +187,7 @@ xfs_swap_extents_check_format(*/ if (tip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ;if (XFS_IFORK_NEXTENTS (tip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (ip,XFS_DATA_FORK ))
@@ -194,9 +197,8 @@ xfs_swap_extents_check_format(/* Reciprocal target->temp btree format checks */ if (ip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ; -if (XFS_IFORK_NEXTENTS (ip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (tip,XFS_DATA_FORK ))return EINVAL ;
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 11 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.
Quoted 5 lines
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.
Hm, as usually happens right after finalizing this I stumbled on something else. xfs_iroot_realloc() does essentially the same test, but uses a funky macro to resolve the incore/ondisk size difference:
ASSERT(ifp->if_broot_bytes <=
XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);so dfrag.c could be fixed up the same way, I suppose, using XFS_BROOT_SIZE_ADJ if desired (though I have no real love for that undocumented macro!)
-Eric
Quoted 49 lines
Reported-by Gabriel VLASIU <[email protected]>Signed-off-by Eric Sandeen <[email protected]>---
fs/xfs/xfs_bmap_btree.h +3
-1@@ -189,12 +189,14 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;#define XFS_BMAP_BROOT_SPACE_CALC (nrecs) \ (int)(XFS_BTREE_LBLOCK_LEN + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) -#define XFS_BMAP_BROOT_SPACE (bb) \ (XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) +#define XFS_BMDR_SPACE_CALC (nrecs) \ (int)(sizeof(xfs_bmdr_block_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. fs/xfs/xfs_dfrag.c +4
-1@@ -26,6 +26,9 @@#include "xfs_ag.h" #include "xfs_mount.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_inode.h" #include "xfs_inode_item.h" @@ -184,7 +187,7 @@ xfs_swap_extents_check_format(*/ if (tip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ;if (XFS_IFORK_NEXTENTS (tip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (ip,XFS_DATA_FORK ))
fs/xfs/xfs_dfrag.c xfs_swap_extents_check_format( · line 204
Quoted 10 lines
fs/xfs/xfs_dfrag.c +1
-2@@ -194,9 +197,8 @@ xfs_swap_extents_check_format(/* Reciprocal target->temp btree format checks */ if (ip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ; -if (XFS_IFORK_NEXTENTS (ip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (tip,XFS_DATA_FORK ))return EINVAL ;
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Dave Chinner
Reviewed-byQuoted 23 lines · Eric Sandeen
Quoted 11 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.Quoted 5 lines
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.
Hm, as usually happens right after finalizing this I stumbled on something else.
xfs_iroot_realloc()does essentially the same test, but uses a funky macro to resolve the incore/ondisk size difference:
Quoted 6 lines
ASSERT(ifp->if_broot_bytes <= XFS_IFORK_SIZE(ip, whichfork) + XFS_BROOT_SIZE_ADJ);so
dfrag.ccould be fixed up the same way, I suppose, usingXFS_BROOT_SIZE_ADJif desired (though I have no real love for that undocumented macro!)
I much prefer the addition of a XFS_BMAP_BMDR_SPACE() macro. Perhaps it might be worthwhile to convert those uses of XFS_BROOT_SIZE_ADJ to use your new macro, and get rid of the XFS_BROOT_SIZE_ADJ grot altogether?
Anyway, consider your patch:
Cheers,
Dave.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
[PATCH 2/1] xfs: use XFS_BMAP_BMDR_SPACE vs. XFS_BROOT_SIZE_ADJ
In reply to Eric SandeenXFS_BROOT_SIZE_ADJ is an undocumented macro which accounts for the difference in size between the on-disk and in-core btree root. It's much clearer to just use the newly-added XFS_BMAP_BMDR_SPACE macro which gives us the on-disk size directly.
In one case, we must test that the if_broot exists before applying the macro, however.
---
fs/xfs/xfs_dinode.h +0 -3
@@ -107,9 +107,6 @@ typedef enum xfs_dinode_fmt {#define XFS_LITINO (mp) \ ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode))) -#define XFS_BROOT_SIZE_ADJ \ - (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) -/* * Inode data & attribute fork sizes, per inode. */
fs/xfs/xfs_inode.c +7 -7
@@ -1833,8 +1833,8 @@ xfs_iroot_realloc( np = (char *)XFS_BMAP_BROOT_PTR_ADDR (mp, ifp->if_broot,1 , (int )new_size); ifp->if_broot_bytes = (int )new_size; -ASSERT (ifp->if_broot_bytes <= -XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ ); +ASSERT (XFS_BMAP_BMDR_SPACE (ifp->if_broot) <= +XFS_IFORK_SIZE (ip, whichfork));memmove (np, op, cur_max * (uint )sizeof (xfs_dfsbno_t));return ; }
@@ -1886,8 +1886,9 @@ xfs_iroot_realloc(kmem_free (ifp->if_broot); ifp->if_broot = new_broot; ifp->if_broot_bytes = (int )new_size; -ASSERT (ifp->if_broot_bytes <= -XFS_IFORK_SIZE (ip, whichfork) +XFS_BROOT_SIZE_ADJ ); +if (ifp->if_broot) +ASSERT (XFS_BMAP_BMDR_SPACE (ifp->if_broot) <= +XFS_IFORK_SIZE (ip, whichfork));return ; }
@@ -2201,9 +2202,8 @@ xfs_iflush_fork(if ((iip->ili_format.ilf_fields & brootflag[whichfork]) && (ifp->if_broot_bytes >0 )) {ASSERT (ifp->if_broot !=NULL ); -ASSERT (ifp->if_broot_bytes <= - (XFS_IFORK_SIZE (ip, whichfork) + -XFS_BROOT_SIZE_ADJ )); +ASSERT (XFS_BMAP_BMDR_SPACE (ifp->if_broot) <= +XFS_IFORK_SIZE (ip, whichfork));xfs_bmbt_to_bmdr (mp, ifp->if_broot, ifp->if_broot_bytes, (xfs_bmdr_block_t *)cp,XFS_DFORK_SIZE (dip, mp, whichfork));
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Dave Chinner
Reviewed-byRe: [PATCH 2/1] xfs: use XFS_BMAP_BMDR_SPACE vs. XFS_BROOT_SIZE_ADJ
Quoted 10 lines · Eric Sandeen
XFS_BROOT_SIZE_ADJis an undocumented macro which accounts for the difference in size between the on-disk and in-core btree root. It's much clearer to just use the newly-addedXFS_BMAP_BMDR_SPACEmacro which gives us the on-disk size directly.In one case, we must test that the
if_brootexists before applying the macro, however.Signed-off-by Eric Sandeen <[email protected]>
Looks good.
Signature · 7 lines
Dave Chinner [email protected] _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
Quoted 11 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.
Quoted 5 lines
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.
I think this and the followup patch 2/1 got lost.
Ben, any idea?
Thanks,
-Eric
Quoted 59 lines
Reported-by Gabriel VLASIU <[email protected]>Signed-off-by Eric Sandeen <[email protected]>---
fs/xfs/xfs_bmap_btree.h +3
-1@@ -189,12 +189,14 @@ typedef __be64 xfs_bmbt_ptr_t, xfs_bmdr_ptr_t;#define XFS_BMAP_BROOT_SPACE_CALC (nrecs) \ (int)(XFS_BTREE_LBLOCK_LEN + \ ((nrecs) * (sizeof(xfs_bmbt_key_t) + sizeof(xfs_bmbt_ptr_t)))) -#define XFS_BMAP_BROOT_SPACE (bb) \ (XFS_BMAP_BROOT_SPACE_CALC(be16_to_cpu((bb)->bb_numrecs))) +#define XFS_BMDR_SPACE_CALC (nrecs) \ (int)(sizeof(xfs_bmdr_block_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. fs/xfs/xfs_dfrag.c +5
-3@@ -26,6 +26,9 @@#include "xfs_ag.h" #include "xfs_mount.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_inode.h" #include "xfs_inode_item.h" @@ -184,7 +187,7 @@ xfs_swap_extents_check_format(*/ if (tip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ;if (XFS_IFORK_NEXTENTS (tip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (ip,XFS_DATA_FORK ))@@ -194,9 +197,8 @@ xfs_swap_extents_check_format(/* Reciprocal target->temp btree format checks */ if (ip->i_d.di_format ==XFS_DINODE_FMT_BTREE ) {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 ; -if (XFS_IFORK_NEXTENTS (ip,XFS_DATA_FORK ) <=XFS_IFORK_MAXEXT (tip,XFS_DATA_FORK ))return EINVAL ;
Quoted 5 lines
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 15 lines · Eric Sandeen
Quoted 14 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.
Quoted 6 lines
Quoted 2 lines
With this change, the filesystem image provided by Gabriel allows for proper file degragmentation.
I think this and the followup patch 2/1 got lost.
Ben, any idea?
Yeah. Sorry Eric.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Quoted 16 lines · Ben Myers
Quoted 15 lines · Eric Sandeen
Quoted 14 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.
Quoted 8 lines
Quoted 6 lines
Quoted 2 lines
With this change, the filesystem image provided by Gabriel allows for proper file degragmentation.
I think this and the followup patch 2/1 got lost.
Ben, any idea?
Yeah. Sorry Eric.
I see the first patch is now merged. Can you please also merge the 2nd patch? It is also reviewed already.
Thanks,
-Eric
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs
Ben Myers
Reviewed-byQuoted 20 lines · Eric Sandeen
Quoted 19 lines · Ben Myers
Quoted 18 lines · Eric Sandeen
Quoted 16 lines · Eric Sandeen
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 wherexfs_fsrreturned 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.
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
I think this and the followup patch 2/1 got lost.
Ben, any idea?
Yeah. Sorry Eric.
I see the first patch is now merged. Can you please also merge the 2nd patch? It is also reviewed already.
Patch still looks good in light of the crc work. Applied.
_______________________________________________
xfs mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/xfs