xref: /openbmc/linux/fs/btrfs/disk-io.c (revision e089f05c)
1eb60ceacSChris Mason #define _XOPEN_SOURCE 500
2eb60ceacSChris Mason #include <stdio.h>
3eb60ceacSChris Mason #include <stdlib.h>
4eb60ceacSChris Mason #include <sys/types.h>
5eb60ceacSChris Mason #include <sys/stat.h>
6eb60ceacSChris Mason #include <fcntl.h>
7eb60ceacSChris Mason #include <unistd.h>
8eb60ceacSChris Mason #include "kerncompat.h"
9eb60ceacSChris Mason #include "radix-tree.h"
10eb60ceacSChris Mason #include "ctree.h"
11eb60ceacSChris Mason #include "disk-io.h"
12e089f05cSChris Mason #include "transaction.h"
13eb60ceacSChris Mason 
14eb60ceacSChris Mason static int allocated_blocks = 0;
15ed2ff2cbSChris Mason int cache_max = 10000;
16eb60ceacSChris Mason 
17234b63a0SChris Mason static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf)
18eb60ceacSChris Mason {
197518a238SChris Mason 	if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
209a8dd150SChris Mason 		BUG();
217518a238SChris Mason 	if (root->node && btrfs_header_parentid(&buf->node.header) !=
227518a238SChris Mason 	    btrfs_header_parentid(&root->node->node.header))
239a8dd150SChris Mason 		BUG();
249a8dd150SChris Mason 	return 0;
25eb60ceacSChris Mason }
26eb60ceacSChris Mason 
27234b63a0SChris Mason static int free_some_buffers(struct btrfs_root *root)
28ed2ff2cbSChris Mason {
29ed2ff2cbSChris Mason 	struct list_head *node, *next;
30234b63a0SChris Mason 	struct btrfs_buffer *b;
31ed2ff2cbSChris Mason 	if (root->cache_size < cache_max)
32ed2ff2cbSChris Mason 		return 0;
33ed2ff2cbSChris Mason 	list_for_each_safe(node, next, &root->cache) {
34234b63a0SChris Mason 		b = list_entry(node, struct btrfs_buffer, cache);
35ed2ff2cbSChris Mason 		if (b->count == 1) {
36ed2ff2cbSChris Mason 			BUG_ON(!list_empty(&b->dirty));
37ed2ff2cbSChris Mason 			list_del_init(&b->cache);
38234b63a0SChris Mason 			btrfs_block_release(root, b);
39ed2ff2cbSChris Mason 			if (root->cache_size < cache_max)
4077ce6846SChris Mason 				break;
41ed2ff2cbSChris Mason 		}
42ed2ff2cbSChris Mason 	}
43ed2ff2cbSChris Mason 	return 0;
44ed2ff2cbSChris Mason }
45ed2ff2cbSChris Mason 
46234b63a0SChris Mason struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr)
47eb60ceacSChris Mason {
48234b63a0SChris Mason 	struct btrfs_buffer *buf;
49eb60ceacSChris Mason 	int ret;
50123abc88SChris Mason 
51123abc88SChris Mason 	buf = malloc(sizeof(struct btrfs_buffer) + root->blocksize);
52eb60ceacSChris Mason 	if (!buf)
53eb60ceacSChris Mason 		return buf;
54eb60ceacSChris Mason 	allocated_blocks++;
55eb60ceacSChris Mason 	buf->blocknr = blocknr;
56ed2ff2cbSChris Mason 	buf->count = 2;
57ed2ff2cbSChris Mason 	INIT_LIST_HEAD(&buf->dirty);
58ed2ff2cbSChris Mason 	free_some_buffers(root);
59eb60ceacSChris Mason 	radix_tree_preload(GFP_KERNEL);
60eb60ceacSChris Mason 	ret = radix_tree_insert(&root->cache_radix, blocknr, buf);
61eb60ceacSChris Mason 	radix_tree_preload_end();
62ed2ff2cbSChris Mason 	list_add_tail(&buf->cache, &root->cache);
63ed2ff2cbSChris Mason 	root->cache_size++;
64eb60ceacSChris Mason 	if (ret) {
65eb60ceacSChris Mason 		free(buf);
66eb60ceacSChris Mason 		return NULL;
67eb60ceacSChris Mason 	}
68eb60ceacSChris Mason 	return buf;
69eb60ceacSChris Mason }
70eb60ceacSChris Mason 
71234b63a0SChris Mason struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr)
72eb60ceacSChris Mason {
73234b63a0SChris Mason 	struct btrfs_buffer *buf;
749a8dd150SChris Mason 	buf = radix_tree_lookup(&root->cache_radix, blocknr);
759a8dd150SChris Mason 	if (buf) {
769a8dd150SChris Mason 		buf->count++;
779a8dd150SChris Mason 	} else {
789a8dd150SChris Mason 		buf = alloc_tree_block(root, blocknr);
799a8dd150SChris Mason 		if (!buf) {
80eb60ceacSChris Mason 			BUG();
81eb60ceacSChris Mason 			return NULL;
82eb60ceacSChris Mason 		}
839a8dd150SChris Mason 	}
84eb60ceacSChris Mason 	return buf;
85eb60ceacSChris Mason }
86eb60ceacSChris Mason 
87234b63a0SChris Mason struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr)
88eb60ceacSChris Mason {
89123abc88SChris Mason 	loff_t offset = blocknr * root->blocksize;
90234b63a0SChris Mason 	struct btrfs_buffer *buf;
91eb60ceacSChris Mason 	int ret;
92eb60ceacSChris Mason 
93eb60ceacSChris Mason 	buf = radix_tree_lookup(&root->cache_radix, blocknr);
94eb60ceacSChris Mason 	if (buf) {
95eb60ceacSChris Mason 		buf->count++;
969a8dd150SChris Mason 	} else {
97eb60ceacSChris Mason 		buf = alloc_tree_block(root, blocknr);
98eb60ceacSChris Mason 		if (!buf)
99eb60ceacSChris Mason 			return NULL;
100123abc88SChris Mason 		ret = pread(root->fp, &buf->node, root->blocksize, offset);
101123abc88SChris Mason 		if (ret != root->blocksize) {
102eb60ceacSChris Mason 			free(buf);
103eb60ceacSChris Mason 			return NULL;
104eb60ceacSChris Mason 		}
1059a8dd150SChris Mason 	}
1069a8dd150SChris Mason 	if (check_tree_block(root, buf))
107cfaa7295SChris Mason 		BUG();
108eb60ceacSChris Mason 	return buf;
109eb60ceacSChris Mason }
110eb60ceacSChris Mason 
111e089f05cSChris Mason int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
112e089f05cSChris Mason 		     struct btrfs_buffer *buf)
113ed2ff2cbSChris Mason {
114ed2ff2cbSChris Mason 	if (!list_empty(&buf->dirty))
115ed2ff2cbSChris Mason 		return 0;
116ed2ff2cbSChris Mason 	list_add_tail(&buf->dirty, &root->trans);
117ed2ff2cbSChris Mason 	buf->count++;
118ed2ff2cbSChris Mason 	return 0;
119ed2ff2cbSChris Mason }
120ed2ff2cbSChris Mason 
121e089f05cSChris Mason int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
122e089f05cSChris Mason 		     struct btrfs_buffer *buf)
123ed2ff2cbSChris Mason {
124ed2ff2cbSChris Mason 	if (!list_empty(&buf->dirty)) {
125ed2ff2cbSChris Mason 		list_del_init(&buf->dirty);
126234b63a0SChris Mason 		btrfs_block_release(root, buf);
127ed2ff2cbSChris Mason 	}
128ed2ff2cbSChris Mason 	return 0;
129ed2ff2cbSChris Mason }
130ed2ff2cbSChris Mason 
131e089f05cSChris Mason int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
132e089f05cSChris Mason 		     struct btrfs_buffer *buf)
133eb60ceacSChris Mason {
134eb60ceacSChris Mason 	u64 blocknr = buf->blocknr;
135123abc88SChris Mason 	loff_t offset = blocknr * root->blocksize;
136eb60ceacSChris Mason 	int ret;
137eb60ceacSChris Mason 
1387518a238SChris Mason 	if (buf->blocknr != btrfs_header_blocknr(&buf->node.header))
139eb60ceacSChris Mason 		BUG();
140123abc88SChris Mason 	ret = pwrite(root->fp, &buf->node, root->blocksize, offset);
141123abc88SChris Mason 	if (ret != root->blocksize)
142eb60ceacSChris Mason 		return ret;
143eb60ceacSChris Mason 	return 0;
144eb60ceacSChris Mason }
145eb60ceacSChris Mason 
146e089f05cSChris Mason static int __commit_transaction(struct btrfs_trans_handle *trans, struct
147e089f05cSChris Mason 				btrfs_root *root)
148ed2ff2cbSChris Mason {
149234b63a0SChris Mason 	struct btrfs_buffer *b;
150ed2ff2cbSChris Mason 	int ret = 0;
151ed2ff2cbSChris Mason 	int wret;
152ed2ff2cbSChris Mason 	while(!list_empty(&root->trans)) {
153234b63a0SChris Mason 		b = list_entry(root->trans.next, struct btrfs_buffer, dirty);
154ed2ff2cbSChris Mason 		list_del_init(&b->dirty);
155e089f05cSChris Mason 		wret = write_tree_block(trans, root, b);
156ed2ff2cbSChris Mason 		if (wret)
157ed2ff2cbSChris Mason 			ret = wret;
158234b63a0SChris Mason 		btrfs_block_release(root, b);
159ed2ff2cbSChris Mason 	}
160ed2ff2cbSChris Mason 	return ret;
161ed2ff2cbSChris Mason }
162ed2ff2cbSChris Mason 
163e089f05cSChris Mason static int commit_extent_and_tree_roots(struct btrfs_trans_handle *trans,
164e089f05cSChris Mason 					struct btrfs_root *tree_root, struct
165e089f05cSChris Mason 					btrfs_root *extent_root)
1663768f368SChris Mason {
1673768f368SChris Mason 	int ret;
1683768f368SChris Mason 	u64 old_extent_block;
1693768f368SChris Mason 
1703768f368SChris Mason 	while(1) {
1713768f368SChris Mason 		old_extent_block = btrfs_root_blocknr(&extent_root->root_item);
1723768f368SChris Mason 		if (old_extent_block == extent_root->node->blocknr)
1733768f368SChris Mason 			break;
1743768f368SChris Mason 		btrfs_set_root_blocknr(&extent_root->root_item,
1753768f368SChris Mason 				       extent_root->node->blocknr);
176e089f05cSChris Mason 		ret = btrfs_update_root(trans, tree_root,
1773768f368SChris Mason 					&extent_root->root_key,
1783768f368SChris Mason 					&extent_root->root_item);
1793768f368SChris Mason 		BUG_ON(ret);
1803768f368SChris Mason 	}
181e089f05cSChris Mason 	__commit_transaction(trans, extent_root);
182e089f05cSChris Mason 	__commit_transaction(trans, tree_root);
1833768f368SChris Mason 	return 0;
1843768f368SChris Mason }
1853768f368SChris Mason 
186e089f05cSChris Mason int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct
187e089f05cSChris Mason 			     btrfs_root *root, struct btrfs_super_block *s)
188ed2ff2cbSChris Mason {
189a28ec197SChris Mason 	int ret = 0;
1903768f368SChris Mason 	struct btrfs_buffer *snap = root->commit_root;
1913768f368SChris Mason 	struct btrfs_key snap_key;
192a28ec197SChris Mason 
193e089f05cSChris Mason 	ret = __commit_transaction(trans, root);
194ed2ff2cbSChris Mason 	BUG_ON(ret);
1953768f368SChris Mason 
1963768f368SChris Mason 	if (root->commit_root == root->node)
1973768f368SChris Mason 		return 0;
1983768f368SChris Mason 
1993768f368SChris Mason 	memcpy(&snap_key, &root->root_key, sizeof(snap_key));
2003768f368SChris Mason 	root->root_key.offset++;
2013768f368SChris Mason 
2023768f368SChris Mason 	btrfs_set_root_blocknr(&root->root_item, root->node->blocknr);
203e089f05cSChris Mason 	ret = btrfs_insert_root(trans, root->tree_root, &root->root_key,
2043768f368SChris Mason 				&root->root_item);
2053768f368SChris Mason 	BUG_ON(ret);
2063768f368SChris Mason 
207e089f05cSChris Mason 	ret = commit_extent_and_tree_roots(trans, root->tree_root,
208e089f05cSChris Mason 					   root->extent_root);
2093768f368SChris Mason 	BUG_ON(ret);
2103768f368SChris Mason 
211e089f05cSChris Mason 	write_ctree_super(trans, root, s);
212e089f05cSChris Mason 	btrfs_finish_extent_commit(trans, root->extent_root);
213e089f05cSChris Mason 	btrfs_finish_extent_commit(trans, root->tree_root);
2143768f368SChris Mason 
215a28ec197SChris Mason 	root->commit_root = root->node;
216a28ec197SChris Mason 	root->node->count++;
217e089f05cSChris Mason 	ret = btrfs_drop_snapshot(trans, root, snap);
218a28ec197SChris Mason 	BUG_ON(ret);
2193768f368SChris Mason 
220e089f05cSChris Mason 	ret = btrfs_del_root(trans, root->tree_root, &snap_key);
2213768f368SChris Mason 	BUG_ON(ret);
2223768f368SChris Mason 
223ed2ff2cbSChris Mason 	return ret;
224ed2ff2cbSChris Mason }
225ed2ff2cbSChris Mason 
226123abc88SChris Mason static int __setup_root(struct btrfs_super_block *super,
227123abc88SChris Mason 			struct btrfs_root *root, u64 objectid, int fp)
228d97e63b6SChris Mason {
229ed2ff2cbSChris Mason 	INIT_LIST_HEAD(&root->trans);
230ed2ff2cbSChris Mason 	INIT_LIST_HEAD(&root->cache);
231a28ec197SChris Mason 	root->cache_size = 0;
232d97e63b6SChris Mason 	root->fp = fp;
233cfaa7295SChris Mason 	root->node = NULL;
234a28ec197SChris Mason 	root->commit_root = NULL;
235123abc88SChris Mason 	root->blocksize = btrfs_super_blocksize(super);
236123abc88SChris Mason 	root->ref_cows = 0;
237a28ec197SChris Mason 	memset(&root->current_insert, 0, sizeof(root->current_insert));
2380579da42SChris Mason 	memset(&root->last_insert, 0, sizeof(root->last_insert));
2393768f368SChris Mason 	memset(&root->root_key, 0, sizeof(root->root_key));
2403768f368SChris Mason 	memset(&root->root_item, 0, sizeof(root->root_item));
2413768f368SChris Mason 	return 0;
2423768f368SChris Mason }
2433768f368SChris Mason 
244123abc88SChris Mason static int find_and_setup_root(struct btrfs_super_block *super,
245123abc88SChris Mason 			       struct btrfs_root *tree_root, u64 objectid,
2463768f368SChris Mason 			       struct btrfs_root *root, int fp)
2473768f368SChris Mason {
2483768f368SChris Mason 	int ret;
2493768f368SChris Mason 
250123abc88SChris Mason 	__setup_root(super, root, objectid, fp);
2513768f368SChris Mason 	ret = btrfs_find_last_root(tree_root, objectid,
2523768f368SChris Mason 				   &root->root_item, &root->root_key);
2533768f368SChris Mason 	BUG_ON(ret);
2543768f368SChris Mason 
2553768f368SChris Mason 	root->node = read_tree_block(root,
2563768f368SChris Mason 				     btrfs_root_blocknr(&root->root_item));
2573768f368SChris Mason 	BUG_ON(!root->node);
258d97e63b6SChris Mason 	return 0;
259d97e63b6SChris Mason }
260d97e63b6SChris Mason 
261234b63a0SChris Mason struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super)
262eb60ceacSChris Mason {
263234b63a0SChris Mason 	struct btrfs_root *root = malloc(sizeof(struct btrfs_root));
264234b63a0SChris Mason 	struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root));
2653768f368SChris Mason 	struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root));
266eb60ceacSChris Mason 	int fp;
267eb60ceacSChris Mason 	int ret;
268eb60ceacSChris Mason 
2693768f368SChris Mason 	root->extent_root = extent_root;
2703768f368SChris Mason 	root->tree_root = tree_root;
2713768f368SChris Mason 
2723768f368SChris Mason 	extent_root->extent_root = extent_root;
2733768f368SChris Mason 	extent_root->tree_root = tree_root;
2743768f368SChris Mason 
2753768f368SChris Mason 	tree_root->extent_root = extent_root;
2763768f368SChris Mason 	tree_root->tree_root = tree_root;
2773768f368SChris Mason 
278c673024aSChris Mason 	fp = open(filename, O_CREAT | O_RDWR, 0600);
279eb60ceacSChris Mason 	if (fp < 0) {
280eb60ceacSChris Mason 		free(root);
281eb60ceacSChris Mason 		return NULL;
282eb60ceacSChris Mason 	}
2839a8dd150SChris Mason 	INIT_RADIX_TREE(&root->cache_radix, GFP_KERNEL);
284a28ec197SChris Mason 	INIT_RADIX_TREE(&root->pinned_radix, GFP_KERNEL);
285a28ec197SChris Mason 	INIT_RADIX_TREE(&extent_root->pinned_radix, GFP_KERNEL);
2869a8dd150SChris Mason 	INIT_RADIX_TREE(&extent_root->cache_radix, GFP_KERNEL);
2873768f368SChris Mason 	INIT_RADIX_TREE(&tree_root->pinned_radix, GFP_KERNEL);
2883768f368SChris Mason 	INIT_RADIX_TREE(&tree_root->cache_radix, GFP_KERNEL);
2893768f368SChris Mason 
290234b63a0SChris Mason 	ret = pread(fp, super, sizeof(struct btrfs_super_block),
291123abc88SChris Mason 		     BTRFS_SUPER_INFO_OFFSET);
2923768f368SChris Mason 	if (ret == 0 || btrfs_super_root(super) == 0) {
2935c680ed6SChris Mason 		printf("making new FS!\n");
294123abc88SChris Mason 		ret = mkfs(fp, 0, 1024);
295d97e63b6SChris Mason 		if (ret)
296d97e63b6SChris Mason 			return NULL;
297234b63a0SChris Mason 		ret = pread(fp, super, sizeof(struct btrfs_super_block),
298123abc88SChris Mason 			     BTRFS_SUPER_INFO_OFFSET);
299234b63a0SChris Mason 		if (ret != sizeof(struct btrfs_super_block))
300d97e63b6SChris Mason 			return NULL;
301d97e63b6SChris Mason 	}
302d97e63b6SChris Mason 	BUG_ON(ret < 0);
3033768f368SChris Mason 
304123abc88SChris Mason 	__setup_root(super, tree_root, BTRFS_ROOT_TREE_OBJECTID, fp);
3053768f368SChris Mason 	tree_root->node = read_tree_block(tree_root, btrfs_super_root(super));
3063768f368SChris Mason 	BUG_ON(!tree_root->node);
3073768f368SChris Mason 
308123abc88SChris Mason 	ret = find_and_setup_root(super, tree_root, BTRFS_EXTENT_TREE_OBJECTID,
3093768f368SChris Mason 				  extent_root, fp);
3103768f368SChris Mason 	BUG_ON(ret);
3113768f368SChris Mason 
312123abc88SChris Mason 	ret = find_and_setup_root(super, tree_root, BTRFS_FS_TREE_OBJECTID,
3133768f368SChris Mason 				  root, fp);
3143768f368SChris Mason 	BUG_ON(ret);
3153768f368SChris Mason 
316a28ec197SChris Mason 	root->commit_root = root->node;
317a28ec197SChris Mason 	root->node->count++;
3183768f368SChris Mason 	root->ref_cows = 1;
319eb60ceacSChris Mason 	return root;
320eb60ceacSChris Mason }
321eb60ceacSChris Mason 
322e089f05cSChris Mason int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root
323e089f05cSChris Mason 		      *root, struct btrfs_super_block *s)
324cfaa7295SChris Mason {
325cfaa7295SChris Mason 	int ret;
3263768f368SChris Mason 	btrfs_set_super_root(s, root->tree_root->node->blocknr);
327234b63a0SChris Mason 	ret = pwrite(root->fp, s, sizeof(*s),
328123abc88SChris Mason 		     BTRFS_SUPER_INFO_OFFSET);
329cfaa7295SChris Mason 	if (ret != sizeof(*s)) {
330cfaa7295SChris Mason 		fprintf(stderr, "failed to write new super block err %d\n", ret);
331cfaa7295SChris Mason 		return ret;
332cfaa7295SChris Mason 	}
333cfaa7295SChris Mason 	return 0;
334cfaa7295SChris Mason }
335cfaa7295SChris Mason 
336234b63a0SChris Mason static int drop_cache(struct btrfs_root *root)
337ed2ff2cbSChris Mason {
338ed2ff2cbSChris Mason 	while(!list_empty(&root->cache)) {
339234b63a0SChris Mason 		struct btrfs_buffer *b = list_entry(root->cache.next,
340234b63a0SChris Mason 						   struct btrfs_buffer, cache);
341ed2ff2cbSChris Mason 		list_del_init(&b->cache);
342234b63a0SChris Mason 		btrfs_block_release(root, b);
343ed2ff2cbSChris Mason 	}
344ed2ff2cbSChris Mason 	return 0;
345ed2ff2cbSChris Mason }
346234b63a0SChris Mason int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s)
347eb60ceacSChris Mason {
3483768f368SChris Mason 	int ret;
349e089f05cSChris Mason 	struct btrfs_trans_handle *trans;
350e089f05cSChris Mason 
351e089f05cSChris Mason 	trans = root->running_transaction;
352e089f05cSChris Mason 	btrfs_commit_transaction(trans, root, s);
353e089f05cSChris Mason 	ret = commit_extent_and_tree_roots(trans, root->tree_root,
354e089f05cSChris Mason 					   root->extent_root);
3553768f368SChris Mason 	BUG_ON(ret);
356e089f05cSChris Mason 	write_ctree_super(trans, root, s);
357ed2ff2cbSChris Mason 	drop_cache(root->extent_root);
3583768f368SChris Mason 	drop_cache(root->tree_root);
359ed2ff2cbSChris Mason 	drop_cache(root);
360ed2ff2cbSChris Mason 	BUG_ON(!list_empty(&root->trans));
361ed2ff2cbSChris Mason 	BUG_ON(!list_empty(&root->extent_root->trans));
3623768f368SChris Mason 	BUG_ON(!list_empty(&root->tree_root->trans));
363ed2ff2cbSChris Mason 
364eb60ceacSChris Mason 	close(root->fp);
365eb60ceacSChris Mason 	if (root->node)
366234b63a0SChris Mason 		btrfs_block_release(root, root->node);
367cfaa7295SChris Mason 	if (root->extent_root->node)
368234b63a0SChris Mason 		btrfs_block_release(root->extent_root, root->extent_root->node);
3693768f368SChris Mason 	if (root->tree_root->node)
3703768f368SChris Mason 		btrfs_block_release(root->tree_root, root->tree_root->node);
371234b63a0SChris Mason 	btrfs_block_release(root, root->commit_root);
372eb60ceacSChris Mason 	free(root);
373eb60ceacSChris Mason 	printf("on close %d blocks are allocated\n", allocated_blocks);
374eb60ceacSChris Mason 	return 0;
375eb60ceacSChris Mason }
376eb60ceacSChris Mason 
377234b63a0SChris Mason void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf)
378eb60ceacSChris Mason {
379eb60ceacSChris Mason 	buf->count--;
380cfaa7295SChris Mason 	if (buf->count < 0)
381cfaa7295SChris Mason 		BUG();
382eb60ceacSChris Mason 	if (buf->count == 0) {
38302217ed2SChris Mason 		BUG_ON(!list_empty(&buf->cache));
38402217ed2SChris Mason 		BUG_ON(!list_empty(&buf->dirty));
385eb60ceacSChris Mason 		if (!radix_tree_lookup(&root->cache_radix, buf->blocknr))
386eb60ceacSChris Mason 			BUG();
387eb60ceacSChris Mason 		radix_tree_delete(&root->cache_radix, buf->blocknr);
388eb60ceacSChris Mason 		memset(buf, 0, sizeof(*buf));
389eb60ceacSChris Mason 		free(buf);
390eb60ceacSChris Mason 		BUG_ON(allocated_blocks == 0);
391eb60ceacSChris Mason 		allocated_blocks--;
392ed2ff2cbSChris Mason 		BUG_ON(root->cache_size == 0);
393ed2ff2cbSChris Mason 		root->cache_size--;
394eb60ceacSChris Mason 	}
395eb60ceacSChris Mason }
396eb60ceacSChris Mason 
397