block_group->disk_cache_state = BTRFS_DC_CLEAR;
}
- if (!btrfs_fs_closing(root->fs_info)) {
+ if (!block_group->iref) {
block_group->inode = igrab(inode);
block_group->iref = 1;
}
rsv = trans->block_rsv;
trans->block_rsv = root->orphan_block_rsv;
- ret = btrfs_block_rsv_check(trans, root,
- root->orphan_block_rsv,
- 0, 5);
+ ret = btrfs_block_rsv_check(root, root->orphan_block_rsv, 0, 5, 0);
if (ret)
return ret;
u64 num_bitmaps;
u64 generation;
pgoff_t index = 0;
+ gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int ret = 0;
INIT_LIST_HEAD(&bitmaps);
if (!num_entries && !num_bitmaps)
break;
- page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
+ page = find_or_create_page(inode->i_mapping, index, mask);
if (!page)
goto free_cache;
return ret;
}
+/**
+ * __btrfs_write_out_cache - write out cached info to an inode
+ * @root - the root the inode belongs to
+ * @ctl - the free space cache we are going to write out
+ * @block_group - the block_group for this cache if it belongs to a block_group
+ * @trans - the trans handle
+ * @path - the path to use
+ * @offset - the offset for the key we'll insert
+ *
+ * This function writes out a free space cache struct to disk for quick recovery
+ * on mount. This will return 0 if it was successfull in writing the cache out,
+ * and -1 if it was not.
+ */
int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode,
struct btrfs_free_space_ctl *ctl,
struct btrfs_block_group_cache *block_group,
u64 start, end, len;
u64 bytes = 0;
u32 crc = ~(u32)0;
+ gfp_t mask = btrfs_alloc_write_mask(inode->i_mapping);
int index = 0, num_pages = 0;
int entries = 0;
int bitmaps = 0;
- int ret = -1;
+ int ret;
+ int err = -1;
bool next_page = false;
bool out_of_space = false;
INIT_LIST_HEAD(&bitmap_list);
- node = rb_first(&ctl->free_space_offset);
- if (!node)
- return 0;
-
if (!i_size_read(inode))
return -1;
* know and don't freak out.
*/
while (index < num_pages) {
- page = find_or_create_page(inode->i_mapping, index, GFP_NOFS);
+ page = find_or_create_page(inode->i_mapping, index, mask);
if (!page) {
int i;
if (block_group)
start = block_group->key.objectid;
+ node = rb_first(&ctl->free_space_offset);
+ if (!node && cluster) {
+ node = rb_first(&cluster->root);
+ cluster = NULL;
+ }
+
/* Write out the extent entries */
do {
struct btrfs_free_space_entry *entry;
unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
i_size_read(inode) - 1, &cached_state,
GFP_NOFS);
- ret = 0;
goto out;
}
unlock_extent_cached(&BTRFS_I(inode)->io_tree, 0,
i_size_read(inode) - 1, &cached_state, GFP_NOFS);
- if (ret) {
- ret = 0;
+ if (ret)
goto out;
- }
BTRFS_I(inode)->generation = trans->transid;
key.offset = offset;
key.type = 0;
- ret = btrfs_search_slot(trans, root, &key, path, 1, 1);
+ ret = btrfs_search_slot(trans, root, &key, path, 0, 1);
if (ret < 0) {
- ret = -1;
clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1,
EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING, 0, 0, NULL, GFP_NOFS);
btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]);
if (found_key.objectid != BTRFS_FREE_SPACE_OBJECTID ||
found_key.offset != offset) {
- ret = -1;
clear_extent_bit(&BTRFS_I(inode)->io_tree, 0, bytes - 1,
EXTENT_DIRTY | EXTENT_DELALLOC |
EXTENT_DO_ACCOUNTING, 0, 0, NULL,
btrfs_mark_buffer_dirty(leaf);
btrfs_release_path(path);
- ret = 1;
-
+ err = 0;
out:
kfree(pages);
- if (ret != 1) {
+ if (err) {
invalidate_inode_pages2_range(inode->i_mapping, 0, index);
BTRFS_I(inode)->generation = 0;
}
btrfs_update_inode(trans, root, inode);
- return ret;
+ return err;
}
int btrfs_write_out_cache(struct btrfs_root *root,
ret = __btrfs_write_out_cache(root, inode, ctl, block_group, trans,
path, block_group->key.objectid);
- if (ret < 0) {
+ if (ret) {
+ btrfs_delalloc_release_metadata(inode, inode->i_size);
spin_lock(&block_group->lock);
block_group->disk_cache_state = BTRFS_DC_ERROR;
spin_unlock(&block_group->lock);
ret = 0;
-
+#ifdef DEBUG
printk(KERN_ERR "btrfs: failed to write free space cace "
"for block group %llu\n", block_group->key.objectid);
+#endif
}
iput(inode);
return 0;
ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0);
- if (ret < 0)
+ if (ret) {
+ btrfs_delalloc_release_metadata(inode, inode->i_size);
+#ifdef DEBUG
printk(KERN_ERR "btrfs: failed to write free ino cache "
"for root %llu\n", root->root_key.objectid);
+#endif
+ }
iput(inode);
return ret;