<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/fs/btrfs/ordered-data.c, branch v4.5</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>Btrfs: change how we wait for pending ordered extents</title>
<updated>2015-10-22T01:51:40+00:00</updated>
<author>
<name>Josef Bacik</name>
<email>jbacik@fb.com</email>
</author>
<published>2015-09-24T20:17:39+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=161c3549b45aeef05451b6822d8aaaf39c7bedce'/>
<id>161c3549b45aeef05451b6822d8aaaf39c7bedce</id>
<content type='text'>
We have a mechanism to make sure we don't lose updates for ordered extents that
were logged in the transaction that is currently running.  We add the ordered
extent to a transaction list and then the transaction waits on all the ordered
extents in that list.  However are substantially large file systems this list
can be extremely large, and can give us soft lockups, since the ordered extents
don't remove themselves from the list when they do complete.

To fix this we simply add a counter to the transaction that is incremented any
time we have a logged extent that needs to be completed in the current
transaction.  Then when the ordered extent finally completes it decrements the
per transaction counter and wakes up the transaction if we are the last ones.
This will eliminate the softlockup.  Thanks,

Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We have a mechanism to make sure we don't lose updates for ordered extents that
were logged in the transaction that is currently running.  We add the ordered
extent to a transaction list and then the transaction waits on all the ordered
extents in that list.  However are substantially large file systems this list
can be extremely large, and can give us soft lockups, since the ordered extents
don't remove themselves from the list when they do complete.

To fix this we simply add a counter to the transaction that is incremented any
time we have a logged extent that needs to be completed in the current
transaction.  Then when the ordered extent finally completes it decrements the
per transaction counter and wakes up the transaction if we are the last ones.
This will eliminate the softlockup.  Thanks,

Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>btrfs: add comments to barriers before waitqueue_active</title>
<updated>2015-10-10T16:40:04+00:00</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.com</email>
</author>
<published>2015-02-16T18:36:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=a83342aa0c8f0ca90057d3837ae8d198186e5153'/>
<id>a83342aa0c8f0ca90057d3837ae8d198186e5153</id>
<content type='text'>
Reduce number of undocumented barriers out there.

Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Reduce number of undocumented barriers out there.

