<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/fs/btrfs/inode.c, branch linux-4.2.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-4.2.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-4.2.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2015-12-15T05:25:44Z</updated>
<entry>
<title>Btrfs: fix regression running delayed references when using qgroups</title>
<updated>2015-12-15T05:25:44Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-10-23T06:52:54Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=dacd97b8c00cfae5f7f743846d4025bbd246ac5e'/>
<id>urn:sha1:dacd97b8c00cfae5f7f743846d4025bbd246ac5e</id>
<content type='text'>
commit b06c4bf5c874a57254b197f53ddf588e7a24a2bf upstream.

In the kernel 4.2 merge window we had a big changes to the implementation
of delayed references and qgroups which made the no_quota field of delayed
references not used anymore. More specifically the no_quota field is not
used anymore as of:

  commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented qgroup mechanism.")

Leaving the no_quota field actually prevents delayed references from
getting merged, which in turn cause the following BUG_ON(), at
fs/btrfs/extent-tree.c, to be hit when qgroups are enabled:

  static int run_delayed_tree_ref(...)
  {
     (...)
     BUG_ON(node-&gt;ref_mod != 1);
     (...)
  }

This happens on a scenario like the following:

  1) Ref1 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.

  2) Ref2 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
     It's not merged with Ref1 because Ref1-&gt;no_quota != Ref2-&gt;no_quota.

  3) Ref3 bytenr X, action = BTRFS_ADD_DELAYED_REF, no_quota = 1, added.
     It's not merged with the reference at the tail of the list of refs
     for bytenr X because the reference at the tail, Ref2 is incompatible
     due to Ref2-&gt;no_quota != Ref3-&gt;no_quota.

  4) Ref4 bytenr X, action = BTRFS_DROP_DELAYED_REF, no_quota = 0, added.
     It's not merged with the reference at the tail of the list of refs
     for bytenr X because the reference at the tail, Ref3 is incompatible
     due to Ref3-&gt;no_quota != Ref4-&gt;no_quota.

  5) We run delayed references, trigger merging of delayed references,
     through __btrfs_run_delayed_refs() -&gt; btrfs_merge_delayed_refs().

  6) Ref1 and Ref3 are merged as Ref1-&gt;no_quota = Ref3-&gt;no_quota and
     all other conditions are satisfied too. So Ref1 gets a ref_mod
     value of 2.

  7) Ref2 and Ref4 are merged as Ref2-&gt;no_quota = Ref4-&gt;no_quota and
     all other conditions are satisfied too. So Ref2 gets a ref_mod
     value of 2.

  8) Ref1 and Ref2 aren't merged, because they have different values
     for their no_quota field.

  9) Delayed reference Ref1 is picked for running (select_delayed_ref()
     always prefers references with an action == BTRFS_ADD_DELAYED_REF).
     So run_delayed_tree_ref() is called for Ref1 which triggers the
     BUG_ON because Ref1-&gt;red_mod != 1 (equals 2).

So fix this by removing the no_quota field, as it's not used anymore as
of commit 0ed4792af0e8 ("btrfs: qgroup: Switch to new extent-oriented
qgroup mechanism.").

The use of no_quota was also buggy in at least two places:

1) At delayed-refs.c:btrfs_add_delayed_tree_ref() - we were setting
   no_quota to 0 instead of 1 when the following condition was true:
   is_fstree(ref_root) || !fs_info-&gt;quota_enabled

2) At extent-tree.c:__btrfs_inc_extent_ref() - we were attempting to
   reset a node's no_quota when the condition "!is_fstree(root_objectid)
   || !root-&gt;fs_info-&gt;quota_enabled" was true but we did it only in
   an unused local stack variable, that is, we never reset the no_quota
   value in the node itself.

This fixes the remainder of problems several people have been having when
running delayed references, mostly while a balance is running in parallel,
on a 4.2+ kernel.

Very special thanks to Stéphane Lesimple for helping debugging this issue
and testing this fix on his multi terabyte filesystem (which took more
than one day to balance alone, plus fsck, etc).

