diff options
Diffstat (limited to 'fs/btrfs/root-tree.c')
| -rw-r--r-- | fs/btrfs/root-tree.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index 0ddc6d61c55a..5ef72599a581 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c | |||
| @@ -278,31 +278,57 @@ out: | |||
| 278 | return ret; | 278 | return ret; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | #if 0 /* this will get used when snapshot deletion is implemented */ | ||
| 282 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, | 281 | int btrfs_del_root_ref(struct btrfs_trans_handle *trans, |
| 283 | struct btrfs_root *tree_root, | 282 | struct btrfs_root *tree_root, |
| 284 | u64 root_id, u8 type, u64 ref_id) | 283 | u64 root_id, u64 ref_id, u64 dirid, u64 *sequence, |
| 284 | const char *name, int name_len) | ||
| 285 | |||
| 285 | { | 286 | { |
| 287 | struct btrfs_path *path; | ||
| 288 | struct btrfs_root_ref *ref; | ||
| 289 | struct extent_buffer *leaf; | ||
| 286 | struct btrfs_key key; | 290 | struct btrfs_key key; |
| 291 | unsigned long ptr; | ||
| 292 | int err = 0; | ||
| 287 | int ret; | 293 | int ret; |
| 288 | struct btrfs_path *path; | ||
| 289 | 294 | ||
| 290 | path = btrfs_alloc_path(); | 295 | path = btrfs_alloc_path(); |
| 296 | if (!path) | ||
| 297 | return -ENOMEM; | ||
| 291 | 298 | ||
| 292 | key.objectid = root_id; | 299 | key.objectid = root_id; |
| 293 | key.type = type; | 300 | key.type = BTRFS_ROOT_BACKREF_KEY; |
| 294 | key.offset = ref_id; | 301 | key.offset = ref_id; |
| 295 | 302 | again: | |
| 296 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); | 303 | ret = btrfs_search_slot(trans, tree_root, &key, path, -1, 1); |
| 297 | BUG_ON(ret); | 304 | BUG_ON(ret < 0); |
| 298 | 305 | if (ret == 0) { | |
| 299 | ret = btrfs_del_item(trans, tree_root, path); | 306 | leaf = path->nodes[0]; |
| 300 | BUG_ON(ret); | 307 | ref = btrfs_item_ptr(leaf, path->slots[0], |
| 308 | struct btrfs_root_ref); | ||
| 309 | |||
| 310 | WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid); | ||
| 311 | WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len); | ||
| 312 | ptr = (unsigned long)(ref + 1); | ||
| 313 | WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len)); | ||
| 314 | *sequence = btrfs_root_ref_sequence(leaf, ref); | ||
| 315 | |||
| 316 | ret = btrfs_del_item(trans, tree_root, path); | ||
| 317 | BUG_ON(ret); | ||
| 318 | } else | ||
| 319 | err = -ENOENT; | ||
| 320 | |||
| 321 | if (key.type == BTRFS_ROOT_BACKREF_KEY) { | ||
| 322 | btrfs_release_path(tree_root, path); | ||
| 323 | key.objectid = ref_id; | ||
| 324 | key.type = BTRFS_ROOT_REF_KEY; | ||
| 325 | key.offset = root_id; | ||
| 326 | goto again; | ||
| 327 | } | ||
| 301 | 328 | ||
| 302 | btrfs_free_path(path); | 329 | btrfs_free_path(path); |
| 303 | return ret; | 330 | return err; |
| 304 | } | 331 | } |
| 305 | #endif | ||
| 306 | 332 | ||
| 307 | int btrfs_find_root_ref(struct btrfs_root *tree_root, | 333 | int btrfs_find_root_ref(struct btrfs_root *tree_root, |
| 308 | struct btrfs_path *path, | 334 | struct btrfs_path *path, |
| @@ -319,7 +345,6 @@ int btrfs_find_root_ref(struct btrfs_root *tree_root, | |||
| 319 | return ret; | 345 | return ret; |
| 320 | } | 346 | } |
| 321 | 347 | ||
| 322 | |||
| 323 | /* | 348 | /* |
| 324 | * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY | 349 | * add a btrfs_root_ref item. type is either BTRFS_ROOT_REF_KEY |
| 325 | * or BTRFS_ROOT_BACKREF_KEY. | 350 | * or BTRFS_ROOT_BACKREF_KEY. |
| @@ -335,8 +360,7 @@ int btrfs_find_root_ref(struct btrfs_root *tree_root, | |||
| 335 | */ | 360 | */ |
| 336 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | 361 | int btrfs_add_root_ref(struct btrfs_trans_handle *trans, |
| 337 | struct btrfs_root *tree_root, | 362 | struct btrfs_root *tree_root, |
| 338 | u64 root_id, u8 type, u64 ref_id, | 363 | u64 root_id, u64 ref_id, u64 dirid, u64 sequence, |
| 339 | u64 dirid, u64 sequence, | ||
| 340 | const char *name, int name_len) | 364 | const char *name, int name_len) |
| 341 | { | 365 | { |
| 342 | struct btrfs_key key; | 366 | struct btrfs_key key; |
| @@ -346,13 +370,14 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | |||
| 346 | struct extent_buffer *leaf; | 370 | struct extent_buffer *leaf; |
| 347 | unsigned long ptr; | 371 | unsigned long ptr; |
| 348 | 372 | ||
| 349 | |||
| 350 | path = btrfs_alloc_path(); | 373 | path = btrfs_alloc_path(); |
| 374 | if (!path) | ||
| 375 | return -ENOMEM; | ||
| 351 | 376 | ||
| 352 | key.objectid = root_id; | 377 | key.objectid = root_id; |
| 353 | key.type = type; | 378 | key.type = BTRFS_ROOT_BACKREF_KEY; |
| 354 | key.offset = ref_id; | 379 | key.offset = ref_id; |
| 355 | 380 | again: | |
| 356 | ret = btrfs_insert_empty_item(trans, tree_root, path, &key, | 381 | ret = btrfs_insert_empty_item(trans, tree_root, path, &key, |
| 357 | sizeof(*ref) + name_len); | 382 | sizeof(*ref) + name_len); |
| 358 | BUG_ON(ret); | 383 | BUG_ON(ret); |
| @@ -366,6 +391,14 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, | |||
| 366 | write_extent_buffer(leaf, name, ptr, name_len); | 391 | write_extent_buffer(leaf, name, ptr, name_len); |
| 367 | btrfs_mark_buffer_dirty(leaf); | 392 | btrfs_mark_buffer_dirty(leaf); |
| 368 | 393 | ||
| 394 | if (key.type == BTRFS_ROOT_BACKREF_KEY) { | ||
| 395 | btrfs_release_path(tree_root, path); | ||
| 396 | key.objectid = ref_id; | ||
| 397 | key.type = BTRFS_ROOT_REF_KEY; | ||
| 398 | key.offset = root_id; | ||
| 399 | goto again; | ||
| 400 | } | ||
| 401 | |||
| 369 | btrfs_free_path(path); | 402 | btrfs_free_path(path); |
| 370 | return ret; | 403 | return 0; |
| 371 | } | 404 | } |
