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,138 +1144,70 @@ xfs_fsync( ...@@ -1144,138 +1144,70 @@ 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
* Timestamps/size haven't changed since last inode */
* flush or inode transaction commit. That means if ((flag & FSYNC_DATA) ?
* either nothing got written or a transaction (ip->i_update_size == 0) :
* committed which caught the updates. If the (ip->i_update_core == 0)) {
* latter happened and the transaction hasn't /*
* hit the disk yet, the inode will be still * Timestamps/size haven't changed since last inode
* be pinned. If it is, force the log. * flush or inode transaction commit. That means
*/ * either nothing got written or a transaction
if (xfs_ipincount(ip) == 0) { * committed which caught the updates. If the
xfs_iunlock(ip, XFS_IOLOCK_EXCL | * latter happened and the transaction hasn't
XFS_ILOCK_SHARED); * hit the disk yet, the inode will be still
} else { * be pinned. If it is, force the log.
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 transaction to log the inode
* core to get the updates. Make it
* sync if FSYNC_WAIT is passed in (which
* is done by everybody but specfs). 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);
/* xfs_iunlock(ip, XFS_IOLOCK_EXCL | XFS_ILOCK_SHARED);
* Note - it's possible that we might have pushed
* ourselves out of the way during trans_reserve if (xfs_ipincount(ip)) {
* which would flush the inode. But there's no xfs_log_force(ip->i_mount, (xfs_lsn_t)0,
* guarantee that the inode buffer has actually XFS_LOG_FORCE |
* gone out yet (it's delwri). Plus the buffer ((flag & FSYNC_WAIT)
* could be pinned anyway if it's part of an ? XFS_LOG_SYNC : 0));
* 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);
} }
} else { error = 0;
} else {
/* /*
* We don't care about the timestamps here. We * Kick off a transaction to log the inode
* only care about the size field growing on us * core to get the updates. Make it
* and forcing any space allocation transactions. * sync if FSYNC_WAIT is passed in (which
* We have to flush changes to the size fields * is done by everybody but specfs). The
* otherwise we could write out data that * sync transaction will also force the log.
* becomes inaccessible after a crash.
*/ */
xfs_ilock(ip, XFS_ILOCK_SHARED); xfs_iunlock(ip, XFS_ILOCK_SHARED);
tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS);
if (ip->i_update_size == 0) { if ((error = xfs_trans_reserve(tp, 0,
/* XFS_FSYNC_TS_LOG_RES(ip->i_mount),
* Force the log if the inode is pinned. 0, 0, 0))) {
* That ensures that all transactions committed xfs_trans_cancel(tp, 0);
* against the inode hit the disk. This may do xfs_iunlock(ip, XFS_IOLOCK_EXCL);
* too much work but it's safe. return error;
*/ }
if (xfs_ipincount(ip) == 0) { xfs_ilock(ip, XFS_ILOCK_EXCL);
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, * Note - it's possible that we might have pushed
XFS_FSYNC_TS_LOG_RES(ip->i_mount), * ourselves out of the way during trans_reserve
0, 0, 0))) { * which would flush the inode. But there's no
xfs_trans_cancel(tp, 0); * guarantee that the inode buffer has actually
xfs_iunlock(ip, XFS_IOLOCK_EXCL); * gone out yet (it's delwri). Plus the buffer
return error; * could be pinned anyway if it's part of an
} * inode in another recent transaction. So we
xfs_ilock(ip, XFS_ILOCK_EXCL); * 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);
* 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