xfs: use dedicated log worker wq to avoid deadlock with cil wq
The log covering background task used to be part of the xfssyncd workqueue. That workqueue was removed as of commit5889608df
("xfs: syncd workqueue is no more") and the associated work item scheduled to the xfs-log wq. The latter is used for log buffer I/O completion. Since xfs_log_worker() can invoke a log flush, a deadlock is possible between the xfs-log and xfs-cil workqueues. Consider the following codepath from xfs_log_worker(): xfs_log_worker() xfs_log_force() _xfs_log_force() xlog_cil_force() xlog_cil_force_lsn() xlog_cil_push_now() flush_work() The above is in xfs-log wq context and blocked waiting on the completion of an xfs-cil work item. Concurrently, the cil push in progress can end up blocked here: xlog_cil_push_work() xlog_cil_push() xlog_write() xlog_state_get_iclog_space() xlog_wait(&log->l_flush_wait, ...) The above is in xfs-cil context waiting on log buffer I/O completion, which executes in xfs-log wq context. In this scenario both workqueues are deadlocked waiting on eachother. Add a new workqueue specifically for the high level log covering and ail pushing worker, as was the case prior to commit5889608df
. Diagnosed-by: David Jeffery <djeffery@redhat.com> Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
This commit is contained in:
Родитель
f1c0e20243
Коммит
696a562072
|
@ -1293,7 +1293,7 @@ void
|
|||
xfs_log_work_queue(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
queue_delayed_work(mp->m_log_workqueue, &mp->m_log->l_work,
|
||||
queue_delayed_work(mp->m_sync_workqueue, &mp->m_log->l_work,
|
||||
msecs_to_jiffies(xfs_syncd_centisecs * 10));
|
||||
}
|
||||
|
||||
|
|
|
@ -183,6 +183,7 @@ typedef struct xfs_mount {
|
|||
struct workqueue_struct *m_reclaim_workqueue;
|
||||
struct workqueue_struct *m_log_workqueue;
|
||||
struct workqueue_struct *m_eofblocks_workqueue;
|
||||
struct workqueue_struct *m_sync_workqueue;
|
||||
|
||||
/*
|
||||
* Generation of the filesysyem layout. This is incremented by each
|
||||
|
|
|
@ -877,8 +877,15 @@ xfs_init_mount_workqueues(
|
|||
if (!mp->m_eofblocks_workqueue)
|
||||
goto out_destroy_log;
|
||||
|
||||
mp->m_sync_workqueue = alloc_workqueue("xfs-sync/%s", WQ_FREEZABLE, 0,
|
||||
mp->m_fsname);
|
||||
if (!mp->m_sync_workqueue)
|
||||
goto out_destroy_eofb;
|
||||
|
||||
return 0;
|
||||
|
||||
out_destroy_eofb:
|
||||
destroy_workqueue(mp->m_eofblocks_workqueue);
|
||||
out_destroy_log:
|
||||
destroy_workqueue(mp->m_log_workqueue);
|
||||
out_destroy_reclaim:
|
||||
|
@ -899,6 +906,7 @@ STATIC void
|
|||
xfs_destroy_mount_workqueues(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
destroy_workqueue(mp->m_sync_workqueue);
|
||||
destroy_workqueue(mp->m_eofblocks_workqueue);
|
||||
destroy_workqueue(mp->m_log_workqueue);
|
||||
destroy_workqueue(mp->m_reclaim_workqueue);
|
||||
|
|
Загрузка…
Ссылка в новой задаче