Commit dd401770 authored by Dave Chinner's avatar Dave Chinner Committed by Darrick J. Wong

xfs: refactor and split xfs_log_done()

xfs_log_done() does two separate things. Firstly, it triggers commit
records to be written for permanent transactions, and secondly it
releases or regrants transaction reservation space.

Since delayed logging was introduced, transactions no longer write
directly to the log, hence they never have the XLOG_TIC_INITED flag
cleared on them. Hence transactions never write commit records to
the log and only need to modify reservation space.

Split up xfs_log_done into two parts, and only call the parts of the
operation needed for the context xfs_log_done() is currently being
called from.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
parent 9590e9c6
...@@ -487,62 +487,40 @@ xfs_log_reserve( ...@@ -487,62 +487,40 @@ xfs_log_reserve(
*/ */
/* /*
* This routine is called when a user of a log manager ticket is done with * Write a commit record to the log to close off a running log write.
* the reservation. If the ticket was ever used, then a commit record for
* the associated transaction is written out as a log operation header with
* no data. The flag XLOG_TIC_INITED is set when the first write occurs with
* a given ticket. If the ticket was one with a permanent reservation, then
* a few operations are done differently. Permanent reservation tickets by
* default don't release the reservation. They just commit the current
* transaction with the belief that the reservation is still needed. A flag
* must be passed in before permanent reservations are actually released.
* When these type of tickets are not released, they need to be set into
* the inited state again. By doing this, a start record will be written
* out when the next write occurs.
*/ */
xfs_lsn_t int
xfs_log_done( xlog_write_done(
struct xfs_mount *mp, struct xlog *log,
struct xlog_ticket *ticket, struct xlog_ticket *ticket,
struct xlog_in_core **iclog, struct xlog_in_core **iclog,
bool regrant) xfs_lsn_t *lsn)
{ {
struct xlog *log = mp->m_log; if (XLOG_FORCED_SHUTDOWN(log))
xfs_lsn_t lsn = 0; return -EIO;
if (XLOG_FORCED_SHUTDOWN(log) ||
/*
* If nothing was ever written, don't write out commit record.
* If we get an error, just continue and give back the log ticket.
*/
(((ticket->t_flags & XLOG_TIC_INITED) == 0) &&
(xlog_commit_record(log, ticket, iclog, &lsn)))) {
lsn = (xfs_lsn_t) -1;
regrant = false;
}
if (!regrant) { return xlog_commit_record(log, ticket, iclog, lsn);
trace_xfs_log_done_nonperm(log, ticket); }
/* /*
* Release ticket if not permanent reservation or a specific * Release or regrant the ticket reservation now the transaction is done with
* request has been made to release a permanent reservation. * it depending on caller context. Rolling transactions need the ticket
* regranted, otherwise we release it completely.
*/ */
void
xlog_ticket_done(
struct xlog *log,
struct xlog_ticket *ticket,
bool regrant)
{
if (!regrant || XLOG_FORCED_SHUTDOWN(log)) {
trace_xfs_log_done_nonperm(log, ticket);
xlog_ungrant_log_space(log, ticket); xlog_ungrant_log_space(log, ticket);
} else { } else {
trace_xfs_log_done_perm(log, ticket); trace_xfs_log_done_perm(log, ticket);
xlog_regrant_reserve_log_space(log, ticket); xlog_regrant_reserve_log_space(log, ticket);
/* If this ticket was a permanent reservation and we aren't
* trying to release it, reset the inited flags; so next time
* we write, a start record will be written out.
*/
ticket->t_flags |= XLOG_TIC_INITED;
} }
xfs_log_ticket_put(ticket); xfs_log_ticket_put(ticket);
return lsn;
} }
static bool static bool
......
...@@ -105,10 +105,6 @@ struct xfs_log_item; ...@@ -105,10 +105,6 @@ struct xfs_log_item;
struct xfs_item_ops; struct xfs_item_ops;
struct xfs_trans; struct xfs_trans;
xfs_lsn_t xfs_log_done(struct xfs_mount *mp,
struct xlog_ticket *ticket,
struct xlog_in_core **iclog,
bool regrant);
int xfs_log_force(struct xfs_mount *mp, uint flags); int xfs_log_force(struct xfs_mount *mp, uint flags);
int xfs_log_force_lsn(struct xfs_mount *mp, xfs_lsn_t lsn, uint flags, int xfs_log_force_lsn(struct xfs_mount *mp, xfs_lsn_t lsn, uint flags,
int *log_forced); int *log_forced);
......
...@@ -839,10 +839,11 @@ xlog_cil_push_work( ...@@ -839,10 +839,11 @@ xlog_cil_push_work(
} }
spin_unlock(&cil->xc_push_lock); spin_unlock(&cil->xc_push_lock);
/* xfs_log_done always frees the ticket on error. */ error = xlog_write_done(log, tic, &commit_iclog, &commit_lsn);
commit_lsn = xfs_log_done(log->l_mp, tic, &commit_iclog, false); if (error)
if (commit_lsn == -1) goto out_abort_free_ticket;
goto out_abort;
xlog_ticket_done(log, tic, false);
spin_lock(&commit_iclog->ic_callback_lock); spin_lock(&commit_iclog->ic_callback_lock);
if (commit_iclog->ic_state == XLOG_STATE_IOERROR) { if (commit_iclog->ic_state == XLOG_STATE_IOERROR) {
...@@ -875,7 +876,7 @@ xlog_cil_push_work( ...@@ -875,7 +876,7 @@ xlog_cil_push_work(
return; return;
out_abort_free_ticket: out_abort_free_ticket:
xfs_log_ticket_put(tic); xlog_ticket_done(log, tic, false);
out_abort: out_abort:
ASSERT(XLOG_FORCED_SHUTDOWN(log)); ASSERT(XLOG_FORCED_SHUTDOWN(log));
xlog_cil_committed(ctx); xlog_cil_committed(ctx);
...@@ -1007,7 +1008,7 @@ xfs_log_commit_cil( ...@@ -1007,7 +1008,7 @@ xfs_log_commit_cil(
if (commit_lsn) if (commit_lsn)
*commit_lsn = xc_commit_lsn; *commit_lsn = xc_commit_lsn;
xfs_log_done(mp, tp->t_ticket, NULL, regrant); xlog_ticket_done(log, tp->t_ticket, regrant);
tp->t_ticket = NULL; tp->t_ticket = NULL;
xfs_trans_unreserve_and_mod_sb(tp); xfs_trans_unreserve_and_mod_sb(tp);
......
...@@ -443,6 +443,10 @@ int xlog_write(struct xlog *log, struct xfs_log_vec *log_vector, ...@@ -443,6 +443,10 @@ int xlog_write(struct xlog *log, struct xfs_log_vec *log_vector,
struct xlog_ticket *tic, xfs_lsn_t *start_lsn, struct xlog_ticket *tic, xfs_lsn_t *start_lsn,
struct xlog_in_core **commit_iclog, uint flags, struct xlog_in_core **commit_iclog, uint flags,
bool need_start_rec); bool need_start_rec);
int xlog_write_done(struct xlog *log, struct xlog_ticket *ticket,
struct xlog_in_core **iclog, xfs_lsn_t *lsn);
void xlog_ticket_done(struct xlog *log, struct xlog_ticket *ticket,
bool regrant);
/* /*
* When we crack an atomic LSN, we sample it first so that the value will not * When we crack an atomic LSN, we sample it first so that the value will not
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "xfs_shared.h" #include "xfs_shared.h"
#include "xfs_format.h" #include "xfs_format.h"
#include "xfs_log_format.h" #include "xfs_log_format.h"
#include "xfs_log_priv.h"
#include "xfs_trans_resv.h" #include "xfs_trans_resv.h"
#include "xfs_mount.h" #include "xfs_mount.h"
#include "xfs_extent_busy.h" #include "xfs_extent_busy.h"
...@@ -150,6 +151,7 @@ xfs_trans_reserve( ...@@ -150,6 +151,7 @@ xfs_trans_reserve(
uint blocks, uint blocks,
uint rtextents) uint rtextents)
{ {
struct xfs_mount *mp = tp->t_mountp;
int error = 0; int error = 0;
bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; bool rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0;
...@@ -162,7 +164,7 @@ xfs_trans_reserve( ...@@ -162,7 +164,7 @@ xfs_trans_reserve(
* fail if the count would go below zero. * fail if the count would go below zero.
*/ */
if (blocks > 0) { if (blocks > 0) {
error = xfs_mod_fdblocks(tp->t_mountp, -((int64_t)blocks), rsvd); error = xfs_mod_fdblocks(mp, -((int64_t)blocks), rsvd);
if (error != 0) { if (error != 0) {
current_restore_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS); current_restore_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS);
return -ENOSPC; return -ENOSPC;
...@@ -191,9 +193,9 @@ xfs_trans_reserve( ...@@ -191,9 +193,9 @@ xfs_trans_reserve(
if (tp->t_ticket != NULL) { if (tp->t_ticket != NULL) {
ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES); ASSERT(resp->tr_logflags & XFS_TRANS_PERM_LOG_RES);
error = xfs_log_regrant(tp->t_mountp, tp->t_ticket); error = xfs_log_regrant(mp, tp->t_ticket);
} else { } else {
error = xfs_log_reserve(tp->t_mountp, error = xfs_log_reserve(mp,
resp->tr_logres, resp->tr_logres,
resp->tr_logcount, resp->tr_logcount,
&tp->t_ticket, XFS_TRANSACTION, &tp->t_ticket, XFS_TRANSACTION,
...@@ -213,7 +215,7 @@ xfs_trans_reserve( ...@@ -213,7 +215,7 @@ xfs_trans_reserve(
* fail if the count would go below zero. * fail if the count would go below zero.
*/ */
if (rtextents > 0) { if (rtextents > 0) {
error = xfs_mod_frextents(tp->t_mountp, -((int64_t)rtextents)); error = xfs_mod_frextents(mp, -((int64_t)rtextents));
if (error) { if (error) {
error = -ENOSPC; error = -ENOSPC;
goto undo_log; goto undo_log;
...@@ -229,7 +231,7 @@ xfs_trans_reserve( ...@@ -229,7 +231,7 @@ xfs_trans_reserve(
*/ */
undo_log: undo_log:
if (resp->tr_logres > 0) { if (resp->tr_logres > 0) {
xfs_log_done(tp->t_mountp, tp->t_ticket, NULL, false); xlog_ticket_done(mp->m_log, tp->t_ticket, false);
tp->t_ticket = NULL; tp->t_ticket = NULL;
tp->t_log_res = 0; tp->t_log_res = 0;
tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES; tp->t_flags &= ~XFS_TRANS_PERM_LOG_RES;
...@@ -237,7 +239,7 @@ xfs_trans_reserve( ...@@ -237,7 +239,7 @@ xfs_trans_reserve(
undo_blocks: undo_blocks:
if (blocks > 0) { if (blocks > 0) {
xfs_mod_fdblocks(tp->t_mountp, (int64_t)blocks, rsvd); xfs_mod_fdblocks(mp, (int64_t)blocks, rsvd);
tp->t_blk_res = 0; tp->t_blk_res = 0;
} }
...@@ -1004,9 +1006,7 @@ __xfs_trans_commit( ...@@ -1004,9 +1006,7 @@ __xfs_trans_commit(
*/ */
xfs_trans_unreserve_and_mod_dquots(tp); xfs_trans_unreserve_and_mod_dquots(tp);
if (tp->t_ticket) { if (tp->t_ticket) {
commit_lsn = xfs_log_done(mp, tp->t_ticket, NULL, regrant); xlog_ticket_done(mp->m_log, tp->t_ticket, regrant);
if (commit_lsn == -1 && !error)
error = -EIO;
tp->t_ticket = NULL; tp->t_ticket = NULL;
} }
current_restore_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS); current_restore_flags_nested(&tp->t_pflags, PF_MEMALLOC_NOFS);
...@@ -1065,7 +1065,7 @@ xfs_trans_cancel( ...@@ -1065,7 +1065,7 @@ xfs_trans_cancel(
xfs_trans_unreserve_and_mod_dquots(tp); xfs_trans_unreserve_and_mod_dquots(tp);
if (tp->t_ticket) { if (tp->t_ticket) {
xfs_log_done(mp, tp->t_ticket, NULL, false); xlog_ticket_done(mp->m_log, tp->t_ticket, false);
tp->t_ticket = NULL; tp->t_ticket = NULL;
} }
......
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