From: Dave Chinner <dchinner@xxxxxxxxxx>
With the addition of CRCs to the filesystem format, the AGFL has a
new format structure definition. Existing code that pulls freelist
blocks out via dereferencing agfl->agfl_bno no longer works as the
location of the free list is now variable depending on the disk
format in use.
Hence all the users of agfl_bno need ot be converted to extract the
location of the first free list entry from the AGFL and grab entries
relative to that first entry. It's a simple change, but needs to be
made in several places as there is very little code reuse within and
between the different utilities in xfsprogs.
Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx>
---
db/check.c | 6 +++++-
db/freesp.c | 7 ++++++-
repair/phase5.c | 6 ++++--
repair/scan.c | 6 +++---
4 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/db/check.c b/db/check.c
index 353530b..127e407 100644
--- a/db/check.c
+++ b/db/check.c
@@ -3806,6 +3806,7 @@ scan_freelist(
xfs_agblock_t bno;
uint count;
int i;
+ __be32 *freelist;
if (XFS_SB_BLOCK(mp) != XFS_AGFL_BLOCK(mp) &&
XFS_AGF_BLOCK(mp) != XFS_AGFL_BLOCK(mp) &&
@@ -3835,9 +3836,12 @@ scan_freelist(
return;
}
+ /* open coded XFS_BUF_TO_AGFL_BNO */
+ freelist = xfs_sb_version_hascrc(&((mp)->m_sb)) ? &agfl->agfl_bno[0]
+ : (__be32 *)agfl;
count = 0;
for (;;) {
- bno = be32_to_cpu(agfl->agfl_bno[i]);
+ bno = be32_to_cpu(freelist[i]);
set_dbmap(seqno, bno, 1, DBM_FREELIST, seqno,
XFS_AGFL_BLOCK(mp));
count++;
diff --git a/db/freesp.c b/db/freesp.c
index 472b1f7..228ca07 100644
--- a/db/freesp.c
+++ b/db/freesp.c
@@ -231,6 +231,7 @@ scan_freelist(
xfs_agfl_t *agfl;
xfs_agblock_t bno;
int i;
+ __be32 *agfl_bno;
if (be32_to_cpu(agf->agf_flcount) == 0)
return;
@@ -240,6 +241,10 @@ scan_freelist(
agfl = iocur_top->data;
i = be32_to_cpu(agf->agf_flfirst);
+ /* open coded XFS_BUF_TO_AGFL_BNO */
+ agfl_bno = xfs_sb_version_hascrc(&mp->m_sb) ? &agfl->agfl_bno[0]
+ : (__be32 *)agfl;
+
/* verify agf values before proceeding */
if (be32_to_cpu(agf->agf_flfirst) >= XFS_AGFL_SIZE(mp) ||
be32_to_cpu(agf->agf_fllast) >= XFS_AGFL_SIZE(mp)) {
@@ -250,7 +255,7 @@ scan_freelist(
}
for (;;) {
- bno = be32_to_cpu(agfl->agfl_bno[i]);
+ bno = be32_to_cpu(agfl_bno[i]);
addtohist(seqno, bno, 1);
if (i == be32_to_cpu(agf->agf_fllast))
break;
diff --git a/repair/phase5.c b/repair/phase5.c
index 1f71cac..c7cef4f 100644
--- a/repair/phase5.c
+++ b/repair/phase5.c
@@ -1208,6 +1208,7 @@ build_agf_agfl(xfs_mount_t *mp,
int j;
xfs_agfl_t *agfl;
xfs_agf_t *agf;
+ __be32 *freelist;
agf_buf = libxfs_getbuf(mp->m_dev,
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
@@ -1277,19 +1278,20 @@ build_agf_agfl(xfs_mount_t *mp,
XFS_AG_DADDR(mp, agno, XFS_AGFL_DADDR(mp)),
mp->m_sb.sb_sectsize/BBSIZE);
agfl = XFS_BUF_TO_AGFL(agfl_buf);
+ freelist = XFS_BUF_TO_AGFL_BNO(mp, agfl_buf);
memset(agfl, 0, mp->m_sb.sb_sectsize);
/*
* ok, now grab as many blocks as we can
*/
i = j = 0;
while (bno_bt->num_free_blocks > 0 && i < XFS_AGFL_SIZE(mp)) {
- agfl->agfl_bno[i] = cpu_to_be32(
+ freelist[i] = cpu_to_be32(
get_next_blockaddr(agno, 0, bno_bt));
i++;
}
while (bcnt_bt->num_free_blocks > 0 && i < XFS_AGFL_SIZE(mp)) {
- agfl->agfl_bno[i] = cpu_to_be32(
+ freelist[i] = cpu_to_be32(
get_next_blockaddr(agno, 0, bcnt_bt));
i++;
}
diff --git a/repair/scan.c b/repair/scan.c
index 76bb7f1..f79342a 100644
--- a/repair/scan.c
+++ b/repair/scan.c
@@ -1041,12 +1041,12 @@ scan_freelist(
xfs_agf_t *agf,
struct aghdr_cnts *agcnts)
{
- xfs_agfl_t *agfl;
xfs_buf_t *agflbuf;
xfs_agnumber_t agno;
xfs_agblock_t bno;
int count;
int i;
+ __be32 *freelist;
agno = be32_to_cpu(agf->agf_seqno);
@@ -1065,7 +1065,7 @@ scan_freelist(
do_abort(_("can't read agfl block for ag %d\n"), agno);
return;
}
- agfl = XFS_BUF_TO_AGFL(agflbuf);
+ freelist = XFS_BUF_TO_AGFL_BNO(mp, agflbuf);
i = be32_to_cpu(agf->agf_flfirst);
if (no_modify) {
@@ -1080,7 +1080,7 @@ scan_freelist(
count = 0;
for (;;) {
- bno = be32_to_cpu(agfl->agfl_bno[i]);
+ bno = be32_to_cpu(freelist[i]);
if (verify_agbno(mp, agno, bno))
set_bmap(agno, bno, XR_E_FREE);
else
--
1.7.10.4
|