diff options
Diffstat (limited to 'fs/btrfs/tree-log.c')
| -rw-r--r-- | fs/btrfs/tree-log.c | 48 |
1 files changed, 41 insertions, 7 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 4edfdc2acc5f..741666a7676a 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -1980,6 +1980,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 1980 | int ret; | 1980 | int ret; |
| 1981 | struct btrfs_root *log = root->log_root; | 1981 | struct btrfs_root *log = root->log_root; |
| 1982 | 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; | ||
| 1983 | 1984 | ||
| 1984 | mutex_lock(&root->log_mutex); | 1985 | mutex_lock(&root->log_mutex); |
| 1985 | index1 = root->log_transid % 2; | 1986 | index1 = root->log_transid % 2; |
| @@ -1994,12 +1995,13 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 1994 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) | 1995 | if (atomic_read(&root->log_commit[(index1 + 1) % 2])) |
| 1995 | wait_log_commit(trans, root, root->log_transid - 1); | 1996 | wait_log_commit(trans, root, root->log_transid - 1); |
| 1996 | 1997 | ||
| 1997 | while (root->log_multiple_pids) { | 1998 | while (1) { |
| 1998 | unsigned long batch = root->log_batch; | 1999 | unsigned long batch = root->log_batch; |
| 1999 | mutex_unlock(&root->log_mutex); | 2000 | if (root->log_multiple_pids) { |
| 2000 | schedule_timeout_uninterruptible(1); | 2001 | mutex_unlock(&root->log_mutex); |
| 2001 | mutex_lock(&root->log_mutex); | 2002 | schedule_timeout_uninterruptible(1); |
| 2002 | 2003 | mutex_lock(&root->log_mutex); | |
| 2004 | } | ||
| 2003 | wait_for_writer(trans, root); | 2005 | wait_for_writer(trans, root); |
| 2004 | if (batch == root->log_batch) | 2006 | if (batch == root->log_batch) |
| 2005 | break; | 2007 | break; |
| @@ -2012,12 +2014,16 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2012 | goto out; | 2014 | goto out; |
| 2013 | } | 2015 | } |
| 2014 | 2016 | ||
| 2015 | 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); | ||
| 2016 | BUG_ON(ret); | 2021 | BUG_ON(ret); |
| 2017 | 2022 | ||
| 2018 | btrfs_set_root_node(&log->root_item, log->node); | 2023 | btrfs_set_root_node(&log->root_item, log->node); |
| 2019 | 2024 | ||
| 2020 | root->log_batch = 0; | 2025 | root->log_batch = 0; |
| 2026 | log_transid = root->log_transid; | ||
| 2021 | root->log_transid++; | 2027 | root->log_transid++; |
| 2022 | log->log_transid = root->log_transid; | 2028 | log->log_transid = root->log_transid; |
| 2023 | root->log_start_pid = 0; | 2029 | root->log_start_pid = 0; |
| @@ -2046,6 +2052,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2046 | 2052 | ||
| 2047 | index2 = log_root_tree->log_transid % 2; | 2053 | index2 = log_root_tree->log_transid % 2; |
| 2048 | 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); | ||
| 2049 | wait_log_commit(trans, log_root_tree, | 2056 | wait_log_commit(trans, log_root_tree, |
| 2050 | log_root_tree->log_transid); | 2057 | log_root_tree->log_transid); |
| 2051 | mutex_unlock(&log_root_tree->log_mutex); | 2058 | mutex_unlock(&log_root_tree->log_mutex); |
| @@ -2065,6 +2072,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2065 | * check the full commit flag again | 2072 | * check the full commit flag again |
| 2066 | */ | 2073 | */ |
| 2067 | 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); | ||
| 2068 | mutex_unlock(&log_root_tree->log_mutex); | 2076 | mutex_unlock(&log_root_tree->log_mutex); |
| 2069 | ret = -EAGAIN; | 2077 | ret = -EAGAIN; |
| 2070 | goto out_wake_log_root; | 2078 | goto out_wake_log_root; |
| @@ -2073,6 +2081,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2073 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, | 2081 | ret = btrfs_write_and_wait_marked_extents(log_root_tree, |
| 2074 | &log_root_tree->dirty_log_pages); | 2082 | &log_root_tree->dirty_log_pages); |
| 2075 | BUG_ON(ret); | 2083 | BUG_ON(ret); |
| 2084 | btrfs_wait_marked_extents(log, &log->dirty_log_pages); | ||
| 2076 | 2085 | ||
| 2077 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, | 2086 | btrfs_set_super_log_root(&root->fs_info->super_for_commit, |
| 2078 | log_root_tree->node->start); | 2087 | log_root_tree->node->start); |
| @@ -2092,9 +2101,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, | |||
| 2092 | * the running transaction open, so a full commit can't hop | 2101 | * the running transaction open, so a full commit can't hop |
| 2093 | * in and cause problems either. | 2102 | * in and cause problems either. |
| 2094 | */ | 2103 | */ |
| 2095 | write_ctree_super(trans, root->fs_info->tree_root, 2); | 2104 | write_ctree_super(trans, root->fs_info->tree_root, 1); |
| 2096 | ret = 0; | 2105 | ret = 0; |
| 2097 | 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 | |||
| 2098 | out_wake_log_root: | 2112 | out_wake_log_root: |
| 2099 | atomic_set(&log_root_tree->log_commit[index2], 0); | 2113 | atomic_set(&log_root_tree->log_commit[index2], 0); |
| 2100 | smp_mb(); | 2114 | smp_mb(); |
| @@ -2862,6 +2876,21 @@ out: | |||
| 2862 | return ret; | 2876 | return ret; |
| 2863 | } | 2877 | } |
| 2864 | 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 | |||
| 2865 | /* | 2894 | /* |
| 2866 | * helper function around btrfs_log_inode to make sure newly created | 2895 | * helper function around btrfs_log_inode to make sure newly created |
| 2867 | * 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 |
| @@ -2901,6 +2930,11 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2901 | if (ret) | 2930 | if (ret) |
| 2902 | goto end_no_trans; | 2931 | goto end_no_trans; |
| 2903 | 2932 | ||
| 2933 | if (inode_in_log(trans, inode)) { | ||
| 2934 | ret = BTRFS_NO_LOG_SYNC; | ||
| 2935 | goto end_no_trans; | ||
| 2936 | } | ||
| 2937 | |||
| 2904 | start_log_trans(trans, root); | 2938 | start_log_trans(trans, root); |
| 2905 | 2939 | ||
| 2906 | ret = btrfs_log_inode(trans, root, inode, inode_only); | 2940 | ret = btrfs_log_inode(trans, root, inode, inode_only); |
