aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/free-space-cache.c
diff options
context:
space:
mode:
authorLi Zefan <lizf@cn.fujitsu.com>2011-04-19 22:33:24 -0400
committerLi Zefan <lizf@cn.fujitsu.com>2011-04-25 04:46:11 -0400
commit82d5902d9c681be37ffa9d70482907f9f0b7ec1f (patch)
treec9c99f0b60004ac14d09d277d3216667df09c32d /fs/btrfs/free-space-cache.c
parent33345d01522f8152f99dc84a3e7a1a45707f387f (diff)
Btrfs: Support reading/writing on disk free ino cache
This is similar to block group caching. We dedicate a special inode in fs tree to save free ino cache. At the very first time we create/delete a file after mount, the free ino cache will be loaded from disk into memory. When the fs tree is commited, the cache will be written back to disk. To keep compatibility, we check the root generation against the generation of the special inode when loading the cache, so the loading will fail if the btrfs filesystem was mounted in an older kernel before. Signed-off-by: Li Zefan <lizf@cn.fujitsu.com>
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r--fs/btrfs/free-space-cache.c97
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
215static int readahead_cache(struct inode *inode) 216static 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
2465struct 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
2489int 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
2497int 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);
2529out_put:
2530 iput(inode);
2531out:
2532 btrfs_free_path(path);
2533 return ret;
2534}
2535
2536int 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}