]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.5-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 May 2016 00:02:09 +0000 (17:02 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 17 May 2016 00:02:09 +0000 (17:02 -0700)
added patches:
btrfs-change-max_inline-default-to-2048.patch
btrfs-fix-file-loss-on-log-replay-after-renaming-a-file-and-fsync.patch
btrfs-fix-unreplayable-log-after-snapshot-delete-parent-dir-fsync.patch

queue-4.5/btrfs-change-max_inline-default-to-2048.patch [new file with mode: 0644]
queue-4.5/btrfs-fix-file-loss-on-log-replay-after-renaming-a-file-and-fsync.patch [new file with mode: 0644]
queue-4.5/btrfs-fix-unreplayable-log-after-snapshot-delete-parent-dir-fsync.patch [new file with mode: 0644]
queue-4.5/series

diff --git a/queue-4.5/btrfs-change-max_inline-default-to-2048.patch b/queue-4.5/btrfs-change-max_inline-default-to-2048.patch
new file mode 100644 (file)
index 0000000..19903da
--- /dev/null
@@ -0,0 +1,58 @@
+From f7e98a7fff8634ae655c666dc2c9fc55a48d0a73 Mon Sep 17 00:00:00 2001
+From: David Sterba <dsterba@suse.com>
+Date: Thu, 8 Oct 2015 14:14:16 +0200
+Subject: btrfs: change max_inline default to 2048
+
+From: David Sterba <dsterba@suse.com>
+
+commit f7e98a7fff8634ae655c666dc2c9fc55a48d0a73 upstream.
+
+The current practical default is ~4k on x86_64 (the logic is more complex,
+simplified for brevity), the inlined files land in the metadata group and
+thus consume space that could be needed for the real metadata.
+
+The inlining brings some usability surprises:
+
+1) total space consumption measured on various filesystems and btrfs
+   with DUP metadata was quite visible because of the duplicated data
+   within metadata
+
+2) inlined data may exhaust the metadata, which are more precious in case
+   the entire device space is allocated to chunks (ie. balance cannot
+   make the space more compact)
+
+3) performance suffers a bit as the inlined blocks are duplicate and
+   stored far away on the device.
+
+Proposed fix: set the default to 2048
+
+This fixes namely 1), the total filesysystem space consumption will be on
+par with other filesystems.
+
+Partially fixes 2), more data are pushed to the data block groups.
+
+The characteristics of 3) are based on actual small file size
+distribution.
+
+The change is independent of the metadata blockgroup type (though it's
+most visible with DUP) or system page size as these parameters are not
+trival to find out, compared to file size.
+
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ctree.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/ctree.h
++++ b/fs/btrfs/ctree.h
+@@ -2252,7 +2252,7 @@ struct btrfs_ioctl_defrag_range_args {
+ #define BTRFS_MOUNT_FREE_SPACE_TREE   (1 << 26)
+ #define BTRFS_DEFAULT_COMMIT_INTERVAL (30)
+-#define BTRFS_DEFAULT_MAX_INLINE      (8192)
++#define BTRFS_DEFAULT_MAX_INLINE      (2048)
+ #define btrfs_clear_opt(o, opt)               ((o) &= ~BTRFS_MOUNT_##opt)
+ #define btrfs_set_opt(o, opt)         ((o) |= BTRFS_MOUNT_##opt)
diff --git a/queue-4.5/btrfs-fix-file-loss-on-log-replay-after-renaming-a-file-and-fsync.patch b/queue-4.5/btrfs-fix-file-loss-on-log-replay-after-renaming-a-file-and-fsync.patch
new file mode 100644 (file)
index 0000000..bc77270
--- /dev/null
@@ -0,0 +1,251 @@
+From 2be63d5ce929603d4e7cedabd9e992eb34a0ff95 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 12 Feb 2016 11:34:23 +0000
+Subject: Btrfs: fix file loss on log replay after renaming a file and fsync
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 2be63d5ce929603d4e7cedabd9e992eb34a0ff95 upstream.
+
+We have two cases where we end up deleting a file at log replay time
+when we should not. For this to happen the file must have been renamed
+and a directory inode must have been fsynced/logged.
+
+Two examples that exercise these two cases are listed below.
+
+  Case 1)
+
+  $ mkfs.btrfs -f /dev/sdb
+  $ mount /dev/sdb /mnt
+  $ mkdir -p /mnt/a/b
+  $ mkdir /mnt/c
+  $ touch /mnt/a/b/foo
+  $ sync
+  $ mv /mnt/a/b/foo /mnt/c/
+  # Create file bar just to make sure the fsync on directory a/ does
+  # something and it's not a no-op.
+  $ touch /mnt/a/bar
+  $ xfs_io -c "fsync" /mnt/a
+  < power fail / crash >
+
+  The next time the filesystem is mounted, the log replay procedure
+  deletes file foo.
+
+  Case 2)
+
+  $ mkfs.btrfs -f /dev/sdb
+  $ mount /dev/sdb /mnt
+  $ mkdir /mnt/a
+  $ mkdir /mnt/b
+  $ mkdir /mnt/c
+  $ touch /mnt/a/foo
+  $ ln /mnt/a/foo /mnt/b/foo_link
+  $ touch /mnt/b/bar
+  $ sync
+  $ unlink /mnt/b/foo_link
+  $ mv /mnt/b/bar /mnt/c/
+  $ xfs_io -c "fsync" /mnt/a/foo
+  < power fail / crash >
+
+  The next time the filesystem is mounted, the log replay procedure
+  deletes file bar.
+
+The reason why the files are deleted is because when we log inodes
+other then the fsync target inode, we ignore their last_unlink_trans
+value and leave the log without enough information to later replay the
+rename operations. So we need to look at the last_unlink_trans values
+and fallback to a transaction commit if they are greater than the
+id of the last committed transaction.
+
+So fix this by looking at the last_unlink_trans values and fallback to
+transaction commits when needed. Also, when logging other inodes (for
+case 1 we logged descendants of the fsync target inode while for case 2
+we logged ascendants) we need to care about concurrent tasks updating
+the last_unlink_trans of inodes we are logging (which was already an
+existing problem in check_parent_dirs_for_sync()). Since we can not
+acquire their inode mutex (vfs' struct inode ->i_mutex), as that causes
+deadlocks with other concurrent operations that acquire the i_mutex of
+2 inodes (other fsyncs or renames for example), we need to serialize on
+the log_mutex of the inode we are logging. A task setting a new value for
+an inode's last_unlink_trans must acquire the inode's log_mutex and it
+must do this update before doing the actual unlink operation (which is
+already the case except when deleting a snapshot). Conversely the task
+logging the inode must first log the inode and then check the inode's
+last_unlink_trans value while holding its log_mutex, as if its value is
+not greater then the id of the last committed transaction it means it
+logged a safe state of the inode's items, while if its value is not
+smaller then the id of the last committed transaction it means the inode
+state it has logged might not be safe (the concurrent task might have
+just updated last_unlink_trans but hasn't done yet the unlink operation)
+and therefore a transaction commit must be done.
+
+Test cases for xfstests follow in separate patches.
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c    |    4 +--
+ fs/btrfs/tree-log.c |   67 ++++++++++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 59 insertions(+), 12 deletions(-)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -2475,6 +2475,8 @@ static noinline int btrfs_ioctl_snap_des
+       trans->block_rsv = &block_rsv;
+       trans->bytes_reserved = block_rsv.size;
++      btrfs_record_snapshot_destroy(trans, dir);
++
+       ret = btrfs_unlink_subvol(trans, root, dir,
+                               dest->root_key.objectid,
+                               dentry->d_name.name,
+@@ -2526,8 +2528,6 @@ static noinline int btrfs_ioctl_snap_des
+ out_end_trans:
+       trans->block_rsv = NULL;
+       trans->bytes_reserved = 0;
+-      if (!err)
+-              btrfs_record_snapshot_destroy(trans, dir);
+       ret = btrfs_end_transaction(trans, root);
+       if (ret && !err)
+               err = ret;
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -4909,6 +4909,42 @@ out_unlock:
+ }
+ /*
++ * Check if we must fallback to a transaction commit when logging an inode.
++ * This must be called after logging the inode and is used only in the context
++ * when fsyncing an inode requires the need to log some other inode - in which
++ * case we can't lock the i_mutex of each other inode we need to log as that
++ * can lead to deadlocks with concurrent fsync against other inodes (as we can
++ * log inodes up or down in the hierarchy) or rename operations for example. So
++ * we take the log_mutex of the inode after we have logged it and then check for
++ * its last_unlink_trans value - this is safe because any task setting
++ * last_unlink_trans must take the log_mutex and it must do this before it does
++ * the actual unlink operation, so if we do this check before a concurrent task
++ * sets last_unlink_trans it means we've logged a consistent version/state of
++ * all the inode items, otherwise we are not sure and must do a transaction
++ * commit (the concurrent task migth have only updated last_unlink_trans before
++ * we logged the inode or it might have also done the unlink).
++ */
++static bool btrfs_must_commit_transaction(struct btrfs_trans_handle *trans,
++                                        struct inode *inode)
++{
++      struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
++      bool ret = false;
++
++      mutex_lock(&BTRFS_I(inode)->log_mutex);
++      if (BTRFS_I(inode)->last_unlink_trans > fs_info->last_trans_committed) {
++              /*
++               * Make sure any commits to the log are forced to be full
++               * commits.
++               */
++              btrfs_set_log_full_commit(fs_info, trans);
++              ret = true;
++      }
++      mutex_unlock(&BTRFS_I(inode)->log_mutex);
++
++      return ret;
++}
++
++/*
+  * follow the dentry parent pointers up the chain and see if any
+  * of the directories in it require a full commit before they can
+  * be logged.  Returns zero if nothing special needs to be done or 1 if
+@@ -4921,7 +4957,6 @@ static noinline int check_parent_dirs_fo
+                                              u64 last_committed)
+ {
+       int ret = 0;
+-      struct btrfs_root *root;
+       struct dentry *old_parent = NULL;
+       struct inode *orig_inode = inode;
+@@ -4953,14 +4988,7 @@ static noinline int check_parent_dirs_fo
+                       BTRFS_I(inode)->logged_trans = trans->transid;
+               smp_mb();
+-              if (BTRFS_I(inode)->last_unlink_trans > last_committed) {
+-                      root = BTRFS_I(inode)->root;
+-
+-                      /*
+-                       * make sure any commits to the log are forced
+-                       * to be full commits
+-                       */
+-                      btrfs_set_log_full_commit(root->fs_info, trans);
++              if (btrfs_must_commit_transaction(trans, inode)) {
+                       ret = 1;
+                       break;
+               }
+@@ -5119,6 +5147,9 @@ process_leaf:
+                       btrfs_release_path(path);
+                       ret = btrfs_log_inode(trans, root, di_inode,
+                                             log_mode, 0, LLONG_MAX, ctx);
++                      if (!ret &&
++                          btrfs_must_commit_transaction(trans, di_inode))
++                              ret = 1;
+                       iput(di_inode);
+                       if (ret)
+                               goto next_dir_inode;
+@@ -5233,6 +5264,9 @@ static int btrfs_log_all_parents(struct
+                       ret = btrfs_log_inode(trans, root, dir_inode,
+                                             LOG_INODE_ALL, 0, LLONG_MAX, ctx);
++                      if (!ret &&
++                          btrfs_must_commit_transaction(trans, dir_inode))
++                              ret = 1;
+                       iput(dir_inode);
+                       if (ret)
+                               goto out;
+@@ -5584,6 +5618,9 @@ error:
+  * They revolve around files there were unlinked from the directory, and
+  * this function updates the parent directory so that a full commit is
+  * properly done if it is fsync'd later after the unlinks are done.
++ *
++ * Must be called before the unlink operations (updates to the subvolume tree,
++ * inodes, etc) are done.
+  */
+ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
+                            struct inode *dir, struct inode *inode,
+@@ -5599,8 +5636,11 @@ void btrfs_record_unlink_dir(struct btrf
+        * into the file.  When the file is logged we check it and
+        * don't log the parents if the file is fully on disk.
+        */
+-      if (S_ISREG(inode->i_mode))
++      if (S_ISREG(inode->i_mode)) {
++              mutex_lock(&BTRFS_I(inode)->log_mutex);
+               BTRFS_I(inode)->last_unlink_trans = trans->transid;
++              mutex_unlock(&BTRFS_I(inode)->log_mutex);
++      }
+       /*
+        * if this directory was already logged any new
+@@ -5631,7 +5671,9 @@ void btrfs_record_unlink_dir(struct btrf
+       return;
+ record:
++      mutex_lock(&BTRFS_I(dir)->log_mutex);
+       BTRFS_I(dir)->last_unlink_trans = trans->transid;
++      mutex_unlock(&BTRFS_I(dir)->log_mutex);
+ }
+ /*
+@@ -5642,11 +5684,16 @@ record:
+  * corresponding to the deleted snapshot's root, which could lead to replaying
+  * it after replaying the log tree of the parent directory (which would replay
+  * the snapshot delete operation).
++ *
++ * Must be called before the actual snapshot destroy operation (updates to the
++ * parent root and tree of tree roots trees, etc) are done.
+  */
+ void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans,
+                                  struct inode *dir)
+ {
++      mutex_lock(&BTRFS_I(dir)->log_mutex);
+       BTRFS_I(dir)->last_unlink_trans = trans->transid;
++      mutex_unlock(&BTRFS_I(dir)->log_mutex);
+ }
+ /*
diff --git a/queue-4.5/btrfs-fix-unreplayable-log-after-snapshot-delete-parent-dir-fsync.patch b/queue-4.5/btrfs-fix-unreplayable-log-after-snapshot-delete-parent-dir-fsync.patch
new file mode 100644 (file)
index 0000000..93dc458
--- /dev/null
@@ -0,0 +1,222 @@
+From 1ec9a1ae1e30c733077c0b288c4301b66b7a81f2 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 10 Feb 2016 10:42:25 +0000
+Subject: Btrfs: fix unreplayable log after snapshot delete + parent dir fsync
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 1ec9a1ae1e30c733077c0b288c4301b66b7a81f2 upstream.
+
+If we delete a snapshot, fsync its parent directory and crash/power fail
+before the next transaction commit, on the next mount when we attempt to
+replay the log tree of the root containing the parent directory we will
+fail and prevent the filesystem from mounting, which is solvable by wiping
+out the log trees with the btrfs-zero-log tool but very inconvenient as
+we will lose any data and metadata fsynced before the parent directory
+was fsynced.
+
+For example:
+
+  $ mkfs.btrfs -f /dev/sdc
+  $ mount /dev/sdc /mnt
+  $ mkdir /mnt/testdir
+  $ btrfs subvolume snapshot /mnt /mnt/testdir/snap
+  $ btrfs subvolume delete /mnt/testdir/snap
+  $ xfs_io -c "fsync" /mnt/testdir
+  < crash / power failure and reboot >
+  $ mount /dev/sdc /mnt
+  mount: mount(2) failed: No such file or directory
+
+And in dmesg/syslog we get the following message and trace:
+
+[192066.361162] BTRFS info (device dm-0): failed to delete reference to snap, inode 257 parent 257
+[192066.363010] ------------[ cut here ]------------
+[192066.365268] WARNING: CPU: 4 PID: 5130 at fs/btrfs/inode.c:3986 __btrfs_unlink_inode+0x17a/0x354 [btrfs]()
+[192066.367250] BTRFS: Transaction aborted (error -2)
+[192066.368401] Modules linked in: btrfs dm_flakey dm_mod ppdev sha256_generic xor raid6_pq hmac drbg ansi_cprng aesni_intel acpi_cpufreq tpm_tis aes_x86_64 tpm ablk_helper evdev cryptd sg parport_pc i2c_piix4 psmouse lrw parport i2c_core pcspkr gf128mul processor serio_raw glue_helper button loop autofs4 ext4 crc16 mbcache jbd2 sd_mod sr_mod cdrom ata_generic virtio_scsi ata_piix libata virtio_pci virtio_ring crc32c_intel scsi_mod e1000 virtio floppy [last unloaded: btrfs]
+[192066.377154] CPU: 4 PID: 5130 Comm: mount Tainted: G        W       4.4.0-rc6-btrfs-next-20+ #1
+[192066.378875] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS by qemu-project.org 04/01/2014
+[192066.380889]  0000000000000000 ffff880143923670 ffffffff81257570 ffff8801439236b8
+[192066.382561]  ffff8801439236a8 ffffffff8104ec07 ffffffffa039dc2c 00000000fffffffe
+[192066.384191]  ffff8801ed31d000 ffff8801b9fc9c88 ffff8801086875e0 ffff880143923710
+[192066.385827] Call Trace:
+[192066.386373]  [<ffffffff81257570>] dump_stack+0x4e/0x79
+[192066.387387]  [<ffffffff8104ec07>] warn_slowpath_common+0x99/0xb2
+[192066.388429]  [<ffffffffa039dc2c>] ? __btrfs_unlink_inode+0x17a/0x354 [btrfs]
+[192066.389236]  [<ffffffff8104ec68>] warn_slowpath_fmt+0x48/0x50
+[192066.389884]  [<ffffffffa039dc2c>] __btrfs_unlink_inode+0x17a/0x354 [btrfs]
+[192066.390621]  [<ffffffff81184b55>] ? iput+0xb0/0x266
+[192066.391200]  [<ffffffffa039ea25>] btrfs_unlink_inode+0x1c/0x3d [btrfs]
+[192066.391930]  [<ffffffffa03ca623>] check_item_in_log+0x1fe/0x29b [btrfs]
+[192066.392715]  [<ffffffffa03ca827>] replay_dir_deletes+0x167/0x1cf [btrfs]
+[192066.393510]  [<ffffffffa03cccc7>] replay_one_buffer+0x417/0x570 [btrfs]
+[192066.394241]  [<ffffffffa03ca164>] walk_up_log_tree+0x10e/0x1dc [btrfs]
+[192066.394958]  [<ffffffffa03cac72>] walk_log_tree+0xa5/0x190 [btrfs]
+[192066.395628]  [<ffffffffa03ce8b8>] btrfs_recover_log_trees+0x239/0x32c [btrfs]
+[192066.396790]  [<ffffffffa03cc8b0>] ? replay_one_extent+0x50a/0x50a [btrfs]
+[192066.397891]  [<ffffffffa0394041>] open_ctree+0x1d8b/0x2167 [btrfs]
+[192066.398897]  [<ffffffffa03706e1>] btrfs_mount+0x5ef/0x729 [btrfs]
+[192066.399823]  [<ffffffff8108ad98>] ? trace_hardirqs_on+0xd/0xf
+[192066.400739]  [<ffffffff8108959b>] ? lockdep_init_map+0xb9/0x1b3
+[192066.401700]  [<ffffffff811714b9>] mount_fs+0x67/0x131
+[192066.402482]  [<ffffffff81188560>] vfs_kern_mount+0x6c/0xde
+[192066.403930]  [<ffffffffa03702bd>] btrfs_mount+0x1cb/0x729 [btrfs]
+[192066.404831]  [<ffffffff8108ad98>] ? trace_hardirqs_on+0xd/0xf
+[192066.405726]  [<ffffffff8108959b>] ? lockdep_init_map+0xb9/0x1b3
+[192066.406621]  [<ffffffff811714b9>] mount_fs+0x67/0x131
+[192066.407401]  [<ffffffff81188560>] vfs_kern_mount+0x6c/0xde
+[192066.408247]  [<ffffffff8118ae36>] do_mount+0x893/0x9d2
+[192066.409047]  [<ffffffff8113009b>] ? strndup_user+0x3f/0x8c
+[192066.409842]  [<ffffffff8118b187>] SyS_mount+0x75/0xa1
+[192066.410621]  [<ffffffff8147e517>] entry_SYSCALL_64_fastpath+0x12/0x6b
+[192066.411572] ---[ end trace 2de42126c1e0a0f0 ]---
+[192066.412344] BTRFS: error (device dm-0) in __btrfs_unlink_inode:3986: errno=-2 No such entry
+[192066.413748] BTRFS: error (device dm-0) in btrfs_replay_log:2464: errno=-2 No such entry (Failed to recover log tree)
+[192066.415458] BTRFS error (device dm-0): cleaner transaction attach returned -30
+[192066.444613] BTRFS: open_ctree failed
+
+This happens because when we are replaying the log and processing the
+directory entry pointing to the snapshot in the subvolume tree, we treat
+its btrfs_dir_item item as having a location with a key type matching
+BTRFS_INODE_ITEM_KEY, which is wrong because the type matches
+BTRFS_ROOT_ITEM_KEY and therefore must be processed differently, as the
+object id refers to a root number and not to an inode in the root
+containing the parent directory.
+
+So fix this by triggering a transaction commit if an fsync against the
+parent directory is requested after deleting a snapshot. This is the
+simplest approach for a rare use case. Some alternative that avoids the
+transaction commit would require more code to explicitly delete the
+snapshot at log replay time (factoring out common code from ioctl.c:
+btrfs_ioctl_snap_destroy()), special care at fsync time to remove the
+log tree of the snapshot's root from the log root of the root of tree
+roots, amongst other steps.
+
+A test case for xfstests that triggers the issue follows.
+
+  seq=`basename $0`
+  seqres=$RESULT_DIR/$seq
+  echo "QA output created by $seq"
+  tmp=/tmp/$$
+  status=1     # failure is the default!
+  trap "_cleanup; exit \$status" 0 1 2 3 15
+
+  _cleanup()
+  {
+      _cleanup_flakey
+      cd /
+      rm -f $tmp.*
+  }
+
+  # get standard environment, filters and checks
+  . ./common/rc
+  . ./common/filter
+  . ./common/dmflakey
+
+  # real QA test starts here
+  _need_to_be_root
+  _supported_fs btrfs
+  _supported_os Linux
+  _require_scratch
+  _require_dm_target flakey
+  _require_metadata_journaling $SCRATCH_DEV
+
+  rm -f $seqres.full
+
+  _scratch_mkfs >>$seqres.full 2>&1
+  _init_flakey
+  _mount_flakey
+
+  # Create a snapshot at the root of our filesystem (mount point path), delete it,
+  # fsync the mount point path, crash and mount to replay the log. This should
+  # succeed and after the filesystem is mounted the snapshot should not be visible
+  # anymore.
+  _run_btrfs_util_prog subvolume snapshot $SCRATCH_MNT $SCRATCH_MNT/snap1
+  _run_btrfs_util_prog subvolume delete $SCRATCH_MNT/snap1
+  $XFS_IO_PROG -c "fsync" $SCRATCH_MNT
+  _flakey_drop_and_remount
+  [ -e $SCRATCH_MNT/snap1 ] && \
+      echo "Snapshot snap1 still exists after log replay"
+
+  # Similar scenario as above, but this time the snapshot is created inside a
+  # directory and not directly under the root (mount point path).
+  mkdir $SCRATCH_MNT/testdir
+  _run_btrfs_util_prog subvolume snapshot $SCRATCH_MNT $SCRATCH_MNT/testdir/snap2
+  _run_btrfs_util_prog subvolume delete $SCRATCH_MNT/testdir/snap2
+  $XFS_IO_PROG -c "fsync" $SCRATCH_MNT/testdir
+  _flakey_drop_and_remount
+  [ -e $SCRATCH_MNT/testdir/snap2 ] && \
+      echo "Snapshot snap2 still exists after log replay"
+
+  _unmount_flakey
+
+  echo "Silence is golden"
+  status=0
+  exit
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Tested-by: Liu Bo <bo.li.liu@oracle.com>
+Reviewed-by: Liu Bo <bo.li.liu@oracle.com>
+Signed-off-by: Chris Mason <clm@fb.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/ioctl.c    |    3 +++
+ fs/btrfs/tree-log.c |   15 +++++++++++++++
+ fs/btrfs/tree-log.h |    2 ++
+ 3 files changed, 20 insertions(+)
+
+--- a/fs/btrfs/ioctl.c
++++ b/fs/btrfs/ioctl.c
+@@ -59,6 +59,7 @@
+ #include "props.h"
+ #include "sysfs.h"
+ #include "qgroup.h"
++#include "tree-log.h"
+ #ifdef CONFIG_64BIT
+ /* If we have a 32-bit userspace and 64-bit kernel, then the UAPI
+@@ -2525,6 +2526,8 @@ static noinline int btrfs_ioctl_snap_des
+ out_end_trans:
+       trans->block_rsv = NULL;
+       trans->bytes_reserved = 0;
++      if (!err)
++              btrfs_record_snapshot_destroy(trans, dir);
+       ret = btrfs_end_transaction(trans, root);
+       if (ret && !err)
+               err = ret;
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -5635,6 +5635,21 @@ record:
+ }
+ /*
++ * Make sure that if someone attempts to fsync the parent directory of a deleted
++ * snapshot, it ends up triggering a transaction commit. This is to guarantee
++ * that after replaying the log tree of the parent directory's root we will not
++ * see the snapshot anymore and at log replay time we will not see any log tree
++ * corresponding to the deleted snapshot's root, which could lead to replaying
++ * it after replaying the log tree of the parent directory (which would replay
++ * the snapshot delete operation).
++ */
++void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans,
++                                 struct inode *dir)
++{
++      BTRFS_I(dir)->last_unlink_trans = trans->transid;
++}
++
++/*
+  * Call this after adding a new name for a file and it will properly
+  * update the log to reflect the new name.
+  *
+--- a/fs/btrfs/tree-log.h
++++ b/fs/btrfs/tree-log.h
+@@ -79,6 +79,8 @@ int btrfs_pin_log_trans(struct btrfs_roo
+ void btrfs_record_unlink_dir(struct btrfs_trans_handle *trans,
+                            struct inode *dir, struct inode *inode,
+                            int for_rename);
++void btrfs_record_snapshot_destroy(struct btrfs_trans_handle *trans,
++                                 struct inode *dir);
+ int btrfs_log_new_name(struct btrfs_trans_handle *trans,
+                       struct inode *inode, struct inode *old_dir,
+                       struct dentry *parent);
index 5299d3a9877063ac8f07ef2d7fec26f2d6b79392..f7a8be4f0e6a6983ca32ecf8d727f31deeaa0b4a 100644 (file)
@@ -84,3 +84,6 @@ drm-amdgpu-fix-dp-mode-validation.patch
 btrfs-reada-fix-in-segment-calculation-for-reada.patch
 btrfs-fix-truncate_space_check.patch
 btrfs-remove-error-message-from-search-ioctl-for-nonexistent-tree.patch
+btrfs-change-max_inline-default-to-2048.patch
+btrfs-fix-unreplayable-log-after-snapshot-delete-parent-dir-fsync.patch
+btrfs-fix-file-loss-on-log-replay-after-renaming-a-file-and-fsync.patch