diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index fcbdcef6ca28..7d8b6b643403 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -209,7 +209,8 @@ int btrfs_truncate_free_space_cache(struct btrfs_root *root, | |||
209 | return ret; | 209 | return ret; |
210 | } | 210 | } |
211 | 211 | ||
212 | return btrfs_update_inode(trans, root, inode); | 212 | ret = btrfs_update_inode(trans, root, inode); |
213 | return ret; | ||
213 | } | 214 | } |
214 | 215 | ||
215 | static int readahead_cache(struct inode *inode) | 216 | static int readahead_cache(struct inode *inode) |
@@ -525,6 +526,7 @@ out: | |||
525 | spin_lock(&block_group->lock); | 526 | spin_lock(&block_group->lock); |
526 | block_group->disk_cache_state = BTRFS_DC_CLEAR; | 527 | block_group->disk_cache_state = BTRFS_DC_CLEAR; |
527 | spin_unlock(&block_group->lock); | 528 | spin_unlock(&block_group->lock); |
529 | ret = 0; | ||
528 | 530 | ||
529 | printk(KERN_ERR "btrfs: failed to load free space cache " | 531 | printk(KERN_ERR "btrfs: failed to load free space cache " |
530 | "for block group %llu\n", block_group->key.objectid); | 532 | "for block group %llu\n", block_group->key.objectid); |
@@ -893,6 +895,7 @@ int btrfs_write_out_cache(struct btrfs_root *root, | |||
893 | spin_lock(&block_group->lock); | 895 | spin_lock(&block_group->lock); |
894 | block_group->disk_cache_state = BTRFS_DC_ERROR; | 896 | block_group->disk_cache_state = BTRFS_DC_ERROR; |
895 | spin_unlock(&block_group->lock); | 897 | spin_unlock(&block_group->lock); |
898 | ret = 0; | ||
896 | 899 | ||
897 | printk(KERN_ERR "btrfs: failed to write free space cace " | 900 | printk(KERN_ERR "btrfs: failed to write free space cace " |
898 | "for block group %llu\n", block_group->key.objectid); | 901 | "for block group %llu\n", block_group->key.objectid); |
@@ -2458,3 +2461,95 @@ out: | |||
2458 | 2461 | ||
2459 | return ino; | 2462 | return ino; |
2460 | } | 2463 | } |
2464 | |||
2465 | struct inode *lookup_free_ino_inode(struct btrfs_root *root, | ||
2466 | struct btrfs_path *path) | ||
2467 | { | ||
2468 | struct inode *inode = NULL; | ||
2469 | |||
2470 | spin_lock(&root->cache_lock); | ||
2471 | if (root->cache_inode) | ||
2472 | inode = igrab(root->cache_inode); | ||
2473 | spin_unlock(&root->cache_lock); | ||
2474 | if (inode) | ||
2475 | return inode; | ||
2476 | |||
2477 | inode = __lookup_free_space_inode(root, path, 0); | ||
2478 | if (IS_ERR(inode)) | ||
2479 | return inode; | ||
2480 | |||
2481 | spin_lock(&root->cache_lock); | ||
2482 | if (!root->fs_info->closing) | ||
2483 | root->cache_inode = igrab(inode); | ||
2484 | spin_unlock(&root->cache_lock); | ||
2485 | |||
2486 | return inode; | ||
2487 | } | ||
2488 | |||
2489 | int create_free_ino_inode(struct btrfs_root *root, | ||
2490 | struct btrfs_trans_handle *trans, | ||
2491 | struct btrfs_path *path) | ||
2492 | { | ||
2493 | return __create_free_space_inode(root, trans, path, | ||
2494 | BTRFS_FREE_INO_OBJECTID, 0); | ||
2495 | } | ||
2496 | |||
2497 | int load_free_ino_cache(struct btrfs_fs_info *fs_info, struct btrfs_root *root) | ||
2498 | { | ||
2499 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | ||
2500 | struct btrfs_path *path; | ||
2501 | struct inode *inode; | ||
2502 | int ret = 0; | ||
2503 | u64 root_gen = btrfs_root_generation(&root->root_item); | ||
2504 | |||
2505 | /* | ||
2506 | * If we're unmounting then just return, since this does a search on the | ||
2507 | * normal root and not the commit root and we could deadlock. | ||
2508 | */ | ||
2509 | smp_mb(); | ||
2510 | if (fs_info->closing) | ||
2511 | return 0; | ||
2512 | |||
2513 | path = btrfs_alloc_path(); | ||
2514 | if (!path) | ||
2515 | return 0; | ||
2516 | |||
2517 | inode = lookup_free_ino_inode(root, path); | ||
2518 | if (IS_ERR(inode)) | ||
2519 | goto out; | ||
2520 | |||
2521 | if (root_gen != BTRFS_I(inode)->generation) | ||
2522 | goto out_put; | ||
2523 | |||
2524 | ret = __load_free_space_cache(root, inode, ctl, path, 0); | ||
2525 | |||
2526 | if (ret < 0) | ||
2527 | printk(KERN_ERR "btrfs: failed to load free ino cache for " | ||
2528 | "root %llu\n", root->root_key.objectid); | ||
2529 | out_put: | ||
2530 | iput(inode); | ||
2531 | out: | ||
2532 | btrfs_free_path(path); | ||
2533 | return ret; | ||
2534 | } | ||
2535 | |||
2536 | int btrfs_write_out_ino_cache(struct btrfs_root *root, | ||
2537 | struct btrfs_trans_handle *trans, | ||
2538 | struct btrfs_path *path) | ||
2539 | { | ||
2540 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | ||
2541 | struct inode *inode; | ||
2542 | int ret; | ||
2543 | |||
2544 | inode = lookup_free_ino_inode(root, path); | ||
2545 | if (IS_ERR(inode)) | ||
2546 | return 0; | ||
2547 | |||
2548 | ret = __btrfs_write_out_cache(root, inode, ctl, NULL, trans, path, 0); | ||
2549 | if (ret < 0) | ||
2550 | printk(KERN_ERR "btrfs: failed to write free ino cache " | ||
2551 | "for root %llu\n", root->root_key.objectid); | ||
2552 | |||
2553 | iput(inode); | ||
2554 | return ret; | ||
2555 | } | ||