Also, this fixes deadlock issue when using the clone ioctl with qgroups
enabled, as reported by Elias Probst in the mailing list. The deadlock
happens because after calling btrfs_insert_empty_item we have our path
holding a write lock on a leaf of the fs/subvol tree and then before
releasing the path we called check_ref() which did backref walking, when
qgroups are enabled, and tried to read lock the same leaf. The trace for
this case is the following:

  INFO: task systemd-nspawn:6095 blocked for more than 120 seconds.
  (...)
  Call Trace:
    [&lt;ffffffff86999201&gt;] schedule+0x74/0x83
    [&lt;ffffffff863ef64c&gt;] btrfs_tree_read_lock+0xc0/0xea
    [&lt;ffffffff86137ed7&gt;] ? wait_woken+0x74/0x74
    [&lt;ffffffff8639f0a7&gt;] btrfs_search_old_slot+0x51a/0x810
    [&lt;ffffffff863a129b&gt;] btrfs_next_old_leaf+0xdf/0x3ce
    [&lt;ffffffff86413a00&gt;] ? ulist_add_merge+0x1b/0x127
    [&lt;ffffffff86411688&gt;] __resolve_indirect_refs+0x62a/0x667
    [&lt;ffffffff863ef546&gt;] ? btrfs_clear_lock_blocking_rw+0x78/0xbe
    [&lt;ffffffff864122d3&gt;] find_parent_nodes+0xaf3/0xfc6
    [&lt;ffffffff86412838&gt;] __btrfs_find_all_roots+0x92/0xf0
    [&lt;ffffffff864128f2&gt;] btrfs_find_all_roots+0x45/0x65
    [&lt;ffffffff8639a75b&gt;] ? btrfs_get_tree_mod_seq+0x2b/0x88
    [&lt;ffffffff863e852e&gt;] check_ref+0x64/0xc4
    [&lt;ffffffff863e9e01&gt;] btrfs_clone+0x66e/0xb5d
    [&lt;ffffffff863ea77f&gt;] btrfs_ioctl_clone+0x48f/0x5bb
    [&lt;ffffffff86048a68&gt;] ? native_sched_clock+0x28/0x77
    [&lt;ffffffff863ed9b0&gt;] btrfs_ioctl+0xabc/0x25cb
  (...)

The problem goes away by eleminating check_ref(), which no longer is
needed as its purpose was to get a value for the no_quota field of
a delayed reference (this patch removes the no_quota field as mentioned
earlier).

Reported-by: Stéphane Lesimple &lt;stephane_btrfs@lesimple.fr&gt;
Tested-by: Stéphane Lesimple &lt;stephane_btrfs@lesimple.fr&gt;
Reported-by: Elias Probst &lt;mail@eliasprobst.eu&gt;
Reported-by: Peter Becker &lt;floyd.net@gmail.com&gt;
Reported-by: Malte Schröder &lt;malte@tnxip.de&gt;
Reported-by: Derek Dongray &lt;derek@valedon.co.uk&gt;
Reported-by: Erkki Seppala &lt;flux-btrfs@inside.org&gt;
Cc: stable@vger.kernel.org  # 4.2+
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: Qu Wenruo &lt;quwenruo@cn.fujitsu.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix race leading to BUG_ON when running delalloc for nodatacow</title>
<updated>2015-12-15T05:25:41Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-11-09T00:33:58Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=3e25e3a0eb6e7ba4ffe4a15b45ad7bf25a222edc'/>
<id>urn:sha1:3e25e3a0eb6e7ba4ffe4a15b45ad7bf25a222edc</id>
<content type='text'>
commit 1d512cb77bdbda80f0dd0620a3b260d697fd581d upstream.

If we are using the NO_HOLES feature, we have a tiny time window when
running delalloc for a nodatacow inode where we can race with a concurrent
link or xattr add operation leading to a BUG_ON.

This happens because at run_delalloc_nocow() we end up casting a leaf item
of type BTRFS_INODE_[REF|EXTREF]_KEY or of type BTRFS_XATTR_ITEM_KEY to a
file extent item (struct btrfs_file_extent_item) and then analyse its
extent type field, which won't match any of the expected extent types
(values BTRFS_FILE_EXTENT_[REG|PREALLOC|INLINE]) and therefore trigger an
explicit BUG_ON(1).

