diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-11-03 01:10:07 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2009-11-03 01:10:07 -0500 |
| commit | 7a53c7f56bbfc9b0ef892e68f5cfae3d902544d1 (patch) | |
| tree | 19dec256fc80ad06d631ece78b9eb68a457ce66b /fs/btrfs/tree-log.c | |
| parent | e57130698fe3dd2b7d617d90bbf86474473cb40c (diff) | |
| parent | 012abeea669ea49636cf952d13298bb68654146a (diff) | |
Merge commit 'v2.6.32-rc5' into for-linus
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 83 |
1 files changed, 65 insertions, 18 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index d91b0de7c502..741666a7676a 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -137,11 +137,20 @@ static int start_log_trans(struct btrfs_trans_handle *trans, | |||
| 137 | 137 | ||
| 138 | mutex_lock(&root->log_mutex); | 138 | mutex_lock(&root->log_mutex); |
| 139 | if (root->log_root) { | 139 | if (root->log_root) { |
| 140 | if (!root->log_start_pid) { | ||
| 141 | root->log_start_pid = current->pid; | ||
| 142 | root->log_multiple_pids = false; | ||
| 143 | } else if (root->log_start_pid != current->pid) { | ||
| 144 | root->log_multiple_pids = true; | ||
| 145 | } | ||
| 146 | |||
| 140 | root->log_batch++; | 147 | root->log_batch++; |
| 141 | atomic_inc(&root->log_writers); | 148 | atomic_inc(&root->log_writers); |
| 142 | mutex_unlock(&root->log_mutex); | 149 | mutex_unlock(&root->log_mutex); |
| 143 | return 0; | 150 | return 0; |
| 144 | } | 151 | } |
| 152 | root->log_multiple_pids = false; | ||
| 153 | root->log_start_pid = current->pid; | ||
| 145 | mutex_lock(&root->fs_info->tree_log_mutex); | 154 | mutex_lock(&root->fs_info->tree_log_mutex); |
| 146 | if (!root->fs_info->log_root_tree) { | 155 | if (!root->fs_info->log_root_tree) { |
| 147 | ret = btrfs_init_log_root_tree(trans, root->fs_info); | 156 | ret = btrfs_init_log_root_tree(trans, root->fs_info); |
| @@ -263,8 +272,8 @@ static int process_one_buffer(struct btrfs_root *log, | |||
| 263 | struct walk_control *wc, u64 gen) | 272 | struct walk_control *wc, u64 gen) |
| 264 | { | 273 | { |
| 265 | if (wc->pin) | 274 | if (wc->pin) |
| 266 | btrfs_update_pinned_extents(log->fs_info->extent_root, | 275 | btrfs_pin_extent(log->fs_info->extent_root, |
| 267 | eb->start, eb->len, 1); | 276 | eb->start, eb->len, 0); |
| 268 | 277 | ||
| 269 | if (btrfs_buffer_uptodate(eb, gen)) { | 278 | if (btrfs_buffer_uptodate(eb, gen)) { |
| 270 | if (wc->write) | 279 | if (wc->write) |
| @@ -534,7 +543,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
| 534 | saved_nbytes = inode_get_bytes(inode); | 543 | saved_nbytes = inode_get_bytes(inode); |
| 535 | /* drop any overlapping extents */ | 544 | /* drop any overlapping extents */ |
| 536 | ret = btrfs_drop_extents(trans, root, inode, | 545 | ret = btrfs_drop_extents(trans, root, inode, |
| 537 | start, extent_end, extent_end, start, &alloc_hint); | 546 | start, extent_end, extent_end, start, &alloc_hint, 1); |
| 538 | BUG_ON(ret); | 547 | BUG_ON(ret); |
| 539 | 548 | ||
| 540 | if (found_type == BTRFS_FILE_EXTENT_REG || | 549 | if (found_type == BTRFS_FILE_EXTENT_REG || |
| @@ -1971,6 +1980,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 1971 | int ret; | 1980 | int ret; |
| 1972 | struct btrfs_root *log = root->log_root; | 1981 | struct btrfs_root *log = root->log_root; |
| 1973 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; | 1982 | struct btrfs_root *log_root_tree = root->fs_info->log_root_tree; |
| 1983 | u64 log_transid = 0; | ||
| 1974 | 1984 | ||
| 1975 | mutex_lock(&root->log_mutex); | 1985 | mutex_lock(&root->log_mutex); |
| 1976 | index1 = root->log_transid % 2; | 1986 | index1 = root->log_transid % 2; |
| @@ -1987,10 +1997,11 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 1987 | 1997 | ||
| 1988 | while (1) { | 1998 | while (1) { |
| 1989 | unsigned long batch = root->log_batch; | 1999 | unsigned long batch = root->log_batch; |
| 1990 | mutex_unlock(&root->log_mutex); | 2000 | if (root->log_multiple_pids) { |
| 1991 | schedule_timeout_uninterruptible(1); | 2001 | mutex_unlock(&root->log_mutex); |
| 1992 | mutex_lock(&root->log_mutex); | 2002 | schedule_timeout_uninterruptible(1); |
| 1993 | 2003 | mutex_lock(&root->log_mutex); | |
| 2004 | } | ||
| 1994 | wait_for_writer(trans, root); | 2005 | wait_for_writer(trans, root); |
| 1995 | if (batch == root->log_batch) | 2006 | if (batch == root->log_batch) |
| 1996 | break; | 2007 | break; |
| @@ -2003,14 +2014,19 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2003 | goto out; | 2014 | goto out; |
| 2004 | } | 2015 | } |
| 2005 | 2016 | ||
| 2006 | ret = btrfs_write_and_wait_marked_extents(log, &log->dirty_log_pages); | 2017 | /* we start IO on all the marked extents here, but we don't actually |
| 2018 | * wait for them until later. | ||
| 2019 | */ | ||
| 2020 | ret = btrfs_write_marked_extents(log, &log->dirty_log_pages); | ||
| 2007 | BUG_ON(ret); | 2021 | BUG_ON(ret); |
| 2008 | 2022 | ||
| 2009 | btrfs_set_root_node(&log->root_item, log->node); | 2023 | btrfs_set_root_node(&log->root_item, log->node); |
| 2010 | 2024 | ||
| 2011 | root->log_batch = 0; | 2025 | root->log_batch = 0; |
| 2026 | log_transid = root->log_transid; | ||
| 2012 | root->log_transid++; | 2027 | root->log_transid++; |
| 2013 | log->log_transid = root->log_transid; | 2028 | log->log_transid = root->log_transid; |
| 2029 | root->log_start_pid = 0; | ||
| 2014 | smp_mb(); | 2030 | smp_mb(); |
| 2015 | /* | 2031 | /* |
| 2016 | * log tree has been flushed to disk, new modifications of | 2032 | * log tree has been flushed to disk, new modifications of |
| @@ -2036,6 +2052,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2036 | 2052 | ||
| 2037 | index2 = log_root_tree->log_transid % 2; | 2053 | index2 = log_root_tree->log_transid % 2; |
| 2038 | if (atomic_read(&log_root_tree->log_commit[index2])) { | 2054 | if (atomic_read(&log_root_tree->log_commit[index2])) { |
| 2055 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
| 2039 | wait_log_commit(trans, log_root_tree, | 2056 | wait_log_commit(trans, log_root_tree, |
| 2040 | log_root_tree->log_transid); | 2057 | log_root_tree->log_transid); |
| 2041 | mutex_unlock(&log_root_tree->log_mutex); | 2058 | mutex_unlock(&log_root_tree->log_mutex); |
| @@ -2055,6 +2072,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2055 | * check the full commit flag again | 2072 | * check the full commit flag again |
| 2056 | */ | 2073 | */ |
| 2057 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { | 2074 | if (root->fs_info->last_trans_log_full_commit == trans->transid) { |
| 2075 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
| 2058 | mutex_unlock(&log_root_tree->log_mutex); | 2076 | mutex_unlock(&log_root_tree->log_mutex); |
| 2059 | ret = -EAGAIN; | 2077 | ret = -EAGAIN; |
| 2060 | goto out_wake_log_root; | 2078 | goto out_wake_log_root; |
| @@ -2063,6 +2081,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2063 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | 2081 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, |
| 2064 | &log_root_tree->dirty_log_pages); | 2082 | &log_root_tree->dirty_log_pages); |
| 2065 | BUG_ON(ret); | 2083 | BUG_ON(ret); |
| 2084 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
| 2066 | 2085 | ||
| 2067 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 2086 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
| 2068 | log_root_tree->node->start); | 2087 | log_root_tree->node->start); |
| @@ -2082,9 +2101,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2082 | * the running transaction open, so a full commit can't hop | 2101 | * the running transaction open, so a full commit can't hop |
| 2083 | * in and cause problems either. | 2102 | * in and cause problems either. |
| 2084 | */ | 2103 | */ |
| 2085 | write_ctree_super(trans, root->fs_info->tree_root, 2); | 2104 | write_ctree_super(trans, root->fs_info->tree_root, 1); |
| 2086 | ret = 0; | 2105 | ret = 0; |
| 2087 | 2106 | ||
| 2107 | mutex_lock(&root->log_mutex); | ||
| 2108 | if (root->last_log_commit < log_transid) | ||
| 2109 | root->last_log_commit = log_transid; | ||
| 2110 | mutex_unlock(&root->log_mutex); | ||
| 2111 | |||
| 2088 | out_wake_log_root: | 2112 | out_wake_log_root: |
| 2089 | atomic_set(&log_root_tree->log_commit[index2], 0); | 2113 | atomic_set(&log_root_tree->log_commit[index2], 0); |
| 2090 | smp_mb(); | 2114 | smp_mb(); |
| @@ -2605,7 +2629,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2605 | extent); | 2629 | extent); |
| 2606 | cs = btrfs_file_extent_offset(src, extent); | 2630 | cs = btrfs_file_extent_offset(src, extent); |
| 2607 | cl = btrfs_file_extent_num_bytes(src, | 2631 | cl = btrfs_file_extent_num_bytes(src, |
| 2608 | extent);; | 2632 | extent); |
| 2609 | if (btrfs_file_extent_compression(src, | 2633 | if (btrfs_file_extent_compression(src, |
| 2610 | extent)) { | 2634 | extent)) { |
| 2611 | cs = 0; | 2635 | cs = 0; |
| @@ -2841,7 +2865,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
| 2841 | if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) | 2865 | if (!parent || !parent->d_inode || sb != parent->d_inode->i_sb) |
| 2842 | break; | 2866 | break; |
| 2843 | 2867 | ||
| 2844 | if (parent == sb->s_root) | 2868 | if (IS_ROOT(parent)) |
| 2845 | break; | 2869 | break; |
| 2846 | 2870 | ||
| 2847 | parent = parent->d_parent; | 2871 | parent = parent->d_parent; |
| @@ -2852,6 +2876,21 @@ out: | |||
| 2852 | return ret; | 2876 | return ret; |
| 2853 | } | 2877 | } |
| 2854 | 2878 | ||
| 2879 | static int inode_in_log(struct btrfs_trans_handle *trans, | ||
| 2880 | struct inode *inode) | ||
| 2881 | { | ||
| 2882 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 2883 | int ret = 0; | ||
| 2884 | |||
| 2885 | mutex_lock(&root->log_mutex); | ||
| 2886 | if (BTRFS_I(inode)->logged_trans == trans->transid && | ||
| 2887 | BTRFS_I(inode)->last_sub_trans <= root->last_log_commit) | ||
| 2888 | ret = 1; | ||
| 2889 | mutex_unlock(&root->log_mutex); | ||
| 2890 | return ret; | ||
| 2891 | } | ||
| 2892 | |||
| 2893 | |||
| 2855 | /* | 2894 | /* |
| 2856 | * helper function around btrfs_log_inode to make sure newly created | 2895 | * helper function around btrfs_log_inode to make sure newly created |
| 2857 | * parent directories also end up in the log. A minimal inode and backref | 2896 | * parent directories also end up in the log. A minimal inode and backref |
| @@ -2880,11 +2919,22 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2880 | goto end_no_trans; | 2919 | goto end_no_trans; |
| 2881 | } | 2920 | } |
| 2882 | 2921 | ||
| 2922 | if (root != BTRFS_I(inode)->root || | ||
| 2923 | btrfs_root_refs(&root->root_item) == 0) { | ||
| 2924 | ret = 1; | ||
| 2925 | goto end_no_trans; | ||
| 2926 | } | ||
| 2927 | |||
| 2883 | ret = check_parent_dirs_for_sync(trans, inode, parent, | 2928 | ret = check_parent_dirs_for_sync(trans, inode, parent, |
| 2884 | sb, last_committed); | 2929 | sb, last_committed); |
| 2885 | if (ret) | 2930 | if (ret) |
| 2886 | goto end_no_trans; | 2931 | goto end_no_trans; |
| 2887 | 2932 | ||
| 2933 | if (inode_in_log(trans, inode)) { | ||
| 2934 | ret = BTRFS_NO_LOG_SYNC; | ||
| 2935 | goto end_no_trans; | ||
| 2936 | } | ||
| 2937 | |||
| 2888 | start_log_trans(trans, root); | 2938 | start_log_trans(trans, root); |
| 2889 | 2939 | ||
| 2890 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2940 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
| @@ -2907,12 +2957,15 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2907 | break; | 2957 | break; |
| 2908 | 2958 | ||
| 2909 | inode = parent->d_inode; | 2959 | inode = parent->d_inode; |
| 2960 | if (root != BTRFS_I(inode)->root) | ||
| 2961 | break; | ||
| 2962 | |||
| 2910 | if (BTRFS_I(inode)->generation > | 2963 | if (BTRFS_I(inode)->generation > |
| 2911 | root->fs_info->last_trans_committed) { | 2964 | root->fs_info->last_trans_committed) { |
| 2912 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2965 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
| 2913 | BUG_ON(ret); | 2966 | BUG_ON(ret); |
| 2914 | } | 2967 | } |
| 2915 | if (parent == sb->s_root) | 2968 | if (IS_ROOT(parent)) |
| 2916 | break; | 2969 | break; |
| 2917 | 2970 | ||
| 2918 | parent = parent->d_parent; | 2971 | parent = parent->d_parent; |
| @@ -2951,7 +3004,6 @@ int btrfs_recover_log_trees(struct btrfs_root *log_root_tree) | |||
| 2951 | struct btrfs_key tmp_key; | 3004 | struct btrfs_key tmp_key; |
| 2952 | struct btrfs_root *log; | 3005 | struct btrfs_root *log; |
| 2953 | struct btrfs_fs_info *fs_info = log_root_tree->fs_info; | 3006 | struct btrfs_fs_info *fs_info = log_root_tree->fs_info; |
| 2954 | u64 highest_inode; | ||
| 2955 | struct walk_control wc = { | 3007 | struct walk_control wc = { |
| 2956 | .process_func = process_one_buffer, | 3008 | .process_func = process_one_buffer, |
| 2957 | .stage = 0, | 3009 | .stage = 0, |
| @@ -3010,11 +3062,6 @@ again: | |||
| 3010 | path); | 3062 | path); |
| 3011 | BUG_ON(ret); | 3063 | BUG_ON(ret); |
| 3012 | } | 3064 | } |
| 3013 | ret = btrfs_find_highest_inode(wc.replay_dest, &highest_inode); | ||
| 3014 | if (ret == 0) { | ||
| 3015 | wc.replay_dest->highest_inode = highest_inode; | ||
| 3016 | wc.replay_dest->last_inode_alloc = highest_inode; | ||
| 3017 | } | ||
| 3018 | 3065 | ||
| 3019 | key.offset = found_key.offset - 1; | 3066 | key.offset = found_key.offset - 1; |
| 3020 | wc.replay_dest->log_root = NULL; | 3067 | wc.replay_dest->log_root = NULL; |
