--- /dev/null
+From 4559b0a71749c442d34f7cfb9e72c9e58db83948 Mon Sep 17 00:00:00 2001
+From: Josef Bacik <josef@toxicpanda.com>
+Date: Thu, 19 Jul 2018 10:49:51 -0400
+Subject: btrfs: don't leak ret from do_chunk_alloc
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+commit 4559b0a71749c442d34f7cfb9e72c9e58db83948 upstream.
+
+If we're trying to make a data reservation and we have to allocate a
+data chunk we could leak ret == 1, as do_chunk_alloc() will return 1 if
+it allocated a chunk. Since the end of the function is the success path
+just return 0.
+
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/extent-tree.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/btrfs/extent-tree.c
++++ b/fs/btrfs/extent-tree.c
+@@ -4358,7 +4358,7 @@ commit_trans:
+ data_sinfo->flags, bytes, 1);
+ spin_unlock(&data_sinfo->lock);
+
+- return ret;
++ return 0;
+ }
+
+ int btrfs_check_data_free_space(struct inode *inode,
--- /dev/null
+From 3c4276936f6fbe52884b4ea4e6cc120b890a0f9f Mon Sep 17 00:00:00 2001
+From: Josef Bacik <jbacik@fb.com>
+Date: Fri, 20 Jul 2018 11:46:10 -0700
+Subject: Btrfs: fix btrfs_write_inode vs delayed iput deadlock
+
+From: Josef Bacik <jbacik@fb.com>
+
+commit 3c4276936f6fbe52884b4ea4e6cc120b890a0f9f upstream.
+
+We recently ran into the following deadlock involving
+btrfs_write_inode():
+
+[ +0.005066] __schedule+0x38e/0x8c0
+[ +0.007144] schedule+0x36/0x80
+[ +0.006447] bit_wait+0x11/0x60
+[ +0.006446] __wait_on_bit+0xbe/0x110
+[ +0.007487] ? bit_wait_io+0x60/0x60
+[ +0.007319] __inode_wait_for_writeback+0x96/0xc0
+[ +0.009568] ? autoremove_wake_function+0x40/0x40
+[ +0.009565] inode_wait_for_writeback+0x21/0x30
+[ +0.009224] evict+0xb0/0x190
+[ +0.006099] iput+0x1a8/0x210
+[ +0.006103] btrfs_run_delayed_iputs+0x73/0xc0
+[ +0.009047] btrfs_commit_transaction+0x799/0x8c0
+[ +0.009567] btrfs_write_inode+0x81/0xb0
+[ +0.008008] __writeback_single_inode+0x267/0x320
+[ +0.009569] writeback_sb_inodes+0x25b/0x4e0
+[ +0.008702] wb_writeback+0x102/0x2d0
+[ +0.007487] wb_workfn+0xa4/0x310
+[ +0.006794] ? wb_workfn+0xa4/0x310
+[ +0.007143] process_one_work+0x150/0x410
+[ +0.008179] worker_thread+0x6d/0x520
+[ +0.007490] kthread+0x12c/0x160
+[ +0.006620] ? put_pwq_unlocked+0x80/0x80
+[ +0.008185] ? kthread_park+0xa0/0xa0
+[ +0.007484] ? do_syscall_64+0x53/0x150
+[ +0.007837] ret_from_fork+0x29/0x40
+
+Writeback calls:
+
+btrfs_write_inode
+ btrfs_commit_transaction
+ btrfs_run_delayed_iputs
+
+If iput() is called on that same inode, evict() will wait for writeback
+forever.
+
+btrfs_write_inode() was originally added way back in 4730a4bc5bf3
+("btrfs_dirty_inode") to support O_SYNC writes. However, ->write_inode()
+hasn't been used for O_SYNC since 148f948ba877 ("vfs: Introduce new
+helpers for syncing after writing to O_SYNC file or IS_SYNC inode"), so
+btrfs_write_inode() is actually unnecessary (and leads to a bunch of
+unnecessary commits). Get rid of it, which also gets rid of the
+deadlock.
+
+CC: stable@vger.kernel.org # 3.2+
+Signed-off-by: Josef Bacik <jbacik@fb.com>
+[Omar: new commit message]
+Signed-off-by: Omar Sandoval <osandov@fb.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/inode.c | 26 --------------------------
+ fs/btrfs/super.c | 1 -
+ 2 files changed, 27 deletions(-)
+
+--- a/fs/btrfs/inode.c
++++ b/fs/btrfs/inode.c
+@@ -6027,32 +6027,6 @@ err:
+ return ret;
+ }
+
+-int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc)
+-{
+- struct btrfs_root *root = BTRFS_I(inode)->root;
+- struct btrfs_trans_handle *trans;
+- int ret = 0;
+- bool nolock = false;
+-
+- if (test_bit(BTRFS_INODE_DUMMY, &BTRFS_I(inode)->runtime_flags))
+- return 0;
+-
+- if (btrfs_fs_closing(root->fs_info) &&
+- btrfs_is_free_space_inode(BTRFS_I(inode)))
+- nolock = true;
+-
+- if (wbc->sync_mode == WB_SYNC_ALL) {
+- if (nolock)
+- trans = btrfs_join_transaction_nolock(root);
+- else
+- trans = btrfs_join_transaction(root);
+- if (IS_ERR(trans))
+- return PTR_ERR(trans);
+- ret = btrfs_commit_transaction(trans);
+- }
+- return ret;
+-}
+-
+ /*
+ * This is somewhat expensive, updating the tree every time the
+ * inode changes. But, it is most likely to find the inode in cache.
+--- a/fs/btrfs/super.c
++++ b/fs/btrfs/super.c
+@@ -2331,7 +2331,6 @@ static const struct super_operations btr
+ .sync_fs = btrfs_sync_fs,
+ .show_options = btrfs_show_options,
+ .show_devname = btrfs_show_devname,
+- .write_inode = btrfs_write_inode,
+ .alloc_inode = btrfs_alloc_inode,
+ .destroy_inode = btrfs_destroy_inode,
+ .statfs = btrfs_statfs,
--- /dev/null
+From 0d836392cadd5535f4184d46d901a82eb276ed62 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Fri, 20 Jul 2018 10:59:06 +0100
+Subject: Btrfs: fix mount failure after fsync due to hard link recreation
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 0d836392cadd5535f4184d46d901a82eb276ed62 upstream.
+
+If we end up with logging an inode reference item which has the same name
+but different index from the one we have persisted, we end up failing when
+replaying the log with an errno value of -EEXIST. The error comes from
+btrfs_add_link(), which is called from add_inode_ref(), when we are
+replaying an inode reference item.
+
+Example scenario where this happens:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ touch /mnt/foo
+ $ ln /mnt/foo /mnt/bar
+
+ $ sync
+
+ # Rename the first hard link (foo) to a new name and rename the second
+ # hard link (bar) to the old name of the first hard link (foo).
+ $ mv /mnt/foo /mnt/qwerty
+ $ mv /mnt/bar /mnt/foo
+
+ # Create a new file, in the same parent directory, with the old name of
+ # the second hard link (bar) and fsync this new file.
+ # We do this instead of calling fsync on foo/qwerty because if we did
+ # that the fsync resulted in a full transaction commit, not triggering
+ # the problem.
+ $ touch /mnt/bar
+ $ xfs_io -c "fsync" /mnt/bar
+
+ <power fail>
+
+ $ mount /dev/sdb /mnt
+ mount: mount /dev/sdb on /mnt failed: File exists
+
+So fix this by checking if a conflicting inode reference exists (same
+name, same parent but different index), removing it (and the associated
+dir index entries from the parent inode) if it exists, before attempting
+to add the new reference.
+
+A test case for fstests follows soon.
+
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/tree-log.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 66 insertions(+)
+
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -1291,6 +1291,46 @@ again:
+ return ret;
+ }
+
++static int btrfs_inode_ref_exists(struct inode *inode, struct inode *dir,
++ const u8 ref_type, const char *name,
++ const int namelen)
++{
++ struct btrfs_key key;
++ struct btrfs_path *path;
++ const u64 parent_id = btrfs_ino(BTRFS_I(dir));
++ int ret;
++
++ path = btrfs_alloc_path();
++ if (!path)
++ return -ENOMEM;
++
++ key.objectid = btrfs_ino(BTRFS_I(inode));
++ key.type = ref_type;
++ if (key.type == BTRFS_INODE_REF_KEY)
++ key.offset = parent_id;
++ else
++ key.offset = btrfs_extref_hash(parent_id, name, namelen);
++
++ ret = btrfs_search_slot(NULL, BTRFS_I(inode)->root, &key, path, 0, 0);
++ if (ret < 0)
++ goto out;
++ if (ret > 0) {
++ ret = 0;
++ goto out;
++ }
++ if (key.type == BTRFS_INODE_EXTREF_KEY)
++ ret = btrfs_find_name_in_ext_backref(path->nodes[0],
++ path->slots[0], parent_id,
++ name, namelen, NULL);
++ else
++ ret = btrfs_find_name_in_backref(path->nodes[0], path->slots[0],
++ name, namelen, NULL);
++
++out:
++ btrfs_free_path(path);
++ return ret;
++}
++
+ /*
+ * replay one inode back reference item found in the log tree.
+ * eb, slot and key refer to the buffer and key found in the log tree.
+@@ -1400,6 +1440,32 @@ static noinline int add_inode_ref(struct
+ }
+ }
+
++ /*
++ * If a reference item already exists for this inode
++ * with the same parent and name, but different index,
++ * drop it and the corresponding directory index entries
++ * from the parent before adding the new reference item
++ * and dir index entries, otherwise we would fail with
++ * -EEXIST returned from btrfs_add_link() below.
++ */
++ ret = btrfs_inode_ref_exists(inode, dir, key->type,
++ name, namelen);
++ if (ret > 0) {
++ ret = btrfs_unlink_inode(trans, root,
++ BTRFS_I(dir),
++ BTRFS_I(inode),
++ name, namelen);
++ /*
++ * If we dropped the link count to 0, bump it so
++ * that later the iput() on the inode will not
++ * free it. We will fixup the link count later.
++ */
++ if (!ret && inode->i_nlink == 0)
++ inc_nlink(inode);
++ }
++ if (ret < 0)
++ goto out;
++
+ /* insert our name */
+ ret = btrfs_add_link(trans, BTRFS_I(dir),
+ BTRFS_I(inode),
--- /dev/null
+From 46b2f4590aab71d31088a265c86026b1e96c9de4 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Tue, 24 Jul 2018 11:54:04 +0100
+Subject: Btrfs: fix send failure when root has deleted files still open
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 46b2f4590aab71d31088a265c86026b1e96c9de4 upstream.
+
+The more common use case of send involves creating a RO snapshot and then
+use it for a send operation. In this case it's not possible to have inodes
+in the snapshot that have a link count of zero (inode with an orphan item)
+since during snapshot creation we do the orphan cleanup. However, other
+less common use cases for send can end up seeing inodes with a link count
+of zero and in this case the send operation fails with a ENOENT error
+because any attempt to generate a path for the inode, with the purpose
+of creating it or updating it at the receiver, fails since there are no
+inode reference items. One use case it to use a regular subvolume for
+a send operation after turning it to RO mode or turning a RW snapshot
+into RO mode and then using it for a send operation. In both cases, if a
+file gets all its hard links deleted while there is an open file
+descriptor before turning the subvolume/snapshot into RO mode, the send
+operation will encounter an inode with a link count of zero and then
+fail with errno ENOENT.
+
+Example using a full send with a subvolume:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ btrfs subvolume create /mnt/sv1
+ $ touch /mnt/sv1/foo
+ $ touch /mnt/sv1/bar
+
+ # keep an open file descriptor on file bar
+ $ exec 73</mnt/sv1/bar
+ $ unlink /mnt/sv1/bar
+
+ # Turn the subvolume to RO mode and use it for a full send, while
+ # holding the open file descriptor.
+ $ btrfs property set /mnt/sv1 ro true
+
+ $ btrfs send -f /tmp/full.send /mnt/sv1
+ At subvol /mnt/sv1
+ ERROR: send ioctl failed with -2: No such file or directory
+
+Example using an incremental send with snapshots:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ btrfs subvolume create /mnt/sv1
+ $ touch /mnt/sv1/foo
+ $ touch /mnt/sv1/bar
+
+ $ btrfs subvolume snapshot -r /mnt/sv1 /mnt/snap1
+
+ $ echo "hello world" >> /mnt/sv1/bar
+
+ $ btrfs subvolume snapshot -r /mnt/sv1 /mnt/snap2
+
+ # Turn the second snapshot to RW mode and delete file foo while
+ # holding an open file descriptor on it.
+ $ btrfs property set /mnt/snap2 ro false
+ $ exec 73</mnt/snap2/foo
+ $ unlink /mnt/snap2/foo
+
+ # Set the second snapshot back to RO mode and do an incremental send.
+ $ btrfs property set /mnt/snap2 ro true
+
+ $ btrfs send -f /tmp/inc.send -p /mnt/snap1 /mnt/snap2
+ At subvol /mnt/snap2
+ ERROR: send ioctl failed with -2: No such file or directory
+
+So fix this by ignoring inodes with a link count of zero if we are either
+doing a full send or if they do not exist in the parent snapshot (they
+are new in the send snapshot), and unlink all paths found in the parent
+snapshot when doing an incremental send (and ignoring all other inode
+items, such as xattrs and extents).
+
+A test case for fstests follows soon.
+
+CC: stable@vger.kernel.org # 4.4+
+Reported-by: Martin Wilck <martin.wilck@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 129 insertions(+), 8 deletions(-)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -100,6 +100,7 @@ struct send_ctx {
+ u64 cur_inode_rdev;
+ u64 cur_inode_last_extent;
+ u64 cur_inode_next_write_offset;
++ bool ignore_cur_inode;
+
+ u64 send_progress;
+
+@@ -5799,6 +5800,9 @@ static int finish_inode_if_needed(struct
+ int pending_move = 0;
+ int refs_processed = 0;
+
++ if (sctx->ignore_cur_inode)
++ return 0;
++
+ ret = process_recorded_refs_if_needed(sctx, at_end, &pending_move,
+ &refs_processed);
+ if (ret < 0)
+@@ -5917,6 +5921,93 @@ out:
+ return ret;
+ }
+
++struct parent_paths_ctx {
++ struct list_head *refs;
++ struct send_ctx *sctx;
++};
++
++static int record_parent_ref(int num, u64 dir, int index, struct fs_path *name,
++ void *ctx)
++{
++ struct parent_paths_ctx *ppctx = ctx;
++
++ return record_ref(ppctx->sctx->parent_root, dir, name, ppctx->sctx,
++ ppctx->refs);
++}
++
++/*
++ * Issue unlink operations for all paths of the current inode found in the
++ * parent snapshot.
++ */
++static int btrfs_unlink_all_paths(struct send_ctx *sctx)
++{
++ LIST_HEAD(deleted_refs);
++ struct btrfs_path *path;
++ struct btrfs_key key;
++ struct parent_paths_ctx ctx;
++ int ret;
++
++ path = alloc_path_for_send();
++ if (!path)
++ return -ENOMEM;
++
++ key.objectid = sctx->cur_ino;
++ key.type = BTRFS_INODE_REF_KEY;
++ key.offset = 0;
++ ret = btrfs_search_slot(NULL, sctx->parent_root, &key, path, 0, 0);
++ if (ret < 0)
++ goto out;
++
++ ctx.refs = &deleted_refs;
++ ctx.sctx = sctx;
++
++ while (true) {
++ struct extent_buffer *eb = path->nodes[0];
++ int slot = path->slots[0];
++
++ if (slot >= btrfs_header_nritems(eb)) {
++ ret = btrfs_next_leaf(sctx->parent_root, path);
++ if (ret < 0)
++ goto out;
++ else if (ret > 0)
++ break;
++ continue;
++ }
++
++ btrfs_item_key_to_cpu(eb, &key, slot);
++ if (key.objectid != sctx->cur_ino)
++ break;
++ if (key.type != BTRFS_INODE_REF_KEY &&
++ key.type != BTRFS_INODE_EXTREF_KEY)
++ break;
++
++ ret = iterate_inode_ref(sctx->parent_root, path, &key, 1,
++ record_parent_ref, &ctx);
++ if (ret < 0)
++ goto out;
++
++ path->slots[0]++;
++ }
++
++ while (!list_empty(&deleted_refs)) {
++ struct recorded_ref *ref;
++
++ ref = list_first_entry(&deleted_refs, struct recorded_ref, list);
++ ret = send_unlink(sctx, ref->full_path);
++ if (ret < 0)
++ goto out;
++ fs_path_free(ref->full_path);
++ list_del(&ref->list);
++ kfree(ref);
++ }
++ ret = 0;
++out:
++ btrfs_free_path(path);
++ if (ret)
++ __free_recorded_refs(&deleted_refs);
++ return ret;
++}
++
+ static int changed_inode(struct send_ctx *sctx,
+ enum btrfs_compare_tree_result result)
+ {
+@@ -5931,6 +6022,7 @@ static int changed_inode(struct send_ctx
+ sctx->cur_inode_new_gen = 0;
+ sctx->cur_inode_last_extent = (u64)-1;
+ sctx->cur_inode_next_write_offset = 0;
++ sctx->ignore_cur_inode = false;
+
+ /*
+ * Set send_progress to current inode. This will tell all get_cur_xxx
+@@ -5971,6 +6063,33 @@ static int changed_inode(struct send_ctx
+ sctx->cur_inode_new_gen = 1;
+ }
+
++ /*
++ * Normally we do not find inodes with a link count of zero (orphans)
++ * because the most common case is to create a snapshot and use it
++ * for a send operation. However other less common use cases involve
++ * using a subvolume and send it after turning it to RO mode just
++ * after deleting all hard links of a file while holding an open
++ * file descriptor against it or turning a RO snapshot into RW mode,
++ * keep an open file descriptor against a file, delete it and then
++ * turn the snapshot back to RO mode before using it for a send
++ * operation. So if we find such cases, ignore the inode and all its
++ * items completely if it's a new inode, or if it's a changed inode
++ * make sure all its previous paths (from the parent snapshot) are all
++ * unlinked and all other the inode items are ignored.
++ */
++ if (result == BTRFS_COMPARE_TREE_NEW ||
++ result == BTRFS_COMPARE_TREE_CHANGED) {
++ u32 nlinks;
++
++ nlinks = btrfs_inode_nlink(sctx->left_path->nodes[0], left_ii);
++ if (nlinks == 0) {
++ sctx->ignore_cur_inode = true;
++ if (result == BTRFS_COMPARE_TREE_CHANGED)
++ ret = btrfs_unlink_all_paths(sctx);
++ goto out;
++ }
++ }
++
+ if (result == BTRFS_COMPARE_TREE_NEW) {
+ sctx->cur_inode_gen = left_gen;
+ sctx->cur_inode_new = 1;
+@@ -6309,15 +6428,17 @@ static int changed_cb(struct btrfs_path
+ key->objectid == BTRFS_FREE_SPACE_OBJECTID)
+ goto out;
+
+- if (key->type == BTRFS_INODE_ITEM_KEY)
++ if (key->type == BTRFS_INODE_ITEM_KEY) {
+ ret = changed_inode(sctx, result);
+- else if (key->type == BTRFS_INODE_REF_KEY ||
+- key->type == BTRFS_INODE_EXTREF_KEY)
+- ret = changed_ref(sctx, result);
+- else if (key->type == BTRFS_XATTR_ITEM_KEY)
+- ret = changed_xattr(sctx, result);
+- else if (key->type == BTRFS_EXTENT_DATA_KEY)
+- ret = changed_extent(sctx, result);
++ } else if (!sctx->ignore_cur_inode) {
++ if (key->type == BTRFS_INODE_REF_KEY ||
++ key->type == BTRFS_INODE_EXTREF_KEY)
++ ret = changed_ref(sctx, result);
++ else if (key->type == BTRFS_XATTR_ITEM_KEY)
++ ret = changed_xattr(sctx, result);
++ else if (key->type == BTRFS_EXTENT_DATA_KEY)
++ ret = changed_extent(sctx, result);
++ }
+
+ out:
+ return ret;
--- /dev/null
+From 22d3151c2c4cb517a309154d1e828a28106508c7 Mon Sep 17 00:00:00 2001
+From: Filipe Manana <fdmanana@suse.com>
+Date: Mon, 30 Jul 2018 12:39:58 +0100
+Subject: Btrfs: send, fix incorrect file layout after hole punching beyond eof
+
+From: Filipe Manana <fdmanana@suse.com>
+
+commit 22d3151c2c4cb517a309154d1e828a28106508c7 upstream.
+
+When doing an incremental send, if we have a file in the parent snapshot
+that has prealloc extents beyond EOF and in the send snapshot it got a
+hole punch that partially covers the prealloc extents, the send stream,
+when replayed by a receiver, can result in a file that has a size bigger
+than it should and filled with zeroes past the correct EOF.
+
+For example:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ xfs_io -f -c "falloc -k 0 4M" /mnt/foobar
+ $ xfs_io -c "pwrite -S 0xea 0 1M" /mnt/foobar
+
+ $ btrfs subvolume snapshot -r /mnt /mnt/snap1
+ $ btrfs send -f /tmp/1.send /mnt/snap1
+
+ $ xfs_io -c "fpunch 1M 2M" /mnt/foobar
+
+ $ btrfs subvolume snapshot -r /mnt /mnt/snap2
+ $ btrfs send -f /tmp/2.send -p /mnt/snap1 /mnt/snap2
+
+ $ stat --format %s /mnt/snap2/foobar
+ 1048576
+ $ md5sum /mnt/snap2/foobar
+ d31659e82e87798acd4669a1e0a19d4f /mnt/snap2/foobar
+
+ $ umount /mnt
+ $ mkfs.btrfs -f /dev/sdc
+ $ mount /dev/sdc /mnt
+
+ $ btrfs receive -f /mnt/1.snap /mnt
+ $ btrfs receive -f /mnt/2.snap /mnt
+
+ $ stat --format %s /mnt/snap2/foobar
+ 3145728
+ # --> should be 1Mb and not 3Mb (which was the end offset of hole
+ # punch operation)
+ $ md5sum /mnt/snap2/foobar
+ 117baf295297c2a995f92da725b0b651 /mnt/snap2/foobar
+ # --> should be d31659e82e87798acd4669a1e0a19d4f as in the original fs
+
+This issue actually happens only since commit ffa7c4296e93 ("Btrfs: send,
+do not issue unnecessary truncate operations"), but before that commit we
+were issuing a write operation full of zeroes (to "punch" a hole) which
+was extending the file size beyond the correct value and then immediately
+issue a truncate operation to the correct size and undoing the previous
+write operation. Since the send protocol does not support fallocate, for
+extent preallocation and hole punching, fix this by not even attempting
+to send a "hole" (regular write full of zeroes) if it starts at an offset
+greater then or equals to the file's size. This approach, besides being
+much more simple then making send issue the truncate operation, adds the
+benefit of avoiding the useless pair of write of zeroes and truncate
+operations, saving time and IO at the receiver and reducing the size of
+the send stream.
+
+A test case for fstests follows soon.
+
+Fixes: ffa7c4296e93 ("Btrfs: send, do not issue unnecessary truncate operations")
+CC: stable@vger.kernel.org # 4.17+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/send.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+--- a/fs/btrfs/send.c
++++ b/fs/btrfs/send.c
+@@ -5007,6 +5007,15 @@ static int send_hole(struct send_ctx *sc
+ u64 len;
+ int ret = 0;
+
++ /*
++ * A hole that starts at EOF or beyond it. Since we do not yet support
++ * fallocate (for extent preallocation and hole punching), sending a
++ * write of zeroes starting at EOF or beyond would later require issuing
++ * a truncate operation which would undo the write and achieve nothing.
++ */
++ if (offset >= sctx->cur_inode_size)
++ return 0;
++
+ if (sctx->flags & BTRFS_SEND_FLAG_NO_FILE_DATA)
+ return send_update_extent(sctx, offset, end - offset);
+
--- /dev/null
+From d814a49198eafa6163698bdd93961302f3a877a4 Mon Sep 17 00:00:00 2001
+From: Ethan Lien <ethanlien@synology.com>
+Date: Mon, 2 Jul 2018 15:44:58 +0800
+Subject: btrfs: use correct compare function of dirty_metadata_bytes
+
+From: Ethan Lien <ethanlien@synology.com>
+
+commit d814a49198eafa6163698bdd93961302f3a877a4 upstream.
+
+We use customized, nodesize batch value to update dirty_metadata_bytes.
+We should also use batch version of compare function or we will easily
+goto fast path and get false result from percpu_counter_compare().
+
+Fixes: e2d845211eda ("Btrfs: use percpu counter for dirty metadata count")
+CC: stable@vger.kernel.org # 4.4+
+Signed-off-by: Ethan Lien <ethanlien@synology.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/btrfs/disk-io.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -961,8 +961,9 @@ static int btree_writepages(struct addre
+
+ fs_info = BTRFS_I(mapping->host)->root->fs_info;
+ /* this is a bit racy, but that's ok */
+- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes,
+- BTRFS_DIRTY_METADATA_THRESH);
++ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes,
++ BTRFS_DIRTY_METADATA_THRESH,
++ fs_info->dirty_metadata_batch);
+ if (ret < 0)
+ return 0;
+ }
+@@ -4150,8 +4151,9 @@ static void __btrfs_btree_balance_dirty(
+ if (flush_delayed)
+ btrfs_balance_delayed_items(fs_info);
+
+- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes,
+- BTRFS_DIRTY_METADATA_THRESH);
++ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes,
++ BTRFS_DIRTY_METADATA_THRESH,
++ fs_info->dirty_metadata_batch);
+ if (ret > 0) {
+ balance_dirty_pages_ratelimited(fs_info->btree_inode->i_mapping);
+ }
--- /dev/null
+From 950132afd59385caf6e2b84e5235d069fa10681d Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Thu, 28 Jun 2018 18:46:40 -0500
+Subject: cifs: add missing debug entries for kconfig options
+
+From: Steve French <stfrench@microsoft.com>
+
+commit 950132afd59385caf6e2b84e5235d069fa10681d upstream.
+
+/proc/fs/cifs/DebugData displays the features (Kconfig options)
+used to build cifs.ko but it was missing some, and needed comma
+separator. These can be useful in debugging certain problems
+so we know which optional features were enabled in the user's build.
+Also clarify them, by making them more closely match the
+corresponding CONFIG_CIFS_* parm.
+
+Old format:
+Features: dfs fscache posix spnego xattr acl
+
+New format:
+Features: DFS,FSCACHE,SMB_DIRECT,STATS,DEBUG2,ALLOW_INSECURE_LEGACY,CIFS_POSIX,UPCALL(SPNEGO),XATTR,ACL
+
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Reviewed-by: Paulo Alcantara <palcantara@suse.de>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifs_debug.c | 30 +++++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/fs/cifs/cifs_debug.c
++++ b/fs/cifs/cifs_debug.c
+@@ -160,25 +160,41 @@ static int cifs_debug_data_proc_show(str
+ seq_printf(m, "CIFS Version %s\n", CIFS_VERSION);
+ seq_printf(m, "Features:");
+ #ifdef CONFIG_CIFS_DFS_UPCALL
+- seq_printf(m, " dfs");
++ seq_printf(m, " DFS");
+ #endif
+ #ifdef CONFIG_CIFS_FSCACHE
+- seq_printf(m, " fscache");
++ seq_printf(m, ",FSCACHE");
++#endif
++#ifdef CONFIG_CIFS_SMB_DIRECT
++ seq_printf(m, ",SMB_DIRECT");
++#endif
++#ifdef CONFIG_CIFS_STATS2
++ seq_printf(m, ",STATS2");
++#elif defined(CONFIG_CIFS_STATS)
++ seq_printf(m, ",STATS");
++#endif
++#ifdef CONFIG_CIFS_DEBUG2
++ seq_printf(m, ",DEBUG2");
++#elif defined(CONFIG_CIFS_DEBUG)
++ seq_printf(m, ",DEBUG");
++#endif
++#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
++ seq_printf(m, ",ALLOW_INSECURE_LEGACY");
+ #endif
+ #ifdef CONFIG_CIFS_WEAK_PW_HASH
+- seq_printf(m, " lanman");
++ seq_printf(m, ",WEAK_PW_HASH");
+ #endif
+ #ifdef CONFIG_CIFS_POSIX
+- seq_printf(m, " posix");
++ seq_printf(m, ",CIFS_POSIX");
+ #endif
+ #ifdef CONFIG_CIFS_UPCALL
+- seq_printf(m, " spnego");
++ seq_printf(m, ",UPCALL(SPNEGO)");
+ #endif
+ #ifdef CONFIG_CIFS_XATTR
+- seq_printf(m, " xattr");
++ seq_printf(m, ",XATTR");
+ #endif
+ #ifdef CONFIG_CIFS_ACL
+- seq_printf(m, " acl");
++ seq_printf(m, ",ACL");
+ #endif
+ seq_putc(m, '\n');
+ seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
--- /dev/null
+From c1777df1a5d541cda918ff0450c8adcc8b69c2fd Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Fri, 10 Aug 2018 11:03:55 +1000
+Subject: cifs: add missing support for ACLs in SMB 3.11
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit c1777df1a5d541cda918ff0450c8adcc8b69c2fd upstream.
+
+We were missing the methods for get_acl and friends for the 3.11
+dialect.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -3366,6 +3366,11 @@ struct smb_version_operations smb311_ope
+ .query_all_EAs = smb2_query_eas,
+ .set_EA = smb2_set_ea,
+ #endif /* CIFS_XATTR */
++#ifdef CONFIG_CIFS_ACL
++ .get_acl = get_smb2_acl,
++ .get_acl_by_fid = get_smb2_acl_by_fid,
++ .set_acl = set_smb2_acl,
++#endif /* CIFS_ACL */
+ .next_header = smb2_next_header,
+ };
+ #endif /* CIFS_SMB311 */
--- /dev/null
+From 126c97f4d0d1b5b956e8b0740c81a2b2a2ae548c Mon Sep 17 00:00:00 2001
+From: Nicholas Mc Guire <hofrat@osadl.org>
+Date: Thu, 23 Aug 2018 12:24:02 +0200
+Subject: cifs: check kmalloc before use
+
+From: Nicholas Mc Guire <hofrat@osadl.org>
+
+commit 126c97f4d0d1b5b956e8b0740c81a2b2a2ae548c upstream.
+
+The kmalloc was not being checked - if it fails issue a warning
+and return -ENOMEM to the caller.
+
+Signed-off-by: Nicholas Mc Guire <hofrat@osadl.org>
+Fixes: b8da344b74c8 ("cifs: dynamic allocation of ntlmssp blob")
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+cc: Stable <stable@vger.kernel.org>`
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/sess.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/fs/cifs/sess.c
++++ b/fs/cifs/sess.c
+@@ -398,6 +398,12 @@ int build_ntlmssp_auth_blob(unsigned cha
+ goto setup_ntlmv2_ret;
+ }
+ *pbuffer = kmalloc(size_of_ntlmssp_blob(ses), GFP_KERNEL);
++ if (!*pbuffer) {
++ rc = -ENOMEM;
++ cifs_dbg(VFS, "Error %d during NTLMSSP allocation\n", rc);
++ *buflen = 0;
++ goto setup_ntlmv2_ret;
++ }
+ sec_blob = (AUTHENTICATE_MESSAGE *)*pbuffer;
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
--- /dev/null
+From a5c62f4833c2c8e6e0f35367b99b717b78f5c029 Mon Sep 17 00:00:00 2001
+From: Aurelien Aptel <aaptel@suse.com>
+Date: Thu, 2 Aug 2018 16:39:52 +0200
+Subject: CIFS: fix uninitialized ptr deref in smb2 signing
+
+From: Aurelien Aptel <aaptel@suse.com>
+
+commit a5c62f4833c2c8e6e0f35367b99b717b78f5c029 upstream.
+
+server->secmech.sdeschmacsha256 is not properly initialized before
+smb2_shash_allocate(), set shash after that call.
+
+also fix typo in error message
+
+Fixes: 8de8c4608fe9 ("cifs: Fix validation of signed data in smb2")
+
+Signed-off-by: Aurelien Aptel <aaptel@suse.com>
+Reviewed-by: Paulo Alcantara <palcantara@suse.com>
+Reported-by: Xiaoli Feng <xifeng@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2transport.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/smb2transport.c
++++ b/fs/cifs/smb2transport.c
+@@ -173,7 +173,7 @@ smb2_calc_signature(struct smb_rqst *rqs
+ struct kvec *iov = rqst->rq_iov;
+ struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)iov[0].iov_base;
+ struct cifs_ses *ses;
+- struct shash_desc *shash = &server->secmech.sdeschmacsha256->shash;
++ struct shash_desc *shash;
+ struct smb_rqst drqst;
+
+ ses = smb2_find_smb_ses(server, shdr->SessionId);
+@@ -187,7 +187,7 @@ smb2_calc_signature(struct smb_rqst *rqs
+
+ rc = smb2_crypto_shash_allocate(server);
+ if (rc) {
+- cifs_dbg(VFS, "%s: shah256 alloc failed\n", __func__);
++ cifs_dbg(VFS, "%s: sha256 alloc failed\n", __func__);
+ return rc;
+ }
+
+@@ -198,6 +198,7 @@ smb2_calc_signature(struct smb_rqst *rqs
+ return rc;
+ }
+
++ shash = &server->secmech.sdeschmacsha256->shash;
+ rc = crypto_shash_init(shash);
+ if (rc) {
+ cifs_dbg(VFS, "%s: Could not init sha256", __func__);
--- /dev/null
+From 9da6ec7775d2cd76df53fbf4f1f35f6d490204f5 Mon Sep 17 00:00:00 2001
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+Date: Tue, 31 Jul 2018 08:48:22 +1000
+Subject: cifs: use a refcount to protect open/closing the cached file handle
+
+From: Ronnie Sahlberg <lsahlber@redhat.com>
+
+commit 9da6ec7775d2cd76df53fbf4f1f35f6d490204f5 upstream.
+
+Signed-off-by: Ronnie Sahlberg <lsahlber@redhat.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsglob.h | 1 +
+ fs/cifs/smb2inode.c | 4 +++-
+ fs/cifs/smb2ops.c | 31 ++++++++++++++++++++++++++-----
+ fs/cifs/smb2proto.h | 1 +
+ 4 files changed, 31 insertions(+), 6 deletions(-)
+
+--- a/fs/cifs/cifsglob.h
++++ b/fs/cifs/cifsglob.h
+@@ -913,6 +913,7 @@ cap_unix(struct cifs_ses *ses)
+
+ struct cached_fid {
+ bool is_valid:1; /* Do we have a useable root fid */
++ struct kref refcount;
+ struct cifs_fid *fid;
+ struct mutex fid_mutex;
+ struct cifs_tcon *tcon;
+--- a/fs/cifs/smb2inode.c
++++ b/fs/cifs/smb2inode.c
+@@ -120,7 +120,9 @@ smb2_open_op_close(const unsigned int xi
+ break;
+ }
+
+- if (use_cached_root_handle == false)
++ if (use_cached_root_handle)
++ close_shroot(&tcon->crfid);
++ else
+ rc = SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+ if (tmprc)
+ rc = tmprc;
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -466,21 +466,36 @@ out:
+ return rc;
+ }
+
+-void
+-smb2_cached_lease_break(struct work_struct *work)
++static void
++smb2_close_cached_fid(struct kref *ref)
+ {
+- struct cached_fid *cfid = container_of(work,
+- struct cached_fid, lease_break);
+- mutex_lock(&cfid->fid_mutex);
++ struct cached_fid *cfid = container_of(ref, struct cached_fid,
++ refcount);
++
+ if (cfid->is_valid) {
+ cifs_dbg(FYI, "clear cached root file handle\n");
+ SMB2_close(0, cfid->tcon, cfid->fid->persistent_fid,
+ cfid->fid->volatile_fid);
+ cfid->is_valid = false;
+ }
++}
++
++void close_shroot(struct cached_fid *cfid)
++{
++ mutex_lock(&cfid->fid_mutex);
++ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ mutex_unlock(&cfid->fid_mutex);
+ }
+
++void
++smb2_cached_lease_break(struct work_struct *work)
++{
++ struct cached_fid *cfid = container_of(work,
++ struct cached_fid, lease_break);
++
++ close_shroot(cfid);
++}
++
+ /*
+ * Open the directory at the root of a share
+ */
+@@ -495,6 +510,7 @@ int open_shroot(unsigned int xid, struct
+ if (tcon->crfid.is_valid) {
+ cifs_dbg(FYI, "found a cached root file handle\n");
+ memcpy(pfid, tcon->crfid.fid, sizeof(struct cifs_fid));
++ kref_get(&tcon->crfid.refcount);
+ mutex_unlock(&tcon->crfid.fid_mutex);
+ return 0;
+ }
+@@ -511,6 +527,8 @@ int open_shroot(unsigned int xid, struct
+ memcpy(tcon->crfid.fid, pfid, sizeof(struct cifs_fid));
+ tcon->crfid.tcon = tcon;
+ tcon->crfid.is_valid = true;
++ kref_init(&tcon->crfid.refcount);
++ kref_get(&tcon->crfid.refcount);
+ }
+ mutex_unlock(&tcon->crfid.fid_mutex);
+ return rc;
+@@ -552,6 +570,9 @@ smb3_qfs_tcon(const unsigned int xid, st
+ FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
+ if (no_cached_open)
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
++ else
++ close_shroot(&tcon->crfid);
++
+ return;
+ }
+
+--- a/fs/cifs/smb2proto.h
++++ b/fs/cifs/smb2proto.h
+@@ -68,6 +68,7 @@ extern int smb3_handle_read_data(struct
+
+ extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
+ struct cifs_fid *pfid);
++extern void close_shroot(struct cached_fid *cfid);
+ extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
+ struct smb2_file_all_info *src);
+ extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
--- /dev/null
+From 484a84f25ca7817c3662001316ba7d1e06b74ae2 Mon Sep 17 00:00:00 2001
+From: Michael Larabel <michael@phoronix.com>
+Date: Tue, 7 Aug 2018 09:54:54 -0400
+Subject: hwmon: (k10temp) 27C Offset needed for Threadripper2
+
+From: Michael Larabel <michael@phoronix.com>
+
+commit 484a84f25ca7817c3662001316ba7d1e06b74ae2 upstream.
+
+For at least the Threadripper 2950X and Threadripper 2990WX,
+it's confirmed a 27 degree offset is needed.
+
+Signed-off-by: Michael Larabel <michael@phoronix.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hwmon/k10temp.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/hwmon/k10temp.c
++++ b/drivers/hwmon/k10temp.c
+@@ -105,6 +105,8 @@ static const struct tctl_offset tctl_off
+ { 0x17, "AMD Ryzen Threadripper 1950", 10000 },
+ { 0x17, "AMD Ryzen Threadripper 1920", 10000 },
+ { 0x17, "AMD Ryzen Threadripper 1910", 10000 },
++ { 0x17, "AMD Ryzen Threadripper 2950X", 27000 },
++ { 0x17, "AMD Ryzen Threadripper 2990WX", 27000 },
+ };
+
+ static void read_htcreg_pci(struct pci_dev *pdev, u32 *regval)
scsi-libsas-dynamically-allocate-and-free-ata-host.patch
xprtrdma-fix-disconnect-regression.patch
mei-don-t-update-offset-in-write.patch
+cifs-add-missing-support-for-acls-in-smb-3.11.patch
+cifs-fix-uninitialized-ptr-deref-in-smb2-signing.patch
+cifs-add-missing-debug-entries-for-kconfig-options.patch
+cifs-use-a-refcount-to-protect-open-closing-the-cached-file-handle.patch
+cifs-check-kmalloc-before-use.patch
+smb3-enumerating-snapshots-was-leaving-part-of-the-data-off-end.patch
+smb3-do-not-send-smb3-set_info-if-nothing-changed.patch
+smb3-don-t-request-leases-in-symlink-creation-and-query.patch
+smb3-fill-in-statfs-fsid-and-correct-namelen.patch
+btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch
+btrfs-don-t-leak-ret-from-do_chunk_alloc.patch
+btrfs-fix-mount-failure-after-fsync-due-to-hard-link-recreation.patch
+btrfs-fix-btrfs_write_inode-vs-delayed-iput-deadlock.patch
+btrfs-fix-send-failure-when-root-has-deleted-files-still-open.patch
+btrfs-send-fix-incorrect-file-layout-after-hole-punching-beyond-eof.patch
+hwmon-k10temp-27c-offset-needed-for-threadripper2.patch
--- /dev/null
+From fd09b7d3b352105f08b8e02f7afecf7e816380ef Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Thu, 2 Aug 2018 20:28:18 -0500
+Subject: smb3: Do not send SMB3 SET_INFO if nothing changed
+
+From: Steve French <stfrench@microsoft.com>
+
+commit fd09b7d3b352105f08b8e02f7afecf7e816380ef upstream.
+
+An earlier commit had a typo which prevented the
+optimization from working:
+
+commit 18dd8e1a65dd ("Do not send SMB3 SET_INFO request if nothing is changing")
+
+Thank you to Metze for noticing this. Also clear a
+reserved field in the FILE_BASIC_INFO struct we send
+that should be zero (all the other fields in that
+struct were set or cleared explicitly already in
+cifs_set_file_info).
+
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+CC: Stable <stable@vger.kernel.org> # 4.9.x+
+Reported-by: Stefan Metzmacher <metze@samba.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/inode.c | 2 ++
+ fs/cifs/smb2inode.c | 2 +-
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+--- a/fs/cifs/inode.c
++++ b/fs/cifs/inode.c
+@@ -1122,6 +1122,8 @@ cifs_set_file_info(struct inode *inode,
+ if (!server->ops->set_file_info)
+ return -ENOSYS;
+
++ info_buf.Pad = 0;
++
+ if (attrs->ia_valid & ATTR_ATIME) {
+ set_time = true;
+ info_buf.LastAccessTime =
+--- a/fs/cifs/smb2inode.c
++++ b/fs/cifs/smb2inode.c
+@@ -283,7 +283,7 @@ smb2_set_file_info(struct inode *inode,
+ int rc;
+
+ if ((buf->CreationTime == 0) && (buf->LastAccessTime == 0) &&
+- (buf->LastWriteTime == 0) && (buf->ChangeTime) &&
++ (buf->LastWriteTime == 0) && (buf->ChangeTime == 0) &&
+ (buf->Attributes == 0))
+ return 0; /* would be a no op, no sense sending this */
+
--- /dev/null
+From 22783155f4bf956c346a81624ec9258930a6fe06 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Fri, 27 Jul 2018 22:01:49 -0500
+Subject: smb3: don't request leases in symlink creation and query
+
+From: Steve French <stfrench@microsoft.com>
+
+commit 22783155f4bf956c346a81624ec9258930a6fe06 upstream.
+
+Fixes problem pointed out by Pavel in discussions about commit
+729c0c9dd55204f0c9a823ac8a7bfa83d36c7e78
+
+Signed-off-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
+CC: Stable <stable@vger.kernel.org> # 3.18.x+
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/link.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/fs/cifs/link.c
++++ b/fs/cifs/link.c
+@@ -396,7 +396,7 @@ smb3_query_mf_symlink(unsigned int xid,
+ struct cifs_io_parms io_parms;
+ int buf_type = CIFS_NO_BUFFER;
+ __le16 *utf16_path;
+- __u8 oplock = SMB2_OPLOCK_LEVEL_II;
++ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct smb2_file_all_info *pfile_info = NULL;
+
+ oparms.tcon = tcon;
+@@ -459,7 +459,7 @@ smb3_create_mf_symlink(unsigned int xid,
+ struct cifs_io_parms io_parms;
+ int create_options = CREATE_NOT_DIR;
+ __le16 *utf16_path;
+- __u8 oplock = SMB2_OPLOCK_LEVEL_EXCLUSIVE;
++ __u8 oplock = SMB2_OPLOCK_LEVEL_NONE;
+ struct kvec iov[2];
+
+ if (backup_cred(cifs_sb))
--- /dev/null
+From e02789a53d71334b067ad72eee5d4e88a0158083 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Thu, 9 Aug 2018 14:33:12 -0500
+Subject: smb3: enumerating snapshots was leaving part of the data off end
+
+From: Steve French <stfrench@microsoft.com>
+
+commit e02789a53d71334b067ad72eee5d4e88a0158083 upstream.
+
+When enumerating snapshots, the last few bytes of the final
+snapshot could be left off since we were miscalculating the
+length returned (leaving off the sizeof struct SRV_SNAPSHOT_ARRAY)
+See MS-SMB2 section 2.2.32.2. In addition fixup the length used
+to allow smaller buffer to be passed in, in order to allow
+returning the size of the whole snapshot array more easily.
+
+Sample userspace output with a kernel patched with this
+(mounted to a Windows volume with two snapshots).
+Before this patch, the second snapshot would be missing a
+few bytes at the end.
+
+~/cifs-2.6# ~/enum-snapshots /mnt/file
+press enter to issue the ioctl to retrieve snapshot information ...
+
+size of snapshot array = 102
+Num snapshots: 2 Num returned: 2 Array Size: 102
+
+Snapshot 0:@GMT-2018.06.30-19.34.17
+Snapshot 1:@GMT-2018.06.30-19.33.37
+
+CC: Stable <stable@vger.kernel.org>
+Signed-off-by: Steve French <stfrench@microsoft.com>
+Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/smb2ops.c | 34 +++++++++++++++++++++++++++-------
+ 1 file changed, 27 insertions(+), 7 deletions(-)
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -1374,6 +1374,13 @@ smb3_set_integrity(const unsigned int xi
+
+ }
+
++/* GMT Token is @GMT-YYYY.MM.DD-HH.MM.SS Unicode which is 48 bytes + null */
++#define GMT_TOKEN_SIZE 50
++
++/*
++ * Input buffer contains (empty) struct smb_snapshot array with size filled in
++ * For output see struct SRV_SNAPSHOT_ARRAY in MS-SMB2 section 2.2.32.2
++ */
+ static int
+ smb3_enum_snapshots(const unsigned int xid, struct cifs_tcon *tcon,
+ struct cifsFileInfo *cfile, void __user *ioc_buf)
+@@ -1403,14 +1410,27 @@ smb3_enum_snapshots(const unsigned int x
+ kfree(retbuf);
+ return rc;
+ }
+- if (snapshot_in.snapshot_array_size < sizeof(struct smb_snapshot_array)) {
+- rc = -ERANGE;
+- kfree(retbuf);
+- return rc;
+- }
+
+- if (ret_data_len > snapshot_in.snapshot_array_size)
+- ret_data_len = snapshot_in.snapshot_array_size;
++ /*
++ * Check for min size, ie not large enough to fit even one GMT
++ * token (snapshot). On the first ioctl some users may pass in
++ * smaller size (or zero) to simply get the size of the array
++ * so the user space caller can allocate sufficient memory
++ * and retry the ioctl again with larger array size sufficient
++ * to hold all of the snapshot GMT tokens on the second try.
++ */
++ if (snapshot_in.snapshot_array_size < GMT_TOKEN_SIZE)
++ ret_data_len = sizeof(struct smb_snapshot_array);
++
++ /*
++ * We return struct SRV_SNAPSHOT_ARRAY, followed by
++ * the snapshot array (of 50 byte GMT tokens) each
++ * representing an available previous version of the data
++ */
++ if (ret_data_len > (snapshot_in.snapshot_array_size +
++ sizeof(struct smb_snapshot_array)))
++ ret_data_len = snapshot_in.snapshot_array_size +
++ sizeof(struct smb_snapshot_array);
+
+ if (copy_to_user(ioc_buf, retbuf, ret_data_len))
+ rc = -EFAULT;
--- /dev/null
+From 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 Mon Sep 17 00:00:00 2001
+From: Steve French <stfrench@microsoft.com>
+Date: Sun, 24 Jun 2018 23:18:52 -0500
+Subject: smb3: fill in statfs fsid and correct namelen
+
+From: Steve French <stfrench@microsoft.com>
+
+commit 21ba3845b59c733a79ed4fe1c4f3732e7ece9df7 upstream.
+
+Fil in the correct namelen (typically 255 not 4096) in the
+statfs response and also fill in a reasonably unique fsid
+(in this case taken from the volume id, and the creation time
+of the volume).
+
+In the case of the POSIX statfs all fields are now filled in,
+and in the case of non-POSIX mounts, all fields are filled
+in which can be.
+
+Signed-off-by: Steve French <stfrench@gmail.com>
+CC: Stable <stable@vger.kernel.org>
+Reviewed-by: Aurelien Aptel <aaptel@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/cifs/cifsfs.c | 18 ++++++++++--------
+ fs/cifs/smb2ops.c | 2 ++
+ fs/cifs/smb2pdu.c | 8 ++++++++
+ fs/cifs/smb2pdu.h | 11 +++++++++++
+ 4 files changed, 31 insertions(+), 8 deletions(-)
+
+--- a/fs/cifs/cifsfs.c
++++ b/fs/cifs/cifsfs.c
+@@ -209,14 +209,16 @@ cifs_statfs(struct dentry *dentry, struc
+
+ xid = get_xid();
+
+- /*
+- * PATH_MAX may be too long - it would presumably be total path,
+- * but note that some servers (includinng Samba 3) have a shorter
+- * maximum path.
+- *
+- * Instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO.
+- */
+- buf->f_namelen = PATH_MAX;
++ if (le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength) > 0)
++ buf->f_namelen =
++ le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength);
++ else
++ buf->f_namelen = PATH_MAX;
++
++ buf->f_fsid.val[0] = tcon->vol_serial_number;
++ /* are using part of create time for more randomness, see man statfs */
++ buf->f_fsid.val[1] = (int)le64_to_cpu(tcon->vol_create_time);
++
+ buf->f_files = 0; /* undefined */
+ buf->f_ffree = 0; /* unlimited */
+
+--- a/fs/cifs/smb2ops.c
++++ b/fs/cifs/smb2ops.c
+@@ -567,6 +567,8 @@ smb3_qfs_tcon(const unsigned int xid, st
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_DEVICE_INFORMATION);
+ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
++ FS_VOLUME_INFORMATION);
++ SMB2_QFS_attr(xid, tcon, fid.persistent_fid, fid.volatile_fid,
+ FS_SECTOR_SIZE_INFORMATION); /* SMB3 specific */
+ if (no_cached_open)
+ SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
+--- a/fs/cifs/smb2pdu.c
++++ b/fs/cifs/smb2pdu.c
+@@ -4046,6 +4046,9 @@ SMB2_QFS_attr(const unsigned int xid, st
+ } else if (level == FS_SECTOR_SIZE_INFORMATION) {
+ max_len = sizeof(struct smb3_fs_ss_info);
+ min_len = sizeof(struct smb3_fs_ss_info);
++ } else if (level == FS_VOLUME_INFORMATION) {
++ max_len = sizeof(struct smb3_fs_vol_info) + MAX_VOL_LABEL_LEN;
++ min_len = sizeof(struct smb3_fs_vol_info);
+ } else {
+ cifs_dbg(FYI, "Invalid qfsinfo level %d\n", level);
+ return -EINVAL;
+@@ -4090,6 +4093,11 @@ SMB2_QFS_attr(const unsigned int xid, st
+ tcon->ss_flags = le32_to_cpu(ss_info->Flags);
+ tcon->perf_sector_size =
+ le32_to_cpu(ss_info->PhysicalBytesPerSectorForPerf);
++ } else if (level == FS_VOLUME_INFORMATION) {
++ struct smb3_fs_vol_info *vol_info = (struct smb3_fs_vol_info *)
++ (offset + (char *)rsp);
++ tcon->vol_serial_number = vol_info->VolumeSerialNumber;
++ tcon->vol_create_time = vol_info->VolumeCreationTime;
+ }
+
+ qfsattr_exit:
+--- a/fs/cifs/smb2pdu.h
++++ b/fs/cifs/smb2pdu.h
+@@ -1248,6 +1248,17 @@ struct smb3_fs_ss_info {
+ __le32 ByteOffsetForPartitionAlignment;
+ } __packed;
+
++/* volume info struct - see MS-FSCC 2.5.9 */
++#define MAX_VOL_LABEL_LEN 32
++struct smb3_fs_vol_info {
++ __le64 VolumeCreationTime;
++ __u32 VolumeSerialNumber;
++ __le32 VolumeLabelLength; /* includes trailing null */
++ __u8 SupportsObjects; /* True if eg like NTFS, supports objects */
++ __u8 Reserved;
++ __u8 VolumeLabel[0]; /* variable len */
++} __packed;
++
+ /* partial list of QUERY INFO levels */
+ #define FILE_DIRECTORY_INFORMATION 1
+ #define FILE_FULL_DIRECTORY_INFORMATION 2