Signed-off-by: David Sterba &lt;dsterba@suse.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix memory corruption on failure to submit bio for direct IO</title>
<updated>2015-07-02T00:17:18+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-07-01T11:13:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=61de718fceb6bc028dafe4d06a1f87a9e0998303'/>
<id>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>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
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;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: don't attach unnecessary extents to transaction on fsync</title>
<updated>2015-06-10T14:02:44+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-04-17T16:08:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=7558c8bc17481c1f856e009af8503ab40fec348a'/>
<id>7558c8bc17481c1f856e009af8503ab40fec348a</id>
<content type='text'>
We don't need to attach ordered extents that have completed to the current
transaction. Doing so only makes us hold memory for longer than necessary
and delaying the iput of the inode until the transaction is committed (for
each created ordered extent we do an igrab and then schedule an asynchronous
iput when the ordered extent's reference count drops to 0), preventing the
inode from being evictable until the transaction commits.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We don't need to attach ordered extents that have completed to the current
transaction. Doing so only makes us hold memory for longer than necessary
and delaying the iput of the inode until the transaction is committed (for
each created ordered extent we do an igrab and then schedule an asynchronous
iput when the ordered extent's reference count drops to 0), preventing the
inode from being evictable until the transaction commits.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: avoid syncing log in the fast fsync path when not necessary</title>
<updated>2015-06-10T14:02:43+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-03-31T13:16:52+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=b659ef027792219b590d67a2baf1643a93727d29'/>
<id>b659ef027792219b590d67a2baf1643a93727d29</id>
<content type='text'>
Commit 3a8b36f37806 ("Btrfs: fix data loss in the fast fsync path") added
a performance regression for that causes an unnecessary sync of the log
trees (fs/subvol and root log trees) when 2 consecutive fsyncs are done
against a file, without no writes or any metadata updates to the inode in
between them and if a transaction is committed before the second fsync is
called.

Huang Ying reported this to lkml (https://lkml.org/lkml/2015/3/18/99)
after a test sysbench test that measured a -62% decrease of file io
requests per second for that tests' workload.

The test is:

  echo performance &gt; /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor
  mkfs -t btrfs /dev/sda2
  mount -t btrfs /dev/sda2 /fs/sda2
  cd /fs/sda2
  for ((i = 0; i &lt; 1024; i++)); do fallocate -l 67108864 testfile.$i; done
  sysbench --test=fileio --max-requests=0 --num-threads=4 --max-time=600 \
    --file-test-mode=rndwr --file-total-size=68719476736 --file-io-mode=sync \
    --file-num=1024 run

A test on kvm guest, running a debug kernel gave me the following results:

Without 3a8b36f378060d:             16.01 reqs/sec
With 3a8b36f378060d:                 3.39 reqs/sec
With 3a8b36f378060d and this patch: 16.04 reqs/sec

Reported-by: Huang Ying &lt;ying.huang@intel.com&gt;
Tested-by: Huang, Ying &lt;ying.huang@intel.com&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Commit 3a8b36f37806 ("Btrfs: fix data loss in the fast fsync path") added
a performance regression for that causes an unnecessary sync of the log
trees (fs/subvol and root log trees) when 2 consecutive fsyncs are done
against a file, without no writes or any metadata updates to the inode in
between them and if a transaction is committed before the second fsync is
called.

Huang Ying reported this to lkml (https://lkml.org/lkml/2015/3/18/99)
after a test sysbench test that measured a -62% decrease of file io
requests per second for that tests' workload.

The test is:

  echo performance &gt; /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu1/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu2/cpufreq/scaling_governor
  echo performance &gt; /sys/devices/system/cpu/cpu3/cpufreq/scaling_governor
  mkfs -t btrfs /dev/sda2
  mount -t btrfs /dev/sda2 /fs/sda2
  cd /fs/sda2
  for ((i = 0; i &lt; 1024; i++)); do fallocate -l 67108864 testfile.$i; done
  sysbench --test=fileio --max-requests=0 --num-threads=4 --max-time=600 \
    --file-test-mode=rndwr --file-total-size=68719476736 --file-io-mode=sync \
    --file-num=1024 run

A test on kvm guest, running a debug kernel gave me the following results:

Without 3a8b36f378060d:             16.01 reqs/sec
With 3a8b36f378060d:                 3.39 reqs/sec
With 3a8b36f378060d and this patch: 16.04 reqs/sec

Reported-by: Huang Ying &lt;ying.huang@intel.com&gt;
Tested-by: Huang, Ying &lt;ying.huang@intel.com&gt;
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: remove csum_bytes_left</title>
<updated>2015-06-03T11:03:06+00:00</updated>
<author>
<name>Liu Bo</name>
<email>bo.li.liu@oracle.com</email>
</author>
<published>2015-05-25T03:20:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=0c304304feab8a576ed6ba6ec964255d00d2886e'/>
<id>0c304304feab8a576ed6ba6ec964255d00d2886e</id>
<content type='text'>
After commit 8407f553268a
("Btrfs: fix data corruption after fast fsync and writeback error"),
during wait_ordered_extents(), we wait for ordered extent setting
BTRFS_ORDERED_IO_DONE or BTRFS_ORDERED_IOERR, at which point we've
already got checksum information, so we don't need to check
(csum_bytes_left == 0) in the whole logging path.

Signed-off-by: Liu Bo &lt;bo.li.liu@oracle.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
After commit 8407f553268a
("Btrfs: fix data corruption after fast fsync and writeback error"),
during wait_ordered_extents(), we wait for ordered extent setting
BTRFS_ORDERED_IO_DONE or BTRFS_ORDERED_IOERR, at which point we've
already got checksum information, so we don't need to check
(csum_bytes_left == 0) in the whole logging path.

Signed-off-by: Liu Bo &lt;bo.li.liu@oracle.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix panic when starting bg cache writeout after IO error</title>
<updated>2015-05-11T14:59:10+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-05-05T18:03:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=28aeeac1dd3080db5108b7b446be69f05c470a90'/>
<id>28aeeac1dd3080db5108b7b446be69f05c470a90</id>
<content type='text'>
When waiting for the writeback of block group cache we returned
immediately if there was an error during writeback without waiting
for the ordered extent to complete. This left a short time window
where if some other task attempts to start the writeout for the same
block group cache it can attempt to add a new ordered extent, starting
at the same offset (0) before the previous one is removed from the
ordered tree, causing an ordered tree panic (calls BUG()).

This normally doesn't happen in other write paths, such as buffered
writes or direct IO writes for regular files, since before marking
page ranges dirty we lock the ranges and wait for any ordered extents
within the range to complete first.

Fix this by making btrfs_wait_ordered_range() not return immediately
if it gets an error from the writeback, waiting for all ordered extents
to complete first.

This issue happened often when running the fstest btrfs/088 and it's
easy to trigger it by running in a loop until the panic happens:

  for ((i = 1; i &lt;= 10000; i++)) do ./check btrfs/088 ; done

[17156.862573] BTRFS critical (device sdc): panic in ordered_data_tree_panic:70: Inconsistency in ordered tree at offset 0 (errno=-17 Object already exists)
[17156.864052] ------------[ cut here ]------------
[17156.864052] kernel BUG at fs/btrfs/ordered-data.c:70!
(...)
[17156.864052] Call Trace:
[17156.864052]  [&lt;ffffffffa03876e3&gt;] btrfs_add_ordered_extent+0x12/0x14 [btrfs]
[17156.864052]  [&lt;ffffffffa03787e2&gt;] run_delalloc_nocow+0x5bf/0x747 [btrfs]
[17156.864052]  [&lt;ffffffffa03789ff&gt;] run_delalloc_range+0x95/0x353 [btrfs]
[17156.864052]  [&lt;ffffffffa038b7fe&gt;] writepage_delalloc.isra.16+0xb9/0x13f [btrfs]
[17156.864052]  [&lt;ffffffffa038d75b&gt;] __extent_writepage+0x129/0x1f7 [btrfs]
[17156.864052]  [&lt;ffffffffa038da5a&gt;] extent_write_cache_pages.isra.15.constprop.28+0x231/0x2f4 [btrfs]
[17156.864052]  [&lt;ffffffff810ad2af&gt;] ? __module_text_address+0x12/0x59
[17156.864052]  [&lt;ffffffff8107d33d&gt;] ? trace_hardirqs_on+0xd/0xf
[17156.864052]  [&lt;ffffffffa038df76&gt;] extent_writepages+0x4b/0x5c [btrfs]
[17156.864052]  [&lt;ffffffff81144431&gt;] ? kmem_cache_free+0x9b/0xce
[17156.864052]  [&lt;ffffffffa0376a46&gt;] ? btrfs_submit_direct+0x3fc/0x3fc [btrfs]
[17156.864052]  [&lt;ffffffffa0389cd6&gt;] ? free_extent_state+0x8c/0xc1 [btrfs]
[17156.864052]  [&lt;ffffffffa0374871&gt;] btrfs_writepages+0x28/0x2a [btrfs]
[17156.864052]  [&lt;ffffffff8110c4c8&gt;] do_writepages+0x23/0x2c
[17156.864052]  [&lt;ffffffff81102f36&gt;] __filemap_fdatawrite_range+0x5a/0x61
[17156.864052]  [&lt;ffffffff81102f6e&gt;] filemap_fdatawrite_range+0x13/0x15
[17156.864052]  [&lt;ffffffffa0383ef7&gt;] btrfs_fdatawrite_range+0x21/0x48 [btrfs]
[17156.864052]  [&lt;ffffffffa03ab89e&gt;] __btrfs_write_out_cache.isra.14+0x2d9/0x3a7 [btrfs]
[17156.864052]  [&lt;ffffffffa03ac1ab&gt;] ? btrfs_write_out_cache+0x41/0xdc [btrfs]
[17156.864052]  [&lt;ffffffffa03ac1fd&gt;] btrfs_write_out_cache+0x93/0xdc [btrfs]
[17156.864052]  [&lt;ffffffffa0363847&gt;] ? btrfs_start_dirty_block_groups+0x13a/0x2b2 [btrfs]
[17156.864052]  [&lt;ffffffffa03638e6&gt;] btrfs_start_dirty_block_groups+0x1d9/0x2b2 [btrfs]
[17156.864052]  [&lt;ffffffff8107d33d&gt;] ? trace_hardirqs_on+0xd/0xf
[17156.864052]  [&lt;ffffffffa037209e&gt;] btrfs_commit_transaction+0x130/0x9c9 [btrfs]
[17156.864052]  [&lt;ffffffffa034c748&gt;] btrfs_sync_fs+0xe1/0x12d [btrfs]

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When waiting for the writeback of block group cache we returned
immediately if there was an error during writeback without waiting
for the ordered extent to complete. This left a short time window
where if some other task attempts to start the writeout for the same
block group cache it can attempt to add a new ordered extent, starting
at the same offset (0) before the previous one is removed from the
ordered tree, causing an ordered tree panic (calls BUG()).

This normally doesn't happen in other write paths, such as buffered
writes or direct IO writes for regular files, since before marking
page ranges dirty we lock the ranges and wait for any ordered extents
within the range to complete first.

Fix this by making btrfs_wait_ordered_range() not return immediately
if it gets an error from the writeback, waiting for all ordered extents
to complete first.

This issue happened often when running the fstest btrfs/088 and it's
easy to trigger it by running in a loop until the panic happens:

  for ((i = 1; i &lt;= 10000; i++)) do ./check btrfs/088 ; done

[17156.862573] BTRFS critical (device sdc): panic in ordered_data_tree_panic:70: Inconsistency in ordered tree at offset 0 (errno=-17 Object already exists)
[17156.864052] ------------[ cut here ]------------
[17156.864052] kernel BUG at fs/btrfs/ordered-data.c:70!
(...)
[17156.864052] Call Trace:
[17156.864052]  [&lt;ffffffffa03876e3&gt;] btrfs_add_ordered_extent+0x12/0x14 [btrfs]
[17156.864052]  [&lt;ffffffffa03787e2&gt;] run_delalloc_nocow+0x5bf/0x747 [btrfs]
[17156.864052]  [&lt;ffffffffa03789ff&gt;] run_delalloc_range+0x95/0x353 [btrfs]
[17156.864052]  [&lt;ffffffffa038b7fe&gt;] writepage_delalloc.isra.16+0xb9/0x13f [btrfs]
[17156.864052]  [&lt;ffffffffa038d75b&gt;] __extent_writepage+0x129/0x1f7 [btrfs]
[17156.864052]  [&lt;ffffffffa038da5a&gt;] extent_write_cache_pages.isra.15.constprop.28+0x231/0x2f4 [btrfs]
[17156.864052]  [&lt;ffffffff810ad2af&gt;] ? __module_text_address+0x12/0x59
[17156.864052]  [&lt;ffffffff8107d33d&gt;] ? trace_hardirqs_on+0xd/0xf
[17156.864052]  [&lt;ffffffffa038df76&gt;] extent_writepages+0x4b/0x5c [btrfs]
[17156.864052]  [&lt;ffffffff81144431&gt;] ? kmem_cache_free+0x9b/0xce
[17156.864052]  [&lt;ffffffffa0376a46&gt;] ? btrfs_submit_direct+0x3fc/0x3fc [btrfs]
[17156.864052]  [&lt;ffffffffa0389cd6&gt;] ? free_extent_state+0x8c/0xc1 [btrfs]
[17156.864052]  [&lt;ffffffffa0374871&gt;] btrfs_writepages+0x28/0x2a [btrfs]
[17156.864052]  [&lt;ffffffff8110c4c8&gt;] do_writepages+0x23/0x2c
[17156.864052]  [&lt;ffffffff81102f36&gt;] __filemap_fdatawrite_range+0x5a/0x61
[17156.864052]  [&lt;ffffffff81102f6e&gt;] filemap_fdatawrite_range+0x13/0x15
[17156.864052]  [&lt;ffffffffa0383ef7&gt;] btrfs_fdatawrite_range+0x21/0x48 [btrfs]
[17156.864052]  [&lt;ffffffffa03ab89e&gt;] __btrfs_write_out_cache.isra.14+0x2d9/0x3a7 [btrfs]
[17156.864052]  [&lt;ffffffffa03ac1ab&gt;] ? btrfs_write_out_cache+0x41/0xdc [btrfs]
[17156.864052]  [&lt;ffffffffa03ac1fd&gt;] btrfs_write_out_cache+0x93/0xdc [btrfs]
[17156.864052]  [&lt;ffffffffa0363847&gt;] ? btrfs_start_dirty_block_groups+0x13a/0x2b2 [btrfs]
[17156.864052]  [&lt;ffffffffa03638e6&gt;] btrfs_start_dirty_block_groups+0x1d9/0x2b2 [btrfs]
[17156.864052]  [&lt;ffffffff8107d33d&gt;] ? trace_hardirqs_on+0xd/0xf
[17156.864052]  [&lt;ffffffffa037209e&gt;] btrfs_commit_transaction+0x130/0x9c9 [btrfs]
[17156.864052]  [&lt;ffffffffa034c748&gt;] btrfs_sync_fs+0xe1/0x12d [btrfs]

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix fsync race leading to ordered extent memory leaks</title>
<updated>2015-03-02T22:04:44+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2015-02-09T17:17:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=4d884fceaa2c838abb598778813e93f6d9fea723'/>
<id>4d884fceaa2c838abb598778813e93f6d9fea723</id>
<content type='text'>
We can have multiple fsync operations against the same file during the
same transaction and they can collect the same ordered extents while they
don't complete (still accessible from the inode's ordered tree). If this
happens, those ordered extents will never get their reference counts
decremented to 0, leading to memory leaks and inode leaks (an iput for an
ordered extent's inode is scheduled only when the ordered extent's refcount
drops to 0). The following sequence diagram explains this race:

         CPU 1                                         CPU 2

btrfs_sync_file()

                                                 btrfs_sync_file()

  mutex_lock(inode-&gt;i_mutex)
  btrfs_log_inode()
    btrfs_get_logged_extents()
      --&gt; collects ordered extent X
      --&gt; increments ordered
          extent X's refcount
    btrfs_submit_logged_extents()
  mutex_unlock(inode-&gt;i_mutex)

                                                   mutex_lock(inode-&gt;i_mutex)
  btrfs_sync_log()
     btrfs_wait_logged_extents()
       --&gt; list_del_init(&amp;ordered-&gt;log_list)
                                                     btrfs_log_inode()
                                                       btrfs_get_logged_extents()
                                                         --&gt; Adds ordered extent X
                                                             to logged_list because
                                                             at this point:
                                                             list_empty(&amp;ordered-&gt;log_list)
                                                             &amp;&amp; test_bit(BTRFS_ORDERED_LOGGED,
                                                                         &amp;ordered-&gt;flags) == 0
                                                         --&gt; Increments ordered extent
                                                             X's refcount
       --&gt; check if ordered extent's io is
           finished or not, start it if
           necessary and wait for it to finish
       --&gt; sets bit BTRFS_ORDERED_LOGGED
           on ordered extent X's flags
           and adds it to trans-&gt;ordered
  btrfs_sync_log() finishes

                                                       btrfs_submit_logged_extents()
                                                     btrfs_log_inode() finishes
                                                   mutex_unlock(inode-&gt;i_mutex)

btrfs_sync_file() finishes

                                                   btrfs_sync_log()
                                                      btrfs_wait_logged_extents()
                                                        --&gt; Sees ordered extent X has the
                                                            bit BTRFS_ORDERED_LOGGED set in
                                                            its flags
                                                        --&gt; X's refcount is untouched
                                                   btrfs_sync_log() finishes

                                                 btrfs_sync_file() finishes

btrfs_commit_transaction()
  --&gt; called by transaction kthread for e.g.
  btrfs_wait_pending_ordered()
    --&gt; waits for ordered extent X to
        complete
    --&gt; decrements ordered extent X's
        refcount by 1 only, corresponding
        to the increment done by the fsync
        task ran by CPU 1

In the scenario of the above diagram, after the transaction commit,
the ordered extent will remain with a refcount of 1 forever, leaking
the ordered extent structure and preventing the i_count of its inode
from ever decreasing to 0, since the delayed iput is scheduled only
when the ordered extent's refcount drops to 0, preventing the inode
from ever being evicted by the VFS.

Fix this by using the flag BTRFS_ORDERED_LOGGED differently. Use it to
mean that an ordered extent is already being processed by an fsync call,
which will attach it to the current transaction, preventing it from being
collected by subsequent fsync operations against the same inode.

This race was introduced with the following change (added in 3.19 and
backported to stable 3.18 and 3.17):

  Btrfs: make sure logged extents complete in the current transaction V3
  commit 50d9aa99bd35c77200e0e3dd7a72274f8304701f

I ran into this issue while running xfstests/generic/113 in a loop, which
failed about 1 out of 10 runs with the following warning in dmesg:

[ 2612.440038] WARNING: CPU: 4 PID: 22057 at fs/btrfs/disk-io.c:3558 free_fs_root+0x36/0x133 [btrfs]()
[ 2612.442810] Modules linked in: btrfs crc32c_generic xor raid6_pq nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache sunrpc loop processor parport_pc parport psmouse therma
l_sys i2c_piix4 serio_raw pcspkr evdev microcode button i2c_core ext4 crc16 jbd2 mbcache sd_mod sg sr_mod cdrom virtio_scsi ata_generic virtio_pci ata_piix virtio_ring libata virtio flo
ppy e1000 scsi_mod [last unloaded: btrfs]
[ 2612.452711] CPU: 4 PID: 22057 Comm: umount Tainted: G        W      3.19.0-rc5-btrfs-next-4+ #1
[ 2612.454921] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2612.457709]  0000000000000009 ffff8801342c3c78 ffffffff8142425e ffff88023ec8f2d8
[ 2612.459829]  0000000000000000 ffff8801342c3cb8 ffffffff81045308 ffff880046460000
[ 2612.461564]  ffffffffa036da56 ffff88003d07b000 ffff880046460000 ffff880046460068
[ 2612.463163] Call Trace:
[ 2612.463719]  [&lt;ffffffff8142425e&gt;] dump_stack+0x4c/0x65
[ 2612.464789]  [&lt;ffffffff81045308&gt;] warn_slowpath_common+0xa1/0xbb
[ 2612.466026]  [&lt;ffffffffa036da56&gt;] ? free_fs_root+0x36/0x133 [btrfs]
[ 2612.467247]  [&lt;ffffffff810453c5&gt;] warn_slowpath_null+0x1a/0x1c
[ 2612.468416]  [&lt;ffffffffa036da56&gt;] free_fs_root+0x36/0x133 [btrfs]
[ 2612.469625]  [&lt;ffffffffa036f2a7&gt;] btrfs_drop_and_free_fs_root+0x93/0x9b [btrfs]
[ 2612.471251]  [&lt;ffffffffa036f353&gt;] btrfs_free_fs_roots+0xa4/0xd6 [btrfs]
[ 2612.472536]  [&lt;ffffffff8142612e&gt;] ? wait_for_completion+0x24/0x26
[ 2612.473742]  [&lt;ffffffffa0370bbc&gt;] close_ctree+0x1f3/0x33c [btrfs]
[ 2612.475477]  [&lt;ffffffff81059d1d&gt;] ? destroy_workqueue+0x148/0x1ba
[ 2612.476695]  [&lt;ffffffffa034e3da&gt;] btrfs_put_super+0x19/0x1b [btrfs]
[ 2612.477911]  [&lt;ffffffff81153e53&gt;] generic_shutdown_super+0x73/0xef
[ 2612.479106]  [&lt;ffffffff811540e2&gt;] kill_anon_super+0x13/0x1e
[ 2612.480226]  [&lt;ffffffffa034e1e3&gt;] btrfs_kill_super+0x17/0x23 [btrfs]
[ 2612.481471]  [&lt;ffffffff81154307&gt;] deactivate_locked_super+0x3b/0x50
[ 2612.482686]  [&lt;ffffffff811547a7&gt;] deactivate_super+0x3f/0x43
[ 2612.483791]  [&lt;ffffffff8116b3ed&gt;] cleanup_mnt+0x59/0x78
[ 2612.484842]  [&lt;ffffffff8116b44c&gt;] __cleanup_mnt+0x12/0x14
[ 2612.485900]  [&lt;ffffffff8105d019&gt;] task_work_run+0x8f/0xbc
[ 2612.486960]  [&lt;ffffffff810028d8&gt;] do_notify_resume+0x5a/0x6b
[ 2612.488083]  [&lt;ffffffff81236e5b&gt;] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 2612.489333]  [&lt;ffffffff8142a17f&gt;] int_signal+0x12/0x17
[ 2612.490353] ---[ end trace 54a960a6bdcb8d93 ]---
[ 2612.557253] VFS: Busy inodes after unmount of sdb. Self-destruct in 5 seconds.  Have a nice day...

Kmemleak confirmed the ordered extent leak (and btrfs inode specific
structures such as delayed nodes):

$ cat /sys/kernel/debug/kmemleak
unreferenced object 0xffff880154290db0 (size 576):
  comm "btrfsck", pid 21980, jiffies 4295542503 (age 1273.412s)
  hex dump (first 32 bytes):
    01 40 00 00 01 00 00 00 b0 1d f1 4e 01 88 ff ff  .@.........N....
    00 00 00 00 00 00 00 00 c8 0d 29 54 01 88 ff ff  ..........)T....
  backtrace:
    [&lt;ffffffff8141d74d&gt;] kmemleak_update_trace+0x4c/0x6a
    [&lt;ffffffff8122f2c0&gt;] radix_tree_node_alloc+0x6d/0x83
    [&lt;ffffffff8122fb26&gt;] __radix_tree_create+0x109/0x190
    [&lt;ffffffff8122fbdd&gt;] radix_tree_insert+0x30/0xac
    [&lt;ffffffffa03b9bde&gt;] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [&lt;ffffffffa03bb82d&gt;] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [&lt;ffffffffa0379dae&gt;] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [&lt;ffffffffa037c715&gt;] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [&lt;ffffffffa037c797&gt;] btrfs_unlink+0x60/0x9b [btrfs]
    [&lt;ffffffff8115d7f0&gt;] vfs_unlink+0x9c/0xed
    [&lt;ffffffff8115f5de&gt;] do_unlinkat+0x12c/0x1fa
    [&lt;ffffffff811601a7&gt;] SyS_unlinkat+0x29/0x2b
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17
    [&lt;ffffffffffffffff&gt;] 0xffffffffffffffff
