summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrom: Christoph Hellwig <hch@lst.de>2008-11-28 14:23:38 +1100
committerNiv Sardi <xaiki@sgi.com>2008-12-01 11:37:20 +1100
commit4805621a37d9b2b16641b5c68597651419e9e252 (patch)
treea3c63689100a8c7ca2eb72efe4036f7863c34e12
parent5e1be0fb1a3950597aeda448698e85b0595a2e92 (diff)
[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: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <david@fromorbit.com> Signed-off-by: Niv Sardi <xaiki@sgi.com>
-rw-r--r--fs/xfs/xfs_ag.h2
-rw-r--r--fs/xfs/xfs_alloc.c69
-rw-r--r--fs/xfs/xfs_log_recover.c26
3 files changed, 61 insertions, 36 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index f4a315390c6..f2e21817a22 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -91,6 +91,8 @@ typedef struct xfs_agf {
#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))
+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.
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index c47ce907572..028e44e58ea 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -2233,44 +2233,41 @@ xfs_alloc_put_freelist(
* Read in the allocation group header (free/alloc section).
*/
int /* error */
-xfs_alloc_read_agf(
- xfs_mount_t *mp, /* mount point structure */
- xfs_trans_t *tp, /* transaction pointer */
- xfs_agnumber_t agno, /* allocation group number */
- int flags, /* XFS_ALLOC_FLAG_... */
- xfs_buf_t **bpp) /* buffer for the ag freelist header */
+xfs_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_BUF_ */
+ 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 */
- xfs_buf_t *bp; /* return value */
- xfs_perag_t *pag; /* per allocation group data */
int error;
ASSERT(agno != NULLAGNUMBER);
error = xfs_trans_read_buf(
mp, tp, mp->m_ddev_targp,
XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp)),
- XFS_FSS_TO_BB(mp, 1),
- (flags & XFS_ALLOC_FLAG_TRYLOCK) ? XFS_BUF_TRYLOCK : 0U,
- &bp);
+ XFS_FSS_TO_BB(mp, 1), flags, bpp);
if (error)
return error;
- ASSERT(!bp || !XFS_BUF_GETERROR(bp));
- if (!bp) {
- *bpp = NULL;
+ if (!*bpp)
return 0;
- }
+
+ ASSERT(!XFS_BUF_GETERROR(*bpp));
+ agf = XFS_BUF_TO_AGF(*bpp);
+
/*
* Validate the magic number of the agf block.
*/
- agf = XFS_BUF_TO_AGF(bp);
agf_ok =
be32_to_cpu(agf->agf_magicnum) == XFS_AGF_MAGIC &&
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_flfirst) < 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))
agf_ok = agf_ok && be32_to_cpu(agf->agf_btreeblks) <=
be32_to_cpu(agf->agf_length);
@@ -2278,9 +2275,41 @@ xfs_alloc_read_agf(
XFS_RANDOM_ALLOC_READ_AGF))) {
XFS_CORRUPTION_ERROR("xfs_alloc_read_agf",
XFS_ERRLEVEL_LOW, mp, agf);
- xfs_trans_brelse(tp, bp);
+ xfs_trans_brelse(tp, *bpp);
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];
if (!pag->pagf_init) {
pag->pagf_freeblks = be32_to_cpu(agf->agf_freeblks);
@@ -2308,8 +2337,6 @@ xfs_alloc_read_agf(
be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNTi]));
}
#endif
- XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGF, XFS_AGF_REF);
- *bpp = bp;
return 0;
}
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index b552676ca5c..d94987915d5 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3970,7 +3970,6 @@ xlog_recover_check_summary(
xfs_agf_t *agfp;
xfs_buf_t *agfbp;
xfs_buf_t *agibp;
- xfs_daddr_t agfdaddr;
xfs_buf_t *sbbp;
#ifdef XFS_LOUD_RECOVERY
xfs_sb_t *sbp;
@@ -3987,21 +3986,18 @@ xlog_recover_check_summary(
itotal = 0LL;
ifree = 0LL;
for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
- agfdaddr = XFS_AG_DADDR(mp, agno, XFS_AGF_DADDR(mp));
- agfbp = xfs_buf_read(mp->m_ddev_targp, agfdaddr,
- XFS_FSS_TO_BB(mp, 1), 0);
- if (XFS_BUF_ISERROR(agfbp)) {
- xfs_ioerror_alert("xlog_recover_check_summary(agf)",
- mp, agfbp, agfdaddr);
+ error = xfs_read_agf(mp, NULL, agno, 0, &agfbp);
+ if (error) {
+ xfs_fs_cmn_err(CE_ALERT, mp,
+ "xlog_recover_check_summary(agf)"
+ "agf read failed agno %d error %d",
+ 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);
if (!error) {