Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 371059
b: refs/heads/master
c: 983d09f
h: refs/heads/master
i:
  371057: 8fd64bb
  371055: e7df8b3
v: v3
  • Loading branch information
Dave Chinner authored and Ben Myers committed Apr 21, 2013
1 parent bb990ba commit 516df44
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 77c95bba013089fa868217283eb6d98a05913e53
refs/heads/master: 983d09ffe396ed5d5339a1b9ff994dd0b0f2069f
8 changes: 8 additions & 0 deletions trunk/fs/xfs/xfs_ag.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,13 +152,21 @@ typedef struct xfs_agi {
__be32 agi_root; /* root of inode btree */
__be32 agi_level; /* levels in inode btree */
__be32 agi_freecount; /* number of free inodes */

__be32 agi_newino; /* new inode just allocated */
__be32 agi_dirino; /* last directory inode chunk */
/*
* Hash table of inodes which have been unlinked but are
* still being referenced.
*/
__be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];

uuid_t agi_uuid; /* uuid of filesystem */
__be32 agi_crc; /* crc of agi sector */
__be32 agi_pad32;
__be64 agi_lsn; /* last write sequence */

/* structure must be padded to 64 bit alignment */
} xfs_agi_t;

#define XFS_AGI_MAGICNUM 0x00000001
Expand Down
4 changes: 3 additions & 1 deletion trunk/fs/xfs/xfs_buf_item.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,16 @@ extern kmem_zone_t *xfs_buf_item_zone;
#define XFS_BLF_BTREE_BUF (1<<5)
#define XFS_BLF_AGF_BUF (1<<6)
#define XFS_BLF_AGFL_BUF (1<<7)
#define XFS_BLF_AGI_BUF (1<<8)

#define XFS_BLF_TYPE_MASK \
(XFS_BLF_UDQUOT_BUF | \
XFS_BLF_PDQUOT_BUF | \
XFS_BLF_GDQUOT_BUF | \
XFS_BLF_BTREE_BUF | \
XFS_BLF_AGF_BUF | \
XFS_BLF_AGFL_BUF)
XFS_BLF_AGFL_BUF | \
XFS_BLF_AGI_BUF)

#define XFS_BLF_CHUNK 128
#define XFS_BLF_SHIFT 7
Expand Down
3 changes: 3 additions & 0 deletions trunk/fs/xfs/xfs_fsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,8 +304,11 @@ xfs_growfs_data_private(
agi->agi_freecount = 0;
agi->agi_newino = cpu_to_be32(NULLAGINO);
agi->agi_dirino = cpu_to_be32(NULLAGINO);
if (xfs_sb_version_hascrc(&mp->m_sb))
uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid);
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);

error = xfs_bwrite(bp);
xfs_buf_relse(bp);
if (error)
Expand Down
57 changes: 43 additions & 14 deletions trunk/fs/xfs/xfs_ialloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include "xfs_rtalloc.h"
#include "xfs_error.h"
#include "xfs_bmap.h"
#include "xfs_cksum.h"
#include "xfs_buf_item.h"


/*
Expand Down Expand Up @@ -1453,6 +1455,7 @@ xfs_ialloc_log_agi(
/*
* Log the allocation group inode header buffer.
*/
xfs_trans_buf_set_type(tp, bp, XFS_BLF_AGI_BUF);
xfs_trans_log_buf(tp, bp, first, last);
}

Expand All @@ -1470,50 +1473,76 @@ xfs_check_agi_unlinked(
#define xfs_check_agi_unlinked(agi)
#endif

static void
static bool
xfs_agi_verify(
struct xfs_buf *bp)
{
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_agi *agi = XFS_BUF_TO_AGI(bp);
int agi_ok;

if (xfs_sb_version_hascrc(&mp->m_sb) &&
!uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid))
return false;
/*
* Validate the magic number of the agi block.
*/
agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) &&
XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
if (agi->agi_magicnum != cpu_to_be32(XFS_AGI_MAGIC))
return false;
if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))
return false;

/*
* during growfs operations, the perag is not fully initialised,
* so we can't use it for any useful checking. growfs ensures we can't
* use it by using uncached buffers that don't have the perag attached
* so we can detect and avoid this problem.
*/
if (bp->b_pag)
agi_ok = agi_ok && be32_to_cpu(agi->agi_seqno) ==
bp->b_pag->pag_agno;
if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno)
return false;

if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
XFS_RANDOM_IALLOC_READ_AGI))) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agi);
xfs_buf_ioerror(bp, EFSCORRUPTED);
}
xfs_check_agi_unlinked(agi);
return true;
}

static void
xfs_agi_read_verify(
struct xfs_buf *bp)
{
xfs_agi_verify(bp);
struct xfs_mount *mp = bp->b_target->bt_mount;
int agi_ok = 1;

if (xfs_sb_version_hascrc(&mp->m_sb))
agi_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
offsetof(struct xfs_agi, agi_crc));
agi_ok = agi_ok && xfs_agi_verify(bp);

if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
XFS_RANDOM_IALLOC_READ_AGI))) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED);
}
}

static void
xfs_agi_write_verify(
struct xfs_buf *bp)
{
xfs_agi_verify(bp);
struct xfs_mount *mp = bp->b_target->bt_mount;
struct xfs_buf_log_item *bip = bp->b_fspriv;

if (!xfs_agi_verify(bp)) {
XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
xfs_buf_ioerror(bp, EFSCORRUPTED);
return;
}

if (!xfs_sb_version_hascrc(&mp->m_sb))
return;

if (bip)
XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn);
xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
offsetof(struct xfs_agi, agi_crc));
}

const struct xfs_buf_ops xfs_agi_buf_ops = {
Expand Down
8 changes: 8 additions & 0 deletions trunk/fs/xfs/xfs_log_recover.c
Original file line number Diff line number Diff line change
Expand Up @@ -1971,6 +1971,14 @@ xlog_recover_do_reg_buffer(
}
bp->b_ops = &xfs_agfl_buf_ops;
break;
case XFS_BLF_AGI_BUF:
if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) {
xfs_warn(mp, "Bad AGI block magic!");
ASSERT(0);
break;
}
bp->b_ops = &xfs_agi_buf_ops;
break;
default:
break;
}
Expand Down

0 comments on commit 516df44

Please sign in to comment.