Btrfs: Metadata reservation for orphan inodes

reserve metadata space for handling orphan inodes

Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Signed-off-by: Chris Mason <chris.mason@oracle.com>
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 6217bb6..cfe7f58 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -676,6 +676,7 @@
 
 			btrfs_free_log(trans, root);
 			btrfs_update_reloc_root(trans, root);
+			btrfs_orphan_commit_root(trans, root);
 
 			if (root->commit_root != root->node) {
 				switch_commit_root(root);
@@ -835,6 +836,8 @@
 	struct extent_buffer *tmp;
 	struct extent_buffer *old;
 	int ret;
+	int retries = 0;
+	u64 to_reserve = 0;
 	u64 index = 0;
 	u64 objectid;
 
@@ -850,6 +853,17 @@
 		goto fail;
 	}
 
+	btrfs_orphan_pre_snapshot(trans, pending, &to_reserve);
+
+	if (to_reserve > 0) {
+		ret = btrfs_block_rsv_add(trans, root, &pending->block_rsv,
+					  to_reserve, &retries);
+		if (ret) {
+			pending->error = ret;
+			goto fail;
+		}
+	}
+
 	key.objectid = objectid;
 	key.offset = (u64)-1;
 	key.type = BTRFS_ROOT_ITEM_KEY;
@@ -909,6 +923,8 @@
 	key.offset = (u64)-1;
 	pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key);
 	BUG_ON(IS_ERR(pending->snap));
+
+	btrfs_orphan_post_snapshot(trans, pending);
 fail:
 	kfree(new_root_item);
 	btrfs_block_rsv_release(root, &pending->block_rsv, (u64)-1);