From: Bob Peterson <rpeterso@redhat.com>
To: cluster-devel.redhat.com
Subject: [Cluster-devel] [gfs2-utils PATCH 24/47] fsck.gfs2: Rework the "undo" functions
Date: Thu, 16 May 2013 11:02:07 -0400 (EDT) [thread overview]
Message-ID: <439495569.10483675.1368716527959.JavaMail.root@redhat.com> (raw)
In-Reply-To: <1368712925.2680.33.camel@menhir>
----- Original Message -----
| Yes, but the undo side of things worries me... it is very easy to get
| tied in knots doing that. The question is what is "damage it can't
| recover from"? this is a bit vague and doesn't really explain what is
| going on here.
|
| I don't yet understand why we'd need to run through each inodes metadata
| tree more than once in this case,
|
| Steve.
Hi,
One thing to bear in mind is that the fsck blockmap is supposed to
represent the correct state of all blocks in the on-disk bitmap.
The job of pass1 is to build the blockmap, which starts out entirely "free".
As the metadata is traversed, the blocks are filled in with the appropriate
type.
The job of pass5 is to synchronize the on-disk bitmap to the blockmap.
So we must ensure that the blockmap is accurate at ALL times after pass1.
One of the primary checks pass1 does is to make sure that a block is "free"
in the blockmap before changing its designation, otherwise it's a duplicate
block reference that must be resolved in pass1b.
Here's an example: Suppose you have a file with di_height==2, two levels of
indirection. Suppose the dinode is layed out something like this:
dinode indirect data
------ -------- ------
0x1000 - dinode
---> 0x1001
---> 0x1002
---> 0x1003
...
---> 0x1010
---> 0x1011
---> 0x1012
---> 0x1013
...
---> 0x1020
---> 0x1021
---> 0x1022
---> 0x1023
---> 0x7777777777777777777
---> 0x1025
...
---> 0x1030
Now let's further suppose that this file was supposed to be deleted,
and many of its blocks were in fact reused by a newer, valid dinode,
but somehow, the bitmap was corrupted into saying this dinode is still
alive (a dinode, not free or unlinked).
For the sake of argument, say that second dinode appears later in the
bitmap, so pass1 gets to corrupt dinode 0x1000 before it gets to the
valid dinode that correctly references the blocks.
As it traverses the metadata tree, it builds an array of lists, one for
each height. Each item in the linked list corresponds to a metadata block.
So pass1 traverses the array, marks down in its blockmap that block 0x1000 is
dinode, blocks 0x1001, 0x1011, and 0x1021 are metadata blocks. Then it
processes the data block pointers within the metadata blocks, marking
0x1002, 0x1003, all the way up to 1023 as "data" blocks.
When it hits the block 0x7777777777777777777, it determines that's out
of range for the device, and therefore the data file has an unrecoverable
data block error.
At this point, it doesn't make sense to continue marking 0x1025 and beyond
as referenced data blocks, because that will only make matters worse.
Now we've got a problem: Before we knew 0x1000 was corrupt, we marked all
its references in the blockmap. We can't just delete the corrupt dinode
because most of its blocks are in-use by that other dinode.
One strategy is to keep the blocks it previously marked as "data" and "meta"
"as is" in the blockmap, mark the dinode as "invalid dinode" in the blockmap
and move along. Later, when we get to the other valid dinode, we'll see
potentially tens of thousands of duplicate references. Assuming we have
enough memory to record all these references, and time enough to resolve
them, these can all be checked in pass1b and resolved properly, due to
the fact that we marked the dinode as "invalid" (we favor the valid reference).
The problems with this strategy is (1) it takes lots of time and memory to
record and resolve all these duplicate references, and (2) when it gets to
pass5, the blocks that AREN'T referenced elsewhere are now set to "data"
in the blockmap, so pass5 will set the bitmap accordingly. But a subsequent
run of fsck.gfs2 will determine that no valid dinode references those
data blocks, and it will complain about blocks improperly marked as
"data" that should, in fact, be "free". This is bad behavior: a second run of
fsck.gfs2 should come up clean.
So to prevent this from happening, pass1, upon discovering the out-of-range
block, makes an effort to "undo" its blockmap designations. It traverses
the dinode's metadata tree once more, but sets all the blocks back to
"free". Well, not all of them, because if the invalid dinode referenced
blocks that were previously encountered, it would have recorded them as
duplicate references, so it has to "undo" that designation as well.
Another alternative is to do a pre-check for all possible types of
corruption of every block. This involves making two passes through the
metadata: The first pass validates the blocks are all valid, and there are
absolutely no problems with data or metadata. The second pass marks all the
blocks in the blockmap as their appropriate type.
Yes, it gets very sticky, very messy. That's why it's taken so long to
get it right.
Regards,
Bob Peterson
Red Hat File Systems
next prev parent reply other threads:[~2013-05-16 15:02 UTC|newest]
Thread overview: 59+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-05-14 16:21 [Cluster-devel] [gfs2-utils PATCH 01/47] libgfs2: externalize dir_split_leaf Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 02/47] libgfs2: allow dir_split_leaf to receive a leaf buffer Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 03/47] libgfs2: let dir_split_leaf receive a "broken" lindex Bob Peterson
2013-05-15 16:01 ` Steven Whitehouse
2013-05-20 16:02 ` Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 04/47] fsck.gfs2: Move function find_free_blk to util.c Bob Peterson
2013-05-15 16:04 ` Steven Whitehouse
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 05/47] fsck.gfs2: Split out function to make sure lost+found exists Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 06/47] fsck.gfs2: Check for formal inode mismatch when adding to lost+found Bob Peterson
2013-05-15 16:08 ` Steven Whitehouse
2013-05-17 12:47 ` Bob Peterson
2013-05-17 12:55 ` Steven Whitehouse
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 07/47] fsck.gfs2: shorten some debug messages in lost+found Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 08/47] fsck.gfs2: Move basic directory entry checks to separate function Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 09/47] fsck.gfs2: Add formal inode check to basic dirent checks Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 10/47] fsck.gfs2: Add new function to check dir hash tables Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 11/47] fsck.gfs2: Special case '..' when processing bad formal inode number Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 12/47] fsck.gfs2: Move function to read directory hash table to util.c Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 13/47] fsck.gfs2: Misc cleanups Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 14/47] fsck.gfs2: Verify dirent hash values correspond to proper leaf block Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 15/47] fsck.gfs2: re-read hash table if directory height or depth changes Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 16/47] fsck.gfs2: fix leaf blocks, don't try to patch the hash table Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 17/47] fsck.gfs2: check leaf depth when validating leaf blocks Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 18/47] fsck.gfs2: small cleanups Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 19/47] fsck.gfs2: reprocess inodes when blocks are added Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 20/47] fsck.gfs2: Remove redundant leaf depth check Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 21/47] fsck.gfs2: link dinodes that only have extended attribute problems Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 22/47] fsck.gfs2: Add clarifying message to duplicate processing Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 23/47] fsck.gfs2: separate function to calculate metadata block header size Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 24/47] fsck.gfs2: Rework the "undo" functions Bob Peterson
2013-05-16 13:27 ` Steven Whitehouse
2013-05-16 13:49 ` Bob Peterson
2013-05-16 14:02 ` Steven Whitehouse
2013-05-16 15:02 ` Bob Peterson [this message]
2013-05-16 15:24 ` Steven Whitehouse
2013-05-20 13:08 ` Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 25/47] fsck.gfs2: Check for interrupt when resolving duplicates Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 26/47] fsck.gfs2: Consistent naming of struct duptree variables Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 27/47] fsck.gfs2: Keep proper counts when duplicates are found Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 28/47] fsck.gfs2: print metadata block reference on data errors Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 29/47] fsck.gfs2: print block count values when fixing them Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 30/47] fsck.gfs2: Do not invalidate metablocks of dinodes with invalid mode Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 31/47] fsck.gfs2: Log when unrecoverable data block errors are encountered Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 32/47] fsck.gfs2: don't remove buffers from the list when errors are found Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 33/47] fsck.gfs2: Don't flag GFS1 non-dinode blocks as duplicates Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 34/47] fsck.gfs2: externalize check_leaf Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 35/47] fsck.gfs2: pass2: check leaf blocks when fixing hash table Bob Peterson
2013-05-14 16:21 ` [Cluster-devel] [gfs2-utils PATCH 36/47] fsck.gfs2: standardize check_metatree return codes Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 37/47] fsck.gfs2: don't invalidate files with duplicate data block refs Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 38/47] fsck.gfs2: check for duplicate first references Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 39/47] fsck.gfs2: When flagging a duplicate reference, show valid or invalid Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 40/47] fsck.gfs2: major duplicate reference reform Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 41/47] fsck.gfs2: Remove all bad eattr blocks Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 42/47] fsck.gfs2: Remove unused variable Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 43/47] fsck.gfs2: double-check transitions from dinode to data Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 44/47] fsck.gfs2: Stop "undo" process when error data block is reached Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 45/47] fsck.gfs2: Don't allocate leaf blocks in pass1 Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 46/47] fsck.gfs2: take hash table start boundaries into account Bob Peterson
2013-05-14 16:22 ` [Cluster-devel] [gfs2-utils PATCH 47/47] fsck.gfs2: delete all duplicates from unrecoverable damaged dinodes Bob Peterson
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=439495569.10483675.1368716527959.JavaMail.root@redhat.com \
--to=rpeterso@redhat.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;
as well as URLs for NNTP newsgroup(s).