Skip to content

Commit 04755d2

Browse files
dgchinnerdchinner
authored andcommitted
xfs: refactor xlog_recover_process_iunlinks()
For upcoming changes to the way inode unlinked list processing is done, the structure of recovery needs to change slightly. We also really need to untangle the messy error handling in list recovery so that actions like emptying the bucket on inode lookup failure are associated with the bucket list walk failing, not failing to look up the inode. Refactor the recovery code now to keep the re-organisation seperate to the algorithm changes. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org>
1 parent 4fcc94d commit 04755d2

1 file changed

Lines changed: 71 additions & 66 deletions

File tree

fs/xfs/xfs_log_recover.c

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2667,41 +2667,35 @@ xlog_recover_clear_agi_bucket(
26672667
return;
26682668
}
26692669

2670-
STATIC xfs_agino_t
2671-
xlog_recover_process_one_iunlink(
2672-
struct xfs_perag *pag,
2673-
xfs_agino_t agino,
2674-
int bucket)
2670+
static int
2671+
xlog_recover_iunlink_bucket(
2672+
struct xfs_perag *pag,
2673+
struct xfs_agi *agi,
2674+
int bucket)
26752675
{
2676-
struct xfs_inode *ip;
2677-
xfs_ino_t ino;
2678-
int error;
2676+
struct xfs_mount *mp = pag->pag_mount;
2677+
struct xfs_inode *ip;
2678+
xfs_agino_t agino;
26792679

2680-
ino = XFS_AGINO_TO_INO(pag->pag_mount, pag->pag_agno, agino);
2681-
error = xfs_iget(pag->pag_mount, NULL, ino, 0, 0, &ip);
2682-
if (error)
2683-
goto fail;
2680+
agino = be32_to_cpu(agi->agi_unlinked[bucket]);
2681+
while (agino != NULLAGINO) {
2682+
int error;
26842683

2685-
xfs_iflags_clear(ip, XFS_IRECOVERY);
2686-
ASSERT(VFS_I(ip)->i_nlink == 0);
2687-
ASSERT(VFS_I(ip)->i_mode != 0);
2684+
error = xfs_iget(mp, NULL,
2685+
XFS_AGINO_TO_INO(mp, pag->pag_agno, agino),
2686+
0, 0, &ip);
2687+
if (error)
2688+
return error;;
26882689

2689-
agino = ip->i_next_unlinked;
2690-
xfs_irele(ip);
2691-
return agino;
2690+
ASSERT(VFS_I(ip)->i_nlink == 0);
2691+
ASSERT(VFS_I(ip)->i_mode != 0);
2692+
xfs_iflags_clear(ip, XFS_IRECOVERY);
2693+
agino = ip->i_next_unlinked;
26922694

2693-
fail:
2694-
/*
2695-
* We can't read in the inode this bucket points to, or this inode
2696-
* is messed up. Just ditch this bucket of inodes. We will lose
2697-
* some inodes and space, but at least we won't hang.
2698-
*
2699-
* Call xlog_recover_clear_agi_bucket() to perform a transaction to
2700-
* clear the inode pointer in the bucket.
2701-
*/
2702-
xfs_inodegc_flush(pag->pag_mount);
2703-
xlog_recover_clear_agi_bucket(pag, bucket);
2704-
return NULLAGINO;
2695+
xfs_irele(ip);
2696+
cond_resched();
2697+
}
2698+
return 0;
27052699
}
27062700

27072701
/*
@@ -2727,59 +2721,70 @@ xlog_recover_process_one_iunlink(
27272721
* scheduled on this CPU to ensure other scheduled work can run without undue
27282722
* latency.
27292723
*/
2730-
STATIC void
2731-
xlog_recover_process_iunlinks(
2732-
struct xlog *log)
2724+
static void
2725+
xlog_recover_iunlink_ag(
2726+
struct xfs_perag *pag)
27332727
{
2734-
struct xfs_mount *mp = log->l_mp;
2735-
struct xfs_perag *pag;
2736-
xfs_agnumber_t agno;
27372728
struct xfs_agi *agi;
27382729
struct xfs_buf *agibp;
2739-
xfs_agino_t agino;
27402730
int bucket;
27412731
int error;
27422732

2743-
for_each_perag(mp, agno, pag) {
2744-
error = xfs_read_agi(pag, NULL, &agibp);
2733+
error = xfs_read_agi(pag, NULL, &agibp);
2734+
if (error) {
2735+
/*
2736+
* AGI is b0rked. Don't process it.
2737+
*
2738+
* We should probably mark the filesystem as corrupt after we've
2739+
* recovered all the ag's we can....
2740+
*/
2741+
return;
2742+
}
2743+
2744+
/*
2745+
* Unlock the buffer so that it can be acquired in the normal course of
2746+
* the transaction to truncate and free each inode. Because we are not
2747+
* racing with anyone else here for the AGI buffer, we don't even need
2748+
* to hold it locked to read the initial unlinked bucket entries out of
2749+
* the buffer. We keep buffer reference though, so that it stays pinned
2750+
* in memory while we need the buffer.
2751+
*/
2752+
agi = agibp->b_addr;
2753+
xfs_buf_unlock(agibp);
2754+
2755+
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
2756+
error = xlog_recover_iunlink_bucket(pag, agi, bucket);
27452757
if (error) {
27462758
/*
2747-
* AGI is b0rked. Don't process it.
2748-
*
2749-
* We should probably mark the filesystem as corrupt
2750-
* after we've recovered all the ag's we can....
2759+
* Bucket is unrecoverable, so only a repair scan can
2760+
* free the remaining unlinked inodes. Just empty the
2761+
* bucket and remaining inodes on it unreferenced and
2762+
* unfreeable.
27512763
*/
2752-
continue;
2753-
}
2754-
/*
2755-
* Unlock the buffer so that it can be acquired in the normal
2756-
* course of the transaction to truncate and free each inode.
2757-
* Because we are not racing with anyone else here for the AGI
2758-
* buffer, we don't even need to hold it locked to read the
2759-
* initial unlinked bucket entries out of the buffer. We keep
2760-
* buffer reference though, so that it stays pinned in memory
2761-
* while we need the buffer.
2762-
*/
2763-
agi = agibp->b_addr;
2764-
xfs_buf_unlock(agibp);
2765-
2766-
for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
2767-
agino = be32_to_cpu(agi->agi_unlinked[bucket]);
2768-
while (agino != NULLAGINO) {
2769-
agino = xlog_recover_process_one_iunlink(pag,
2770-
agino, bucket);
2771-
cond_resched();
2772-
}
2764+
xfs_inodegc_flush(pag->pag_mount);
2765+
xlog_recover_clear_agi_bucket(pag, bucket);
27732766
}
2774-
xfs_buf_rele(agibp);
27752767
}
27762768

2769+
xfs_buf_rele(agibp);
2770+
}
2771+
2772+
static void
2773+
xlog_recover_process_iunlinks(
2774+
struct xlog *log)
2775+
{
2776+
struct xfs_perag *pag;
2777+
xfs_agnumber_t agno;
2778+
2779+
for_each_perag(log->l_mp, agno, pag)
2780+
xlog_recover_iunlink_ag(pag);
2781+
27772782
/*
27782783
* Flush the pending unlinked inodes to ensure that the inactivations
27792784
* are fully completed on disk and the incore inodes can be reclaimed
27802785
* before we signal that recovery is complete.
27812786
*/
2782-
xfs_inodegc_flush(mp);
2787+
xfs_inodegc_flush(log->l_mp);
27832788
}
27842789

27852790
STATIC void

0 commit comments

Comments
 (0)