unreferenced object 0xffff88014ef11db0 (size 576):
  comm "rm", pid 22009, jiffies 4295542593 (age 1273.052s)
  hex dump (first 32 bytes):
    02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 c8 1d f1 4e 01 88 ff ff  ...........N....
  backtrace:
    [&lt;ffffffff8141d74d&gt;] kmemleak_update_trace+0x4c/0x6a
    [&lt;ffffffff8122f2c0&gt;] radix_tree_node_alloc+0x6d/0x83
    [&lt;ffffffff8122fb26&gt;] __radix_tree_create+0x109/0x190
    [&lt;ffffffff8122fbdd&gt;] radix_tree_insert+0x30/0xac
    [&lt;ffffffffa03b9bde&gt;] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [&lt;ffffffffa03bb82d&gt;] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [&lt;ffffffffa0379dae&gt;] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [&lt;ffffffffa037c715&gt;] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [&lt;ffffffffa037c797&gt;] btrfs_unlink+0x60/0x9b [btrfs]
    [&lt;ffffffff8115d7f0&gt;] vfs_unlink+0x9c/0xed
    [&lt;ffffffff8115f5de&gt;] do_unlinkat+0x12c/0x1fa
    [&lt;ffffffff811601a7&gt;] SyS_unlinkat+0x29/0x2b
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17
    [&lt;ffffffffffffffff&gt;] 0xffffffffffffffff
