fsck.gfs2: major duplicate reference reform
This patch is a large set of changes designed to rework how pass1b
resolves duplicate block references. There are basically two major
changes with this patch:
First, the metawalk functions were trying to attribute too much
information to the return codes of its callback functions: (1) Was
there an error? (2) Was the inode valid? (3) Was a duplicate block
reference encountered? (4) Should we keep going and process more of
its metadata? This often led to bad decisions made by metawalk:
For example, it would stop processing metadata when it should have
continued, thereby forgetting to mark blocks free that were no longer
in use. This patch introduces two new variables to the metatree
functions, *is_valid and *was_duplicate. The first one indicates
whether the dinode was valid or whether there is good cause to
delete it. The second indicates whether a duplicate block reference
was encountered. With this patch, the return code indicates simply
whether metadata processing should be skipped or not, and nothing
more. This is especially useful in pass1. For example, if it
encounters major corruption in a dinode, it doesn't do any good to
mark all its blocks as duplicates and have the undo functions try
to reverse all those decisions.
The second major change with this patch has to do with the
philosophy of how duplicate references are resolved. Before, pass1
would flag the duplicates and pass1b would try to resolve them all,
marking dinodes that should be deleted as "bad", and pass2 would
delete the bad dinodes. This becomes very problematic and messy
in pass1b, especially in cases where you have a number of duplicate
references that are common between multiple dinodes. For example,
suppose files A, B and C share some of the same blocks, but not
others:
A - 0x3000 0x3001 0x1233 0x1234 0x3004
B - 0x4000 0x4001 0x4002 0x1234 0x1235
C - 0x1231 0x1232 0x1233 0x1234 0x1235
The old strategy that got us into trouble was to log the three
duplicate blocks, delete invalid dinodes A and B, but leave the
duplicate reference structure around for 0x1233, 0x1234 and 0x1235
so that C would be left intact with the only references to all five
blocks. But in cleaning up the leftover duplicate structure often
led to bad decisions where C wouldn't have all its blocks marked
as referenced. Often, you would end up with blocks that were marked
as free which were still in use, and blocks that were marked as
in use that should have been freed, and it was all due to the
existence of those duplicate structures that were still on the list
until pass2.
The new strategy is to resolve-as-you-go. In other words, pass1b
considers the three duplicate blocks, but when it decides that
file A should be deleted, it removes all its references from the
list, thereby making the decision between B and C easier: it no
longer has to worry about block 1233, and there's only one thing
to consider about block 0x1234 and 0x1235. When B is deleted, it
removes all its duplicate references, so block 0x1235 is no longer
considered to be in conflict. Once a file is deleted, all its
duplicate reference structures are removed so as not to confuse
other duplicates being resolved. The duplicate handler structure,
struct dup_handler, is revised with every reference that's resolved
so it's not working off a long list of possibles, most of
which were already taken care of by previous actions.
rhbz#902920