Commit ca825dbc authored by Stephen Lord's avatar Stephen Lord Committed by Christoph Hellwig

XFS: Fold some code paths together in the xfs fsync implementation.

Modid: 2.5.x-xfs:slinx:128239a
parent 7206852c
...@@ -1144,10 +1144,14 @@ xfs_fsync( ...@@ -1144,10 +1144,14 @@ xfs_fsync(
* (Note that xfs_inode_item_format() called at commit clears * (Note that xfs_inode_item_format() called at commit clears
* the update_* fields.) * the update_* fields.)
*/ */
if (!(flag & FSYNC_DATA)) {
xfs_ilock(ip, XFS_ILOCK_SHARED); xfs_ilock(ip, XFS_ILOCK_SHARED);
if (ip->i_update_core == 0) { /* If we are flushing data then we care about update_size
* being set, otherwise we care about update_core
*/
if ((flag & FSYNC_DATA) ?
(ip->i_update_size == 0) :
(ip->i_update_core == 0)) {
/* /*
* Timestamps/size haven't changed since last inode * Timestamps/size haven't changed since last inode
* flush or inode transaction commit. That means * flush or inode transaction commit. That means
...@@ -1157,12 +1161,10 @@ xfs_fsync( ...@@ -1157,12 +1161,10 @@ xfs_fsync(
* hit the disk yet, the inode will be still * hit the disk yet, the inode will be still
* be pinned. If it is, force the log. * be pinned. If it is, force the log.
*/ */
if (xfs_ipincount(ip) == 0) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL | xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED);
XFS_ILOCK_SHARED);
} else { if (xfs_ipincount(ip)) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL |
XFS_ILOCK_SHARED);
xfs_log_force(ip->i_mount, (xfs_lsn_t)0, xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
XFS_LOG_FORCE | XFS_LOG_FORCE |
((flag & FSYNC_WAIT) ((flag & FSYNC_WAIT)
...@@ -1207,76 +1209,6 @@ xfs_fsync( ...@@ -1207,76 +1209,6 @@ xfs_fsync(
xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL); xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
} }
} else {
/*
* We don't care about the timestamps here. We
* only care about the size field growing on us
* and forcing any space allocation transactions.
* We have to flush changes to the size fields
* otherwise we could write out data that
* becomes inaccessible after a crash.
*/
xfs_ilock(ip, XFS_ILOCK_SHARED);
if (ip->i_update_size == 0) {
/*
* Force the log if the inode is pinned.
* That ensures that all transactions committed
* against the inode hit the disk. This may do
* too much work but it's safe.
*/
if (xfs_ipincount(ip) == 0) {
xfs_iunlock(ip, XFS_IOLOCK_EXCL |
XFS_ILOCK_SHARED);
} else {
xfs_iunlock(ip, XFS_IOLOCK_EXCL |
XFS_ILOCK_SHARED);
xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
XFS_LOG_FORCE |
((flag & FSYNC_WAIT)
? XFS_LOG_SYNC : 0));
}
error = 0;
} else {
/*
* Kick off a sync transaction to log the inode
* core. The transaction has to be sync since
* we need these updates to guarantee that the
* data written will be seen. The sync
* transaction will also force the log.
*/
xfs_iunlock(ip, XFS_ILOCK_SHARED);
tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
if ((error = xfs_trans_reserve(tp, 0,
XFS_FSYNC_TS_LOG_RES(ip->i_mount),
0, 0, 0))) {
xfs_trans_cancel(tp, 0);
xfs_iunlock(ip, XFS_IOLOCK_EXCL);
return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
/*
* Note - it's possible that we might have pushed
* ourselves out of the way during trans_reserve
* which would flush the inode. But there's no
* guarantee that the inode buffer has actually
* gone out yet (it's delwri). Plus the buffer
* could be pinned anyway if it's part of an
* inode in another recent transaction. So we
* play it safe and fire off the transaction anyway.
*/
xfs_trans_ijoin(tp, ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
if (flag & FSYNC_WAIT)
xfs_trans_set_sync(tp);
error = xfs_trans_commit(tp, 0, NULL);
xfs_iunlock(ip, XFS_IOLOCK_EXCL|XFS_ILOCK_EXCL);
}
}
return error; return error;
} }
......
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