forked from Minki/linux
[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:
parent
4e8938feba
commit
2af75df7be
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user