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>

authored by

Dave Chinner and committed by
Christoph Hellwig
e43afd72 5825294e

+10 -3
+9 -3
fs/xfs/linux-2.6/xfs_sync.c
··· 404 404 xfs_syncd_queue_work( 405 405 struct xfs_mount *mp, 406 406 void *data, 407 - void (*syncer)(struct xfs_mount *, void *)) 407 + void (*syncer)(struct xfs_mount *, void *), 408 + struct completion *completion) 408 409 { 409 410 struct xfs_sync_work *work; 410 411 ··· 414 413 work->w_syncer = syncer; 415 414 work->w_data = data; 416 415 work->w_mount = mp; 416 + work->w_completion = completion; 417 417 spin_lock(&mp->m_sync_lock); 418 418 list_add_tail(&work->w_list, &mp->m_sync_list); 419 419 spin_unlock(&mp->m_sync_lock); ··· 443 441 xfs_inode_t *ip) 444 442 { 445 443 struct inode *inode = VFS_I(ip); 444 + DECLARE_COMPLETION_ONSTACK(completion); 446 445 447 446 igrab(inode); 448 - xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work); 449 - delay(msecs_to_jiffies(500)); 447 + xfs_syncd_queue_work(ip->i_mount, inode, xfs_flush_inodes_work, &completion); 448 + wait_for_completion(&completion); 450 449 xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); 451 450 } 452 451 ··· 517 514 list_del(&work->w_list); 518 515 if (work == &mp->m_sync_work) 519 516 continue; 517 + if (work->w_completion) 518 + complete(work->w_completion); 520 519 kmem_free(work); 521 520 } 522 521 } ··· 532 527 { 533 528 mp->m_sync_work.w_syncer = xfs_sync_worker; 534 529 mp->m_sync_work.w_mount = mp; 530 + mp->m_sync_work.w_completion = NULL; 535 531 mp->m_sync_task = kthread_run(xfssyncd, mp, "xfssyncd"); 536 532 if (IS_ERR(mp->m_sync_task)) 537 533 return -PTR_ERR(mp->m_sync_task);
+1
fs/xfs/linux-2.6/xfs_sync.h
··· 26 26 struct xfs_mount *w_mount; 27 27 void *w_data; /* syncer routine argument */ 28 28 void (*w_syncer)(struct xfs_mount *, void *); 29 + struct completion *w_completion; 29 30 } xfs_sync_work_t; 30 31 31 32 #define SYNC_ATTR 0x0001 /* sync attributes */