forked from Minki/linux
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: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
5825294edd
commit
e43afd72d2
@ -404,7 +404,8 @@ STATIC void
|
||||
xfs_syncd_queue_work(
|
||||
struct xfs_mount *mp,
|
||||
void *data,
|
||||
void (*syncer)(struct xfs_mount *, void *))
|
||||
void (*syncer)(struct xfs_mount *, void *),
|
||||
struct completion *completion)
|
||||
{
|
||||
struct xfs_sync_work *work;
|
||||
|
||||
@ -413,6 +414,7 @@ xfs_syncd_queue_work(
|
||||
work->w_syncer = syncer;
|
||||
work->w_data = data;
|
||||
work->w_mount = mp;
|
||||
work->w_completion = completion;
|
||||
spin_lock(&mp->m_sync_lock);
|
||||
list_add_tail(&work->w_list, &mp->m_sync_list);
|
||||
spin_unlock(&mp->m_sync_lock);
|
||||
@ -441,10 +443,11 @@ xfs_flush_inodes(
|
||||
xfs_inode_t *ip)
|
||||
{
|
||||
struct inode *inode = VFS_I(ip);
|
||||
DECLARE_COMPLETION_ONSTACK(completion);
|
||||
|
||||
igrab(inode);
|
||||
xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work);
|
||||
delay(msecs_to_jiffies(500));
|
||||
xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion);
|
||||
wait_for_completion(&completion);
|
||||
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC);
|
||||
}
|
||||
|
||||
@ -514,6 +517,8 @@ xfssyncd(
|
||||
list_del(&work->w_list);
|
||||
if (work == &mp->m_sync_work)
|
||||
continue;
|
||||
if (work->w_completion)
|
||||
complete(work->w_completion);
|
||||
kmem_free(work);
|
||||
}
|
||||
}
|
||||
@ -527,6 +532,7 @@ xfs_syncd_init(
|
||||
{
|
||||
mp->m_sync_work.w_syncer = xfs_sync_worker;
|
||||
mp->m_sync_work.w_mount = mp;
|
||||
mp->m_sync_work.w_completion = NULL;
|
||||
mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd");
|
||||
if (IS_ERR(mp->m_sync_task))
|
||||
return -PTR_ERR(mp->m_sync_task);
|
||||
|
@ -26,6 +26,7 @@ typedef struct xfs_sync_work {
|
||||
struct xfs_mount *w_mount;
|
||||
void *w_data; /* syncer routine argument */
|
||||
void (*w_syncer)(struct xfs_mount *, void *);
|
||||
struct completion *w_completion;
|
||||
} xfs_sync_work_t;
|
||||
|
||||
#define SYNC_ATTR 0x0001 /* sync attributes */
|
||||
|
Loading…
Reference in New Issue
Block a user