--- /dev/null
+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)
--- /dev/null
+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);
+ }
+
+ /*
--- /dev/null
+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);
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