| From d1052d236eddf6aa851434db1897b942e8db9921 Mon Sep 17 00:00:00 2001 |
| From: Jinke Han <hanjinke.666@bytedance.com> |
| Date: Sat, 3 Sep 2022 09:24:29 +0800 |
| Subject: ext4: place buffer head allocation before handle start |
| |
| From: Jinke Han <hanjinke.666@bytedance.com> |
| |
| commit d1052d236eddf6aa851434db1897b942e8db9921 upstream. |
| |
| In our product environment, we encounter some jbd hung waiting handles to |
| stop while several writters were doing memory reclaim for buffer head |
| allocation in delay alloc write path. Ext4 do buffer head allocation with |
| holding transaction handle which may be blocked too long if the reclaim |
| works not so smooth. According to our bcc trace, the reclaim time in |
| buffer head allocation can reach 258s and the jbd transaction commit also |
| take almost the same time meanwhile. Except for these extreme cases, |
| we often see several seconds delays for cgroup memory reclaim on our |
| servers. This is more likely to happen considering docker environment. |
| |
| One thing to note, the allocation of buffer heads is as often as page |
| allocation or more often when blocksize less than page size. Just like |
| page cache allocation, we should also place the buffer head allocation |
| before startting the handle. |
| |
| Cc: stable@kernel.org |
| Signed-off-by: Jinke Han <hanjinke.666@bytedance.com> |
| Link: https://lore.kernel.org/r/20220903012429.22555-1-hanjinke.666@bytedance.com |
| Signed-off-by: Theodore Ts'o <tytso@mit.edu> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| fs/ext4/inode.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| --- a/fs/ext4/inode.c |
| +++ b/fs/ext4/inode.c |
| @@ -1188,6 +1188,13 @@ retry_grab: |
| page = grab_cache_page_write_begin(mapping, index); |
| if (!page) |
| return -ENOMEM; |
| + /* |
| + * The same as page allocation, we prealloc buffer heads before |
| + * starting the handle. |
| + */ |
| + if (!page_has_buffers(page)) |
| + create_empty_buffers(page, inode->i_sb->s_blocksize, 0); |
| + |
| unlock_page(page); |
| |
| retry_journal: |