<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel.git/fs/btrfs/delayed-inode.c, branch linux-3.17.y</title>
<subtitle>Hosts the 0x221E linux distro kernel.
</subtitle>
<id>https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.17.y</id>
<link rel='self' href='https://git.0xinfinity.dev/distro/kernel.git/atom?h=linux-3.17.y'/>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/'/>
<updated>2014-08-24T14:17:02Z</updated>
<entry>
<title>Btrfs: fix task hang under heavy compressed write</title>
<updated>2014-08-24T14:17:02Z</updated>
<author>
<name>Liu Bo</name>
</author>
<published>2014-08-15T15:36:53Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=9e0af23764344f7f1b68e4eefbe7dc865018b63d'/>
<id>urn:sha1: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>
</entry>
<entry>
<title>btrfs: free delayed node outside of root-&gt;inode_lock</title>
<updated>2014-06-10T00:21:08Z</updated>
<author>
<name>Jeff Mahoney</name>
</author>
<published>2014-05-27T17:53:20Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=964930312aec583809a690868119ce716f4ee926'/>
<id>urn:sha1:964930312aec583809a690868119ce716f4ee926</id>
<content type='text'>
On heavy workloads, we're seeing soft lockup warnings on
root-&gt;inode_lock in __btrfs_release_delayed_node. The low hanging fruit
is to reduce the size of the critical section.

Signed-off-by: Jeff Mahoney &lt;jeffm@suse.com&gt;
Reviewed-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>btrfs: Cleanup the "_struct" suffix in btrfs_workequeue</title>
<updated>2014-03-10T19:17:16Z</updated>
<author>
<name>Qu Wenruo</name>
</author>
<published>2014-02-28T02:46:19Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=d458b0540ebd728b4d6ef47cc5ef0dbfd4dd361a'/>
<id>urn:sha1:d458b0540ebd728b4d6ef47cc5ef0dbfd4dd361a</id>
<content type='text'>
Since the "_struct" suffix is mainly used for distinguish the differnt
btrfs_work between the original and the newly created one,
there is no need using the suffix since all btrfs_workers are changed
into btrfs_workqueue.

Also this patch fixed some codes whose code style is changed due to the
too long "_struct" suffix.

Signed-off-by: Qu Wenruo &lt;quwenruo@cn.fujitsu.com&gt;
Tested-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</content>
</entry>
<entry>
<title>btrfs: Replace fs_info-&gt;delayed_workers workqueue with btrfs_workqueue.</title>
<updated>2014-03-10T19:17:12Z</updated>
<author>
<name>Qu Wenruo</name>
</author>
<published>2014-02-28T02:46:15Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=5b3bc44e2e69d42edf40ca3785040d233ca949f4'/>
<id>urn:sha1:5b3bc44e2e69d42edf40ca3785040d233ca949f4</id>
<content type='text'>
Replace the fs_info-&gt;delayed_workers with the newly created
btrfs_workqueue.

Signed-off-by: Qu Wenruo &lt;quwenruo@cn.fujitsu.com&gt;
Tested-by: David Sterba &lt;dsterba@suse.cz&gt;
Signed-off-by: Josef Bacik &lt;jbacik@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: introduce the delayed inode ref deletion for the single link inode</title>
<updated>2014-01-28T21:20:09Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:06Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=67de11769bd5ec339a62169f500b04f304826c00'/>
<id>urn:sha1:67de11769bd5ec339a62169f500b04f304826c00</id>
<content type='text'>
The inode reference item is close to inode item, so we insert it simultaneously
with the inode item insertion when we create a file/directory.. In fact, we also
can handle the inode reference deletion by the same way. So we made this patch to
introduce the delayed inode reference deletion for the single link inode(At most
case, the file doesn't has hard link, so we don't take the hard link into account).

This function is based on the delayed inode mechanism. After applying this patch,
we can reduce the time of the file/directory deletion by ~10%.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: use flags instead of the bool variants in delayed node</title>
<updated>2014-01-28T21:20:08Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:05Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=7cf35d91b4f143b5c7529976bf5e7573a07051cd'/>
<id>urn:sha1:7cf35d91b4f143b5c7529976bf5e7573a07051cd</id>
<content type='text'>
Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: remove btrfs_end_transaction_dmeta()</title>
<updated>2014-01-28T21:20:08Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:04Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=a56dbd89400dd2cb9c91d734435dbfe059495da1'/>
<id>urn:sha1:a56dbd89400dd2cb9c91d734435dbfe059495da1</id>
<content type='text'>
Two reasons:
- btrfs_end_transaction_dmeta() is the same as btrfs_end_transaction_throttle()
  so it is unnecessary.
- All the delayed items should be dealt in the current transaction, so the
  workers should not commit the transaction, instead, deal with the delayed
  items as many as possible.

So we can remove btrfs_end_transaction_dmeta()

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: cleanup code of btrfs_balance_delayed_items()</title>
<updated>2014-01-28T21:20:07Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:03Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=0353808cae35bc81c86e3510748a10f6bdff41b8'/>
<id>urn:sha1:0353808cae35bc81c86e3510748a10f6bdff41b8</id>
<content type='text'>
- move the condition check for wait into a function
- use wait_event_interruptible instead of prepare-schedule-finish process

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: don't run delayed nodes again after all nodes flush</title>
<updated>2014-01-28T21:20:06Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:02Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=4dd466d36a50d9c96cd990e2e0d472fe720a10aa'/>
<id>urn:sha1:4dd466d36a50d9c96cd990e2e0d472fe720a10aa</id>
<content type='text'>
If the number of the delayed items is greater than the upper limit, we will
try to flush all the delayed items. After that, it is unnecessary to run
them again because they are being dealt with by the wokers or the number of
them is less than the lower limit.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
<entry>
<title>Btrfs: remove residual code in delayed inode async helper</title>
<updated>2014-01-28T21:20:06Z</updated>
<author>
<name>Miao Xie</name>
</author>
<published>2013-12-26T05:07:01Z</published>
<link rel='alternate' type='text/html' href='https://git.0xinfinity.dev/distro/kernel.git/commit/?id=74c40f925e0d8e1ddfe5f9fc410b4c2f6c70acf5'/>
<id>urn:sha1:74c40f925e0d8e1ddfe5f9fc410b4c2f6c70acf5</id>
<content type='text'>
Before applying the patch
  commit de3cb945db4d8eb3b046dc7a5ea89a893372750c
  title: Btrfs: improve the delayed inode throttling

We need requeue the async work after the current work was done, it
introduced a deadlock problem. So we wrote the code that this patch
removes to avoid the above problem. But after applying the above
patch, the deadlock problem didn't exist. So we should remove that
fix code.

Signed-off-by: Miao Xie &lt;miaox@cn.fujitsu.com&gt;
Signed-off-by: Chris Mason &lt;clm@fb.com&gt;
</content>
</entry>
</feed>