The following sequence diagram shows how the race happens when running a
no-cow dellaloc range [4K, 8K[ for inode 257 and we have the following
neighbour leafs:

             Leaf X (has N items)                    Leaf Y

 [ ... (257 INODE_ITEM 0) (257 INODE_REF 256) ]  [ (257 EXTENT_DATA 8192), ... ]
              slot N - 2         slot N - 1              slot 0

 (Note the implicit hole for inode 257 regarding the [0, 8K[ range)

       CPU 1                                         CPU 2

 run_dealloc_nocow()
   btrfs_lookup_file_extent()
     --&gt; searches for a key with value
         (257 EXTENT_DATA 4096) in the
         fs/subvol tree
     --&gt; returns us a path with
         path-&gt;nodes[0] == leaf X and
         path-&gt;slots[0] == N

   because path-&gt;slots[0] is &gt;=
   btrfs_header_nritems(leaf X), it
   calls btrfs_next_leaf()

   btrfs_next_leaf()
     --&gt; releases the path

                                              hard link added to our inode,
                                              with key (257 INODE_REF 500)
                                              added to the end of leaf X,
                                              so leaf X now has N + 1 keys

     --&gt; searches for the key
         (257 INODE_REF 256), because
         it was the last key in leaf X
         before it released the path,
         with path-&gt;keep_locks set to 1

     --&gt; ends up at leaf X again and
         it verifies that the key
         (257 INODE_REF 256) is no longer
         the last key in the leaf, so it
         returns with path-&gt;nodes[0] ==
         leaf X and path-&gt;slots[0] == N,
         pointing to the new item with
         key (257 INODE_REF 500)

   the loop iteration of run_dealloc_nocow()
   does not break out the loop and continues
   because the key referenced in the path
   at path-&gt;nodes[0] and path-&gt;slots[0] is
   for inode 257, its type is &lt; BTRFS_EXTENT_DATA_KEY
   and its offset (500) is less then our delalloc
   range's end (8192)

   the item pointed by the path, an inode reference item,
   is (incorrectly) interpreted as a file extent item and
   we get an invalid extent type, leading to the BUG_ON(1):

   if (extent_type == BTRFS_FILE_EXTENT_REG ||
      extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
       (...)
   } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
       (...)
   } else {
       BUG_ON(1)
   }

The same can happen if a xattr is added concurrently and ends up having
a key with an offset smaller then the delalloc's range end.

So fix this by skipping keys with a type smaller than
BTRFS_EXTENT_DATA_KEY.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: fix truncation of compressed and inlined extents</title>
<updated>2015-12-15T05:25:41Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-10-16T11:34:25Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=f50bb341aa1f20c7a7151f55172b68158b22bb8e'/>
<id>urn:sha1:f50bb341aa1f20c7a7151f55172b68158b22bb8e</id>
<content type='text'>
commit 0305cd5f7fca85dae392b9ba85b116896eb7c1c7 upstream.

When truncating a file to a smaller size which consists of an inline
extent that is compressed, we did not discard (or made unusable) the
data between the new file size and the old file size, wasting metadata
space and allowing for the truncated data to be leaked and the data
corruption/loss mentioned below.
We were also not correctly decrementing the number of bytes used by the
inode, we were setting it to zero, giving a wrong report for callers of
the stat(2) syscall. The fsck tool also reported an error about a mismatch
between the nbytes of the file versus the real space used by the file.

Now because we weren't discarding the truncated region of the file, it
was possible for a caller of the clone ioctl to actually read the data
that was truncated, allowing for a security breach without requiring root
access to the system, using only standard filesystem operations. The
scenario is the following:

   1) User A creates a file which consists of an inline and compressed
      extent with a size of 2000 bytes - the file is not accessible to
      any other users (no read, write or execution permission for anyone
      else);

   2) The user truncates the file to a size of 1000 bytes;

   3) User A makes the file world readable;

   4) User B creates a file consisting of an inline extent of 2000 bytes;

   5) User B issues a clone operation from user A's file into its own
      file (using a length argument of 0, clone the whole range);

   6) User B now gets to see the 1000 bytes that user A truncated from
      its file before it made its file world readbale. User B also lost
      the bytes in the range [1000, 2000[ bytes from its own file, but
      that might be ok if his/her intention was reading stale data from
      user A that was never supposed to be public.

Note that this contrasts with the case where we truncate a file from 2000
bytes to 1000 bytes and then truncate it back from 1000 to 2000 bytes. In
this case reading any byte from the range [1000, 2000[ will return a value
of 0x00, instead of the original data.

This problem exists since the clone ioctl was added and happens both with
and without my recent data loss and file corruption fixes for the clone
ioctl (patch "Btrfs: fix file corruption and data loss after cloning
inline extents").

So fix this by truncating the compressed inline extents as we do for the
non-compressed case, which involves decompressing, if the data isn't already
in the page cache, compressing the truncated version of the extent, writing
the compressed content into the inline extent and then truncate it.

The following test case for fstests reproduces the problem. In order for
the test to pass both this fix and my previous fix for the clone ioctl
that forbids cloning a smaller inline extent into a larger one,
which is titled "Btrfs: fix file corruption and data loss after cloning
inline extents", are needed. Without that other fix the test fails in a
different way that does not leak the truncated data, instead part of
destination file gets replaced with zeroes (because the destination file
has a larger inline extent than the source).

  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()
  {
      rm -f $tmp.*
  }

  # get standard environment, filters and checks
  . ./common/rc
  . ./common/filter

  # real QA test starts here
  _need_to_be_root
  _supported_fs btrfs
  _supported_os Linux
  _require_scratch
  _require_cloner

  rm -f $seqres.full

  _scratch_mkfs &gt;&gt;$seqres.full 2&gt;&amp;1
  _scratch_mount "-o compress"

  # Create our test files. File foo is going to be the source of a clone operation
  # and consists of a single inline extent with an uncompressed size of 512 bytes,
  # while file bar consists of a single inline extent with an uncompressed size of
  # 256 bytes. For our test's purpose, it's important that file bar has an inline
  # extent with a size smaller than foo's inline extent.
  $XFS_IO_PROG -f -c "pwrite -S 0xa1 0 128"   \
          -c "pwrite -S 0x2a 128 384" \
          $SCRATCH_MNT/foo | _filter_xfs_io
  $XFS_IO_PROG -f -c "pwrite -S 0xbb 0 256" $SCRATCH_MNT/bar | _filter_xfs_io

  # Now durably persist all metadata and data. We do this to make sure that we get
  # on disk an inline extent with a size of 512 bytes for file foo.
  sync

  # Now truncate our file foo to a smaller size. Because it consists of a
  # compressed and inline extent, btrfs did not shrink the inline extent to the
  # new size (if the extent was not compressed, btrfs would shrink it to 128
  # bytes), it only updates the inode's i_size to 128 bytes.
  $XFS_IO_PROG -c "truncate 128" $SCRATCH_MNT/foo

  # Now clone foo's inline extent into bar.
  # This clone operation should fail with errno EOPNOTSUPP because the source
  # file consists only of an inline extent and the file's size is smaller than
  # the inline extent of the destination (128 bytes &lt; 256 bytes). However the
  # clone ioctl was not prepared to deal with a file that has a size smaller
  # than the size of its inline extent (something that happens only for compressed
  # inline extents), resulting in copying the full inline extent from the source
  # file into the destination file.
  #
  # Note that btrfs' clone operation for inline extents consists of removing the
  # inline extent from the destination inode and copy the inline extent from the
  # source inode into the destination inode, meaning that if the destination
  # inode's inline extent is larger (N bytes) than the source inode's inline
  # extent (M bytes), some bytes (N - M bytes) will be lost from the destination
  # file. Btrfs could copy the source inline extent's data into the destination's
  # inline extent so that we would not lose any data, but that's currently not
  # done due to the complexity that would be needed to deal with such cases
  # (specially when one or both extents are compressed), returning EOPNOTSUPP, as
  # it's normally not a very common case to clone very small files (only case
  # where we get inline extents) and copying inline extents does not save any
  # space (unlike for normal, non-inlined extents).
  $CLONER_PROG -s 0 -d 0 -l 0 $SCRATCH_MNT/foo $SCRATCH_MNT/bar

  # Now because the above clone operation used to succeed, and due to foo's inline
  # extent not being shinked by the truncate operation, our file bar got the whole
  # inline extent copied from foo, making us lose the last 128 bytes from bar
  # which got replaced by the bytes in range [128, 256[ from foo before foo was
  # truncated - in other words, data loss from bar and being able to read old and
  # stale data from foo that should not be possible to read anymore through normal
  # filesystem operations. Contrast with the case where we truncate a file from a
  # size N to a smaller size M, truncate it back to size N and then read the range
  # [M, N[, we should always get the value 0x00 for all the bytes in that range.

  # We expected the clone operation to fail with errno EOPNOTSUPP and therefore
  # not modify our file's bar data/metadata. So its content should be 256 bytes
  # long with all bytes having the value 0xbb.
  #
  # Without the btrfs bug fix, the clone operation succeeded and resulted in
  # leaking truncated data from foo, the bytes that belonged to its range
  # [128, 256[, and losing data from bar in that same range. So reading the
  # file gave us the following content:
  #
  # 0000000 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1 a1
  # *
  # 0000200 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a 2a
  # *
  # 0000400
  echo "File bar's content after the clone operation:"
  od -t x1 $SCRATCH_MNT/bar

  # Also because the foo's inline extent was not shrunk by the truncate
  # operation, btrfs' fsck, which is run by the fstests framework everytime a
  # test completes, failed reporting the following error:
  #
  #  root 5 inode 257 errors 400, nbytes wrong

  status=0
  exit

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>btrfs: skip waiting on ordered range for special files</title>
<updated>2015-10-22T21:49:21Z</updated>
<author>
<name>Jeff Mahoney</name>
</author>
<published>2015-09-12T01:44:17Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=6117f99394c62c7873a193303e5e633970df6d1d'/>
<id>urn:sha1:6117f99394c62c7873a193303e5e633970df6d1d</id>
<content type='text'>
commit a30e577c96f59b1e1678ea5462432b09bf7d5cbc upstream.

In btrfs_evict_inode, we properly truncate the page cache for evicted
inodes but then we call btrfs_wait_ordered_range for every inode as well.
It's the right thing to do for regular files but results in incorrect
behavior for device inodes for block devices.

filemap_fdatawrite_range gets called with inode-&gt;i_mapping which gets
resolved to the block device inode before getting passed to
wbc_attach_fdatawrite_inode and ultimately to inode_to_bdi.  What happens
next depends on whether there's an open file handle associated with the
inode.  If there is, we write to the block device, which is unexpected
behavior.  If there isn't, we through normally and inode-&gt;i_data is used.
We can also end up racing against open/close which can result in crashes
when i_mapping points to a block device inode that has been closed.

Since there can't be any page cache associated with special file inodes,
it's safe to skip the btrfs_wait_ordered_range call entirely and avoid
the problem.

Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=100911
Tested-by: Christoph Biedl &lt;linux-kernel.bfrz@manchmal.in-ulm.de&gt;
Signed-off-by: Jeff Mahoney &lt;jeffm@suse.com&gt;
Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>Btrfs: fix shrinking truncate when the no_holes feature is enabled</title>
<updated>2015-07-11T21:33:14Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-06-20T17:20:09Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=c1aa45759e90b4204ab8bce027a925fc7c87d00a'/>
<id>urn:sha1:c1aa45759e90b4204ab8bce027a925fc7c87d00a</id>
<content type='text'>
If the no_holes feature is enabled, we attempt to shrink a file to a size
that ends up in the middle of a hole and we don't have any file extent
items in the fs/subvol tree that go beyond the new file size (or any
ordered extents that will insert such file extent items), we end up not
updating the inode's disk_i_size, we only update the inode's i_size.

This means that after unmounting and mounting the filesystem, or after
the inode is evicted and reloaded, its i_size ends up being incorrect
(an inode's i_size is set to the disk_i_size field when an inode is
loaded). This happens when btrfs_truncate_inode_items() doesn't find
any file extent items to drop - in this case it never makes a call to
btrfs_ordered_update_i_size() in order to update the inode's disk_i_size.

Example reproducer:

  $ mkfs.btrfs -O no-holes -f /dev/sdd
  $ mount /dev/sdd /mnt

  # Create our test file with some data and durably persist it.
  $ xfs_io -f -c "pwrite -S 0xaa 0 128K" /mnt/foo
  $ sync

  # Append some data to the file, increasing its size, and leave a hole
  # between the old size and the start offset if the following write. So
  # our file gets a hole in the range [128Kb, 256Kb[.
  $ xfs_io -c "truncate 160K" /mnt/foo

  # We expect to see our file with a size of 160Kb, with the first 128Kb
  # of data all having the value 0xaa and the remaining 32Kb of data all
  # having the value 0x00.
  $ od -t x1 /mnt/foo
  0000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
  *
  0400000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  *
  0500000

  # Now cleanly unmount and mount again the filesystem.
  $ umount /mnt
  $ mount /dev/sdd /mnt

  # We expect to get the same result as before, a file with a size of
  # 160Kb, with the first 128Kb of data all having the value 0xaa and the
  # remaining 32Kb of data all having the value 0x00.
  $ od -t x1 /mnt/foo
  0000000 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
  *
  0400000

In the example above the file size/data do not match what they were before
the remount.

Fix this by always calling btrfs_ordered_update_i_size() with a size
matching the size the file was truncated to if btrfs_truncate_inode_items()
is not called for a log tree and no file extent items were dropped. This
ensures the same behaviour as when the no_holes feature is not enabled.

A test case for fstests follows soon.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix warning of bytes_may_use</title>
<updated>2015-07-02T00:17:21Z</updated>
<author>
<name>Liu Bo</name>
</author>
<published>2015-06-17T08:59:58Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=ddba1bfc2369cd0566bcfdab47599834a32d1c19'/>
<id>urn:sha1:ddba1bfc2369cd0566bcfdab47599834a32d1c19</id>
<content type='text'>
While running generic/019, dmesg got several warnings from
btrfs_free_reserved_data_space().

Test generic/019 produces some disk failures so sumbit dio will get errors,
in which case, btrfs_direct_IO() goes to the error handling and free
bytes_may_use, but the problem is that bytes_may_use has been free'd
during get_block().

This adds a runtime flag to show if we've gone through get_block(), if so,
don't do the cleanup work.

Signed-off-by: Liu Bo &lt;bo.li.liu@oracle.com&gt;
Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Tested-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix hang when failing to submit bio of directIO</title>
<updated>2015-07-02T00:17:20Z</updated>
<author>
<name>Liu Bo</name>
</author>
<published>2015-06-17T08:59:57Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=ad9ee2053f3f2babebc09ebc4970daa66c56c7ee'/>
<id>urn:sha1:ad9ee2053f3f2babebc09ebc4970daa66c56c7ee</id>
<content type='text'>
The hang is uncoverd by generic/019.

btrfs_endio_direct_write() skips the "finish_ordered_fn" part when it hits
an error, thus those added ordered extents will never get processed, which
block processes that waiting for them via btrfs_start_ordered_extent().

This fixes the above, and meanwhile finish_ordered_fn will do the space
accounting work.

Signed-off-by: Liu Bo &lt;bo.li.liu@oracle.com&gt;
Reviewed-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Tested-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix a comment in inode.c:evict_inode_truncate_pages()</title>
<updated>2015-07-02T00:17:19Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-06-10T11:55:41Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=9c6429d96daec64f6b5b10a1c6b02c7264541ea1'/>
<id>urn:sha1:9c6429d96daec64f6b5b10a1c6b02c7264541ea1</id>
<content type='text'>
The comment was not correct about the part where it says the endio
callback of the bio might have not yet been called - update it
to mention that by that time the endio callback execution might
still be in progress only.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Reviewed-by: Liu Bo &lt;bo.li.liu@oracle.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix memory corruption on failure to submit bio for direct IO</title>
<updated>2015-07-02T00:17:18Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-07-01T11:13:10Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=61de718fceb6bc028dafe4d06a1f87a9e0998303'/>
<id>urn:sha1:61de718fceb6bc028dafe4d06a1f87a9e0998303</id>
<content type='text'>
If we fail to submit a bio for a direct IO request, we were grabbing the
corresponding ordered extent and decrementing its reference count twice,
once for our lookup reference and once for the ordered tree reference.
This was a problem because it caused the ordered extent to be freed
without removing it from the ordered tree and any lists it might be
attached to, leaving dangling pointers to the ordered extent around.
Example trace with CONFIG_DEBUG_PAGEALLOC=y:

[161779.858707] BUG: unable to handle kernel paging request at 0000000087654330
[161779.859983] IP: [&lt;ffffffff8124ca68&gt;] rb_prev+0x22/0x3b
[161779.860636] PGD 34d818067 PUD 0
[161779.860636] Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC
(...)
[161779.860636] Call Trace:
[161779.860636]  [&lt;ffffffffa06b36a6&gt;] __tree_search+0xd9/0xf9 [btrfs]
[161779.860636]  [&lt;ffffffffa06b3708&gt;] tree_search+0x42/0x63 [btrfs]
[161779.860636]  [&lt;ffffffffa06b4868&gt;] ? btrfs_lookup_ordered_range+0x2d/0xa5 [btrfs]
[161779.860636]  [&lt;ffffffffa06b4873&gt;] btrfs_lookup_ordered_range+0x38/0xa5 [btrfs]
[161779.860636]  [&lt;ffffffffa06aab8e&gt;] btrfs_get_blocks_direct+0x11b/0x615 [btrfs]
[161779.860636]  [&lt;ffffffff8119727f&gt;] do_blockdev_direct_IO+0x5ff/0xb43
[161779.860636]  [&lt;ffffffffa06aaa73&gt;] ? btrfs_page_exists_in_range+0x1ad/0x1ad [btrfs]
[161779.860636]  [&lt;ffffffffa06a2c9a&gt;] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
[161779.860636]  [&lt;ffffffff811977f5&gt;] __blockdev_direct_IO+0x32/0x34
[161779.860636]  [&lt;ffffffffa06a2c9a&gt;] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
[161779.860636]  [&lt;ffffffffa06a10ae&gt;] btrfs_direct_IO+0x198/0x21f [btrfs]
[161779.860636]  [&lt;ffffffffa06a2c9a&gt;] ? btrfs_get_extent_fiemap+0x1bc/0x1bc [btrfs]
[161779.860636]  [&lt;ffffffff81112ca1&gt;] generic_file_direct_write+0xb3/0x128
[161779.860636]  [&lt;ffffffffa06affaa&gt;] ? btrfs_file_write_iter+0x15f/0x3e0 [btrfs]
[161779.860636]  [&lt;ffffffffa06b004c&gt;] btrfs_file_write_iter+0x201/0x3e0 [btrfs]
(...)

We were also not freeing the btrfs_dio_private we allocated previously,
which kmemleak reported with the following trace in its sysfs file:

unreferenced object 0xffff8803f553bf80 (size 96):
  comm "xfs_io", pid 4501, jiffies 4295039588 (age 173.936s)
  hex dump (first 32 bytes):
    88 6c 9b f5 02 88 ff ff 00 00 00 00 00 00 00 00  .l..............
    00 00 00 00 00 00 00 00 00 00 c4 00 00 00 00 00  ................
  backtrace:
    [&lt;ffffffff81161ffe&gt;] create_object+0x172/0x29a
    [&lt;ffffffff8145870f&gt;] kmemleak_alloc+0x25/0x41
    [&lt;ffffffff81154e64&gt;] kmemleak_alloc_recursive.constprop.40+0x16/0x18
    [&lt;ffffffff811579ed&gt;] kmem_cache_alloc_trace+0xfb/0x148
    [&lt;ffffffffa03d8cff&gt;] btrfs_submit_direct+0x65/0x16a [btrfs]
    [&lt;ffffffff811968dc&gt;] dio_bio_submit+0x62/0x8f
    [&lt;ffffffff811975fe&gt;] do_blockdev_direct_IO+0x97e/0xb43
    [&lt;ffffffff811977f5&gt;] __blockdev_direct_IO+0x32/0x34
    [&lt;ffffffffa03d70ae&gt;] btrfs_direct_IO+0x198/0x21f [btrfs]
    [&lt;ffffffff81112ca1&gt;] generic_file_direct_write+0xb3/0x128
    [&lt;ffffffffa03e604d&gt;] btrfs_file_write_iter+0x201/0x3e0 [btrfs]
    [&lt;ffffffff8116586a&gt;] __vfs_write+0x7c/0xa5
    [&lt;ffffffff81165da9&gt;] vfs_write+0xa0/0xe4
    [&lt;ffffffff81166675&gt;] SyS_pwrite64+0x64/0x82
    [&lt;ffffffff81464fd7&gt;] system_call_fastpath+0x12/0x6f
    [&lt;ffffffffffffffff&gt;] 0xffffffffffffffff

For read requests we weren't doing any cleanup either (none of the work
done by btrfs_endio_direct_read()), so a failure submitting a bio for a
read request would leave a range in the inode's io_tree locked forever,
blocking any future operations (both reads and writes) against that range.

So fix this by making sure we do the same cleanup that we do for the case
where the bio submission succeeds.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: fix hang during inode eviction due to concurrent readahead</title>
<updated>2015-06-03T11:03:09Z</updated>
<author>
<name>Filipe Manana</name>
</author>
<published>2015-05-25T23:55:42Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=6ca0709756710c47ec604dd08b9fc45929d36390'/>
<id>urn:sha1:6ca0709756710c47ec604dd08b9fc45929d36390</id>
<content type='text'>
Zygo Blaxell and other users have reported occasional hangs while an
inode is being evicted, leading to traces like the following:

[ 5281.972322] INFO: task rm:20488 blocked for more than 120 seconds.
[ 5281.973836]       Not tainted 4.0.0-rc5-btrfs-next-9+ #2
[ 5281.974818] "echo 0 &gt; /proc/sys/kernel/hung_task_timeout_secs" disables this message.
[ 5281.976364] rm              D ffff8800724cfc38     0 20488   7747 0x00000000
[ 5281.977506]  ffff8800724cfc38 ffff8800724cfc38 ffff880065da5c50 0000000000000001
[ 5281.978461]  ffff8800724cffd8 ffff8801540a5f50 0000000000000008 ffff8801540a5f78
[ 5281.979541]  ffff8801540a5f50 ffff8800724cfc58 ffffffff8143107e 0000000000000123
[ 5281.981396] Call Trace:
[ 5281.982066]  [&lt;ffffffff8143107e&gt;] schedule+0x74/0x83
[ 5281.983341]  [&lt;ffffffffa03b33cf&gt;] wait_on_state+0xac/0xcd [btrfs]
[ 5281.985127]  [&lt;ffffffff81075cd6&gt;] ? signal_pending_state+0x31/0x31
[ 5281.986715]  [&lt;ffffffffa03b4b71&gt;] wait_extent_bit.constprop.32+0x7c/0xde [btrfs]
[ 5281.988680]  [&lt;ffffffffa03b540b&gt;] lock_extent_bits+0x5d/0x88 [btrfs]
[ 5281.990200]  [&lt;ffffffffa03a621d&gt;] btrfs_evict_inode+0x24e/0x5be [btrfs]
[ 5281.991781]  [&lt;ffffffff8116964d&gt;] evict+0xa0/0x148
[ 5281.992735]  [&lt;ffffffff8116a43d&gt;] iput+0x18f/0x1e5
[ 5281.993796]  [&lt;ffffffff81160d4a&gt;] do_unlinkat+0x15b/0x1fa
[ 5281.994806]  [&lt;ffffffff81435b54&gt;] ? ret_from_sys_call+0x1d/0x58
[ 5281.996120]  [&lt;ffffffff8107d314&gt;] ? trace_hardirqs_on_caller+0x18f/0x1ab
[ 5281.997562]  [&lt;ffffffff8123960b&gt;] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 5281.998815]  [&lt;ffffffff81161a16&gt;] SyS_unlinkat+0x29/0x2b
[ 5281.999920]  [&lt;ffffffff81435b32&gt;] system_call_fastpath+0x12/0x17
[ 5282.001299] 1 lock held by rm/20488:
[ 5282.002066]  #0:  (sb_writers#12){.+.+.+}, at: [&lt;ffffffff8116dd81&gt;] mnt_want_write+0x24/0x4b

This happens when we have readahead, which calls readpages(), happening
right before the inode eviction handler is invoked. So the reason is
essentially:

1) readpages() is called while a reference on the inode is held, so
   eviction can not be triggered before readpages() returns. It also
   locks one or more ranges in the inode's io_tree (which is done at
   extent_io.c:__do_contiguous_readpages());

2) readpages() submits several read bios, all with an end io callback
   that runs extent_io.c:end_bio_extent_readpage() and that is executed
   by other task when a bio finishes, corresponding to a work queue
   (fs_info-&gt;end_io_workers) worker kthread. This callback unlocks
   the ranges in the inode's io_tree that were previously locked in
   step 1;

