提交 e43afd72 编写于 作者: D Dave Chinner 提交者: Christoph Hellwig

xfs: block callers of xfs_flush_inodes() correctly

xfs_flush_inodes() currently uses a magic timeout to wait for
some inodes to be flushed before returning. This isn't
really reliable but used to be the best that could be done
due to deadlock potential of waiting for the entire flush.

Now the inode flush is safe to execute while we hold page
and inode locks, we can wait for all the inodes to flush
synchronously. Convert the wait mechanism to a completion
to do this efficiently. This should remove all remaining
spurious ENOSPC errors from the delayed allocation reservation
path.

This is extracted almost line for line from a larger patch
from Mikulas Patocka.
Signed-off-by: NMikulas Patocka <mpatocka@redhat.com>
Signed-off-by: NDave Chinner <david@fromorbit.com>
Reviewed-by: NChristoph Hellwig <hch@lst.de>
上级 5825294e
...@@ -404,7 +404,8 @@ STATIC void ...@@ -404,7 +404,8 @@ STATIC void
xfs_syncd_queue_work( xfs_syncd_queue_work(
struct xfs_mount *mp, struct xfs_mount *mp,
void *data, void *data,
void (*syncer)(struct xfs_mount *, void *)) void (*syncer)(struct xfs_mount *, void *),
struct completion *completion)
{ {
struct xfs_sync_work *work; struct xfs_sync_work *work;
...@@ -413,6 +414,7 @@ xfs_syncd_queue_work( ...@@ -413,6 +414,7 @@ xfs_syncd_queue_work(
work->w_syncer = syncer; work->w_syncer = syncer;
work->w_data = data; work->w_data = data;
work->w_mount = mp; work->w_mount = mp;
work->w_completion = completion;
spin_lock(&mp->m_sync_lock); spin_lock(&mp->m_sync_lock);
list_add_tail(&work->w_list, &mp->m_sync_list); list_add_tail(&work->w_list, &mp->m_sync_list);
spin_unlock(&mp->m_sync_lock); spin_unlock(&mp->m_sync_lock);
...@@ -441,10 +443,11 @@ xfs_flush_inodes( ...@@ -441,10 +443,11 @@ xfs_flush_inodes(
xfs_inode_t *ip) xfs_inode_t *ip)
{ {
struct inode *inode = VFS_I(ip); struct inode *inode = VFS_I(ip);
DECLARE_COMPLETION_ONSTACK(completion);
igrab(inode); igrab(inode);
xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work); xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion);
delay(msecs_to_jiffies(500)); wait_for_completion(&completion);
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
} }
...@@ -514,6 +517,8 @@ xfssyncd( ...@@ -514,6 +517,8 @@ xfssyncd(
list_del(&work->w_list); list_del(&work->w_list);
if (work == &mp->m_sync_work) if (work == &mp->m_sync_work)
continue; continue;
if (work->w_completion)
complete(work->w_completion);
kmem_free(work); kmem_free(work);
} }
} }
...@@ -527,6 +532,7 @@ xfs_syncd_init( ...@@ -527,6 +532,7 @@ xfs_syncd_init(
{ {
mp->m_sync_work.w_syncer = xfs_sync_worker; mp->m_sync_work.w_syncer = xfs_sync_worker;
mp->m_sync_work.w_mount = mp; mp->m_sync_work.w_mount = mp;
mp->m_sync_work.w_completion = NULL;
mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
if (IS_ERR(mp->m_sync_task)) if (IS_ERR(mp->m_sync_task))
return -PTR_ERR(mp->m_sync_task); return -PTR_ERR(mp->m_sync_task);
......
...@@ -26,6 +26,7 @@ typedef struct xfs_sync_work { ...@@ -26,6 +26,7 @@ typedef struct xfs_sync_work {
struct xfs_mount *w_mount; struct xfs_mount *w_mount;
void *w_data; /* syncer routine argument */ void *w_data; /* syncer routine argument */
void (*w_syncer)(struct xfs_mount *, void *); void (*w_syncer)(struct xfs_mount *, void *);
struct completion *w_completion;
} xfs_sync_work_t; } xfs_sync_work_t;
#define SYNC_ATTR 0x0001 /* sync attributes */ #define SYNC_ATTR 0x0001 /* sync attributes */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册