disk-io.c (2e635a278354a1a7951e16cfea4c247d6d0e7c99) | disk-io.c (e20d96d64f9cf9288ffecc9ad4714e91c3b97ca8) |
---|---|
1#define _XOPEN_SOURCE 500 2#include <stdio.h> 3#include <stdlib.h> 4#include <sys/types.h> 5#include <sys/stat.h> 6#include <fcntl.h> 7#include <unistd.h> 8#include "kerncompat.h" 9#include "radix-tree.h" | 1#include <linux/module.h> 2#include <linux/fs.h> |
10#include "ctree.h" 11#include "disk-io.h" 12#include "transaction.h" 13 | 3#include "ctree.h" 4#include "disk-io.h" 5#include "transaction.h" 6 |
14static int allocated_blocks = 0; 15int cache_max = 10000; 16 17static int check_tree_block(struct btrfs_root *root, struct btrfs_buffer *buf) | 7static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
18{ | 8{ |
19 if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) | 9 struct btrfs_node *node = btrfs_buffer_node(buf); 10 if (buf->b_blocknr != btrfs_header_blocknr(&node->header)) |
20 BUG(); | 11 BUG(); |
21 if (root->node && btrfs_header_parentid(&buf->node.header) != 22 btrfs_header_parentid(&root->node->node.header)) | 12 if (root->node && btrfs_header_parentid(&node->header) != 13 btrfs_header_parentid(btrfs_buffer_header(root->node))) |
23 BUG(); 24 return 0; 25} 26 | 14 BUG(); 15 return 0; 16} 17 |
27static int free_some_buffers(struct btrfs_root *root) | 18struct buffer_head *alloc_tree_block(struct btrfs_root *root, u64 blocknr) |
28{ | 19{ |
29 struct list_head *node, *next; 30 struct btrfs_buffer *b; 31 if (root->fs_info->cache_size < cache_max) 32 return 0; 33 list_for_each_safe(node, next, &root->fs_info->cache) { 34 b = list_entry(node, struct btrfs_buffer, cache); 35 if (b->count == 1) { 36 BUG_ON(!list_empty(&b->dirty)); 37 list_del_init(&b->cache); 38 btrfs_block_release(root, b); 39 if (root->fs_info->cache_size < cache_max) 40 break; 41 } 42 } 43 return 0; | 20 return sb_getblk(root->fs_info->sb, blocknr); |
44} 45 | 21} 22 |
46struct btrfs_buffer *alloc_tree_block(struct btrfs_root *root, u64 blocknr) | 23struct buffer_head *find_tree_block(struct btrfs_root *root, u64 blocknr) |
47{ | 24{ |
48 struct btrfs_buffer *buf; 49 int ret; 50 51 buf = malloc(sizeof(struct btrfs_buffer) + root->blocksize); 52 if (!buf) 53 return buf; 54 allocated_blocks++; 55 buf->blocknr = blocknr; 56 buf->count = 2; 57 INIT_LIST_HEAD(&buf->dirty); 58 free_some_buffers(root); 59 radix_tree_preload(GFP_KERNEL); 60 ret = radix_tree_insert(&root->fs_info->cache_radix, blocknr, buf); 61 radix_tree_preload_end(); 62 list_add_tail(&buf->cache, &root->fs_info->cache); 63 root->fs_info->cache_size++; 64 if (ret) { 65 free(buf); 66 return NULL; 67 } 68 return buf; | 25 return sb_getblk(root->fs_info->sb, blocknr); |
69} 70 | 26} 27 |
71struct btrfs_buffer *find_tree_block(struct btrfs_root *root, u64 blocknr) | 28struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) |
72{ | 29{ |
73 struct btrfs_buffer *buf; 74 buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); 75 if (buf) { 76 buf->count++; 77 } else { 78 buf = alloc_tree_block(root, blocknr); 79 if (!buf) { 80 BUG(); 81 return NULL; 82 } 83 } 84 return buf; 85} | 30 struct buffer_head *buf = sb_bread(root->fs_info->sb, blocknr); |
86 | 31 |
87struct btrfs_buffer *read_tree_block(struct btrfs_root *root, u64 blocknr) 88{ 89 loff_t offset = blocknr * root->blocksize; 90 struct btrfs_buffer *buf; 91 int ret; 92 93 buf = radix_tree_lookup(&root->fs_info->cache_radix, blocknr); 94 if (buf) { 95 buf->count++; 96 } else { 97 buf = alloc_tree_block(root, blocknr); 98 if (!buf) 99 return NULL; 100 ret = pread(root->fs_info->fp, &buf->node, root->blocksize, 101 offset); 102 if (ret != root->blocksize) { 103 free(buf); 104 return NULL; 105 } 106 } | 32 if (!buf) 33 return buf; |
107 if (check_tree_block(root, buf)) 108 BUG(); 109 return buf; 110} 111 112int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 34 if (check_tree_block(root, buf)) 35 BUG(); 36 return buf; 37} 38 39int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
113 struct btrfs_buffer *buf) | 40 struct buffer_head *buf) |
114{ | 41{ |
115 if (!list_empty(&buf->dirty)) 116 return 0; 117 list_add_tail(&buf->dirty, &root->fs_info->trans); 118 buf->count++; | 42 mark_buffer_dirty(buf); |
119 return 0; 120} 121 122int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 43 return 0; 44} 45 46int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
123 struct btrfs_buffer *buf) | 47 struct buffer_head *buf) |
124{ | 48{ |
125 if (!list_empty(&buf->dirty)) { 126 list_del_init(&buf->dirty); 127 btrfs_block_release(root, buf); 128 } | 49 clear_buffer_dirty(buf); |
129 return 0; 130} 131 132int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 50 return 0; 51} 52 53int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
133 struct btrfs_buffer *buf) | 54 struct buffer_head *buf) |
134{ | 55{ |
135 u64 blocknr = buf->blocknr; 136 loff_t offset = blocknr * root->blocksize; 137 int ret; 138 139 if (buf->blocknr != btrfs_header_blocknr(&buf->node.header)) 140 BUG(); 141 ret = pwrite(root->fs_info->fp, &buf->node, root->blocksize, offset); 142 if (ret != root->blocksize) 143 return ret; | 56 mark_buffer_dirty(buf); |
144 return 0; 145} 146 147static int __commit_transaction(struct btrfs_trans_handle *trans, struct 148 btrfs_root *root) 149{ | 57 return 0; 58} 59 60static int __commit_transaction(struct btrfs_trans_handle *trans, struct 61 btrfs_root *root) 62{ |
150 struct btrfs_buffer *b; 151 int ret = 0; 152 int wret; 153 while(!list_empty(&root->fs_info->trans)) { 154 b = list_entry(root->fs_info->trans.next, struct btrfs_buffer, 155 dirty); 156 list_del_init(&b->dirty); 157 wret = write_tree_block(trans, root, b); 158 if (wret) 159 ret = wret; 160 btrfs_block_release(root, b); 161 } 162 return ret; | 63 filemap_write_and_wait(root->fs_info->sb->s_bdev->bd_inode->i_mapping); 64 return 0; |
163} 164 165static int commit_tree_roots(struct btrfs_trans_handle *trans, 166 struct btrfs_fs_info *fs_info) 167{ 168 int ret; 169 u64 old_extent_block; 170 struct btrfs_root *tree_root = fs_info->tree_root; 171 struct btrfs_root *extent_root = fs_info->extent_root; 172 struct btrfs_root *inode_root = fs_info->inode_root; 173 174 btrfs_set_root_blocknr(&inode_root->root_item, | 65} 66 67static int commit_tree_roots(struct btrfs_trans_handle *trans, 68 struct btrfs_fs_info *fs_info) 69{ 70 int ret; 71 u64 old_extent_block; 72 struct btrfs_root *tree_root = fs_info->tree_root; 73 struct btrfs_root *extent_root = fs_info->extent_root; 74 struct btrfs_root *inode_root = fs_info->inode_root; 75 76 btrfs_set_root_blocknr(&inode_root->root_item, |
175 inode_root->node->blocknr); | 77 inode_root->node->b_blocknr); |
176 ret = btrfs_update_root(trans, tree_root, 177 &inode_root->root_key, 178 &inode_root->root_item); 179 BUG_ON(ret); 180 while(1) { 181 old_extent_block = btrfs_root_blocknr(&extent_root->root_item); | 78 ret = btrfs_update_root(trans, tree_root, 79 &inode_root->root_key, 80 &inode_root->root_item); 81 BUG_ON(ret); 82 while(1) { 83 old_extent_block = btrfs_root_blocknr(&extent_root->root_item); |
182 if (old_extent_block == extent_root->node->blocknr) | 84 if (old_extent_block == extent_root->node->b_blocknr) |
183 break; 184 btrfs_set_root_blocknr(&extent_root->root_item, | 85 break; 86 btrfs_set_root_blocknr(&extent_root->root_item, |
185 extent_root->node->blocknr); | 87 extent_root->node->b_blocknr); |
186 ret = btrfs_update_root(trans, tree_root, 187 &extent_root->root_key, 188 &extent_root->root_item); 189 BUG_ON(ret); 190 } 191 return 0; 192} 193 194int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct 195 btrfs_root *root, struct btrfs_super_block *s) 196{ 197 int ret = 0; | 88 ret = btrfs_update_root(trans, tree_root, 89 &extent_root->root_key, 90 &extent_root->root_item); 91 BUG_ON(ret); 92 } 93 return 0; 94} 95 96int btrfs_commit_transaction(struct btrfs_trans_handle *trans, struct 97 btrfs_root *root, struct btrfs_super_block *s) 98{ 99 int ret = 0; |
198 struct btrfs_buffer *snap = root->commit_root; | 100 struct buffer_head *snap = root->commit_root; |
199 struct btrfs_key snap_key; 200 201 if (root->commit_root == root->node) 202 return 0; 203 204 memcpy(&snap_key, &root->root_key, sizeof(snap_key)); 205 root->root_key.offset++; 206 | 101 struct btrfs_key snap_key; 102 103 if (root->commit_root == root->node) 104 return 0; 105 106 memcpy(&snap_key, &root->root_key, sizeof(snap_key)); 107 root->root_key.offset++; 108 |
207 btrfs_set_root_blocknr(&root->root_item, root->node->blocknr); | 109 btrfs_set_root_blocknr(&root->root_item, root->node->b_blocknr); |
208 ret = btrfs_insert_root(trans, root->fs_info->tree_root, 209 &root->root_key, &root->root_item); 210 BUG_ON(ret); 211 212 ret = commit_tree_roots(trans, root->fs_info); 213 BUG_ON(ret); 214 215 ret = __commit_transaction(trans, root); 216 BUG_ON(ret); 217 218 write_ctree_super(trans, root, s); 219 btrfs_finish_extent_commit(trans, root->fs_info->extent_root); 220 btrfs_finish_extent_commit(trans, root->fs_info->tree_root); 221 222 root->commit_root = root->node; | 110 ret = btrfs_insert_root(trans, root->fs_info->tree_root, 111 &root->root_key, &root->root_item); 112 BUG_ON(ret); 113 114 ret = commit_tree_roots(trans, root->fs_info); 115 BUG_ON(ret); 116 117 ret = __commit_transaction(trans, root); 118 BUG_ON(ret); 119 120 write_ctree_super(trans, root, s); 121 btrfs_finish_extent_commit(trans, root->fs_info->extent_root); 122 btrfs_finish_extent_commit(trans, root->fs_info->tree_root); 123 124 root->commit_root = root->node; |
223 root->node->count++; | 125 get_bh(root->node); |
224 ret = btrfs_drop_snapshot(trans, root, snap); 225 BUG_ON(ret); 226 227 ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key); 228 BUG_ON(ret); 229 root->fs_info->generation = root->root_key.offset + 1; 230 231 return ret; 232} 233 234static int __setup_root(struct btrfs_super_block *super, 235 struct btrfs_root *root, 236 struct btrfs_fs_info *fs_info, | 126 ret = btrfs_drop_snapshot(trans, root, snap); 127 BUG_ON(ret); 128 129 ret = btrfs_del_root(trans, root->fs_info->tree_root, &snap_key); 130 BUG_ON(ret); 131 root->fs_info->generation = root->root_key.offset + 1; 132 133 return ret; 134} 135 136static int __setup_root(struct btrfs_super_block *super, 137 struct btrfs_root *root, 138 struct btrfs_fs_info *fs_info, |
237 u64 objectid, int fp) | 139 u64 objectid) |
238{ 239 root->node = NULL; 240 root->commit_root = NULL; 241 root->blocksize = btrfs_super_blocksize(super); 242 root->ref_cows = 0; 243 root->fs_info = fs_info; 244 memset(&root->root_key, 0, sizeof(root->root_key)); 245 memset(&root->root_item, 0, sizeof(root->root_item)); 246 return 0; 247} 248 249static int find_and_setup_root(struct btrfs_super_block *super, 250 struct btrfs_root *tree_root, 251 struct btrfs_fs_info *fs_info, 252 u64 objectid, | 140{ 141 root->node = NULL; 142 root->commit_root = NULL; 143 root->blocksize = btrfs_super_blocksize(super); 144 root->ref_cows = 0; 145 root->fs_info = fs_info; 146 memset(&root->root_key, 0, sizeof(root->root_key)); 147 memset(&root->root_item, 0, sizeof(root->root_item)); 148 return 0; 149} 150 151static int find_and_setup_root(struct btrfs_super_block *super, 152 struct btrfs_root *tree_root, 153 struct btrfs_fs_info *fs_info, 154 u64 objectid, |
253 struct btrfs_root *root, int fp) | 155 struct btrfs_root *root) |
254{ 255 int ret; 256 | 156{ 157 int ret; 158 |
257 __setup_root(super, root, fs_info, objectid, fp); | 159 __setup_root(super, root, fs_info, objectid); |
258 ret = btrfs_find_last_root(tree_root, objectid, 259 &root->root_item, &root->root_key); 260 BUG_ON(ret); 261 262 root->node = read_tree_block(root, 263 btrfs_root_blocknr(&root->root_item)); 264 BUG_ON(!root->node); 265 return 0; 266} 267 | 160 ret = btrfs_find_last_root(tree_root, objectid, 161 &root->root_item, &root->root_key); 162 BUG_ON(ret); 163 164 root->node = read_tree_block(root, 165 btrfs_root_blocknr(&root->root_item)); 166 BUG_ON(!root->node); 167 return 0; 168} 169 |
268struct btrfs_root *open_ctree(char *filename, struct btrfs_super_block *super) | 170struct btrfs_root *open_ctree(struct super_block *sb, 171 struct buffer_head *sb_buffer, 172 struct btrfs_super_block *disk_super) |
269{ | 173{ |
270 int fp; 271 272 fp = open(filename, O_CREAT | O_RDWR, 0600); 273 if (fp < 0) { 274 return NULL; 275 } 276 return open_ctree_fd(fp, super); 277} 278 279struct btrfs_root *open_ctree_fd(int fp, struct btrfs_super_block *super) 280{ 281 struct btrfs_root *root = malloc(sizeof(struct btrfs_root)); 282 struct btrfs_root *extent_root = malloc(sizeof(struct btrfs_root)); 283 struct btrfs_root *tree_root = malloc(sizeof(struct btrfs_root)); 284 struct btrfs_root *inode_root = malloc(sizeof(struct btrfs_root)); 285 struct btrfs_fs_info *fs_info = malloc(sizeof(*fs_info)); | 174 struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), 175 GFP_NOFS); 176 struct btrfs_root *extent_root = kmalloc(sizeof(struct btrfs_root), 177 GFP_NOFS); 178 struct btrfs_root *tree_root = kmalloc(sizeof(struct btrfs_root), 179 GFP_NOFS); 180 struct btrfs_root *inode_root = kmalloc(sizeof(struct btrfs_root), 181 GFP_NOFS); 182 struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), 183 GFP_NOFS); |
286 int ret; 287 | 184 int ret; 185 |
288 INIT_RADIX_TREE(&fs_info->cache_radix, GFP_KERNEL); | 186 /* FIXME: don't be stupid */ 187 if (!btrfs_super_root(disk_super)) 188 return NULL; |
289 INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); | 189 INIT_RADIX_TREE(&fs_info->pinned_radix, GFP_KERNEL); |
290 INIT_LIST_HEAD(&fs_info->trans); 291 INIT_LIST_HEAD(&fs_info->cache); 292 fs_info->cache_size = 0; 293 fs_info->fp = fp; | |
294 fs_info->running_transaction = NULL; 295 fs_info->fs_root = root; 296 fs_info->tree_root = tree_root; 297 fs_info->extent_root = extent_root; 298 fs_info->inode_root = inode_root; 299 fs_info->last_inode_alloc = 0; 300 fs_info->last_inode_alloc_dirid = 0; | 190 fs_info->running_transaction = NULL; 191 fs_info->fs_root = root; 192 fs_info->tree_root = tree_root; 193 fs_info->extent_root = extent_root; 194 fs_info->inode_root = inode_root; 195 fs_info->last_inode_alloc = 0; 196 fs_info->last_inode_alloc_dirid = 0; |
301 fs_info->disk_super = super; | 197 fs_info->disk_super = disk_super; 198 fs_info->sb_buffer = sb_buffer; 199 fs_info->sb = sb; |
302 memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); 303 memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); 304 | 200 memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); 201 memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); 202 |
305 ret = pread(fp, super, sizeof(struct btrfs_super_block), 306 BTRFS_SUPER_INFO_OFFSET); 307 if (ret == 0 || btrfs_super_root(super) == 0) { 308 BUG(); 309 return NULL; 310 } 311 BUG_ON(ret < 0); 312 313 __setup_root(super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID, fp); 314 tree_root->node = read_tree_block(tree_root, btrfs_super_root(super)); | 203 __setup_root(disk_super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); 204 tree_root->node = read_tree_block(tree_root, 205 btrfs_super_root(disk_super)); |
315 BUG_ON(!tree_root->node); 316 | 206 BUG_ON(!tree_root->node); 207 |
317 ret = find_and_setup_root(super, tree_root, fs_info, 318 BTRFS_EXTENT_TREE_OBJECTID, extent_root, fp); | 208 ret = find_and_setup_root(disk_super, tree_root, fs_info, 209 BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
319 BUG_ON(ret); 320 | 210 BUG_ON(ret); 211 |
321 ret = find_and_setup_root(super, tree_root, fs_info, 322 BTRFS_INODE_MAP_OBJECTID, inode_root, fp); | 212 ret = find_and_setup_root(disk_super, tree_root, fs_info, 213 BTRFS_INODE_MAP_OBJECTID, inode_root); |
323 BUG_ON(ret); 324 | 214 BUG_ON(ret); 215 |
325 ret = find_and_setup_root(super, tree_root, fs_info, 326 BTRFS_FS_TREE_OBJECTID, root, fp); | 216 ret = find_and_setup_root(disk_super, tree_root, fs_info, 217 BTRFS_FS_TREE_OBJECTID, root); |
327 BUG_ON(ret); 328 329 root->commit_root = root->node; | 218 BUG_ON(ret); 219 220 root->commit_root = root->node; |
330 root->node->count++; | 221 get_bh(root->node); |
331 root->ref_cows = 1; 332 root->fs_info->generation = root->root_key.offset + 1; 333 return root; 334} 335 336int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 337 *root, struct btrfs_super_block *s) 338{ | 222 root->ref_cows = 1; 223 root->fs_info->generation = root->root_key.offset + 1; 224 return root; 225} 226 227int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root 228 *root, struct btrfs_super_block *s) 229{ |
230 return 0; 231#if 0 |
|
339 int ret; | 232 int ret; |
340 btrfs_set_super_root(s, root->fs_info->tree_root->node->blocknr); | 233 btrfs_set_super_root(s, root->fs_info->tree_root->node->b_blocknr); 234 |
341 ret = pwrite(root->fs_info->fp, s, sizeof(*s), 342 BTRFS_SUPER_INFO_OFFSET); 343 if (ret != sizeof(*s)) { 344 fprintf(stderr, "failed to write new super block err %d\n", ret); 345 return ret; 346 } 347 return 0; | 235 ret = pwrite(root->fs_info->fp, s, sizeof(*s), 236 BTRFS_SUPER_INFO_OFFSET); 237 if (ret != sizeof(*s)) { 238 fprintf(stderr, "failed to write new super block err %d\n", ret); 239 return ret; 240 } 241 return 0; |
242#endif |
|
348} 349 350static int drop_cache(struct btrfs_root *root) 351{ | 243} 244 245static int drop_cache(struct btrfs_root *root) 246{ |
247 return 0; 248#if 0 |
|
352 while(!list_empty(&root->fs_info->cache)) { | 249 while(!list_empty(&root->fs_info->cache)) { |
353 struct btrfs_buffer *b = list_entry(root->fs_info->cache.next, 354 struct btrfs_buffer, | 250 struct buffer_head *b = list_entry(root->fs_info->cache.next, 251 struct buffer_head, |
355 cache); 356 list_del_init(&b->cache); 357 btrfs_block_release(root, b); 358 } 359 return 0; | 252 cache); 253 list_del_init(&b->cache); 254 btrfs_block_release(root, b); 255 } 256 return 0; |
257#endif |
|
360} | 258} |
361int close_ctree(struct btrfs_root *root, struct btrfs_super_block *s) | 259 260int close_ctree(struct btrfs_root *root) |
362{ 363 int ret; 364 struct btrfs_trans_handle *trans; 365 366 trans = root->fs_info->running_transaction; | 261{ 262 int ret; 263 struct btrfs_trans_handle *trans; 264 265 trans = root->fs_info->running_transaction; |
367 btrfs_commit_transaction(trans, root, s); | 266 btrfs_commit_transaction(trans, root, root->fs_info->disk_super); |
368 ret = commit_tree_roots(trans, root->fs_info); 369 BUG_ON(ret); 370 ret = __commit_transaction(trans, root); 371 BUG_ON(ret); | 267 ret = commit_tree_roots(trans, root->fs_info); 268 BUG_ON(ret); 269 ret = __commit_transaction(trans, root); 270 BUG_ON(ret); |
372 write_ctree_super(trans, root, s); | 271 write_ctree_super(trans, root, root->fs_info->disk_super); |
373 drop_cache(root); | 272 drop_cache(root); |
374 BUG_ON(!list_empty(&root->fs_info->trans)); | |
375 | 273 |
376 close(root->fs_info->fp); | |
377 if (root->node) 378 btrfs_block_release(root, root->node); 379 if (root->fs_info->extent_root->node) 380 btrfs_block_release(root->fs_info->extent_root, 381 root->fs_info->extent_root->node); 382 if (root->fs_info->inode_root->node) 383 btrfs_block_release(root->fs_info->inode_root, 384 root->fs_info->inode_root->node); 385 if (root->fs_info->tree_root->node) 386 btrfs_block_release(root->fs_info->tree_root, 387 root->fs_info->tree_root->node); 388 btrfs_block_release(root, root->commit_root); | 274 if (root->node) 275 btrfs_block_release(root, root->node); 276 if (root->fs_info->extent_root->node) 277 btrfs_block_release(root->fs_info->extent_root, 278 root->fs_info->extent_root->node); 279 if (root->fs_info->inode_root->node) 280 btrfs_block_release(root->fs_info->inode_root, 281 root->fs_info->inode_root->node); 282 if (root->fs_info->tree_root->node) 283 btrfs_block_release(root->fs_info->tree_root, 284 root->fs_info->tree_root->node); 285 btrfs_block_release(root, root->commit_root); |
389 free(root); 390 printf("on close %d blocks are allocated\n", allocated_blocks); | 286 btrfs_block_release(root, root->fs_info->sb_buffer); 287 kfree(root->fs_info->extent_root); 288 kfree(root->fs_info->inode_root); 289 kfree(root->fs_info->tree_root); 290 kfree(root->fs_info); 291 kfree(root); |
391 return 0; 392} 393 | 292 return 0; 293} 294 |
394void btrfs_block_release(struct btrfs_root *root, struct btrfs_buffer *buf) | 295void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
395{ | 296{ |
396 buf->count--; 397 if (buf->count < 0) 398 BUG(); 399 if (buf->count == 0) { 400 BUG_ON(!list_empty(&buf->cache)); 401 BUG_ON(!list_empty(&buf->dirty)); 402 if (!radix_tree_lookup(&root->fs_info->cache_radix, 403 buf->blocknr)) 404 BUG(); 405 radix_tree_delete(&root->fs_info->cache_radix, buf->blocknr); 406 memset(buf, 0, sizeof(*buf)); 407 free(buf); 408 BUG_ON(allocated_blocks == 0); 409 allocated_blocks--; 410 BUG_ON(root->fs_info->cache_size == 0); 411 root->fs_info->cache_size--; 412 } | 297 brelse(buf); |
413} 414 | 298} 299 |