Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2019-03-20 12:57:40 +0100
committerTakashi Iwai <tiwai@suse.de>2019-03-20 12:57:40 +0100
commit6b31f4cc31c78c8d1a2ae43cb718a2eabbd07e18 (patch)
tree4edf8000fbb2251e933c4af43bf5f3ba789e0e39
parente1a0bf978d99c5bb59fa70d40b4feb014cc63bed (diff)
parent773794e7fad4a2acc6f8e48d2532793ab1295f1e (diff)
Merge branch 'users/fdmanana/SLE15/for-next' into SLE15
Pull btrfs fixes from Filipe Manana
-rw-r--r--patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch241
-rw-r--r--patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch361
-rw-r--r--patches.suse/btrfs-simplify-IS_ERR-PTR_ERR-checks.patch59
-rw-r--r--series.conf3
4 files changed, 664 insertions, 0 deletions
diff --git a/patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch b/patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch
new file mode 100644
index 0000000000..defbb8b91f
--- /dev/null
+++ b/patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch
@@ -0,0 +1,241 @@
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 13 Feb 2019 12:14:09 +0000
+Patch-mainline: 5.1-rc1
+Git-commit: a3baaf0d786e22fc86295fda9c58ba0dee07599f
+References: bsc#1126488
+Subject: [PATCH] Btrfs: fix fsync after succession of renames and
+ unlink/rmdir
+
+After a succession of renames operations of different files and unlinking
+one of them, if we fsync one of the renamed files we can end up with a
+log that will either fail to replay at mount time or result in a filesystem
+that is in an inconsistent state. One example scenario:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ mkdir /mnt/testdir
+ $ touch /mnt/testdir/fname1
+ $ touch /mnt/testdir/fname2
+
+ $ sync
+
+ $ mv /mnt/testdir/fname1 /mnt/testdir/fname3
+ $ rm -f /mnt/testdir/fname2
+ $ ln /mnt/testdir/fname3 /mnt/testdir/fname2
+
+ $ touch /mnt/testdir/fname1
+ $ xfs_io -c "fsync" /mnt/testdir/fname1
+
+ <power failure>
+
+ $ mount /dev/sdb /mnt
+ $ umount /mnt
+ $ btrfs check /dev/sdb
+ [1/7] checking root items
+ [2/7] checking extents
+ [3/7] checking free space cache
+ [4/7] checking fs roots
+ root 5 inode 259 errors 2, no orphan item
+ ERROR: errors found in fs roots
+ Opening filesystem to check...
+ Checking filesystem on /dev/sdc
+ UUID: 20e4abb8-5a19-4492-8bb4-6084125c2d0d
+ found 393216 bytes used, error(s) found
+ total csum bytes: 0
+ total tree bytes: 131072
+ total fs tree bytes: 32768
+ total extent tree bytes: 16384
+ btree space waste bytes: 122986
+ file data blocks allocated: 262144
+ referenced 262144
+
+On a kernel without the first patch in this series, titled
+"[PATCH] Btrfs: fix fsync after succession of renames of different files",
+we get instead an error when mounting the filesystem due to failure of
+replaying the log:
+
+ $ mount /dev/sdb /mnt
+ mount: mount /dev/sdb on /mnt failed: File exists
+
+Fix this by logging the parent directory of an inode whenever we find an
+inode that no longer exists (was unlinked in the current transaction),
+during the procedure which finds inodes that have old names that collide
+with new names of other inodes.
+
+A test case for fstests follows soon.
+
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/tree-log.c | 49 ++++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 37 insertions(+), 12 deletions(-)
+
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index ce394b750544..9ba022189666 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -40,6 +40,7 @@
+ #define LOG_INODE_ALL 0
+ #define LOG_INODE_EXISTS 1
+ #define LOG_OTHER_INODE 2
++#define LOG_OTHER_INODE_ALL 3
+
+ /*
+ * directory trouble cases
+@@ -4957,7 +4958,7 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
+ const int slot,
+ const struct btrfs_key *key,
+ struct btrfs_inode *inode,
+- u64 *other_ino)
++ u64 *other_ino, u64 *other_parent)
+ {
+ int ret;
+ struct btrfs_path *search_path;
+@@ -5023,6 +5024,7 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
+ if (di_key.objectid != key->objectid) {
+ ret = 1;
+ *other_ino = di_key.objectid;
++ *other_parent = parent;
+ } else {
+ ret = 0;
+ }
+@@ -5047,6 +5049,7 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
+
+ struct btrfs_ino_list {
+ u64 ino;
++ u64 parent;
+ struct list_head list;
+ };
+
+@@ -5054,7 +5057,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ struct btrfs_root *root,
+ struct btrfs_path *path,
+ struct btrfs_log_ctx *ctx,
+- u64 ino)
++ u64 ino, u64 parent)
+ {
+ struct btrfs_ino_list *ino_elem;
+ LIST_HEAD(inode_list);
+@@ -5064,6 +5067,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ if (!ino_elem)
+ return -ENOMEM;
+ ino_elem->ino = ino;
++ ino_elem->parent = parent;
+ list_add_tail(&ino_elem->list, &inode_list);
+
+ while (!list_empty(&inode_list)) {
+@@ -5074,6 +5078,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ ino_elem = list_first_entry(&inode_list, struct btrfs_ino_list,
+ list);
+ ino = ino_elem->ino;
++ parent = ino_elem->parent;
+ list_del(&ino_elem->list);
+ kfree(ino_elem);
+ if (ret)
+@@ -5087,13 +5092,25 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ inode = btrfs_iget(fs_info->sb, &key, root, NULL);
+ /*
+ * If the other inode that had a conflicting dir entry was
+- * deleted in the current transaction, we don't need to do more
+- * work nor fallback to a transaction commit.
++ * deleted in the current transaction, we need to log its parent
++ * directory.
+ */
+ if (IS_ERR(inode)) {
+ ret = PTR_ERR(inode);
+- if (ret == -ENOENT)
+- ret = 0;
++ if (ret == -ENOENT) {
++ key.objectid = parent;
++ inode = btrfs_iget(fs_info->sb, &key, root,
++ NULL);
++ if (IS_ERR(inode)) {
++ ret = PTR_ERR(inode);
++ } else {
++ ret = btrfs_log_inode(trans, root,
++ BTRFS_I(inode),
++ LOG_OTHER_INODE_ALL,
++ 0, LLONG_MAX, ctx);
++ iput(inode);
++ }
++ }
+ continue;
+ }
+ /*
+@@ -5123,6 +5140,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ struct extent_buffer *leaf = path->nodes[0];
+ int slot = path->slots[0];
+ u64 other_ino = 0;
++ u64 other_parent = 0;
+
+ if (slot >= btrfs_header_nritems(leaf)) {
+ ret = btrfs_next_leaf(root, path);
+@@ -5144,7 +5162,8 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ }
+
+ ret = btrfs_check_ref_name_override(leaf, slot, &key,
+- BTRFS_I(inode), &other_ino);
++ BTRFS_I(inode), &other_ino,
++ &other_parent);
+ if (ret < 0)
+ break;
+ if (ret > 0) {
+@@ -5154,6 +5173,7 @@ static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
+ break;
+ }
+ ino_elem->ino = other_ino;
++ ino_elem->parent = other_parent;
+ list_add_tail(&ino_elem->list, &inode_list);
+ ret = 0;
+ }
+@@ -5206,7 +5226,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ u64 logged_isize = 0;
+ bool need_log_inode_item = true;
+ bool xattrs_logged = false;
+- bool recursive_logging = (inode_only == LOG_OTHER_INODE);
++ bool recursive_logging = false;
+
+ path = btrfs_alloc_path();
+ if (!path)
+@@ -5252,8 +5272,12 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ return ret;
+ }
+
+- if (inode_only == LOG_OTHER_INODE) {
+- inode_only = LOG_INODE_EXISTS;
++ if (inode_only == LOG_OTHER_INODE || inode_only == LOG_OTHER_INODE_ALL) {
++ recursive_logging = true;
++ if (inode_only == LOG_OTHER_INODE)
++ inode_only = LOG_INODE_EXISTS;
++ else
++ inode_only = LOG_INODE_ALL;
+ mutex_lock_nested(&inode->log_mutex, SINGLE_DEPTH_NESTING);
+ } else {
+ mutex_lock(&inode->log_mutex);
+@@ -5351,10 +5375,11 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ inode->generation == trans->transid &&
+ !recursive_logging) {
+ u64 other_ino = 0;
++ u64 other_parent = 0;
+
+ ret = btrfs_check_ref_name_override(path->nodes[0],
+ path->slots[0], &min_key, inode,
+- &other_ino);
++ &other_ino, &other_parent);
+ if (ret < 0) {
+ err = ret;
+ goto out_unlock;
+@@ -5377,7 +5402,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ ins_nr = 0;
+
+ err = log_conflicting_inodes(trans, root, path,
+- ctx, other_ino);
++ ctx, other_ino, other_parent);
+ if (err)
+ goto out_unlock;
+ btrfs_release_path(path);
+--
+2.19.0
+
diff --git a/patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch b/patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch
new file mode 100644
index 0000000000..61d6d54289
--- /dev/null
+++ b/patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch
@@ -0,0 +1,361 @@
+From: Filipe Manana <fdmanana@suse.com>
+Date: Wed, 13 Feb 2019 12:14:03 +0000
+Patch-mainline: 5.1-rc1
+Git-commit: 6b5fc433a7ad6711052d1aa4be0debc6316b219f
+References: bsc#1126481
+Subject: [PATCH] Btrfs: fix fsync after succession of renames of different
+ files
+
+After a succession of rename operations of different files and fsyncing
+one of them, such that each file gets a new name that corresponds to an
+old name of another file, we can end up with a log that will cause a
+failure when attempted to replay at mount time (an EEXIST error).
+We currently have correct behaviour when such succession of renames
+involves only two files, but if there are more files involved, we end up
+not logging all the inodes that are needed, therefore resulting in a
+failure when attempting to replay the log.
+
+Example:
+
+ $ mkfs.btrfs -f /dev/sdb
+ $ mount /dev/sdb /mnt
+
+ $ mkdir /mnt/testdir
+ $ touch /mnt/testdir/fname1
+ $ touch /mnt/testdir/fname2
+
+ $ sync
+
+ $ mv /mnt/testdir/fname1 /mnt/testdir/fname3
+ $ mv /mnt/testdir/fname2 /mnt/testdir/fname4
+ $ ln /mnt/testdir/fname3 /mnt/testdir/fname2
+
+ $ touch /mnt/testdir/fname1
+ $ xfs_io -c "fsync" /mnt/testdir/fname1
+
+ <power failure>
+
+ $ mount /dev/sdb /mnt
+ mount: mount /dev/sdb on /mnt failed: File exists
+
+So fix this by checking all inode dependencies when logging an inode. That
+is, if one logged inode A has a new name that matches the old name of some
+other inode B, check if inode B has a new name that matches the old name
+of some other inode C, and so on. This fix is implemented not by doing any
+recursive function calls but by using an iterative method using a linked
+list that is used in a first-in-first-out fashion.
+
+A test case for fstests follows soon.
+
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+---
+ fs/btrfs/tree-log.c | 241 ++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 197 insertions(+), 44 deletions(-)
+
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index c1feff1ffceb..ce394b750544 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -1359,6 +1359,67 @@ static int btrfs_inode_ref_exists(struct inode *inode, struct inode *dir,
+ return ret;
+ }
+
++static int add_link(struct btrfs_trans_handle *trans, struct btrfs_root *root,
++ struct inode *dir, struct inode *inode, const char *name,
++ int namelen, u64 ref_index)
++{
++ struct btrfs_dir_item *dir_item;
++ struct btrfs_key key;
++ struct btrfs_path *path;
++ struct inode *other_inode = NULL;
++ int ret;
++
++ path = btrfs_alloc_path();
++ if (!path)
++ return -ENOMEM;
++
++ dir_item = btrfs_lookup_dir_item(NULL, root, path,
++ btrfs_ino(BTRFS_I(dir)),
++ name, namelen, 0);
++ if (!dir_item) {
++ btrfs_release_path(path);
++ goto add_link;
++ } else if (IS_ERR(dir_item)) {
++ ret = PTR_ERR(dir_item);
++ goto out;
++ }
++
++ /*
++ * Our inode's dentry collides with the dentry of another inode which is
++ * in the log but not yet processed since it has a higher inode number.
++ * So delete that other dentry.
++ */
++ btrfs_dir_item_key_to_cpu(path->nodes[0], dir_item, &key);
++ btrfs_release_path(path);
++ other_inode = read_one_inode(root, key.objectid);
++ if (!other_inode) {
++ ret = -ENOENT;
++ goto out;
++ }
++ ret = btrfs_unlink_inode(trans, root, BTRFS_I(dir), BTRFS_I(other_inode),
++ name, namelen);
++ if (ret)
++ goto out;
++ /*
++ * 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 (other_inode->i_nlink == 0)
++ inc_nlink(other_inode);
++
++ ret = btrfs_run_delayed_items(trans, trans->fs_info);
++ if (ret)
++ goto out;
++add_link:
++ ret = btrfs_add_link(trans, BTRFS_I(dir), BTRFS_I(inode),
++ name, namelen, 0, ref_index);
++out:
++ iput(other_inode);
++ 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.
+@@ -1495,9 +1556,8 @@ static noinline int add_inode_ref(struct btrfs_trans_handle *trans,
+ goto out;
+
+ /* insert our name */
+- ret = btrfs_add_link(trans, BTRFS_I(dir),
+- BTRFS_I(inode),
+- name, namelen, 0, ref_index);
++ ret = add_link(trans, root, dir, inode, name, namelen,
++ ref_index);
+ if (ret)
+ goto out;
+
+@@ -4960,8 +5020,12 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
+ btrfs_dir_item_key_to_cpu(search_path->nodes[0],
+ di, &di_key);
+ if (di_key.type == BTRFS_INODE_ITEM_KEY) {
+- ret = 1;
+- *other_ino = di_key.objectid;
++ if (di_key.objectid != key->objectid) {
++ ret = 1;
++ *other_ino = di_key.objectid;
++ } else {
++ ret = 0;
++ }
+ } else {
+ ret = -EAGAIN;
+ }
+@@ -4981,6 +5045,126 @@ static int btrfs_check_ref_name_override(struct extent_buffer *eb,
+ return ret;
+ }
+
++struct btrfs_ino_list {
++ u64 ino;
++ struct list_head list;
++};
++
++static int log_conflicting_inodes(struct btrfs_trans_handle *trans,
++ struct btrfs_root *root,
++ struct btrfs_path *path,
++ struct btrfs_log_ctx *ctx,
++ u64 ino)
++{
++ struct btrfs_ino_list *ino_elem;
++ LIST_HEAD(inode_list);
++ int ret = 0;
++
++ ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS);
++ if (!ino_elem)
++ return -ENOMEM;
++ ino_elem->ino = ino;
++ list_add_tail(&ino_elem->list, &inode_list);
++
++ while (!list_empty(&inode_list)) {
++ struct btrfs_fs_info *fs_info = root->fs_info;
++ struct btrfs_key key;
++ struct inode *inode;
++
++ ino_elem = list_first_entry(&inode_list, struct btrfs_ino_list,
++ list);
++ ino = ino_elem->ino;
++ list_del(&ino_elem->list);
++ kfree(ino_elem);
++ if (ret)
++ continue;
++
++ btrfs_release_path(path);
++
++ key.objectid = ino;
++ key.type = BTRFS_INODE_ITEM_KEY;
++ key.offset = 0;
++ inode = btrfs_iget(fs_info->sb, &key, root, NULL);
++ /*
++ * If the other inode that had a conflicting dir entry was
++ * deleted in the current transaction, we don't need to do more
++ * work nor fallback to a transaction commit.
++ */
++ if (IS_ERR(inode)) {
++ ret = PTR_ERR(inode);
++ if (ret == -ENOENT)
++ ret = 0;
++ continue;
++ }
++ /*
++ * We are safe logging the other inode without acquiring its
++ * lock as long as we log with the LOG_INODE_EXISTS mode. We
++ * are safe against concurrent renames of the other inode as
++ * well because during a rename we pin the log and update the
++ * log with the new name before we unpin it.
++ */
++ ret = btrfs_log_inode(trans, root, BTRFS_I(inode),
++ LOG_OTHER_INODE, 0, LLONG_MAX, ctx);
++ if (ret) {
++ iput(inode);
++ continue;
++ }
++
++ key.objectid = ino;
++ key.type = BTRFS_INODE_REF_KEY;
++ key.offset = 0;
++ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
++ if (ret < 0) {
++ iput(inode);
++ continue;
++ }
++
++ while (true) {
++ struct extent_buffer *leaf = path->nodes[0];
++ int slot = path->slots[0];
++ u64 other_ino = 0;
++
++ if (slot >= btrfs_header_nritems(leaf)) {
++ ret = btrfs_next_leaf(root, path);
++ if (ret < 0) {
++ break;
++ } else if (ret > 0) {
++ ret = 0;
++ break;
++ }
++ continue;
++ }
++
++ btrfs_item_key_to_cpu(leaf, &key, slot);
++ if (key.objectid != ino ||
++ (key.type != BTRFS_INODE_REF_KEY &&
++ key.type != BTRFS_INODE_EXTREF_KEY)) {
++ ret = 0;
++ break;
++ }
++
++ ret = btrfs_check_ref_name_override(leaf, slot, &key,
++ BTRFS_I(inode), &other_ino);
++ if (ret < 0)
++ break;
++ if (ret > 0) {
++ ino_elem = kmalloc(sizeof(*ino_elem), GFP_NOFS);
++ if (!ino_elem) {
++ ret = -ENOMEM;
++ break;
++ }
++ ino_elem->ino = other_ino;
++ list_add_tail(&ino_elem->list, &inode_list);
++ ret = 0;
++ }
++ path->slots[0]++;
++ }
++ iput(inode);
++ }
++
++ return ret;
++}
++
+ /* log a single inode in the tree log.
+ * At least one parent directory for this inode must exist in the tree
+ * or be logged already.
+@@ -5022,6 +5206,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ u64 logged_isize = 0;
+ bool need_log_inode_item = true;
+ bool xattrs_logged = false;
++ bool recursive_logging = (inode_only == LOG_OTHER_INODE);
+
+ path = btrfs_alloc_path();
+ if (!path)
+@@ -5163,7 +5348,8 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+
+ if ((min_key.type == BTRFS_INODE_REF_KEY ||
+ min_key.type == BTRFS_INODE_EXTREF_KEY) &&
+- inode->generation == trans->transid) {
++ inode->generation == trans->transid &&
++ !recursive_logging) {
+ u64 other_ino = 0;
+
+ ret = btrfs_check_ref_name_override(path->nodes[0],
+@@ -5174,9 +5360,6 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ goto out_unlock;
+ } else if (ret > 0 && ctx &&
+ other_ino != btrfs_ino(BTRFS_I(ctx->inode))) {
+- struct btrfs_key inode_key;
+- struct inode *other_inode;
+-
+ if (ins_nr > 0) {
+ ins_nr++;
+ } else {
+@@ -5192,43 +5375,13 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ goto out_unlock;
+ }
+ ins_nr = 0;
+- btrfs_release_path(path);
+- inode_key.objectid = other_ino;
+- inode_key.type = BTRFS_INODE_ITEM_KEY;
+- inode_key.offset = 0;
+- other_inode = btrfs_iget(fs_info->sb,
+- &inode_key, root,
+- NULL);
+- /*
+- * If the other inode that had a conflicting dir
+- * entry was deleted in the current transaction,
+- * we don't need to do more work nor fallback to
+- * a transaction commit.
+- */
+- if (other_inode == ERR_PTR(-ENOENT)) {
+- goto next_key;
+- } else if (IS_ERR(other_inode)) {
+- err = PTR_ERR(other_inode);
+- goto out_unlock;
+- }
+- /*
+- * We are safe logging the other inode without
+- * acquiring its i_mutex as long as we log with
+- * the LOG_INODE_EXISTS mode. We're safe against
+- * concurrent renames of the other inode as well
+- * because during a rename we pin the log and
+- * update the log with the new name before we
+- * unpin it.
+- */
+- err = btrfs_log_inode(trans, root,
+- BTRFS_I(other_inode),
+- LOG_OTHER_INODE, 0, LLONG_MAX,
+- ctx);
+- iput(other_inode);
++
++ err = log_conflicting_inodes(trans, root, path,
++ ctx, other_ino);
+ if (err)
+ goto out_unlock;
+- else
+- goto next_key;
++ btrfs_release_path(path);
++ goto next_key;
+ }
+ }
+
+--
+2.19.0
+
diff --git a/patches.suse/btrfs-simplify-IS_ERR-PTR_ERR-checks.patch b/patches.suse/btrfs-simplify-IS_ERR-PTR_ERR-checks.patch
new file mode 100644
index 0000000000..eaeb949fe1
--- /dev/null
+++ b/patches.suse/btrfs-simplify-IS_ERR-PTR_ERR-checks.patch
@@ -0,0 +1,59 @@
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Sun, 29 Jul 2018 23:04:46 +0100
+Patch-mainline: 4.19
+Git-commit: 8d9e220ca0844bf75b98cb5b8e2c25d203c0d0f6
+References: bsc#1126481
+Subject: [PATCH] btrfs: simplify IS_ERR/PTR_ERR checks
+
+IS_ERR(p) && PTR_ERR(p) == n is a weird way to spell p == ERR_PTR(n).
+
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Reviewed-by: Nikolay Borisov <nborisov@suse.com>
+[ update changelog ]
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Filipe Manana <fdmanana@suse.com>
+---
+ fs/btrfs/transaction.c | 2 +-
+ fs/btrfs/tree-log.c | 5 ++---
+ 2 files changed, 3 insertions(+), 4 deletions(-)
+
+diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
+index 276249df791c..50e19d33e73e 100644
+--- a/fs/btrfs/transaction.c
++++ b/fs/btrfs/transaction.c
+@@ -718,7 +718,7 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
+
+ trans = start_transaction(root, 0, TRANS_ATTACH,
+ BTRFS_RESERVE_NO_FLUSH, true);
+- if (IS_ERR(trans) && PTR_ERR(trans) == -ENOENT)
++ if (trans == ERR_PTR(-ENOENT))
+ btrfs_wait_for_commit(root->fs_info, 0);
+
+ return trans;
+diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
+index 8cd571f6747b..c1feff1ffceb 100644
+--- a/fs/btrfs/tree-log.c
++++ b/fs/btrfs/tree-log.c
+@@ -2223,7 +2223,7 @@ static noinline int check_item_in_log(struct btrfs_trans_handle *trans,
+ dir_key->offset,
+ name, name_len, 0);
+ }
+- if (!log_di || (IS_ERR(log_di) && PTR_ERR(log_di) == -ENOENT)) {
++ if (!log_di || log_di == ERR_PTR(-ENOENT)) {
+ btrfs_dir_item_key_to_cpu(eb, di, &location);
+ btrfs_release_path(path);
+ btrfs_release_path(log_path);
+@@ -5205,8 +5205,7 @@ static int btrfs_log_inode(struct btrfs_trans_handle *trans,
+ * we don't need to do more work nor fallback to
+ * a transaction commit.
+ */
+- if (IS_ERR(other_inode) &&
+- PTR_ERR(other_inode) == -ENOENT) {
++ if (other_inode == ERR_PTR(-ENOENT)) {
+ goto next_key;
+ } else if (IS_ERR(other_inode)) {
+ err = PTR_ERR(other_inode);
+--
+2.19.0
+
diff --git a/series.conf b/series.conf
index 1198b7474b..893195fc8a 100644
--- a/series.conf
+++ b/series.conf
@@ -17863,6 +17863,7 @@
patches.suse/0016-btrfs-tree-checker-Detect-invalid-and-empty-essentia.patch
patches.suse/btrfs-fix-mount-failure-after-fsync-due-to-hard-link.patch
patches.suse/btrfs-fix-send-failure-when-root-has-deleted-files-s.patch
+ patches.suse/btrfs-simplify-IS_ERR-PTR_ERR-checks.patch
patches.suse/0017-btrfs-Check-that-each-block-group-has-corresponding-.patch
patches.suse/0018-btrfs-Verify-that-every-chunk-has-corresponding-bloc.patch
patches.suse/0019-btrfs-Introduce-mount-time-chunk-dev-extent-mapping-.patch
@@ -20813,6 +20814,8 @@
patches.suse/0003-btrfs-qgroup-Introduce-per-root-swapped-blocks-infra.patch
patches.suse/0004-btrfs-qgroup-Use-delayed-subtree-rescan-for-balance.patch
patches.suse/0005-btrfs-qgroup-Cleanup-old-subtree-swap-code.patch
+ patches.suse/btrfs-fix-fsync-after-succession-of-renames-of-diffe.patch
+ patches.suse/btrfs-fix-fsync-after-succession-of-renames-and-unli.patch
patches.suse/btrfs-ensure-that-a-dup-or-raid1-block-group-has-exactly-two-stripes.patch
patches.arch/powerpc-pseries-Perform-full-re-add-of-CPU-for-topol.patch
patches.suse/powerpc-64s-clear-on-stack-exception-marker-upon-exception-return.patch