hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAASLU
--------------------------------
When multiple processes or threads write to the same file concurrently, if a network disruption occurs during the write operation, it may lead to a deadlock situation as follow:
Process 1 (dd) Process 2 (cifsd) Process 3 (cifsiod) cifs_writepages lock_page - [1] wait_on_page_writeback - [2] Waiting for writeback, blocked by [4] wait_on_page_bit cifs_demultiplex_thread cifs_read_from_socket cifs_readv_from_socket - If another process triggers reconnect at this point cifs_reconnect - mid->mid_state updated to MID_RETRY_NEEDED smb2_writev_callback mid_entry->callback() - mid_state leads to wdata->result = -EAGAIN wdata->result = -EAGAIN queue_work(cifsiod_wq, &wdata->work); cifs_writev_complete - work function - Condition satisfied - wdata->result == -EAGAIN cifs_writev_requeue lock_page - [3] Blocked by [1] end_page_writeback - [4] Won't execute, blocked by [3] unlock_page
Mainline refactoring patch d08089f649a0 ("cifs: Change the I/O paths to use an iterator rather than a page list") unlock page while waiting for the writeback to complete, thus avoiding potential deadlocks caused by lock ordering issues during reconnection.
Due to the large refactor of the mainline, the patch cannot be backport directly. Therefore, This patch only uses a part of the idea of the mainline patch to fix deadlock.
Fixes: c28c89fc43e3 ("cifs: add cifs_async_writev") Signed-off-by: Wang Zhaolong wangzhaolong1@huawei.com --- fs/cifs/file.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 0b840555a175..e0c10fd93b64 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2223,6 +2223,7 @@ wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages, * back from swapper_space to tmpfs file mapping */
+relock_recheck: if (nr_pages == 0) lock_page(page); else if (!trylock_page(page)) @@ -2245,11 +2246,16 @@ wdata_prepare_pages(struct cifs_writedata *wdata, unsigned int found_pages, break; }
- if (wbc->sync_mode != WB_SYNC_NONE) - wait_on_page_writeback(page); + if (PageWriteback(page)) { + unlock_page(page); + if (wbc->sync_mode != WB_SYNC_NONE) { + wait_on_page_writeback(page); + goto relock_recheck; + } + break; + }
- if (PageWriteback(page) || - !clear_page_dirty_for_io(page)) { + if (!clear_page_dirty_for_io(page)) { unlock_page(page); break; }
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/9869 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/O...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/9869 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/O...