[XFS] split out two helpers from xfs_syncsub

Split out two helpers from xfs_syncsub for the dummy log commit and the
superblock writeout.

SGI-PV: 988140

SGI-Modid: xfs-linux-melb:xfs-kern:32303a

Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: David Chinner <david@fromorbit.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
This commit is contained in:
Christoph Hellwig 2008-10-30 17:14:53 +11:00 committed by Lachlan McIlroy
parent 4e8938feba
commit 2af75df7be
1 changed files with 93 additions and 69 deletions

View File

@ -315,6 +315,93 @@ xfs_sync_inodes(
return XFS_ERROR(last_error);
}
STATIC int
xfs_commit_dummy_trans(
struct xfs_mount *mp,
uint log_flags)
{
struct xfs_inode *ip = mp->m_rootip;
struct xfs_trans *tp;
int error;
/*
* Put a dummy transaction in the log to tell recovery
* that all others are OK.
*/
tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
error = xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0);
if (error) {
xfs_trans_cancel(tp, 0);
return error;
}
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
/* XXX(hch): ignoring the error here.. */
error = xfs_trans_commit(tp, 0);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_log_force(mp, 0, log_flags);
return 0;
}
STATIC int
xfs_sync_fsdata(
struct xfs_mount *mp,
int flags)
{
struct xfs_buf *bp;
struct xfs_buf_log_item *bip;
int error = 0;
/*
* If this is xfssyncd() then only sync the superblock if we can
* lock it without sleeping and it is not pinned.
*/
if (flags & SYNC_BDFLUSH) {
ASSERT(!(flags & SYNC_WAIT));
bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
if (!bp)
goto out;
bip = XFS_BUF_FSPRIVATE(bp, struct xfs_buf_log_item *);
if (!bip || !xfs_buf_item_dirty(bip) || XFS_BUF_ISPINNED(bp))
goto out_brelse;
} else {
bp = xfs_getsb(mp, 0);
/*
* If the buffer is pinned then push on the log so we won't
* get stuck waiting in the write for someone, maybe
* ourselves, to flush the log.
*
* Even though we just pushed the log above, we did not have
* the superblock buffer locked at that point so it can
* become pinned in between there and here.
*/
if (XFS_BUF_ISPINNED(bp))
xfs_log_force(mp, 0, XFS_LOG_FORCE);
}
if (flags & SYNC_WAIT)
XFS_BUF_UNASYNC(bp);
else
XFS_BUF_ASYNC(bp);
return xfs_bwrite(mp, bp);
out_brelse:
xfs_buf_relse(bp);
out:
return error;
}
/*
* xfs sync routine for internal use
*
@ -331,8 +418,6 @@ xfs_syncsub(
int error = 0;
int last_error = 0;
uint log_flags = XFS_LOG_FORCE;
xfs_buf_t *bp;
xfs_buf_log_item_t *bip;
/*
* Sync out the log. This ensures that the log is periodically
@ -355,83 +440,22 @@ xfs_syncsub(
* log activity, so if this isn't vfs_sync() then flush
* the log again.
*/
if (flags & SYNC_DELWRI) {
xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
}
if (flags & SYNC_DELWRI)
xfs_log_force(mp, 0, log_flags);
if (flags & SYNC_FSDATA) {
/*
* If this is vfs_sync() then only sync the superblock
* if we can lock it without sleeping and it is not pinned.
*/
if (flags & SYNC_BDFLUSH) {
bp = xfs_getsb(mp, XFS_BUF_TRYLOCK);
if (bp != NULL) {
bip = XFS_BUF_FSPRIVATE(bp,xfs_buf_log_item_t*);
if ((bip != NULL) &&
xfs_buf_item_dirty(bip)) {
if (!(XFS_BUF_ISPINNED(bp))) {
XFS_BUF_ASYNC(bp);
error = xfs_bwrite(mp, bp);
} else {
xfs_buf_relse(bp);
}
} else {
xfs_buf_relse(bp);
}
}
} else {
bp = xfs_getsb(mp, 0);
/*
* If the buffer is pinned then push on the log so
* we won't get stuck waiting in the write for
* someone, maybe ourselves, to flush the log.
* Even though we just pushed the log above, we
* did not have the superblock buffer locked at
* that point so it can become pinned in between
* there and here.
*/
if (XFS_BUF_ISPINNED(bp))
xfs_log_force(mp, (xfs_lsn_t)0, XFS_LOG_FORCE);
if (flags & SYNC_WAIT)
XFS_BUF_UNASYNC(bp);
else
XFS_BUF_ASYNC(bp);
error = xfs_bwrite(mp, bp);
}
if (error) {
error = xfs_sync_fsdata(mp, flags);
if (error)
last_error = error;
}
}
/*
* Now check to see if the log needs a "dummy" transaction.
*/
if (!(flags & SYNC_REMOUNT) && xfs_log_need_covered(mp)) {
xfs_trans_t *tp;
xfs_inode_t *ip;
/*
* Put a dummy transaction in the log to tell
* recovery that all others are OK.
*/
tp = xfs_trans_alloc(mp, XFS_TRANS_DUMMY1);
if ((error = xfs_trans_reserve(tp, 0,
XFS_ICHANGE_LOG_RES(mp),
0, 0, 0))) {
xfs_trans_cancel(tp, 0);
error = xfs_commit_dummy_trans(mp, log_flags);
if (error)
return error;
}
ip = mp->m_rootip;
xfs_ilock(ip, XFS_ILOCK_EXCL);
xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL);
xfs_trans_ihold(tp, ip);
xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
error = xfs_trans_commit(tp, 0);
xfs_iunlock(ip, XFS_ILOCK_EXCL);
xfs_log_force(mp, (xfs_lsn_t)0, log_flags);
}
/*