unreferenced object 0xffff8800336feda8 (size 584):
  comm "aio-stress", pid 22031, jiffies 4295543006 (age 1271.400s)
  hex dump (first 32 bytes):
    00 40 3e 00 00 00 00 00 00 00 8f 42 00 00 00 00  .@&gt;........B....
    00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 00  ................
  backtrace:
    [&lt;ffffffff8114eb34&gt;] create_object+0x172/0x29a
    [&lt;ffffffff8141d790&gt;] kmemleak_alloc+0x25/0x41
    [&lt;ffffffff81141ae6&gt;] kmemleak_alloc_recursive.constprop.52+0x16/0x18
    [&lt;ffffffff81145288&gt;] kmem_cache_alloc+0xf7/0x198
    [&lt;ffffffffa0389243&gt;] __btrfs_add_ordered_extent+0x43/0x309 [btrfs]
    [&lt;ffffffffa038968b&gt;] btrfs_add_ordered_extent_dio+0x12/0x14 [btrfs]
    [&lt;ffffffffa03810e2&gt;] btrfs_get_blocks_direct+0x3ef/0x571 [btrfs]
    [&lt;ffffffff81181349&gt;] do_blockdev_direct_IO+0x62a/0xb47
    [&lt;ffffffff8118189a&gt;] __blockdev_direct_IO+0x34/0x36
    [&lt;ffffffffa03776e5&gt;] btrfs_direct_IO+0x16a/0x1e8 [btrfs]
    [&lt;ffffffff81100373&gt;] generic_file_direct_write+0xb8/0x12d
    [&lt;ffffffffa038615c&gt;] btrfs_file_write_iter+0x24b/0x42f [btrfs]
    [&lt;ffffffff8118bb0d&gt;] aio_run_iocb+0x2b7/0x32e
    [&lt;ffffffff8118c99a&gt;] do_io_submit+0x26e/0x2ff
    [&lt;ffffffff8118ca3b&gt;] SyS_io_submit+0x10/0x12
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17

CC: &lt;stable@vger.kernel.org&gt; # 3.19, 3.18 and 3.17
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We can have multiple fsync operations against the same file during the
same transaction and they can collect the same ordered extents while they
don't complete (still accessible from the inode's ordered tree). If this
happens, those ordered extents will never get their reference counts
decremented to 0, leading to memory leaks and inode leaks (an iput for an
ordered extent's inode is scheduled only when the ordered extent's refcount
drops to 0). The following sequence diagram explains this race:

         CPU 1                                         CPU 2

btrfs_sync_file()

                                                 btrfs_sync_file()

  mutex_lock(inode-&gt;i_mutex)
  btrfs_log_inode()
    btrfs_get_logged_extents()
      --&gt; collects ordered extent X
      --&gt; increments ordered
          extent X's refcount
    btrfs_submit_logged_extents()
  mutex_unlock(inode-&gt;i_mutex)

                                                   mutex_lock(inode-&gt;i_mutex)
  btrfs_sync_log()
     btrfs_wait_logged_extents()
       --&gt; list_del_init(&amp;ordered-&gt;log_list)
                                                     btrfs_log_inode()
                                                       btrfs_get_logged_extents()
                                                         --&gt; Adds ordered extent X
                                                             to logged_list because
                                                             at this point:
                                                             list_empty(&amp;ordered-&gt;log_list)
                                                             &amp;&amp; test_bit(BTRFS_ORDERED_LOGGED,
                                                                         &amp;ordered-&gt;flags) == 0
                                                         --&gt; Increments ordered extent
                                                             X's refcount
       --&gt; check if ordered extent's io is
           finished or not, start it if
           necessary and wait for it to finish
       --&gt; sets bit BTRFS_ORDERED_LOGGED
           on ordered extent X's flags
           and adds it to trans-&gt;ordered
  btrfs_sync_log() finishes

                                                       btrfs_submit_logged_extents()
                                                     btrfs_log_inode() finishes
                                                   mutex_unlock(inode-&gt;i_mutex)

btrfs_sync_file() finishes

                                                   btrfs_sync_log()
                                                      btrfs_wait_logged_extents()
                                                        --&gt; Sees ordered extent X has the
                                                            bit BTRFS_ORDERED_LOGGED set in
                                                            its flags
                                                        --&gt; X's refcount is untouched
                                                   btrfs_sync_log() finishes

                                                 btrfs_sync_file() finishes

btrfs_commit_transaction()
  --&gt; called by transaction kthread for e.g.
  btrfs_wait_pending_ordered()
    --&gt; waits for ordered extent X to
        complete
    --&gt; decrements ordered extent X's
        refcount by 1 only, corresponding
        to the increment done by the fsync
        task ran by CPU 1

In the scenario of the above diagram, after the transaction commit,
the ordered extent will remain with a refcount of 1 forever, leaking
the ordered extent structure and preventing the i_count of its inode
from ever decreasing to 0, since the delayed iput is scheduled only
when the ordered extent's refcount drops to 0, preventing the inode
from ever being evicted by the VFS.

Fix this by using the flag BTRFS_ORDERED_LOGGED differently. Use it to
mean that an ordered extent is already being processed by an fsync call,
which will attach it to the current transaction, preventing it from being
collected by subsequent fsync operations against the same inode.

This race was introduced with the following change (added in 3.19 and
backported to stable 3.18 and 3.17):

  Btrfs: make sure logged extents complete in the current transaction V3
  commit 50d9aa99bd35c77200e0e3dd7a72274f8304701f

I ran into this issue while running xfstests/generic/113 in a loop, which
failed about 1 out of 10 runs with the following warning in dmesg:

