xfs
[Top] [All Lists]

[PATCH 25/28] repair: do not prefetch holes in sparse inode chunks

To: xfs@xxxxxxxxxxx
Subject: [PATCH 25/28] repair: do not prefetch holes in sparse inode chunks
From: Brian Foster <bfoster@xxxxxxxxxx>
Date: Tue, 2 Jun 2015 14:41:58 -0400
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1433270521-62026-1-git-send-email-bfoster@xxxxxxxxxx>
References: <1433270521-62026-1-git-send-email-bfoster@xxxxxxxxxx>
The repair prefetch mechanism reads all inode chunks in advance of
repair processing to improve performance. Inode buffer verification and
processing can occur within the prefetch mechanism such as when
directories are being processed. Prefetch currently assumes fully
populated inode chunks which leads to corruption errors attempting to
verify inode buffers that do not contain inodes.

Update prefetch to check the previously scanned sparse inode bits and
skip inode buffer reads of clusters that are sparse. We check sparse
state per-inode cluster because the cluster size is the min. allowable
inode chunk hole granularity.

Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
---
 repair/prefetch.c | 17 ++++++++++++++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/repair/prefetch.c b/repair/prefetch.c
index d6246ce..1577971 100644
--- a/repair/prefetch.c
+++ b/repair/prefetch.c
@@ -679,6 +679,7 @@ pf_queuing_worker(
        xfs_agblock_t           bno;
        int                     i;
        int                     err;
+       uint64_t                sparse;
 
        blks_per_cluster = mp->m_inode_cluster_size >> mp->m_sb.sb_blocklog;
        if (blks_per_cluster == 0)
@@ -736,17 +737,27 @@ pf_queuing_worker(
 
                num_inos = 0;
                bno = XFS_AGINO_TO_AGBNO(mp, cur_irec->ino_startnum);
+               sparse = cur_irec->ir_sparse;
 
                do {
                        struct xfs_buf_map      map;
 
                        map.bm_bn = XFS_AGB_TO_DADDR(mp, args->agno, bno);
                        map.bm_len = XFS_FSB_TO_BB(mp, blks_per_cluster);
-                       pf_queue_io(args, &map, 1,
-                                   (cur_irec->ino_isa_dir != 0) ?  B_DIR_INODE
-                                                                : B_INODE);
+
+                       /*
+                        * Queue I/O for each non-sparse cluster. We can check
+                        * sparse state in cluster sized chunks as cluster size
+                        * is the min. granularity of sparse irec regions.
+                        */
+                       if ((sparse & ((1 << inodes_per_cluster) - 1)) == 0)
+                               pf_queue_io(args, &map, 1,
+                                           (cur_irec->ino_isa_dir != 0) ?
+                                            B_DIR_INODE : B_INODE);
+
                        bno += blks_per_cluster;
                        num_inos += inodes_per_cluster;
+                       sparse >>= inodes_per_cluster;
                } while (num_inos < mp->m_ialloc_inos);
        }
 
-- 
1.9.3

<Prev in Thread] Current Thread [Next in Thread>