Btrfs: write out free space cache
This is a simple bit, just dump the free space cache out to our preallocated inode when we're writing out dirty block groups. There are a bunch of changes in inode.c in order to account for special cases. Mostly when we're doing the writeout we're holding trans_mutex, so we need to use the nolock transacation functions. Also we can't do asynchronous completions since the async thread could be blocked on already completed IO waiting for the transaction lock. This has been tested with xfstests and btrfs filesystem balance, as well as my ENOSPC tests. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com>
This commit is contained in:
@ -2847,6 +2847,8 @@ again:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cache->disk_cache_state == BTRFS_DC_SETUP)
|
||||
cache->disk_cache_state = BTRFS_DC_NEED_WRITE;
|
||||
cache->dirty = 0;
|
||||
last = cache->key.objectid + cache->key.offset;
|
||||
|
||||
@ -2855,6 +2857,52 @@ again:
|
||||
btrfs_put_block_group(cache);
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/*
|
||||
* I don't think this is needed since we're just marking our
|
||||
* preallocated extent as written, but just in case it can't
|
||||
* hurt.
|
||||
*/
|
||||
if (last == 0) {
|
||||
err = btrfs_run_delayed_refs(trans, root,
|
||||
(unsigned long)-1);
|
||||
BUG_ON(err);
|
||||
}
|
||||
|
||||
cache = btrfs_lookup_first_block_group(root->fs_info, last);
|
||||
while (cache) {
|
||||
/*
|
||||
* Really this shouldn't happen, but it could if we
|
||||
* couldn't write the entire preallocated extent and
|
||||
* splitting the extent resulted in a new block.
|
||||
*/
|
||||
if (cache->dirty) {
|
||||
btrfs_put_block_group(cache);
|
||||
goto again;
|
||||
}
|
||||
if (cache->disk_cache_state == BTRFS_DC_NEED_WRITE)
|
||||
break;
|
||||
cache = next_block_group(root, cache);
|
||||
}
|
||||
if (!cache) {
|
||||
if (last == 0)
|
||||
break;
|
||||
last = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
btrfs_write_out_cache(root, trans, cache, path);
|
||||
|
||||
/*
|
||||
* If we didn't have an error then the cache state is still
|
||||
* NEED_WRITE, so we can set it to WRITTEN.
|
||||
*/
|
||||
if (cache->disk_cache_state == BTRFS_DC_NEED_WRITE)
|
||||
cache->disk_cache_state = BTRFS_DC_WRITTEN;
|
||||
last = cache->key.objectid + cache->key.offset;
|
||||
btrfs_put_block_group(cache);
|
||||
}
|
||||
|
||||
btrfs_free_path(path);
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user