|
@@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
|
|
|
struct btrfs_free_space_ctl *ctl = root->free_ino_ctl;
|
|
|
struct btrfs_path *path;
|
|
|
struct inode *inode;
|
|
|
+ struct btrfs_block_rsv *rsv;
|
|
|
+ u64 num_bytes;
|
|
|
u64 alloc_hint = 0;
|
|
|
int ret;
|
|
|
int prealloc;
|
|
@@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root,
|
|
|
if (!path)
|
|
|
return -ENOMEM;
|
|
|
|
|
|
+ rsv = trans->block_rsv;
|
|
|
+ trans->block_rsv = &root->fs_info->trans_block_rsv;
|
|
|
+
|
|
|
+ num_bytes = trans->bytes_reserved;
|
|
|
+ /*
|
|
|
+ * 1 item for inode item insertion if need
|
|
|
+ * 3 items for inode item update (in the worst case)
|
|
|
+ * 1 item for free space object
|
|
|
+ * 3 items for pre-allocation
|
|
|
+ */
|
|
|
+ trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8);
|
|
|
+ ret = btrfs_block_rsv_add_noflush(root, trans->block_rsv,
|
|
|
+ trans->bytes_reserved);
|
|
|
+ if (ret)
|
|
|
+ goto out;
|
|
|
again:
|
|
|
inode = lookup_free_ino_inode(root, path);
|
|
|
if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) {
|
|
|
ret = PTR_ERR(inode);
|
|
|
- goto out;
|
|
|
+ goto out_release;
|
|
|
}
|
|
|
|
|
|
if (IS_ERR(inode)) {
|
|
@@ -434,7 +451,7 @@ again:
|
|
|
|
|
|
ret = create_free_ino_inode(root, trans, path);
|
|
|
if (ret)
|
|
|
- goto out;
|
|
|
+ goto out_release;
|
|
|
goto again;
|
|
|
}
|
|
|
|
|
@@ -477,11 +494,14 @@ again:
|
|
|
}
|
|
|
btrfs_free_reserved_data_space(inode, prealloc);
|
|
|
|
|
|
+ ret = btrfs_write_out_ino_cache(root, trans, path);
|
|
|
out_put:
|
|
|
iput(inode);
|
|
|
+out_release:
|
|
|
+ btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved);
|
|
|
out:
|
|
|
- if (ret == 0)
|
|
|
- ret = btrfs_write_out_ino_cache(root, trans, path);
|
|
|
+ trans->block_rsv = rsv;
|
|
|
+ trans->bytes_reserved = num_bytes;
|
|
|
|
|
|
btrfs_free_path(path);
|
|
|
return ret;
|