aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2008-11-27 22:23:37 -0500
committerNiv Sardi <xaiki@sgi.com>2008-11-30 19:37:15 -0500
commit5e1be0fb1a3950597aeda448698e85b0595a2e92 (patch)
treee9cb423d6f253b689a9e0cfb4a1d429de37959cd /fs
parent26c5295135d10fc90cbf160adfda392d91f58279 (diff)
[XFS] factor out xfs_read_agi helper
Add a helper to read the AGI 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>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/xfs_ag.h3
-rw-r--r--fs/xfs/xfs_ialloc.c101
-rw-r--r--fs/xfs/xfs_inode.c57
-rw-r--r--fs/xfs/xfs_log_recover.c72
4 files changed, 98 insertions, 135 deletions
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h
index 2bfd86329141..f4a315390c61 100644
--- a/fs/xfs/xfs_ag.h
+++ b/fs/xfs/xfs_ag.h
@@ -142,6 +142,9 @@ typedef struct xfs_agi {
142#define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp)) 142#define XFS_AGI_BLOCK(mp) XFS_HDR_BLOCK(mp, XFS_AGI_DADDR(mp))
143#define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)XFS_BUF_PTR(bp)) 143#define XFS_BUF_TO_AGI(bp) ((xfs_agi_t *)XFS_BUF_PTR(bp))
144 144
145extern int xfs_read_agi(struct xfs_mount *mp, struct xfs_trans *tp,
146 xfs_agnumber_t agno, struct xfs_buf **bpp);
147
145/* 148/*
146 * The third a.g. block contains the a.g. freelist, an array 149 * The third a.g. block contains the a.g. freelist, an array
147 * of block pointers to blocks owned by the allocation btree code. 150 * of block pointers to blocks owned by the allocation btree code.
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index c8a56c529642..efb65fea203c 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -1462,70 +1462,95 @@ xfs_ialloc_log_agi(
1462 xfs_trans_log_buf(tp, bp, first, last); 1462 xfs_trans_log_buf(tp, bp, first, last);
1463} 1463}
1464 1464
1465#ifdef DEBUG
1466STATIC void
1467xfs_check_agi_unlinked(
1468 struct xfs_agi *agi)
1469{
1470 int i;
1471
1472 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
1473 ASSERT(agi->agi_unlinked[i]);
1474}
1475#else
1476#define xfs_check_agi_unlinked(agi)
1477#endif
1478
1465/* 1479/*
1466 * Read in the allocation group header (inode allocation section) 1480 * Read in the allocation group header (inode allocation section)
1467 */ 1481 */
1468int 1482int
1469xfs_ialloc_read_agi( 1483xfs_read_agi(
1470 xfs_mount_t *mp, /* file system mount structure */ 1484 struct xfs_mount *mp, /* file system mount structure */
1471 xfs_trans_t *tp, /* transaction pointer */ 1485 struct xfs_trans *tp, /* transaction pointer */
1472 xfs_agnumber_t agno, /* allocation group number */ 1486 xfs_agnumber_t agno, /* allocation group number */
1473 xfs_buf_t **bpp) /* allocation group hdr buf */ 1487 struct xfs_buf **bpp) /* allocation group hdr buf */
1474{ 1488{
1475 xfs_agi_t *agi; /* allocation group header */ 1489 struct xfs_agi *agi; /* allocation group header */
1476 int agi_ok; /* agi is consistent */ 1490 int agi_ok; /* agi is consistent */
1477 xfs_buf_t *bp; /* allocation group hdr buf */ 1491 int error;
1478 xfs_perag_t *pag; /* per allocation group data */
1479 int error;
1480 1492
1481 ASSERT(agno != NULLAGNUMBER); 1493 ASSERT(agno != NULLAGNUMBER);
1482 error = xfs_trans_read_buf( 1494
1483 mp, tp, mp->m_ddev_targp, 1495 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
1484 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), 1496 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
1485 XFS_FSS_TO_BB(mp, 1), 0, &bp); 1497 XFS_FSS_TO_BB(mp, 1), 0, bpp);
1486 if (error) 1498 if (error)
1487 return error; 1499 return error;
1488 ASSERT(bp && !XFS_BUF_GETERROR(bp)); 1500
1501 ASSERT(*bpp && !XFS_BUF_GETERROR(*bpp));
1502 agi = XFS_BUF_TO_AGI(*bpp);
1489 1503
1490 /* 1504 /*
1491 * Validate the magic number of the agi block. 1505 * Validate the magic number of the agi block.
1492 */ 1506 */
1493 agi = XFS_BUF_TO_AGI(bp); 1507 agi_ok = be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
1494 agi_ok = 1508 XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum)) &&
1495 be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC && 1509 be32_to_cpu(agi->agi_seqno) == agno;
1496 XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
1497 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI, 1510 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IALLOC_READ_AGI,
1498 XFS_RANDOM_IALLOC_READ_AGI))) { 1511 XFS_RANDOM_IALLOC_READ_AGI))) {
1499 XFS_CORRUPTION_ERROR("xfs_ialloc_read_agi", XFS_ERRLEVEL_LOW, 1512 XFS_CORRUPTION_ERROR("xfs_read_agi", XFS_ERRLEVEL_LOW,
1500 mp, agi); 1513 mp, agi);
1501 xfs_trans_brelse(tp, bp); 1514 xfs_trans_brelse(tp, *bpp);
1502 return XFS_ERROR(EFSCORRUPTED); 1515 return XFS_ERROR(EFSCORRUPTED);
1503 } 1516 }
1517
1518 XFS_BUF_SET_VTYPE_REF(*bpp, B_FS_AGI, XFS_AGI_REF);
1519
1520 xfs_check_agi_unlinked(agi);
1521 return 0;
1522}
1523
1524int
1525xfs_ialloc_read_agi(
1526 struct xfs_mount *mp, /* file system mount structure */
1527 struct xfs_trans *tp, /* transaction pointer */
1528 xfs_agnumber_t agno, /* allocation group number */
1529 struct xfs_buf **bpp) /* allocation group hdr buf */
1530{
1531 struct xfs_agi *agi; /* allocation group header */
1532 struct xfs_perag *pag; /* per allocation group data */
1533 int error;
1534
1535 error = xfs_read_agi(mp, tp, agno, bpp);
1536 if (error)
1537 return error;
1538
1539 agi = XFS_BUF_TO_AGI(*bpp);
1504 pag = &mp->m_perag[agno]; 1540 pag = &mp->m_perag[agno];
1541
1505 if (!pag->pagi_init) { 1542 if (!pag->pagi_init) {
1506 pag->pagi_freecount = be32_to_cpu(agi->agi_freecount); 1543 pag->pagi_freecount = be32_to_cpu(agi->agi_freecount);
1507 pag->pagi_count = be32_to_cpu(agi->agi_count); 1544 pag->pagi_count = be32_to_cpu(agi->agi_count);
1508 pag->pagi_init = 1; 1545 pag->pagi_init = 1;
1509 } else {
1510 /*
1511 * It's possible for these to be out of sync if
1512 * we are in the middle of a forced shutdown.
1513 */
1514 ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
1515 XFS_FORCED_SHUTDOWN(mp));
1516 }
1517
1518#ifdef DEBUG
1519 {
1520 int i;
1521
1522 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++)
1523 ASSERT(agi->agi_unlinked[i]);
1524 } 1546 }
1525#endif
1526 1547
1527 XFS_BUF_SET_VTYPE_REF(bp, B_FS_AGI, XFS_AGI_REF); 1548 /*
1528 *bpp = bp; 1549 * It's possible for these to be out of sync if
1550 * we are in the middle of a forced shutdown.
1551 */
1552 ASSERT(pag->pagi_freecount == be32_to_cpu(agi->agi_freecount) ||
1553 XFS_FORCED_SHUTDOWN(mp));
1529 return 0; 1554 return 0;
1530} 1555}
1531 1556
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index b97710047062..46b0526acd4e 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -1843,13 +1843,10 @@ xfs_iunlink(
1843 xfs_dinode_t *dip; 1843 xfs_dinode_t *dip;
1844 xfs_buf_t *agibp; 1844 xfs_buf_t *agibp;
1845 xfs_buf_t *ibp; 1845 xfs_buf_t *ibp;
1846 xfs_agnumber_t agno;
1847 xfs_daddr_t agdaddr;
1848 xfs_agino_t agino; 1846 xfs_agino_t agino;
1849 short bucket_index; 1847 short bucket_index;
1850 int offset; 1848 int offset;
1851 int error; 1849 int error;
1852 int agi_ok;
1853 1850
1854 ASSERT(ip->i_d.di_nlink == 0); 1851 ASSERT(ip->i_d.di_nlink == 0);
1855 ASSERT(ip->i_d.di_mode != 0); 1852 ASSERT(ip->i_d.di_mode != 0);
@@ -1857,31 +1854,15 @@ xfs_iunlink(
1857 1854
1858 mp = tp->t_mountp; 1855 mp = tp->t_mountp;
1859 1856
1860 agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
1861 agdaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
1862
1863 /* 1857 /*
1864 * Get the agi buffer first. It ensures lock ordering 1858 * Get the agi buffer first. It ensures lock ordering
1865 * on the list. 1859 * on the list.
1866 */ 1860 */
1867 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr, 1861 error = xfs_read_agi(mp, tp, XFS_INO_TO_AGNO(mp, ip->i_ino), &agibp);
1868 XFS_FSS_TO_BB(mp, 1), 0, &agibp);
1869 if (error) 1862 if (error)
1870 return error; 1863 return error;
1871
1872 /*
1873 * Validate the magic number of the agi block.
1874 */
1875 agi = XFS_BUF_TO_AGI(agibp); 1864 agi = XFS_BUF_TO_AGI(agibp);
1876 agi_ok = 1865
1877 be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
1878 XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
1879 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK,
1880 XFS_RANDOM_IUNLINK))) {
1881 XFS_CORRUPTION_ERROR("xfs_iunlink", XFS_ERRLEVEL_LOW, mp, agi);
1882 xfs_trans_brelse(tp, agibp);
1883 return XFS_ERROR(EFSCORRUPTED);
1884 }
1885 /* 1866 /*
1886 * Get the index into the agi hash table for the 1867 * Get the index into the agi hash table for the
1887 * list this inode will go on. 1868 * list this inode will go on.
@@ -1941,7 +1922,6 @@ xfs_iunlink_remove(
1941 xfs_buf_t *agibp; 1922 xfs_buf_t *agibp;
1942 xfs_buf_t *ibp; 1923 xfs_buf_t *ibp;
1943 xfs_agnumber_t agno; 1924 xfs_agnumber_t agno;
1944 xfs_daddr_t agdaddr;
1945 xfs_agino_t agino; 1925 xfs_agino_t agino;
1946 xfs_agino_t next_agino; 1926 xfs_agino_t next_agino;
1947 xfs_buf_t *last_ibp; 1927 xfs_buf_t *last_ibp;
@@ -1949,45 +1929,20 @@ xfs_iunlink_remove(
1949 short bucket_index; 1929 short bucket_index;
1950 int offset, last_offset = 0; 1930 int offset, last_offset = 0;
1951 int error; 1931 int error;
1952 int agi_ok;
1953 1932
1954 /*
1955 * First pull the on-disk inode from the AGI unlinked list.
1956 */
1957 mp = tp->t_mountp; 1933 mp = tp->t_mountp;
1958
1959 agno = XFS_INO_TO_AGNO(mp, ip->i_ino); 1934 agno = XFS_INO_TO_AGNO(mp, ip->i_ino);
1960 agdaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp));
1961 1935
1962 /* 1936 /*
1963 * Get the agi buffer first. It ensures lock ordering 1937 * Get the agi buffer first. It ensures lock ordering
1964 * on the list. 1938 * on the list.
1965 */ 1939 */
1966 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, agdaddr, 1940 error = xfs_read_agi(mp, tp, agno, &agibp);
1967 XFS_FSS_TO_BB(mp, 1), 0, &agibp); 1941 if (error)
1968 if (error) {
1969 cmn_err(CE_WARN,
1970 "xfs_iunlink_remove: xfs_trans_read_buf() returned an error %d on %s. Returning error.",
1971 error, mp->m_fsname);
1972 return error; 1942 return error;
1973 } 1943
1974 /*
1975 * Validate the magic number of the agi block.
1976 */
1977 agi = XFS_BUF_TO_AGI(agibp); 1944 agi = XFS_BUF_TO_AGI(agibp);
1978 agi_ok = 1945
1979 be32_to_cpu(agi->agi_magicnum) == XFS_AGI_MAGIC &&
1980 XFS_AGI_GOOD_VERSION(be32_to_cpu(agi->agi_versionnum));
1981 if (unlikely(XFS_TEST_ERROR(!agi_ok, mp, XFS_ERRTAG_IUNLINK_REMOVE,
1982 XFS_RANDOM_IUNLINK_REMOVE))) {
1983 XFS_CORRUPTION_ERROR("xfs_iunlink_remove", XFS_ERRLEVEL_LOW,
1984 mp, agi);
1985 xfs_trans_brelse(tp, agibp);
1986 cmn_err(CE_WARN,
1987 "xfs_iunlink_remove: XFS_TEST_ERROR() returned an error on %s. Returning EFSCORRUPTED.",
1988 mp->m_fsname);
1989 return XFS_ERROR(EFSCORRUPTED);
1990 }
1991 /* 1946 /*
1992 * Get the index into the agi hash table for the 1947 * Get the index into the agi hash table for the
1993 * list this inode will go on. 1948 * list this inode will go on.
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index b411d4947318..b552676ca5c4 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3117,19 +3117,16 @@ xlog_recover_clear_agi_bucket(
3117 int error; 3117 int error;
3118 3118
3119 tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET); 3119 tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET);
3120 error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0); 3120 error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp),
3121 if (!error) 3121 0, 0, 0);
3122 error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp,
3123 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)),
3124 XFS_FSS_TO_BB(mp, 1), 0, &agibp);
3125 if (error) 3122 if (error)
3126 goto out_abort; 3123 goto out_abort;
3127 3124
3128 error = EINVAL; 3125 error = xfs_read_agi(mp, tp, agno, &agibp);
3129 agi = XFS_BUF_TO_AGI(agibp); 3126 if (error)
3130 if (be32_to_cpu(agi->agi_magicnum) != XFS_AGI_MAGIC)
3131 goto out_abort; 3127 goto out_abort;
3132 3128
3129 agi = XFS_BUF_TO_AGI(agibp);
3133 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO); 3130 agi->agi_unlinked[bucket] = cpu_to_be32(NULLAGINO);
3134 offset = offsetof(xfs_agi_t, agi_unlinked) + 3131 offset = offsetof(xfs_agi_t, agi_unlinked) +
3135 (sizeof(xfs_agino_t) * bucket); 3132 (sizeof(xfs_agino_t) * bucket);
@@ -3190,16 +3187,17 @@ xlog_recover_process_iunlinks(
3190 /* 3187 /*
3191 * Find the agi for this ag. 3188 * Find the agi for this ag.
3192 */ 3189 */
3193 agibp = xfs_buf_read(mp->m_ddev_targp, 3190 error = xfs_read_agi(mp, NULL, agno, &agibp);
3194 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), 3191 if (error) {
3195 XFS_FSS_TO_BB(mp, 1), 0); 3192 /*
3196 if (XFS_BUF_ISERROR(agibp)) { 3193 * AGI is b0rked. Don't process it.
3197 xfs_ioerror_alert("xlog_recover_process_iunlinks(#1)", 3194 *
3198 log->l_mp, agibp, 3195 * We should probably mark the filesystem as corrupt
3199 XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp))); 3196 * after we've recovered all the ag's we can....
3197 */
3198 continue;
3200 } 3199 }
3201 agi = XFS_BUF_TO_AGI(agibp); 3200 agi = XFS_BUF_TO_AGI(agibp);
3202 ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agi->agi_magicnum));
3203 3201
3204 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { 3202 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
3205 3203
@@ -3278,22 +3276,12 @@ xlog_recover_process_iunlinks(
3278 3276
3279 /* 3277 /*
3280 * Reacquire the agibuffer and continue around 3278 * Reacquire the agibuffer and continue around
3281 * the loop. 3279 * the loop. This should never fail as we know
3280 * the buffer was good earlier on.
3282 */ 3281 */
3283 agibp = xfs_buf_read(mp->m_ddev_targp, 3282 error = xfs_read_agi(mp, NULL, agno, &agibp);
3284 XFS_AG_DADDR(mp, agno, 3283 ASSERT(error == 0);
3285 XFS_AGI_DADDR(mp)),
3286 XFS_FSS_TO_BB(mp, 1), 0);
3287 if (XFS_BUF_ISERROR(agibp)) {
3288 xfs_ioerror_alert(
3289 "xlog_recover_process_iunlinks(#2)",
3290 log->l_mp, agibp,
3291 XFS_AG_DADDR(mp, agno,
3292 XFS_AGI_DADDR(mp)));
3293 }
3294 agi = XFS_BUF_TO_AGI(agibp); 3284 agi = XFS_BUF_TO_AGI(agibp);
3295 ASSERT(XFS_AGI_MAGIC == be32_to_cpu(
3296 agi->agi_magicnum));
3297 } 3285 }
3298 } 3286 }
3299 3287
@@ -3980,11 +3968,9 @@ xlog_recover_check_summary(
3980{ 3968{
3981 xfs_mount_t *mp; 3969 xfs_mount_t *mp;
3982 xfs_agf_t *agfp; 3970 xfs_agf_t *agfp;
3983 xfs_agi_t *agip;
3984 xfs_buf_t *agfbp; 3971 xfs_buf_t *agfbp;
3985 xfs_buf_t *agibp; 3972 xfs_buf_t *agibp;
3986 xfs_daddr_t agfdaddr; 3973 xfs_daddr_t agfdaddr;
3987 xfs_daddr_t agidaddr;
3988 xfs_buf_t *sbbp; 3974 xfs_buf_t *sbbp;
3989#ifdef XFS_LOUD_RECOVERY 3975#ifdef XFS_LOUD_RECOVERY
3990 xfs_sb_t *sbp; 3976 xfs_sb_t *sbp;
@@ -3993,6 +3979,7 @@ xlog_recover_check_summary(
3993 __uint64_t freeblks; 3979 __uint64_t freeblks;
3994 __uint64_t itotal; 3980 __uint64_t itotal;
3995 __uint64_t ifree; 3981 __uint64_t ifree;
3982 int error;
3996 3983
3997 mp = log->l_mp; 3984 mp = log->l_mp;
3998 3985
@@ -4016,21 +4003,14 @@ xlog_recover_check_summary(
4016 be32_to_cpu(agfp->agf_flcount); 4003 be32_to_cpu(agfp->agf_flcount);
4017 xfs_buf_relse(agfbp); 4004 xfs_buf_relse(agfbp);
4018 4005
4019 agidaddr = XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)); 4006 error = xfs_read_agi(mp, NULL, agno, &agibp);
4020 agibp = xfs_buf_read(mp->m_ddev_targp, agidaddr, 4007 if (!error) {
4021 XFS_FSS_TO_BB(mp, 1), 0); 4008 struct xfs_agi *agi = XFS_BUF_TO_AGI(agibp);
4022 if (XFS_BUF_ISERROR(agibp)) {
4023 xfs_ioerror_alert("xlog_recover_check_summary(agi)",
4024 mp, agibp, agidaddr);
4025 }
4026 agip = XFS_BUF_TO_AGI(agibp);
4027 ASSERT(XFS_AGI_MAGIC == be32_to_cpu(agip->agi_magicnum));
4028 ASSERT(XFS_AGI_GOOD_VERSION(be32_to_cpu(agip->agi_versionnum)));
4029 ASSERT(be32_to_cpu(agip->agi_seqno) == agno);
4030 4009
4031 itotal += be32_to_cpu(agip->agi_count); 4010 itotal += be32_to_cpu(agi->agi_count);
4032 ifree += be32_to_cpu(agip->agi_freecount); 4011 ifree += be32_to_cpu(agi->agi_freecount);
4033 xfs_buf_relse(agibp); 4012 xfs_buf_relse(agibp);
4013 }
4034 } 4014 }
4035 4015
4036 sbbp = xfs_getsb(mp, 0); 4016 sbbp = xfs_getsb(mp, 0);