diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-16 09:26:18 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-02-16 09:26:18 -0800 |
commit | da370f1d63cd9fdc95b3867662026b2a5624e69a (patch) | |
tree | 7d594bf0d291e38379148ce3e3ec5cf02381bce8 /fs/btrfs/backref.c | |
parent | c85b0b14341c51d8b8962c0d90d71923cad3a218 (diff) | |
parent | fd649f10c3d21ee9d7542c609f29978bdf73ab94 (diff) | |
download | talos-op-linux-da370f1d63cd9fdc95b3867662026b2a5624e69a.tar.gz talos-op-linux-da370f1d63cd9fdc95b3867662026b2a5624e69a.zip |
Merge tag 'for-4.16-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux
Pull btrfs fixes from David Sterba:
"We have a few assorted fixes, some of them show up during fstests so I
gave them more testing"
* tag 'for-4.16-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux:
btrfs: Fix use-after-free when cleaning up fs_devs with a single stale device
Btrfs: fix null pointer dereference when replacing missing device
btrfs: remove spurious WARN_ON(ref->count < 0) in find_parent_nodes
btrfs: Ignore errors from btrfs_qgroup_trace_extent_post
Btrfs: fix unexpected -EEXIST when creating new inode
Btrfs: fix use-after-free on root->orphan_block_rsv
Btrfs: fix btrfs_evict_inode to handle abnormal inodes correctly
Btrfs: fix extent state leak from tree log
Btrfs: fix crash due to not cleaning up tree log block's dirty bits
Btrfs: fix deadlock in run_delalloc_nocow
Diffstat (limited to 'fs/btrfs/backref.c')
-rw-r--r-- | fs/btrfs/backref.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index e4054e533f6d..f94b2d8c744a 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -1264,7 +1264,16 @@ again: while (node) { ref = rb_entry(node, struct prelim_ref, rbnode); node = rb_next(&ref->rbnode); - WARN_ON(ref->count < 0); + /* + * ref->count < 0 can happen here if there are delayed + * refs with a node->action of BTRFS_DROP_DELAYED_REF. + * prelim_ref_insert() relies on this when merging + * identical refs to keep the overall count correct. + * prelim_ref_insert() will merge only those refs + * which compare identically. Any refs having + * e.g. different offsets would not be merged, + * and would retain their original ref->count < 0. + */ if (roots && ref->count && ref->root_id && ref->parent == 0) { if (sc && sc->root_objectid && ref->root_id != sc->root_objectid) { |