Commit 4805621a authored by From: Christoph Hellwig's avatar From: Christoph Hellwig Committed by Niv Sardi

[XFS] factor out xfs_read_agf helper

Add a helper to read the AGF header and perform basic verification.
Based on hunks from a larger patch from Dave Chinner.

(First sent on Juli 23rd)
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDave Chinner <david@fromorbit.com>
Signed-off-by: default avatarNiv Sardi <xaiki@sgi.com>
parent 5e1be0fb
...@@ -91,6 +91,8 @@ typedef struct xfs_agf { ...@@ -91,6 +91,8 @@ typedef struct xfs_agf {
#define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp)) #define XFS_AGF_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGF_DADDR(mp))
#define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)XFS_BUF_PTR(bp)) #define XFS_BUF_TO_AGF(bp) ((xfs_agf_t *)XFS_BUF_PTR(bp))
extern int xfs_read_agf(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, int flags, struct xfs_buf **bpp);
/* /*
* Size of the unlinked inode hash table in the agi. * Size of the unlinked inode hash table in the agi.
......
...@@ -2233,44 +2233,41 @@ xfs_alloc_put_freelist( ...@@ -2233,44 +2233,41 @@ xfs_alloc_put_freelist(
* Read in the allocation group header (free/alloc section). * Read in the allocation group header (free/alloc section).
*/ */
int /* error */ int /* error */
xfs_alloc_read_agf( xfs_read_agf(
xfs_mount_t *mp, /* mount point structure */ struct xfs_mount *mp, /* mount point structure */
xfs_trans_t *tp, /* transaction pointer */ struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */ xfs_agnumber_t agno, /* allocation group number */
int flags, /* XFS_ALLOC_FLAG_... */ int flags, /* XFS_BUF_ */
xfs_buf_t **bpp) /* buffer for the ag freelist header */ struct xfs_buf **bpp) /* buffer for the ag freelist header */
{ {
xfs_agf_t *agf; /* ag freelist header */ struct xfs_agf *agf; /* ag freelist header */
int agf_ok; /* set if agf is consistent */ int agf_ok; /* set if agf is consistent */
xfs_buf_t *bp; /* return value */
xfs_perag_t *pag; /* per allocation group data */
int error; int error;
ASSERT(agno != NULLAGNUMBER); ASSERT(agno != NULLAGNUMBER);
error = xfs_trans_read_buf( error = xfs_trans_read_buf(
mp, tp, mp->m_ddev_targp, mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)), XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
XFS_FSS_TO_BB(mp, 1), XFS_FSS_TO_BB(mp, 1), flags, bpp);
(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0U,
&bp);
if (error) if (error)
return error; return error;
ASSERT(!bp || !XFS_BUF_GETERROR(bp)); if (!*bpp)
if (!bp) {
*bpp = NULL;
return 0; return 0;
}
ASSERT(!XFS_BUF_GETERROR(*bpp));
agf = XFS_BUF_TO_AGF(*bpp);
/* /*
* Validate the magic number of the agf block. * Validate the magic number of the agf block.
*/ */
agf = XFS_BUF_TO_AGF(bp);
agf_ok = agf_ok =
be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC && be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC &&
XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) && XFS_AGF_GOOD_VERSION(be32_to_cpu(agf->agf_versionnum)) &&
be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) && be32_to_cpu(agf->agf_freeblks) <= be32_to_cpu(agf->agf_length) &&
be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) && be32_to_cpu(agf->agf_flfirst) < XFS_AGFL_SIZE(mp) &&
be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) && be32_to_cpu(agf->agf_fllast) < XFS_AGFL_SIZE(mp) &&
be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp); be32_to_cpu(agf->agf_flcount) <= XFS_AGFL_SIZE(mp) &&
be32_to_cpu(agf->agf_seqno) == agno;
if (xfs_sb_version_haslazysbcount(&mp->m_sb)) if (xfs_sb_version_haslazysbcount(&mp->m_sb))
agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <= agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <=
be32_to_cpu(agf->agf_length); be32_to_cpu(agf->agf_length);
...@@ -2278,9 +2275,41 @@ xfs_alloc_read_agf( ...@@ -2278,9 +2275,41 @@ xfs_alloc_read_agf(
XFS_RANDOM_ALLOC_READ_AGF))) { XFS_RANDOM_ALLOC_READ_AGF))) {
XFS_CORRUPTION_ERROR("xfs_alloc_read_agf", XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
XFS_ERRLEVEL_LOW, mp, agf); XFS_ERRLEVEL_LOW, mp, agf);
xfs_trans_brelse(tp, bp); xfs_trans_brelse(tp, *bpp);
return XFS_ERROR(EFSCORRUPTED); return XFS_ERROR(EFSCORRUPTED);
} }
XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGF, XFS_AGF_REF);
return 0;
}
/*
* Read in the allocation group header (free/alloc section).
*/
int /* error */
xfs_alloc_read_agf(
struct xfs_mount *mp, /* mount point structure */
struct xfs_trans *tp, /* transaction pointer */
xfs_agnumber_t agno, /* allocation group number */
int flags, /* XFS_ALLOC_FLAG_... */
struct xfs_buf **bpp) /* buffer for the ag freelist header */
{
struct xfs_agf *agf; /* ag freelist header */
struct xfs_perag *pag; /* per allocation group data */
int error;
ASSERT(agno != NULLAGNUMBER);
error = xfs_read_agf(mp, tp, agno,
(flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0,
bpp);
if (error)
return error;
if (!*bpp)
return 0;
ASSERT(!XFS_BUF_GETERROR(*bpp));
agf = XFS_BUF_TO_AGF(*bpp);
pag = &mp->m_perag[agno]; pag = &mp->m_perag[agno];
if (!pag->pagf_init) { if (!pag->pagf_init) {
pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks); pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
...@@ -2308,8 +2337,6 @@ xfs_alloc_read_agf( ...@@ -2308,8 +2337,6 @@ xfs_alloc_read_agf(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi])); be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
} }
#endif #endif
XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGF, XFS_AGF_REF);
*bpp = bp;
return 0; return 0;
} }
......
...@@ -3970,7 +3970,6 @@ xlog_recover_check_summary( ...@@ -3970,7 +3970,6 @@ xlog_recover_check_summary(
xfs_agf_t *agfp; xfs_agf_t *agfp;
xfs_buf_t *agfbp; xfs_buf_t *agfbp;
xfs_buf_t *agibp; xfs_buf_t *agibp;
xfs_daddr_t agfdaddr;
xfs_buf_t *sbbp; xfs_buf_t *sbbp;
#ifdef XFS_LOUD_RECOVERY #ifdef XFS_LOUD_RECOVERY
xfs_sb_t *sbp; xfs_sb_t *sbp;
...@@ -3987,21 +3986,18 @@ xlog_recover_check_summary( ...@@ -3987,21 +3986,18 @@ xlog_recover_check_summary(
itotal = 0LL; itotal = 0LL;
ifree = 0LL; ifree = 0LL;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) { for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)); error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr, if (error) {
XFS_FSS_TO_BB(mp, 1), 0); xfs_fs_cmn_err(CE_ALERT, mp,
if (XFS_BUF_ISERROR(agfbp)) { "xlog_recover_check_summary(agf)"
xfs_ioerror_alert("xlog_recover_check_summary(agf)", "agf read failed agno %d error %d",
mp, agfbp, agfdaddr); agno, error);
} else {
agfp = XFS_BUF_TO_AGF(agfbp);
freeblks += be32_to_cpu(agfp->agf_freeblks) +
be32_to_cpu(agfp->agf_flcount);
xfs_buf_relse(agfbp);
} }
agfp = XFS_BUF_TO_AGF(agfbp);
ASSERT(XFS_AGF_MAGIC == be32_to_cpu(agfp->agf_magicnum));
ASSERT(XFS_AGF_GOOD_VERSION(be32_to_cpu(agfp->agf_versionnum)));
ASSERT(be32_to_cpu(agfp->agf_seqno) == agno);
freeblks += be32_to_cpu(agfp->agf_freeblks) +
be32_to_cpu(agfp->agf_flcount);
xfs_buf_relse(agfbp);
error = xfs_read_agi(mp, NULL, agno, &agibp); error = xfs_read_agi(mp, NULL, agno, &agibp);
if (!error) { if (!error) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment