xfs: check AGI unlinked inode buckets
Look for corruptions in the AGI unlinked bucket chains. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
2651923d8d
commit
10d587ecb7
@ -15,6 +15,7 @@
|
||||
#include "xfs_ialloc.h"
|
||||
#include "xfs_rmap.h"
|
||||
#include "xfs_ag.h"
|
||||
#include "xfs_inode.h"
|
||||
#include "scrub/scrub.h"
|
||||
#include "scrub/common.h"
|
||||
|
||||
@ -865,6 +866,43 @@ xchk_agi_xref(
|
||||
/* scrub teardown will take care of sc->sa for us */
|
||||
}
|
||||
|
||||
/*
|
||||
* Check the unlinked buckets for links to bad inodes. We hold the AGI, so
|
||||
* there cannot be any threads updating unlinked list pointers in this AG.
|
||||
*/
|
||||
STATIC void
|
||||
xchk_iunlink(
|
||||
struct xfs_scrub *sc,
|
||||
struct xfs_agi *agi)
|
||||
{
|
||||
unsigned int i;
|
||||
struct xfs_inode *ip;
|
||||
|
||||
for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
|
||||
xfs_agino_t agino = be32_to_cpu(agi->agi_unlinked[i]);
|
||||
|
||||
while (agino != NULLAGINO) {
|
||||
if (agino % XFS_AGI_UNLINKED_BUCKETS != i) {
|
||||
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
|
||||
return;
|
||||
}
|
||||
|
||||
ip = xfs_iunlink_lookup(sc->sa.pag, agino);
|
||||
if (!ip) {
|
||||
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xfs_inode_on_unlinked_list(ip)) {
|
||||
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
|
||||
return;
|
||||
}
|
||||
|
||||
agino = ip->i_next_unlinked;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Scrub the AGI. */
|
||||
int
|
||||
xchk_agi(
|
||||
@ -949,6 +987,8 @@ xchk_agi(
|
||||
if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount))
|
||||
xchk_block_set_corrupt(sc, sc->sa.agi_bp);
|
||||
|
||||
xchk_iunlink(sc, agi);
|
||||
|
||||
xchk_agi_xref(sc);
|
||||
out:
|
||||
return error;
|
||||
|
@ -1985,7 +1985,7 @@ out:
|
||||
* only unlinked, referenced inodes can be on the unlinked inode list. If we
|
||||
* don't find the inode in cache, then let the caller handle the situation.
|
||||
*/
|
||||
static struct xfs_inode *
|
||||
struct xfs_inode *
|
||||
xfs_iunlink_lookup(
|
||||
struct xfs_perag *pag,
|
||||
xfs_agino_t agino)
|
||||
|
@ -619,6 +619,7 @@ bool xfs_inode_needs_inactive(struct xfs_inode *ip);
|
||||
int xfs_iunlink(struct xfs_trans *tp, struct xfs_inode *ip);
|
||||
int xfs_iunlink_remove(struct xfs_trans *tp, struct xfs_perag *pag,
|
||||
struct xfs_inode *ip);
|
||||
struct xfs_inode *xfs_iunlink_lookup(struct xfs_perag *pag, xfs_agino_t agino);
|
||||
|
||||
void xfs_end_io(struct work_struct *work);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user