aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dgc@sgi.com>2013-04-03 01:11:15 -0400
committerBen Myers <bpm@sgi.com>2013-04-21 15:57:43 -0400
commit983d09ffe396ed5d5339a1b9ff994dd0b0f2069f (patch)
tree42779460b8910c6537bd4d53fa99f23eb5fde830
parent77c95bba013089fa868217283eb6d98a05913e53 (diff)
xfs: add CRC checks to the AGI
Same set of changes made to the AGF need to be made to the AGI. This patch has a similar history to the AGF, hence a similar sign-off chain. Signed-off-by: Dave Chinner <dgc@sgi.com> Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <dgc@redhat.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
-rw-r--r--fs/xfs/xfs_ag.h8
-rw-r--r--fs/xfs/xfs_buf_item.h4
-rw-r--r--fs/xfs/xfs_fsops.c3
-rw-r--r--fs/xfs/xfs_ialloc.c57
-rw-r--r--fs/xfs/xfs_log_recover.c8
5 files changed, 65 insertions, 15 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 272ef097e2be..317aa86d96ea 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -152,6 +152,7 @@ typedef struct xfs_agi {
152 __be32 agi_root; /* root of inode btree */ 152 __be32 agi_root; /* root of inode btree */
153 __be32 agi_level; /* levels in inode btree */ 153 __be32 agi_level; /* levels in inode btree */
154 __be32 agi_freecount; /* number of free inodes */ 154 __be32 agi_freecount; /* number of free inodes */
155
155 __be32 agi_newino; /* new inode just allocated */ 156 __be32 agi_newino; /* new inode just allocated */
156 __be32 agi_dirino; /* last directory inode chunk */ 157 __be32 agi_dirino; /* last directory inode chunk */
157 /* 158 /*
@@ -159,6 +160,13 @@ typedef struct xfs_agi {
159 * still being referenced. 160 * still being referenced.
160 */ 161 */
161 __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS]; 162 __be32 agi_unlinked[XFS_AGI_UNLINKED_BUCKETS];
163
164 uuid_t agi_uuid; /* uuid of filesystem */
165 __be32 agi_crc; /* crc of agi sector */
166 __be32 agi_pad32;
167 __be64 agi_lsn; /* last write sequence */
168
169 /* structure must be padded to 64 bit alignment */
162} xfs_agi_t; 170} xfs_agi_t;
163 171
164#define XFS_AGI_MAGICNUM 0x00000001 172#define XFS_AGI_MAGICNUM 0x00000001
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 067d5f0fc233..c25660691e08 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -47,6 +47,7 @@ extern kmem_zone_t *xfs_buf_item_zone;
47#define XFS_BLF_BTREE_BUF (1<<5) 47#define XFS_BLF_BTREE_BUF (1<<5)
48#define XFS_BLF_AGF_BUF (1<<6) 48#define XFS_BLF_AGF_BUF (1<<6)
49#define XFS_BLF_AGFL_BUF (1<<7) 49#define XFS_BLF_AGFL_BUF (1<<7)
50#define XFS_BLF_AGI_BUF (1<<8)
50 51
51#define XFS_BLF_TYPE_MASK \ 52#define XFS_BLF_TYPE_MASK \
52 (XFS_BLF_UDQUOT_BUF | \ 53 (XFS_BLF_UDQUOT_BUF | \
@@ -54,7 +55,8 @@ extern kmem_zone_t *xfs_buf_item_zone;
54 XFS_BLF_GDQUOT_BUF | \ 55 XFS_BLF_GDQUOT_BUF | \
55 XFS_BLF_BTREE_BUF | \ 56 XFS_BLF_BTREE_BUF | \
56 XFS_BLF_AGF_BUF | \ 57 XFS_BLF_AGF_BUF | \
57 XFS_BLF_AGFL_BUF) 58 XFS_BLF_AGFL_BUF | \
59 XFS_BLF_AGI_BUF)
58 60
59#define XFS_BLF_CHUNK 128 61#define XFS_BLF_CHUNK 128
60#define XFS_BLF_SHIFT 7 62#define XFS_BLF_SHIFT 7
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index a693a54799e5..87595b211da1 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -304,8 +304,11 @@ xfs_growfs_data_private(
304 agi->agi_freecount = 0; 304 agi->agi_freecount = 0;
305 agi->agi_newino = cpu_to_be32(NULLAGINO); 305 agi->agi_newino = cpu_to_be32(NULLAGINO);
306 agi->agi_dirino = cpu_to_be32(NULLAGINO); 306 agi->agi_dirino = cpu_to_be32(NULLAGINO);
307 if (xfs_sb_version_hascrc(&mp->m_sb))
308 uuid_copy(&agi->agi_uuid, &mp->m_sb.sb_uuid);
307 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) 309 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++)
308 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); 310 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
311
309 error = xfs_bwrite(bp); 312 error = xfs_bwrite(bp);
310 xfs_buf_relse(bp); 313 xfs_buf_relse(bp);
311 if (error) 314 if (error)
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index ba626613bf49..6d0a4954aa8c 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -36,6 +36,8 @@
36#include "xfs_rtalloc.h" 36#include "xfs_rtalloc.h"
37#include "xfs_error.h" 37#include "xfs_error.h"
38#include "xfs_bmap.h" 38#include "xfs_bmap.h"
39#include "xfs_cksum.h"
40#include "xfs_buf_item.h"
39 41
40 42
41/* 43/*
@@ -1453,6 +1455,7 @@ xfs_ialloc_log_agi(
1453 /* 1455 /*
1454 * Log the allocation group inode header buffer. 1456 * Log the allocation group inode header buffer.
1455 */ 1457 */
1458 xfs_trans_buf_set_type(tp, bp, XFS_BLF_AGI_BUF);
1456 xfs_trans_log_buf(tp, bp, first, last); 1459 xfs_trans_log_buf(tp, bp, first, last);
1457} 1460}
1458 1461
@@ -1470,19 +1473,23 @@ xfs_check_agi_unlinked(
1470#define xfs_check_agi_unlinked(agi) 1473#define xfs_check_agi_unlinked(agi)
1471#endif 1474#endif
1472 1475
1473static void 1476static bool
1474xfs_agi_verify( 1477xfs_agi_verify(
1475 struct xfs_buf *bp) 1478 struct xfs_buf *bp)
1476{ 1479{
1477 struct xfs_mount *mp = bp->b_target->bt_mount; 1480 struct xfs_mount *mp = bp->b_target->bt_mount;
1478 struct xfs_agi *agi = XFS_BUF_TO_AGI(bp); 1481 struct xfs_agi *agi = XFS_BUF_TO_AGI(bp);
1479 int agi_ok;
1480 1482
1483 if (xfs_sb_version_hascrc(&mp->m_sb) &&
1484 !uuid_equal(&agi->agi_uuid, &mp->m_sb.sb_uuid))
1485 return false;
1481 /* 1486 /*
1482 * Validate the magic number of the agi block. 1487 * Validate the magic number of the agi block.
1483 */ 1488 */
1484 agi_ok = agi->agi_magicnum == cpu_to_be32(XFS_AGI_MAGIC) && 1489 if (agi->agi_magicnum != cpu_to_be32(XFS_AGI_MAGIC))
1485 XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)); 1490 return false;
1491 if (!XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)))
1492 return false;
1486 1493
1487 /* 1494 /*
1488 * during growfs operations, the perag is not fully initialised, 1495 * during growfs operations, the perag is not fully initialised,
@@ -1490,30 +1497,52 @@ xfs_agi_verify(
1490 * use it by using uncached buffers that don't have the perag attached 1497 * use it by using uncached buffers that don't have the perag attached
1491 * so we can detect and avoid this problem. 1498 * so we can detect and avoid this problem.
1492 */ 1499 */
1493 if (bp->b_pag) 1500 if (bp->b_pag && be32_to_cpu(agi->agi_seqno) != bp->b_pag->pag_agno)
1494 agi_ok = agi_ok && be32_to_cpu(agi->agi_seqno) == 1501 return false;
1495 bp->b_pag->pag_agno;
1496 1502
1497 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
1498 XFS_RANDOM_IALLOC_READ_AGI))) {
1499 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, agi);
1500 xfs_buf_ioerror(bp, EFSCORRUPTED);
1501 }
1502 xfs_check_agi_unlinked(agi); 1503 xfs_check_agi_unlinked(agi);
1504 return true;
1503} 1505}
1504 1506
1505static void 1507static void
1506xfs_agi_read_verify( 1508xfs_agi_read_verify(
1507 struct xfs_buf *bp) 1509 struct xfs_buf *bp)
1508{ 1510{
1509 xfs_agi_verify(bp); 1511 struct xfs_mount *mp = bp->b_target->bt_mount;
1512 int agi_ok = 1;
1513
1514 if (xfs_sb_version_hascrc(&mp->m_sb))
1515 agi_ok = xfs_verify_cksum(bp->b_addr, BBTOB(bp->b_length),
1516 offsetof(struct xfs_agi, agi_crc));
1517 agi_ok = agi_ok && xfs_agi_verify(bp);
1518
1519 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
1520 XFS_RANDOM_IALLOC_READ_AGI))) {
1521 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
1522 xfs_buf_ioerror(bp, EFSCORRUPTED);
1523 }
1510} 1524}
1511 1525
1512static void 1526static void
1513xfs_agi_write_verify( 1527xfs_agi_write_verify(
1514 struct xfs_buf *bp) 1528 struct xfs_buf *bp)
1515{ 1529{
1516 xfs_agi_verify(bp); 1530 struct xfs_mount *mp = bp->b_target->bt_mount;
1531 struct xfs_buf_log_item *bip = bp->b_fspriv;
1532
1533 if (!xfs_agi_verify(bp)) {
1534 XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp, bp->b_addr);
1535 xfs_buf_ioerror(bp, EFSCORRUPTED);
1536 return;
1537 }
1538
1539 if (!xfs_sb_version_hascrc(&mp->m_sb))
1540 return;
1541
1542 if (bip)
1543 XFS_BUF_TO_AGI(bp)->agi_lsn = cpu_to_be64(bip->bli_item.li_lsn);
1544 xfs_update_cksum(bp->b_addr, BBTOB(bp->b_length),
1545 offsetof(struct xfs_agi, agi_crc));
1517} 1546}
1518 1547
1519const struct xfs_buf_ops xfs_agi_buf_ops = { 1548const struct xfs_buf_ops xfs_agi_buf_ops = {
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index da2a19e0554e..6778a7943db4 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -1971,6 +1971,14 @@ xlog_recover_do_reg_buffer(
1971 } 1971 }
1972 bp->b_ops = &xfs_agfl_buf_ops; 1972 bp->b_ops = &xfs_agfl_buf_ops;
1973 break; 1973 break;
1974 case XFS_BLF_AGI_BUF:
1975 if (*(__be32 *)bp->b_addr != cpu_to_be32(XFS_AGI_MAGIC)) {
1976 xfs_warn(mp, "Bad AGI block magic!");
1977 ASSERT(0);
1978 break;
1979 }
1980 bp->b_ops = &xfs_agi_buf_ops;
1981 break;
1974 default: 1982 default:
1975 break; 1983 break;
1976 } 1984 }