[Btrfs-devel] [PATCH 2/2] block accounting+sysfs support for btrfs

Chris Mason chris.mason at oracle.com
Tue Aug 28 08:06:14 PDT 2007


I've got this merged locally (the completion handler version) and the
sysfs bits seem to be working fine.

The only problem is the accounting doesn't record blocks that are
deleted in the root items.  This is because of the somewhat strange
path things take to being freed.  So, lets pretend we've got a 1GB file
named foo and we rm it.

1) start a transaction
2) remove 'foo' from dir (this cows dir blocks)
3) remove extent pointers from foo (this cows all blocks w/extent
4) remove the foo's inode
5) (eventually) commit

At this point, we have two tree roots. There's the most recent root,
where all traces of foo are gone, and there's the old root which has
all the tree blocks from before the cow.  The extents from foo are not
free on disk yet, because they are still referenced by the old root.

btrfs_drop_snapshot comes in and starts dropping reference counts on
blocks in the old root.  It will find the extent pointers for foo and
drop references on those too, and finally those extents will really
freed on disk.

So, this is a very long way of saying that last place actually
calling btrfs_free_extent is actually btrfs_drop_snapshot, and it does
this with a copy of the root item.  So, when we make changes to
root->root_item, they never actually get sent down to the disk.  What
we want to do is update the block count in the most recent root with
the number of blocks that were freed by btrfs_drop_snapshot.  So,
before calling btrfs_drop_snapshot, we need to record the number of
blocks allocated, and the compare it with the number still there after
calling drop_snapshot.

Then update the most recent root to reflect the changes on disk.

Does that make any sense?


More information about the Btrfs-devel mailing list