From: Brian Foster <bfoster@redhat.com>
To: xfs@oss.sgi.com
Subject: [PATCH 21/28] repair: process sparse inode records correctly
Date: Tue, 2 Jun 2015 14:41:54 -0400 [thread overview]
Message-ID: <1433270521-62026-22-git-send-email-bfoster@redhat.com> (raw)
In-Reply-To: <1433270521-62026-1-git-send-email-bfoster@redhat.com>
The inode processing phases of xfs_repair (3 and 4) validate the actual
inodes referred to by the previously scanned inode btrees. The physical
inodes are read from disk and internally validated in various ways. The
inode block state is also verified and corrected if necessary.
Sparse inodes are not physically allocated and the associated blocks may
be allocated to any other area of the fs (file data, internal use,
etc.). Attempts to validate these blocks as inode blocks produce noisy
corruption errors.
Update the inode processing mechanism to handle sparse inode records
correctly. Since sparse inodes do not exist, the general approach here
is to simply skip validation of sparse inodes. Update
process_inode_chunk() to skip reads of sparse clusters and set the buf
pointer of associated clusters to NULL. Update the rest of the function
to only verify non-NULL cluster buffers. Also, skip the inode block
state checks for blocks in sparse inode clusters.
Signed-off-by: Brian Foster <bfoster@redhat.com>
---
repair/dino_chunks.c | 162 +++++++++++++++++++++++++++++++--------------------
1 file changed, 98 insertions(+), 64 deletions(-)
diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c
index a1ce9e7..9b7d017 100644
--- a/repair/dino_chunks.c
+++ b/repair/dino_chunks.c
@@ -615,6 +615,7 @@ process_inode_chunk(
* set up first irec
*/
ino_rec = first_irec;
+ irec_offset = 0;
bplist = malloc(cluster_count * sizeof(xfs_buf_t *));
if (bplist == NULL)
@@ -622,6 +623,18 @@ process_inode_chunk(
cluster_count * sizeof(xfs_buf_t *));
for (bp_index = 0; bp_index < cluster_count; bp_index++) {
+ /*
+ * Skip the cluster buffer if the first inode is sparse. The
+ * remaining inodes in the cluster share the same state as
+ * sparse inodes occur at cluster granularity.
+ */
+ if (is_inode_sparse(ino_rec, irec_offset)) {
+ pftrace("skip sparse inode, startnum 0x%x idx %d",
+ ino_rec->ino_startnum, irec_offset);
+ bplist[bp_index] = NULL;
+ goto next_readbuf;
+ }
+
pftrace("about to read off %llu in AG %d",
XFS_AGB_TO_DADDR(mp, agno, agbno), agno);
@@ -641,12 +654,16 @@ process_inode_chunk(
free(bplist);
return(1);
}
- agbno += blks_per_cluster;
- bplist[bp_index]->b_ops = &xfs_inode_buf_ops;
pftrace("readbuf %p (%llu, %d) in AG %d", bplist[bp_index],
(long long)XFS_BUF_ADDR(bplist[bp_index]),
XFS_BUF_COUNT(bplist[bp_index]), agno);
+
+ bplist[bp_index]->b_ops = &xfs_inode_buf_ops;
+
+next_readbuf:
+ irec_offset += mp->m_sb.sb_inopblock * blks_per_cluster;
+ agbno += blks_per_cluster;
}
agbno = XFS_AGINO_TO_AGBNO(mp, first_irec->ino_startnum);
@@ -665,24 +682,27 @@ process_inode_chunk(
*/
if (ino_discovery) {
for (;;) {
- /*
- * make inode pointer
- */
- dino = xfs_make_iptr(mp, bplist[bp_index], cluster_offset);
agino = irec_offset + ino_rec->ino_startnum;
- /*
- * we always think that the root and realtime
- * inodes are verified even though we may have
- * to reset them later to keep from losing the
- * chunk that they're in
- */
- if (verify_dinode(mp, dino, agno, agino) == 0 ||
- (agno == 0 &&
- (mp->m_sb.sb_rootino == agino ||
- mp->m_sb.sb_rsumino == agino ||
- mp->m_sb.sb_rbmino == agino)))
- status++;
+ /* no buffers for sparse clusters */
+ if (bplist[bp_index]) {
+ /* make inode pointer */
+ dino = xfs_make_iptr(mp, bplist[bp_index],
+ cluster_offset);
+
+ /*
+ * we always think that the root and realtime
+ * inodes are verified even though we may have
+ * to reset them later to keep from losing the
+ * chunk that they're in
+ */
+ if (verify_dinode(mp, dino, agno, agino) == 0 ||
+ (agno == 0 &&
+ (mp->m_sb.sb_rootino == agino ||
+ mp->m_sb.sb_rsumino == agino ||
+ mp->m_sb.sb_rbmino == agino)))
+ status++;
+ }
irec_offset++;
icnt++;
@@ -716,7 +736,8 @@ process_inode_chunk(
if (!status) {
*bogus = 1;
for (bp_index = 0; bp_index < cluster_count; bp_index++)
- libxfs_putbuf(bplist[bp_index]);
+ if (bplist[bp_index])
+ libxfs_putbuf(bplist[bp_index]);
free(bplist);
return(0);
}
@@ -736,35 +757,41 @@ process_inode_chunk(
/*
* mark block as an inode block in the incore bitmap
*/
- pthread_mutex_lock(&ag_locks[agno].lock);
- state = get_bmap(agno, agbno);
- switch (state) {
- case XR_E_INO: /* already marked */
- break;
- case XR_E_UNKNOWN:
- case XR_E_FREE:
- case XR_E_FREE1:
- set_bmap(agno, agbno, XR_E_INO);
- break;
- case XR_E_BAD_STATE:
- do_error(_("bad state in block map %d\n"), state);
- break;
- default:
- set_bmap(agno, agbno, XR_E_MULT);
- do_warn(_("inode block %" PRIu64 " multiply claimed, state was %d\n"),
- XFS_AGB_TO_FSB(mp, agno, agbno), state);
- break;
+ if (!is_inode_sparse(ino_rec, irec_offset)) {
+ pthread_mutex_lock(&ag_locks[agno].lock);
+ state = get_bmap(agno, agbno);
+ switch (state) {
+ case XR_E_INO: /* already marked */
+ break;
+ case XR_E_UNKNOWN:
+ case XR_E_FREE:
+ case XR_E_FREE1:
+ set_bmap(agno, agbno, XR_E_INO);
+ break;
+ case XR_E_BAD_STATE:
+ do_error(_("bad state in block map %d\n"), state);
+ break;
+ default:
+ set_bmap(agno, agbno, XR_E_MULT);
+ do_warn(
+ _("inode block %" PRIu64 " multiply claimed, state was %d\n"),
+ XFS_AGB_TO_FSB(mp, agno, agbno), state);
+ break;
+ }
+ pthread_mutex_unlock(&ag_locks[agno].lock);
}
- pthread_mutex_unlock(&ag_locks[agno].lock);
for (;;) {
- /*
- * make inode pointer
- */
- dino = xfs_make_iptr(mp, bplist[bp_index], cluster_offset);
agino = irec_offset + ino_rec->ino_startnum;
ino = XFS_AGINO_TO_INO(mp, agno, agino);
+ if (is_inode_sparse(ino_rec, irec_offset))
+ goto process_next;
+
+ /* make inode pointer */
+ dino = xfs_make_iptr(mp, bplist[bp_index], cluster_offset);
+
+
is_used = 3;
ino_dirty = 0;
parent = 0;
@@ -895,6 +922,7 @@ process_inode_chunk(
}
}
+process_next:
irec_offset++;
ibuf_offset++;
icnt++;
@@ -906,6 +934,9 @@ process_inode_chunk(
* done! - finished up irec and block simultaneously
*/
for (bp_index = 0; bp_index < cluster_count; bp_index++) {
+ if (!bplist[bp_index])
+ continue;
+
pftrace("put/writebuf %p (%llu) in AG %d",
bplist[bp_index], (long long)
XFS_BUF_ADDR(bplist[bp_index]), agno);
@@ -925,29 +956,32 @@ process_inode_chunk(
ibuf_offset = 0;
agbno++;
- pthread_mutex_lock(&ag_locks[agno].lock);
- state = get_bmap(agno, agbno);
- switch (state) {
- case XR_E_INO: /* already marked */
- break;
- case XR_E_UNKNOWN:
- case XR_E_FREE:
- case XR_E_FREE1:
- set_bmap(agno, agbno, XR_E_INO);
- break;
- case XR_E_BAD_STATE:
- do_error(_("bad state in block map %d\n"),
- state);
- break;
- default:
- set_bmap(agno, agbno, XR_E_MULT);
- do_warn(
- _("inode block %" PRIu64 " multiply claimed, state was %d\n"),
- XFS_AGB_TO_FSB(mp, agno, agbno), state);
- break;
+ if (!is_inode_sparse(ino_rec, irec_offset)) {
+ pthread_mutex_lock(&ag_locks[agno].lock);
+ state = get_bmap(agno, agbno);
+ switch (state) {
+ case XR_E_INO: /* already marked */
+ break;
+ case XR_E_UNKNOWN:
+ case XR_E_FREE:
+ case XR_E_FREE1:
+ set_bmap(agno, agbno, XR_E_INO);
+ break;
+ case XR_E_BAD_STATE:
+ do_error(
+ _("bad state in block map %d\n"),
+ state);
+ break;
+ default:
+ set_bmap(agno, agbno, XR_E_MULT);
+ do_warn(
+ _("inode block %" PRIu64 " multiply claimed, state was %d\n"),
+ XFS_AGB_TO_FSB(mp, agno, agbno),
+ state);
+ break;
+ }
+ pthread_mutex_unlock(&ag_locks[agno].lock);
}
- pthread_mutex_unlock(&ag_locks[agno].lock);
-
} else if (irec_offset == XFS_INODES_PER_CHUNK) {
/*
* get new irec (multiple chunks per block fs)
--
1.9.3
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2015-06-02 18:42 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-06-02 18:41 [PATCH 00/28] xfsprogs: sparse inode chunks Brian Foster
2015-06-02 18:41 ` [PATCH 01/28] xfs: create individual inode alloc. helper Brian Foster
2015-06-02 18:41 ` [PATCH 02/28] xfs: update free inode record logic to support sparse inode records Brian Foster
2015-06-02 18:41 ` [PATCH 03/28] xfs: support min/max agbno args in block allocator Brian Foster
2015-06-02 18:41 ` [PATCH 04/28] xfs: add sparse inode chunk alignment superblock field Brian Foster
2015-06-02 18:41 ` [PATCH 05/28] xfs: use sparse chunk alignment for min. inode allocation requirement Brian Foster
2015-06-02 18:41 ` [PATCH 06/28] xfs: sparse inode chunks feature helpers and mount requirements Brian Foster
2015-06-02 18:41 ` [PATCH 07/28] xfs: add fs geometry bit for sparse inode chunks Brian Foster
2015-06-02 18:41 ` [PATCH 08/28] xfs: introduce inode record hole mask " Brian Foster
2015-06-02 18:41 ` [PATCH 09/28] xfs: pass inode count through ordered icreate log item Brian Foster
2015-06-02 18:41 ` [PATCH 10/28] xfs: enable sparse inode chunks for v5 superblocks Brian Foster
2015-06-02 18:41 ` [PATCH 11/28] mkfs: sparse inode chunk support Brian Foster
2015-06-02 18:41 ` [PATCH 12/28] db: support sparse inode chunk inobt record and sb fields Brian Foster
2015-06-02 18:41 ` [PATCH 13/28] db: show sparse inodes feature state in version command output Brian Foster
2015-06-02 18:41 ` [PATCH 14/28] growfs: display sparse inode status from xfs_info Brian Foster
2015-06-02 18:41 ` [PATCH 15/28] repair: handle sparse format inobt record freecount correctly Brian Foster
2015-06-05 0:53 ` Dave Chinner
2015-06-02 18:41 ` [PATCH 16/28] repair: remove duplicate field from aghdr_cnts Brian Foster
2015-06-02 18:41 ` [PATCH 17/28] repair: use ir_count for filesystems with sparse inode support Brian Foster
2015-06-02 18:41 ` [PATCH 18/28] repair: scan and track sparse inode chunks correctly Brian Foster
2015-06-05 0:56 ` Dave Chinner
2015-06-02 18:41 ` [PATCH 19/28] repair: scan sparse finobt records correctly Brian Foster
2015-06-05 1:03 ` Dave Chinner
2015-06-05 16:52 ` Brian Foster
2015-06-02 18:41 ` [PATCH 20/28] repair: validate ir_count field for sparse format records Brian Foster
2015-06-02 18:41 ` Brian Foster [this message]
2015-06-05 1:12 ` [PATCH 21/28] repair: process sparse inode records correctly Dave Chinner
2015-06-02 18:41 ` [PATCH 22/28] repair: factor out sparse inodes from finobt reconstruction Brian Foster
2015-06-02 18:41 ` [PATCH 23/28] repair: do not account sparse inodes in phase 5 cursor init Brian Foster
2015-06-02 18:41 ` [PATCH 24/28] repair: reconstruct sparse inode records correctly on disk Brian Foster
2015-06-02 18:41 ` [PATCH 25/28] repair: do not prefetch holes in sparse inode chunks Brian Foster
2015-06-02 18:41 ` [PATCH 26/28] repair: handle sparse inode alignment Brian Foster
2015-06-02 18:42 ` [PATCH 27/28] metadump: reorder inode record sanity checks and inode buffer read Brian Foster
2015-06-02 18:42 ` [PATCH 28/28] metadump: support sparse inode records Brian Foster
2015-06-16 0:33 ` [PATCH 00/28] xfsprogs: sparse inode chunks Dave Chinner
2015-06-16 0:39 ` Dave Chinner
2015-06-16 10:55 ` Brian Foster
2015-06-16 20:26 ` Dave Chinner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1433270521-62026-22-git-send-email-bfoster@redhat.com \
--to=bfoster@redhat.com \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox