Commit c16123eb authored by Nathan Scott's avatar Nathan Scott Committed by Linus Torvalds

[XFS] Fix problems with synchronous writes returning EAGAIN incorrectly

for pinned inodes.

SGI-PV: 930364
SGI-Modid: xfs-linux-melb:xfs-kern:21460a
Signed-off-by: default avatarNathan Scott <nathans@sgi.com>
parent c5a6e273
...@@ -962,9 +962,9 @@ xfs_write( ...@@ -962,9 +962,9 @@ xfs_write(
xfs_trans_set_sync(tp); xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0, NULL); error = xfs_trans_commit(tp, 0, NULL);
xfs_iunlock(xip, XFS_ILOCK_EXCL); xfs_iunlock(xip, XFS_ILOCK_EXCL);
if (error)
goto out_unlock_internal;
} }
if (error)
goto out_unlock_internal;
} }
xfs_rwunlock(bdp, locktype); xfs_rwunlock(bdp, locktype);
......
...@@ -348,6 +348,12 @@ linvfs_write_inode( ...@@ -348,6 +348,12 @@ linvfs_write_inode(
if (sync) if (sync)
flags |= FLUSH_SYNC; flags |= FLUSH_SYNC;
VOP_IFLUSH(vp, flags, error); VOP_IFLUSH(vp, flags, error);
if (error == EAGAIN) {
if (sync)
VOP_IFLUSH(vp, flags | FLUSH_LOG, error);
else
error = 0;
}
} }
return -error; return -error;
......
...@@ -3681,27 +3681,27 @@ xfs_inode_flush( ...@@ -3681,27 +3681,27 @@ xfs_inode_flush(
{ {
xfs_inode_t *ip; xfs_inode_t *ip;
xfs_mount_t *mp; xfs_mount_t *mp;
xfs_inode_log_item_t *iip;
int error = 0; int error = 0;
ip = XFS_BHVTOI(bdp); ip = XFS_BHVTOI(bdp);
mp = ip->i_mount; mp = ip->i_mount;
iip = ip->i_itemp;
if (XFS_FORCED_SHUTDOWN(mp)) if (XFS_FORCED_SHUTDOWN(mp))
return XFS_ERROR(EIO); return XFS_ERROR(EIO);
/* Bypass inodes which have already been cleaned by /*
* Bypass inodes which have already been cleaned by
* the inode flush clustering code inside xfs_iflush * the inode flush clustering code inside xfs_iflush
*/ */
if ((ip->i_update_core == 0) && if ((ip->i_update_core == 0) &&
((ip->i_itemp == NULL) || ((iip == NULL) || !(iip->ili_format.ilf_fields & XFS_ILOG_ALL)))
!(ip->i_itemp->ili_format.ilf_fields & XFS_ILOG_ALL)))
return 0; return 0;
if (flags & FLUSH_LOG) { if (flags & FLUSH_LOG) {
xfs_inode_log_item_t *iip = ip->i_itemp;
if (iip && iip->ili_last_lsn) { if (iip && iip->ili_last_lsn) {
xlog_t *log = mp->m_log; xlog_t *log = mp->m_log;
xfs_lsn_t sync_lsn; xfs_lsn_t sync_lsn;
int s, log_flags = XFS_LOG_FORCE; int s, log_flags = XFS_LOG_FORCE;
...@@ -3714,12 +3714,12 @@ xfs_inode_flush( ...@@ -3714,12 +3714,12 @@ xfs_inode_flush(
if (flags & FLUSH_SYNC) if (flags & FLUSH_SYNC)
log_flags |= XFS_LOG_SYNC; log_flags |= XFS_LOG_SYNC;
return xfs_log_force(mp, iip->ili_last_lsn, return xfs_log_force(mp, iip->ili_last_lsn, log_flags);
log_flags);
} }
} }
/* We make this non-blocking if the inode is contended, /*
* We make this non-blocking if the inode is contended,
* return EAGAIN to indicate to the caller that they * return EAGAIN to indicate to the caller that they
* did not succeed. This prevents the flush path from * did not succeed. This prevents the flush path from
* blocking on inodes inside another operation right * blocking on inodes inside another operation right
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment