<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/fs/btrfs/ordered-data.c, branch v4.0</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<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>
<entry>
<title>Btrfs: add helper btrfs_fdatawrite_range</title>
<updated>2014-11-21T01:14:28+00:00</updated>
<author>
<name>Filipe Manana</name>
<email>fdmanana@suse.com</email>
</author>
<published>2014-10-10T08:43:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=728404dacfddb5364d7256d821a2ea482159cbe7'/>
<id>728404dacfddb5364d7256d821a2ea482159cbe7</id>
<content type='text'>
To avoid duplicating this double filemap_fdatawrite_range() call for
inodes with async extents (compressed writes) so often.

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>
To avoid duplicating this double filemap_fdatawrite_range() call for
inodes with async extents (compressed writes) so often.

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 task hang under heavy compressed write</title>
<updated>2014-08-24T14:17:02+00:00</updated>
<author>
<name>Liu Bo</name>
<email>bo.li.liu@oracle.com</email>
</author>
<published>2014-08-15T15:36:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=9e0af23764344f7f1b68e4eefbe7dc865018b63d'/>
<id>9e0af23764344f7f1b68e4eefbe7dc865018b63d</id>
<content type='text'>
This has been reported and discussed for a long time, and this hang occurs in
both 3.15 and 3.16.

Btrfs now migrates to use kernel workqueue, but it introduces this hang problem.

Btrfs has a kind of work queued as an ordered way, which means that its
ordered_func() must be processed in the way of FIFO, so it usually looks like --

normal_work_helper(arg)
    work = container_of(arg, struct btrfs_work, normal_work);

    work-&gt;func() &lt;---- (we name it work X)
    for ordered_work in wq-&gt;ordered_list
            ordered_work-&gt;ordered_func()
            ordered_work-&gt;ordered_free()

The hang is a rare case, first when we find free space, we get an uncached block
group, then we go to read its free space cache inode for free space information,
so it will

file a readahead request
    btrfs_readpages()
         for page that is not in page cache
                __do_readpage()
                     submit_extent_page()
                           btrfs_submit_bio_hook()
                                 btrfs_bio_wq_end_io()
                                 submit_bio()
                                 end_workqueue_bio() &lt;--(ret by the 1st endio)
                                      queue a work(named work Y) for the 2nd
                                      also the real endio()

So the hang occurs when work Y's work_struct and work X's work_struct happens
to share the same address.

A bit more explanation,

A,B,C -- struct btrfs_work
arg   -- struct work_struct

kthread:
worker_thread()
    pick up a work_struct from @worklist
    process_one_work(arg)
	worker-&gt;current_work = arg;  &lt;-- arg is A-&gt;normal_work
	worker-&gt;current_func(arg)
		normal_work_helper(arg)
		     A = container_of(arg, struct btrfs_work, normal_work);

		     A-&gt;func()
		     A-&gt;ordered_func()
		     A-&gt;ordered_free()  &lt;-- A gets freed

		     B-&gt;ordered_func()
			  submit_compressed_extents()
			      find_free_extent()
				  load_free_space_inode()
				      ...   &lt;-- (the above readhead stack)
				      end_workqueue_bio()
					   btrfs_queue_work(work C)
		     B-&gt;ordered_free()

As if work A has a high priority in wq-&gt;ordered_list and there are more ordered
works queued after it, such as B-&gt;ordered_func(), its memory could have been
freed before normal_work_helper() returns, which means that kernel workqueue
code worker_thread() still has worker-&gt;current_work pointer to be work
A-&gt;normal_work's, ie. arg's address.

Meanwhile, work C is allocated after work A is freed, work C-&gt;normal_work
and work A-&gt;normal_work are likely to share the same address(I confirmed this
with ftrace output, so I'm not just guessing, it's rare though).

When another kthread picks up work C-&gt;normal_work to process, and finds our
kthread is processing it(see find_worker_executing_work()), it'll think
work C as a collision and skip then, which ends up nobody processing work C.

So the situation is that our kthread is waiting forever on work C.

Besides, there're other cases that can lead to deadlock, but the real problem
is that all btrfs workqueue shares one work-&gt;func, -- normal_work_helper,
so this makes each workqueue to have its own helper function, but only a
wraper pf normal_work_helper.

With this patch, I no long hit the above hang.

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>
This has been reported and discussed for a long time, and this hang occurs in
both 3.15 and 3.16.

Btrfs now migrates to use kernel workqueue, but it introduces this hang problem.

Btrfs has a kind of work queued as an ordered way, which means that its
ordered_func() must be processed in the way of FIFO, so it usually looks like --

normal_work_helper(arg)
    work = container_of(arg, struct btrfs_work, normal_work);

    work-&gt;func() &lt;---- (we name it work X)
    for ordered_work in wq-&gt;ordered_list
            ordered_work-&gt;ordered_func()
            ordered_work-&gt;ordered_free()

The hang is a rare case, first when we find free space, we get an uncached block
group, then we go to read its free space cache inode for free space information,
so it will

file a readahead request
    btrfs_readpages()
         for page that is not in page cache
                __do_readpage()
                     submit_extent_page()
                           btrfs_submit_bio_hook()
                                 btrfs_bio_wq_end_io()
                                 submit_bio()
                                 end_workqueue_bio() &lt;--(ret by the 1st endio)
                                      queue a work(named work Y) for the 2nd
                                      also the real endio()

So the hang occurs when work Y's work_struct and work X's work_struct happens
to share the same address.

A bit more explanation,

A,B,C -- struct btrfs_work
arg   -- struct work_struct

kthread:
worker_thread()
    pick up a work_struct from @worklist
    process_one_work(arg)
	worker-&gt;current_work = arg;  &lt;-- arg is A-&gt;normal_work
	worker-&gt;current_func(arg)
		normal_work_helper(arg)
		     A = container_of(arg, struct btrfs_work, normal_work);

		     A-&gt;func()
		     A-&gt;ordered_func()
		     A-&gt;ordered_free()  &lt;-- A gets freed

		     B-&gt;ordered_func()
			  submit_compressed_extents()
			      find_free_extent()
				  load_free_space_inode()
				      ...   &lt;-- (the above readhead stack)
				      end_workqueue_bio()
					   btrfs_queue_work(work C)
		     B-&gt;ordered_free()

As if work A has a high priority in wq-&gt;ordered_list and there are more ordered
works queued after it, such as B-&gt;ordered_func(), its memory could have been
freed before normal_work_helper() returns, which means that kernel workqueue
code worker_thread() still has worker-&gt;current_work pointer to be work
A-&gt;normal_work's, ie. arg's address.

Meanwhile, work C is allocated after work A is freed, work C-&gt;normal_work
and work A-&gt;normal_work are likely to share the same address(I confirmed this
with ftrace output, so I'm not just guessing, it's rare though).

When another kthread picks up work C-&gt;normal_work to process, and finds our
kthread is processing it(see find_worker_executing_work()), it'll think
work C as a collision and skip then, which ends up nobody processing work C.

So the situation is that our kthread is waiting forever on work C.

Besides, there're other cases that can lead to deadlock, but the real problem
is that all btrfs workqueue shares one work-&gt;func, -- normal_work_helper,
so this makes each workqueue to have its own helper function, but only a
wraper pf normal_work_helper.

With this patch, I no long hit the above hang.

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: disable strict file flushes for renames and truncates</title>
<updated>2014-08-15T14:43:42+00:00</updated>
<author>
<name>Chris Mason</name>
<email>clm@fb.com</email>
</author>
<published>2014-08-12T17:47:42+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=8d875f95da43c6a8f18f77869f2ef26e9594fecc'/>
<id>8d875f95da43c6a8f18f77869f2ef26e9594fecc</id>
<content type='text'>
Truncates and renames are often used to replace old versions of a file
with new versions.  Applications often expect this to be an atomic
replacement, even if they haven't done anything to make sure the new
version is fully on disk.

Btrfs has strict flushing in place to make sure that renaming over an
old file with a new file will fully flush out the new file before
allowing the transaction commit with the rename to complete.

This ordering means the commit code needs to be able to lock file pages,
and there are a few paths in the filesystem where we will try to end a
transaction with the page lock held.  It's rare, but these things can
deadlock.

This patch removes the ordered flushes and switches to a best effort
filemap_flush like ext4 uses. It's not perfect, but it should fix the
deadlocks.

Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Truncates and renames are often used to replace old versions of a file
with new versions.  Applications often expect this to be an atomic
replacement, even if they haven't done anything to make sure the new
version is fully on disk.

Btrfs has strict flushing in place to make sure that renaming over an
old file with a new file will fully flush out the new file before
allowing the transaction commit with the rename to complete.

This ordering means the commit code needs to be able to lock file pages,
and there are a few paths in the filesystem where we will try to end a
transaction with the page lock held.  It's rare, but these things can
deadlock.

This patch removes the ordered flushes and switches to a best effort
filemap_flush like ext4 uses. It's not perfect, but it should fix the
deadlocks.

Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: fix abnormal long waiting in fsync</title>
<updated>2014-07-19T18:49:44+00:00</updated>
<author>
<name>Liu Bo</name>
<email>bo.li.liu@oracle.com</email>
</author>
<published>2014-07-17T08:08:36+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=98ce2deda23a303682a4253f3016a1436f4b2735'/>
<id>98ce2deda23a303682a4253f3016a1436f4b2735</id>
<content type='text'>
xfstests generic/127 detected this problem.

With commit 7fc34a62ca4434a79c68e23e70ed26111b7a4cf8, now fsync will only flush
data within the passed range.  This is the cause of the above problem,
-- btrfs's fsync has a stage called 'sync log' which will wait for all the
ordered extents it've recorded to finish.

In xfstests/generic/127, with mixed operations such as truncate, fallocate,
punch hole, and mapwrite, we get some pre-allocated extents, and mapwrite will
mmap, and then msync.  And I find that msync will wait for quite a long time
(about 20s in my case), thanks to ftrace, it turns out that the previous
fallocate calls 'btrfs_wait_ordered_range()' to flush dirty pages, but as the
range of dirty pages may be larger than 'btrfs_wait_ordered_range()' wants,
there can be some ordered extents created but not getting corresponding pages
flushed, then they're left in memory until we fsync which runs into the
stage 'sync log', and fsync will just wait for the system writeback thread
to flush those pages and get ordered extents finished, so the latency is
inevitable.

This adds a flush similar to btrfs_start_ordered_extent() in
btrfs_wait_logged_extents() to fix that.

Reviewed-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
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>
xfstests generic/127 detected this problem.

With commit 7fc34a62ca4434a79c68e23e70ed26111b7a4cf8, now fsync will only flush
data within the passed range.  This is the cause of the above problem,
-- btrfs's fsync has a stage called 'sync log' which will wait for all the
ordered extents it've recorded to finish.

In xfstests/generic/127, with mixed operations such as truncate, fallocate,
punch hole, and mapwrite, we get some pre-allocated extents, and mapwrite will
mmap, and then msync.  And I find that msync will wait for quite a long time
(about 20s in my case), thanks to ftrace, it turns out that the previous
fallocate calls 'btrfs_wait_ordered_range()' to flush dirty pages, but as the
range of dirty pages may be larger than 'btrfs_wait_ordered_range()' wants,
there can be some ordered extents created but not getting corresponding pages
flushed, then they're left in memory until we fsync which runs into the
stage 'sync log', and fsync will just wait for the system writeback thread
to flush those pages and get ordered extents finished, so the latency is
inevitable.

This adds a flush similar to btrfs_start_ordered_extent() in
btrfs_wait_logged_extents() to fix that.

Reviewed-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
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: remove stale newlines from log messages</title>
<updated>2014-06-10T00:20:53+00:00</updated>
<author>
<name>David Sterba</name>
<email>dsterba@suse.cz</email>
</author>
<published>2014-05-15T14:48:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=351fd3532159441e810d458a5b681090ff8449fd'/>
<id>351fd3532159441e810d458a5b681090ff8449fd</id>
<content type='text'>
I've noticed an extra line after "use no compression", but search
revealed much more in messages of more critical levels and rare errors.

Signed-off-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I've noticed an extra line after "use no compression", but search
revealed much more in messages of more critical levels and rare errors.

Signed-off-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: split the global ordered extents mutex</title>
<updated>2014-03-10T19:17:28+00:00</updated>
<author>
<name>Miao Xie</name>
<email>miaox@cn.fujitsu.com</email>
</author>
<published>2014-03-06T05:55:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=31f3d255c677073f83daa1e0671bbf2157bf8edc'/>
<id>31f3d255c677073f83daa1e0671bbf2157bf8edc</id>
<content type='text'>
When we create a snapshot, we just need wait the ordered extents in
the source fs/file root, but because we use the global mutex to protect
this ordered extents list of the source fs/file root to avoid accessing
a empty list, if someone got the mutex to access the ordered extents list
of the other fs/file root, we had to wait.

This patch splits the above global mutex, now every fs/file root has
its own mutex to protect its own list.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When we create a snapshot, we just need wait the ordered extents in
the source fs/file root, but because we use the global mutex to protect
this ordered extents list of the source fs/file root to avoid accessing
a empty list, if someone got the mutex to access the ordered extents list
of the other fs/file root, we had to wait.

This patch splits the above global mutex, now every fs/file root has
its own mutex to protect its own list.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>Btrfs: wake up the tasks that wait for the io earlier</title>
<updated>2014-03-10T19:17:23+00:00</updated>
<author>
<name>Miao Xie</name>
<email>miaox@cn.fujitsu.com</email>
</author>
<published>2014-03-06T05:54:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=af7a65097b3f0a63caf1755df78d04e1a33588ef'/>
<id>af7a65097b3f0a63caf1755df78d04e1a33588ef</id>
<content type='text'>
The tasks that wait for the IO_DONE flag just care about the io of the dirty
pages, so it is better to wake up them immediately after all the pages are
written, not the whole process of the io completes.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The tasks that wait for the IO_DONE flag just care about the io of the dirty
pages, so it is better to wake up them immediately after all the pages are
written, not the whole process of the io completes.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</pre>
</div>
</content>
</entry>
</feed>