3) readpages() returns, the reference on the inode is dropped;

4) One or more of the read bios previously submitted are still not
   complete (their end io callback was not yet invoked or has not
   yet finished execution);

5) Inode eviction is triggered (through an unlink call for example).
   The inode reference count was not incremented before submitting
   the read bios, therefore this is possible;

6) The eviction handler starts executing and enters the loop that
   iterates over all extent states in the inode's io_tree;

7) The loop picks one extent state record and uses its -&gt;start and
   -&gt;end fields, after releasing the inode's io_tree spinlock, to
   call lock_extent_bits() and clear_extent_bit(). The call to lock
   the range [state-&gt;start, state-&gt;end] blocks because the whole
   range or a part of it was locked by the previous call to
   readpages() and the corresponding end io callback, which unlocks
   the range was not yet executed;

8) The end io callback for the read bio is executed and unlocks the
   range [state-&gt;start, state-&gt;end] (or a superset of that range).
   And at clear_extent_bit() the extent_state record state is used
   as a second argument to split_state(), which sets state-&gt;start to
   a larger value;

9) The task executing the eviction handler is woken up by the task
   executing the bio's end io callback (through clear_state_bit) and
   the eviction handler locks the range
   [old value for state-&gt;start, state-&gt;end]. Shortly after, when
   calling clear_extent_bit(), it unlocks the range
   [new value for state-&gt;start, state-&gt;end], so it ends up unlocking
   only part of the range that it locked, leaving an extent state
   record in the io_tree that represents the unlocked subrange;

10) The eviction handler loop, in its next iteration, gets the
    extent_state record for the subrange that it did not unlock in the
    previous step and then tries to lock it, resulting in an hang.

So fix this by not using the -&gt;start and -&gt;end fields of an existing
extent_state record. This is a simple solution, and an alternative
could be to bump the inode's reference count before submitting each
read bio and having it dropped in the bio's end io callback. But that
would be a more invasive/complex change and would not protect against
other possible places that are not holding a reference on the inode
as well. Something to consider in the future.

Many thanks to Zygo Blaxell for reporting, in the mailing list, the
issue, a set of scripts to trigger it and testing this fix.

Reported-by: Zygo Blaxell &lt;ce3g8jdj@umail.furryterror.org&gt;
Tested-by: Zygo Blaxell &lt;ce3g8jdj@umail.furryterror.org&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
</feed>