[ 2612.440038] WARNING: CPU: 4 PID: 22057 at fs/btrfs/disk-io.c:3558 free_fs_root+0x36/0x133 [btrfs]()
[ 2612.442810] Modules linked in: btrfs crc32c_generic xor raid6_pq nfsd auth_rpcgss oid_registry nfs_acl nfs lockd grace fscache sunrpc loop processor parport_pc parport psmouse therma
l_sys i2c_piix4 serio_raw pcspkr evdev microcode button i2c_core ext4 crc16 jbd2 mbcache sd_mod sg sr_mod cdrom virtio_scsi ata_generic virtio_pci ata_piix virtio_ring libata virtio flo
ppy e1000 scsi_mod [last unloaded: btrfs]
[ 2612.452711] CPU: 4 PID: 22057 Comm: umount Tainted: G        W      3.19.0-rc5-btrfs-next-4+ #1
[ 2612.454921] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5-0-ge51488c-20140602_164612-nilsson.home.kraxel.org 04/01/2014
[ 2612.457709]  0000000000000009 ffff8801342c3c78 ffffffff8142425e ffff88023ec8f2d8
[ 2612.459829]  0000000000000000 ffff8801342c3cb8 ffffffff81045308 ffff880046460000
[ 2612.461564]  ffffffffa036da56 ffff88003d07b000 ffff880046460000 ffff880046460068
[ 2612.463163] Call Trace:
[ 2612.463719]  [&lt;ffffffff8142425e&gt;] dump_stack+0x4c/0x65
[ 2612.464789]  [&lt;ffffffff81045308&gt;] warn_slowpath_common+0xa1/0xbb
[ 2612.466026]  [&lt;ffffffffa036da56&gt;] ? free_fs_root+0x36/0x133 [btrfs]
[ 2612.467247]  [&lt;ffffffff810453c5&gt;] warn_slowpath_null+0x1a/0x1c
[ 2612.468416]  [&lt;ffffffffa036da56&gt;] free_fs_root+0x36/0x133 [btrfs]
[ 2612.469625]  [&lt;ffffffffa036f2a7&gt;] btrfs_drop_and_free_fs_root+0x93/0x9b [btrfs]
[ 2612.471251]  [&lt;ffffffffa036f353&gt;] btrfs_free_fs_roots+0xa4/0xd6 [btrfs]
[ 2612.472536]  [&lt;ffffffff8142612e&gt;] ? wait_for_completion+0x24/0x26
[ 2612.473742]  [&lt;ffffffffa0370bbc&gt;] close_ctree+0x1f3/0x33c [btrfs]
[ 2612.475477]  [&lt;ffffffff81059d1d&gt;] ? destroy_workqueue+0x148/0x1ba
[ 2612.476695]  [&lt;ffffffffa034e3da&gt;] btrfs_put_super+0x19/0x1b [btrfs]
[ 2612.477911]  [&lt;ffffffff81153e53&gt;] generic_shutdown_super+0x73/0xef
[ 2612.479106]  [&lt;ffffffff811540e2&gt;] kill_anon_super+0x13/0x1e
[ 2612.480226]  [&lt;ffffffffa034e1e3&gt;] btrfs_kill_super+0x17/0x23 [btrfs]
[ 2612.481471]  [&lt;ffffffff81154307&gt;] deactivate_locked_super+0x3b/0x50
[ 2612.482686]  [&lt;ffffffff811547a7&gt;] deactivate_super+0x3f/0x43
[ 2612.483791]  [&lt;ffffffff8116b3ed&gt;] cleanup_mnt+0x59/0x78
[ 2612.484842]  [&lt;ffffffff8116b44c&gt;] __cleanup_mnt+0x12/0x14
[ 2612.485900]  [&lt;ffffffff8105d019&gt;] task_work_run+0x8f/0xbc
[ 2612.486960]  [&lt;ffffffff810028d8&gt;] do_notify_resume+0x5a/0x6b
[ 2612.488083]  [&lt;ffffffff81236e5b&gt;] ? trace_hardirqs_on_thunk+0x3a/0x3f
[ 2612.489333]  [&lt;ffffffff8142a17f&gt;] int_signal+0x12/0x17
[ 2612.490353] ---[ end trace 54a960a6bdcb8d93 ]---
[ 2612.557253] VFS: Busy inodes after unmount of sdb. Self-destruct in 5 seconds.  Have a nice day...

Kmemleak confirmed the ordered extent leak (and btrfs inode specific
structures such as delayed nodes):

$ cat /sys/kernel/debug/kmemleak
unreferenced object 0xffff880154290db0 (size 576):
  comm "btrfsck", pid 21980, jiffies 4295542503 (age 1273.412s)
  hex dump (first 32 bytes):
    01 40 00 00 01 00 00 00 b0 1d f1 4e 01 88 ff ff  .@.........N....
    00 00 00 00 00 00 00 00 c8 0d 29 54 01 88 ff ff  ..........)T....
  backtrace:
    [&lt;ffffffff8141d74d&gt;] kmemleak_update_trace+0x4c/0x6a
    [&lt;ffffffff8122f2c0&gt;] radix_tree_node_alloc+0x6d/0x83
    [&lt;ffffffff8122fb26&gt;] __radix_tree_create+0x109/0x190
    [&lt;ffffffff8122fbdd&gt;] radix_tree_insert+0x30/0xac
    [&lt;ffffffffa03b9bde&gt;] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [&lt;ffffffffa03bb82d&gt;] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [&lt;ffffffffa0379dae&gt;] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [&lt;ffffffffa037c715&gt;] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [&lt;ffffffffa037c797&gt;] btrfs_unlink+0x60/0x9b [btrfs]
    [&lt;ffffffff8115d7f0&gt;] vfs_unlink+0x9c/0xed
    [&lt;ffffffff8115f5de&gt;] do_unlinkat+0x12c/0x1fa
    [&lt;ffffffff811601a7&gt;] SyS_unlinkat+0x29/0x2b
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17
    [&lt;ffffffffffffffff&gt;] 0xffffffffffffffff
