On 03/14/2014 09:36 AM, Wang Shilong wrote: > Hi Josef, > > Just ping this again. > > Did you have any good ideas to rebuild extent tree if broken > filesystem is filled with snapshots.? > > I was working on this recently, i was blocked that i can not verify > if an extent is *FULL BACKREF* mode or not. As a *FULL BACKREF* > extent's refs can be 1 and more than 1.. > > I am willing to test codes or have a try if you could give me some > advice etc. > Full backrefs aren't too hard. Basically all you have to do is walk down the fs tree and keep track of btrfs_header_owner(eb) for everything we walk into. If btrfs_header_owner(eb) == root->objectid for the tree we are walking down then we need a ye olde normal backref for this block. If btrfs_header_owner(eb) != root->objectid we _may_ need a full backref, it depends on who owns the parent block. The following may be incomplete, I'm kind of sick 1) We walk down the original tree, every eb we encounter has btrfs_header_owner(eb) == root->objectid. We add normal references for this root (BTRFS_TREE_BLOCK_REF_KEY) for this root. World peace is achieved. 2) We walk down the snapshotted tree. Say we didn't change anything at all, it was just a clean snapshot and then boom. So the btrfs_header_owner(root->node) == root->objectid, so normal backref. We walk down to the next level, where btrfs_header_owner(eb) != root->objectid, but the level above did, so we add normal refs for all of these blocks. We go down the next level, now our btrfs_header_owner(parent) != root->objectid and btrfs_header_owner(eb) != root->objectid. This is where we need to now go back and see if btrfs_header_owner(eb) currently has a ref on eb. If it does we are done, move on to the next block in this same level, we don't have to go further down. 3) Harder case, we snapshotted and then changed things in the original root. Do the same thing as in step 2, but now we get down to btrfs_header_level(eb) != root->objectid && btrfs_header_level(parent) != root->objectid. We lookup the references we have for eb and notice that btrfs_header_owner(eb) no longer refers to eb. So now we must set FULL_BACKREF on this extent reference and add a SHARED_BLOCK_REF_KEY for this eb using the parent->start as the offset. And we need to keep walking down and doing the same thing until we either hit level 0 or btrfs_header_owner(eb) has a ref on the block. 4) Not really a whole special case, just something to keep in mind, if btrfs_header_owner(parent) == root->objectid but btrfs_header_owner(eb) != root->objectid that means we have a normal TREE_BLOCK_REF on eb, it's only when the parent doesn't match our current root that it's a problem. Does that make sense? Thanks, Josef -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html
