]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.19/btrfs-fix-wrong-ctime-and-mtime-of-a-directory-after-log-replay.patch
4.9-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.19 / btrfs-fix-wrong-ctime-and-mtime-of-a-directory-after-log-replay.patch
CommitLineData
14e9555d
GKH
1From 5338e43abbab13791144d37fd8846847062351c6 Mon Sep 17 00:00:00 2001
2From: Filipe Manana <fdmanana@suse.com>
3Date: Wed, 15 May 2019 16:02:47 +0100
4Subject: Btrfs: fix wrong ctime and mtime of a directory after log replay
5
6From: Filipe Manana <fdmanana@suse.com>
7
8commit 5338e43abbab13791144d37fd8846847062351c6 upstream.
9
10When replaying a log that contains a new file or directory name that needs
11to be added to its parent directory, we end up updating the mtime and the
12ctime of the parent directory to the current time after we have set their
13values to the correct ones (set at fsync time), efectivelly losing them.
14
15Sample reproducer:
16
17 $ mkfs.btrfs -f /dev/sdb
18 $ mount /dev/sdb /mnt
19
20 $ mkdir /mnt/dir
21 $ touch /mnt/dir/file
22
23 # fsync of the directory is optional, not needed
24 $ xfs_io -c fsync /mnt/dir
25 $ xfs_io -c fsync /mnt/dir/file
26
27 $ stat -c %Y /mnt/dir
28 1557856079
29
30 <power failure>
31
32 $ sleep 3
33 $ mount /dev/sdb /mnt
34 $ stat -c %Y /mnt/dir
35 1557856082
36
37 --> should have been 1557856079, the mtime is updated to the current
38 time when replaying the log
39
40Fix this by not updating the mtime and ctime to the current time at
41btrfs_add_link() when we are replaying a log tree.
42
43This could be triggered by my recent fsync fuzz tester for fstests, for
44which an fstests patch exists titled "fstests: generic, fsync fuzz tester
45with fsstress".
46
47Fixes: e02119d5a7b43 ("Btrfs: Add a write ahead tree log to optimize synchronous operations")
48CC: stable@vger.kernel.org # 4.4+
49Reviewed-by: Nikolay Borisov <nborisov@suse.com>
50Signed-off-by: Filipe Manana <fdmanana@suse.com>
51Signed-off-by: David Sterba <dsterba@suse.com>
52Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
53
54---
55 fs/btrfs/inode.c | 14 ++++++++++++--
56 1 file changed, 12 insertions(+), 2 deletions(-)
57
58--- a/fs/btrfs/inode.c
59+++ b/fs/btrfs/inode.c
60@@ -6426,8 +6426,18 @@ int btrfs_add_link(struct btrfs_trans_ha
61 btrfs_i_size_write(parent_inode, parent_inode->vfs_inode.i_size +
62 name_len * 2);
63 inode_inc_iversion(&parent_inode->vfs_inode);
64- parent_inode->vfs_inode.i_mtime = parent_inode->vfs_inode.i_ctime =
65- current_time(&parent_inode->vfs_inode);
66+ /*
67+ * If we are replaying a log tree, we do not want to update the mtime
68+ * and ctime of the parent directory with the current time, since the
69+ * log replay procedure is responsible for setting them to their correct
70+ * values (the ones it had when the fsync was done).
71+ */
72+ if (!test_bit(BTRFS_FS_LOG_RECOVERING, &root->fs_info->flags)) {
73+ struct timespec64 now = current_time(&parent_inode->vfs_inode);
74+
75+ parent_inode->vfs_inode.i_mtime = now;
76+ parent_inode->vfs_inode.i_ctime = now;
77+ }
78 ret = btrfs_update_inode(trans, root, &parent_inode->vfs_inode);
79 if (ret)
80 btrfs_abort_transaction(trans, ret);