unreferenced object 0xffff88014ef11db0 (size 576):
  comm "rm", pid 22009, jiffies 4295542593 (age 1273.052s)
  hex dump (first 32 bytes):
    02 00 00 00 01 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 00 00 00 00 c8 1d f1 4e 01 88 ff ff  ...........N....
  backtrace:
    [&lt;ffffffff8141d74d&gt;] kmemleak_update_trace+0x4c/0x6a
    [&lt;ffffffff8122f2c0&gt;] radix_tree_node_alloc+0x6d/0x83
    [&lt;ffffffff8122fb26&gt;] __radix_tree_create+0x109/0x190
    [&lt;ffffffff8122fbdd&gt;] radix_tree_insert+0x30/0xac
    [&lt;ffffffffa03b9bde&gt;] btrfs_get_or_create_delayed_node+0x130/0x187 [btrfs]
    [&lt;ffffffffa03bb82d&gt;] btrfs_delayed_delete_inode_ref+0x32/0xac [btrfs]
    [&lt;ffffffffa0379dae&gt;] __btrfs_unlink_inode+0xee/0x288 [btrfs]
    [&lt;ffffffffa037c715&gt;] btrfs_unlink_inode+0x1e/0x40 [btrfs]
    [&lt;ffffffffa037c797&gt;] btrfs_unlink+0x60/0x9b [btrfs]
    [&lt;ffffffff8115d7f0&gt;] vfs_unlink+0x9c/0xed
    [&lt;ffffffff8115f5de&gt;] do_unlinkat+0x12c/0x1fa
    [&lt;ffffffff811601a7&gt;] SyS_unlinkat+0x29/0x2b
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17
    [&lt;ffffffffffffffff&gt;] 0xffffffffffffffff
unreferenced object 0xffff8800336feda8 (size 584):
  comm "aio-stress", pid 22031, jiffies 4295543006 (age 1271.400s)
  hex dump (first 32 bytes):
    00 40 3e 00 00 00 00 00 00 00 8f 42 00 00 00 00  .@&gt;........B....
    00 00 01 00 00 00 00 00 00 00 01 00 00 00 00 00  ................
  backtrace:
    [&lt;ffffffff8114eb34&gt;] create_object+0x172/0x29a
    [&lt;ffffffff8141d790&gt;] kmemleak_alloc+0x25/0x41
    [&lt;ffffffff81141ae6&gt;] kmemleak_alloc_recursive.constprop.52+0x16/0x18
    [&lt;ffffffff81145288&gt;] kmem_cache_alloc+0xf7/0x198
    [&lt;ffffffffa0389243&gt;] __btrfs_add_ordered_extent+0x43/0x309 [btrfs]
    [&lt;ffffffffa038968b&gt;] btrfs_add_ordered_extent_dio+0x12/0x14 [btrfs]
    [&lt;ffffffffa03810e2&gt;] btrfs_get_blocks_direct+0x3ef/0x571 [btrfs]
    [&lt;ffffffff81181349&gt;] do_blockdev_direct_IO+0x62a/0xb47
    [&lt;ffffffff8118189a&gt;] __blockdev_direct_IO+0x34/0x36
    [&lt;ffffffffa03776e5&gt;] btrfs_direct_IO+0x16a/0x1e8 [btrfs]
    [&lt;ffffffff81100373&gt;] generic_file_direct_write+0xb8/0x12d
    [&lt;ffffffffa038615c&gt;] btrfs_file_write_iter+0x24b/0x42f [btrfs]
    [&lt;ffffffff8118bb0d&gt;] aio_run_iocb+0x2b7/0x32e
    [&lt;ffffffff8118c99a&gt;] do_io_submit+0x26e/0x2ff
    [&lt;ffffffff8118ca3b&gt;] SyS_io_submit+0x10/0x12
    [&lt;ffffffff81429e92&gt;] system_call_fastpath+0x12/0x17

CC: &lt;stable@vger.kernel.org&gt; # 3.19, 3.18 and 3.17
Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: collect only the necessary ordered extents on ranged fsync</title>
<updated>2014-11-21T19:59:56+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2014-11-13T17:00:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=0870295b2371673b3563735825ad559409d8cedc'/>
<id>0870295b2371673b3563735825ad559409d8cedc</id>
<content type='text'>
Instead of collecting all ordered extents from the inode's ordered tree
and then wait for all of them to complete, just collect the ones that
overlap the fsync range.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Instead of collecting all ordered extents from the inode's ordered tree
and then wait for all of them to complete, just collect the ones that
overlap the fsync range.

Signed-off-by: Filipe Manana &lt;fdmanana@suse.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: make sure logged extents complete in the current transaction V3</title>
<updated>2014-11-21T19:58:32+00:00</updated>
<author>
<name>Josef Bacik</name>
<email>jbacik@fb.com</email>
</author>
<published>2014-11-21T19:52:38+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=50d9aa99bd35c77200e0e3dd7a72274f8304701f'/>
<id>50d9aa99bd35c77200e0e3dd7a72274f8304701f</id>
<content type='text'>
Liu Bo pointed out that my previous fix would lose the generation update in the
scenario I described.  It is actually much worse than that, we could lose the
entire extent if we lose power right after the transaction commits.  Consider
the following

write extent 0-4k
log extent in log tree
commit transaction
	&lt; power fail happens here
ordered extent completes

We would lose the 0-4k extent because it hasn't updated the actual fs tree, and
the transaction commit will reset the log so it isn't replayed.  If we lose
power before the transaction commit we are save, otherwise we are not.

Fix this by keeping track of all extents we logged in this transaction.  Then
when we go to commit the transaction make sure we wait for all of those ordered
extents to complete before proceeding.  This will make sure that if we lose
power after the transaction commit we still have our data.  This also fixes the
problem of the improperly updated extent generation.  Thanks,

cc: stable@vger.kernel.org
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Liu Bo pointed out that my previous fix would lose the generation update in the
scenario I described.  It is actually much worse than that, we could lose the
entire extent if we lose power right after the transaction commits.  Consider
the following

write extent 0-4k
log extent in log tree
commit transaction
	&lt; power fail happens here
ordered extent completes

We would lose the 0-4k extent because it hasn't updated the actual fs tree, and
the transaction commit will reset the log so it isn't replayed.  If we lose
power before the transaction commit we are save, otherwise we are not.

Fix this by keeping track of all extents we logged in this transaction.  Then
when we go to commit the transaction make sure we wait for all of those ordered
extents to complete before proceeding.  This will make sure that if we lose
power after the transaction commit we still have our data.  This also fixes the
problem of the improperly updated extent generation.  Thanks,

cc: stable@vger.kernel.org
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
