summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/tree-log.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-10-10 11:30:51 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-10-10 11:30:51 -0400
commitf8779876d4a79d243870a5b5d60009e4ec6f22f4 (patch)
treeaeb62fd90c9eb089656a7742613c419490bc80fd /fs/btrfs/tree-log.c
parentad338d05438ec003f90ac7304fbac80ef2d8c80e (diff)
parent431d39887d6273d6d84edf3c2eab09f4200e788a (diff)
Merge tag 'for-5.4-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba: "A few more stabitly fixes, one build warning fix. - fix inode allocation under NOFS context - fix leak in fiemap due to concurrent append writes - fix log-root tree updates - fix balance convert of single profile on 32bit architectures - silence false positive warning on old GCCs (code moved in rc1)" * tag 'for-5.4-rc2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: silence maybe-uninitialized warning in clone_range btrfs: fix uninitialized ret in ref-verify btrfs: allocate new inode in NOFS context btrfs: fix balance convert to single on 32-bit host CPUs btrfs: fix incorrect updating of log root tree Btrfs: fix memory leak due to concurrent append writes with fiemap
Diffstat (limited to 'fs/btrfs/tree-log.c')
-rw-r--r--fs/btrfs/tree-log.c36
1 files changed, 27 insertions, 9 deletions
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 29b82a795522..8a6cc600bf18 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2932,7 +2932,8 @@ out:
2932 * in the tree of log roots 2932 * in the tree of log roots
2933 */ 2933 */
2934static int update_log_root(struct btrfs_trans_handle *trans, 2934static int update_log_root(struct btrfs_trans_handle *trans,
2935 struct btrfs_root *log) 2935 struct btrfs_root *log,
2936 struct btrfs_root_item *root_item)
2936{ 2937{
2937 struct btrfs_fs_info *fs_info = log->fs_info; 2938 struct btrfs_fs_info *fs_info = log->fs_info;
2938 int ret; 2939 int ret;
@@ -2940,10 +2941,10 @@ static int update_log_root(struct btrfs_trans_handle *trans,
2940 if (log->log_transid == 1) { 2941 if (log->log_transid == 1) {
2941 /* insert root item on the first sync */ 2942 /* insert root item on the first sync */
2942 ret = btrfs_insert_root(trans, fs_info->log_root_tree, 2943 ret = btrfs_insert_root(trans, fs_info->log_root_tree,
2943 &log->root_key, &log->root_item); 2944 &log->root_key, root_item);
2944 } else { 2945 } else {
2945 ret = btrfs_update_root(trans, fs_info->log_root_tree, 2946 ret = btrfs_update_root(trans, fs_info->log_root_tree,
2946 &log->root_key, &log->root_item); 2947 &log->root_key, root_item);
2947 } 2948 }
2948 return ret; 2949 return ret;
2949} 2950}
@@ -3041,6 +3042,7 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
3041 struct btrfs_fs_info *fs_info = root->fs_info; 3042 struct btrfs_fs_info *fs_info = root->fs_info;
3042 struct btrfs_root *log = root->log_root; 3043 struct btrfs_root *log = root->log_root;
3043 struct btrfs_root *log_root_tree = fs_info->log_root_tree; 3044 struct btrfs_root *log_root_tree = fs_info->log_root_tree;
3045 struct btrfs_root_item new_root_item;
3044 int log_transid = 0; 3046 int log_transid = 0;
3045 struct btrfs_log_ctx root_log_ctx; 3047 struct btrfs_log_ctx root_log_ctx;
3046 struct blk_plug plug; 3048 struct blk_plug plug;
@@ -3104,18 +3106,26 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
3104 goto out; 3106 goto out;
3105 } 3107 }
3106 3108
3109 /*
3110 * We _must_ update under the root->log_mutex in order to make sure we
3111 * have a consistent view of the log root we are trying to commit at
3112 * this moment.
3113 *
3114 * We _must_ copy this into a local copy, because we are not holding the
3115 * log_root_tree->log_mutex yet. This is important because when we
3116 * commit the log_root_tree we must have a consistent view of the
3117 * log_root_tree when we update the super block to point at the
3118 * log_root_tree bytenr. If we update the log_root_tree here we'll race
3119 * with the commit and possibly point at the new block which we may not
3120 * have written out.
3121 */
3107 btrfs_set_root_node(&log->root_item, log->node); 3122 btrfs_set_root_node(&log->root_item, log->node);
3123 memcpy(&new_root_item, &log->root_item, sizeof(new_root_item));
3108 3124
3109 root->log_transid++; 3125 root->log_transid++;
3110 log->log_transid = root->log_transid; 3126 log->log_transid = root->log_transid;
3111 root->log_start_pid = 0; 3127 root->log_start_pid = 0;
3112 /* 3128 /*
3113 * Update or create log root item under the root's log_mutex to prevent
3114 * races with concurrent log syncs that can lead to failure to update
3115 * log root item because it was not created yet.
3116 */
3117 ret = update_log_root(trans, log);
3118 /*
3119 * IO has been started, blocks of the log tree have WRITTEN flag set 3129 * IO has been started, blocks of the log tree have WRITTEN flag set
3120 * in their headers. new modifications of the log will be written to 3130 * in their headers. new modifications of the log will be written to
3121 * new positions. so it's safe to allow log writers to go in. 3131 * new positions. so it's safe to allow log writers to go in.
@@ -3135,6 +3145,14 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans,
3135 mutex_unlock(&log_root_tree->log_mutex); 3145 mutex_unlock(&log_root_tree->log_mutex);
3136 3146
3137 mutex_lock(&log_root_tree->log_mutex); 3147 mutex_lock(&log_root_tree->log_mutex);
3148
3149 /*
3150 * Now we are safe to update the log_root_tree because we're under the
3151 * log_mutex, and we're a current writer so we're holding the commit
3152 * open until we drop the log_mutex.
3153 */
3154 ret = update_log_root(trans, log, &new_root_item);
3155
3138 if (atomic_dec_and_test(&log_root_tree->log_writers)) { 3156 if (atomic_dec_and_test(&log_root_tree->log_writers)) {
3139 /* atomic_dec_and_test implies a barrier */ 3157 /* atomic_dec_and_test implies a barrier */
3140 cond_wake_up_nomb(&log_root_tree->log_writer_wait); 3158 cond_wake_up_nomb(&log_root_tree->log_writer_wait);