xfs: split and cleanup xfs_log_reserve
Split the log regrant case out of xfs_log_reserve into a separate function, and merge xlog_grant_log_space and xlog_regrant_write_log_space into their respective callers. Also replace the XFS_LOG_PERM_RESERV flag, which easily got misused before the previous cleanups with a simple boolean parameter. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Mark Tinguely <tinguely@sgi.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:

committed by
Ben Myers

parent
42ceedb3ca
commit
9006fb91cf
265
fs/xfs/xfs_log.c
265
fs/xfs/xfs_log.c
@@ -67,15 +67,10 @@ STATIC void xlog_state_switch_iclogs(xlog_t *log,
|
||||
int eventual_size);
|
||||
STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
|
||||
|
||||
/* local functions to manipulate grant head */
|
||||
STATIC int xlog_grant_log_space(xlog_t *log,
|
||||
xlog_ticket_t *xtic);
|
||||
STATIC void xlog_grant_push_ail(struct log *log,
|
||||
int need_bytes);
|
||||
STATIC void xlog_regrant_reserve_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket);
|
||||
STATIC int xlog_regrant_write_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket);
|
||||
STATIC void xlog_ungrant_log_space(xlog_t *log,
|
||||
xlog_ticket_t *ticket);
|
||||
|
||||
@@ -323,6 +318,128 @@ xlog_tic_add_region(xlog_ticket_t *tic, uint len, uint type)
|
||||
tic->t_res_num++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replenish the byte reservation required by moving the grant write head.
|
||||
*/
|
||||
int
|
||||
xfs_log_regrant(
|
||||
struct xfs_mount *mp,
|
||||
struct xlog_ticket *tic)
|
||||
{
|
||||
struct log *log = mp->m_log;
|
||||
int need_bytes;
|
||||
int error = 0;
|
||||
|
||||
if (XLOG_FORCED_SHUTDOWN(log))
|
||||
return XFS_ERROR(EIO);
|
||||
|
||||
XFS_STATS_INC(xs_try_logspace);
|
||||
|
||||
/*
|
||||
* This is a new transaction on the ticket, so we need to change the
|
||||
* transaction ID so that the next transaction has a different TID in
|
||||
* the log. Just add one to the existing tid so that we can see chains
|
||||
* of rolling transactions in the log easily.
|
||||
*/
|
||||
tic->t_tid++;
|
||||
|
||||
xlog_grant_push_ail(log, tic->t_unit_res);
|
||||
|
||||
tic->t_curr_res = tic->t_unit_res;
|
||||
xlog_tic_reset_res(tic);
|
||||
|
||||
if (tic->t_cnt > 0)
|
||||
return 0;
|
||||
|
||||
trace_xfs_log_regrant(log, tic);
|
||||
|
||||
error = xlog_grant_head_check(log, &log->l_write_head, tic,
|
||||
&need_bytes);
|
||||
if (error)
|
||||
goto out_error;
|
||||
|
||||
xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
|
||||
trace_xfs_log_regrant_exit(log, tic);
|
||||
xlog_verify_grant_tail(log);
|
||||
return 0;
|
||||
|
||||
out_error:
|
||||
/*
|
||||
* If we are failing, make sure the ticket doesn't have any current
|
||||
* reservations. We don't want to add this back when the ticket/
|
||||
* transaction gets cancelled.
|
||||
*/
|
||||
tic->t_curr_res = 0;
|
||||
tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reserve log space and return a ticket corresponding the reservation.
|
||||
*
|
||||
* Each reservation is going to reserve extra space for a log record header.
|
||||
* When writes happen to the on-disk log, we don't subtract the length of the
|
||||
* log record header from any reservation. By wasting space in each
|
||||
* reservation, we prevent over allocation problems.
|
||||
*/
|
||||
int
|
||||
xfs_log_reserve(
|
||||
struct xfs_mount *mp,
|
||||
int unit_bytes,
|
||||
int cnt,
|
||||
struct xlog_ticket **ticp,
|
||||
__uint8_t client,
|
||||
bool permanent,
|
||||
uint t_type)
|
||||
{
|
||||
struct log *log = mp->m_log;
|
||||
struct xlog_ticket *tic;
|
||||
int need_bytes;
|
||||
int error = 0;
|
||||
|
||||
ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
|
||||
|
||||
if (XLOG_FORCED_SHUTDOWN(log))
|
||||
return XFS_ERROR(EIO);
|
||||
|
||||
XFS_STATS_INC(xs_try_logspace);
|
||||
|
||||
ASSERT(*ticp == NULL);
|
||||
tic = xlog_ticket_alloc(log, unit_bytes, cnt, client, permanent,
|
||||
KM_SLEEP | KM_MAYFAIL);
|
||||
if (!tic)
|
||||
return XFS_ERROR(ENOMEM);
|
||||
|
||||
tic->t_trans_type = t_type;
|
||||
*ticp = tic;
|
||||
|
||||
xlog_grant_push_ail(log, tic->t_unit_res * tic->t_cnt);
|
||||
|
||||
trace_xfs_log_reserve(log, tic);
|
||||
|
||||
error = xlog_grant_head_check(log, &log->l_reserve_head, tic,
|
||||
&need_bytes);
|
||||
if (error)
|
||||
goto out_error;
|
||||
|
||||
xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes);
|
||||
xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
|
||||
trace_xfs_log_reserve_exit(log, tic);
|
||||
xlog_verify_grant_tail(log);
|
||||
return 0;
|
||||
|
||||
out_error:
|
||||
/*
|
||||
* If we are failing, make sure the ticket doesn't have any current
|
||||
* reservations. We don't want to add this back when the ticket/
|
||||
* transaction gets cancelled.
|
||||
*/
|
||||
tic->t_curr_res = 0;
|
||||
tic->t_cnt = 0; /* ungrant will give back unit_res * t_cnt. */
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* NOTES:
|
||||
*
|
||||
@@ -432,88 +549,6 @@ xfs_log_release_iclog(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1. Reserve an amount of on-disk log space and return a ticket corresponding
|
||||
* to the reservation.
|
||||
* 2. Potentially, push buffers at tail of log to disk.
|
||||
*
|
||||
* Each reservation is going to reserve extra space for a log record header.
|
||||
* When writes happen to the on-disk log, we don't subtract the length of the
|
||||
* log record header from any reservation. By wasting space in each
|
||||
* reservation, we prevent over allocation problems.
|
||||
*/
|
||||
int
|
||||
xfs_log_reserve(
|
||||
struct xfs_mount *mp,
|
||||
int unit_bytes,
|
||||
int cnt,
|
||||
struct xlog_ticket **ticket,
|
||||
__uint8_t client,
|
||||
uint flags,
|
||||
uint t_type)
|
||||
{
|
||||
struct log *log = mp->m_log;
|
||||
struct xlog_ticket *internal_ticket;
|
||||
int retval = 0;
|
||||
|
||||
ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
|
||||
|
||||
if (XLOG_FORCED_SHUTDOWN(log))
|
||||
return XFS_ERROR(EIO);
|
||||
|
||||
XFS_STATS_INC(xs_try_logspace);
|
||||
|
||||
|
||||
if (*ticket != NULL) {
|
||||
ASSERT(flags & XFS_LOG_PERM_RESERV);
|
||||
internal_ticket = *ticket;
|
||||
|
||||
/*
|
||||
* this is a new transaction on the ticket, so we need to
|
||||
* change the transaction ID so that the next transaction has a
|
||||
* different TID in the log. Just add one to the existing tid
|
||||
* so that we can see chains of rolling transactions in the log
|
||||
* easily.
|
||||
*/
|
||||
internal_ticket->t_tid++;
|
||||
|
||||
trace_xfs_log_reserve(log, internal_ticket);
|
||||
|
||||
xlog_grant_push_ail(log, internal_ticket->t_unit_res);
|
||||
retval = xlog_regrant_write_log_space(log, internal_ticket);
|
||||
} else {
|
||||
/* may sleep if need to allocate more tickets */
|
||||
internal_ticket = xlog_ticket_alloc(log, unit_bytes, cnt,
|
||||
client, flags,
|
||||
KM_SLEEP|KM_MAYFAIL);
|
||||
if (!internal_ticket)
|
||||
return XFS_ERROR(ENOMEM);
|
||||
internal_ticket->t_trans_type = t_type;
|
||||
*ticket = internal_ticket;
|
||||
|
||||
trace_xfs_log_reserve(log, internal_ticket);
|
||||
|
||||
xlog_grant_push_ail(log,
|
||||
(internal_ticket->t_unit_res *
|
||||
internal_ticket->t_cnt));
|
||||
retval = xlog_grant_log_space(log, internal_ticket);
|
||||
}
|
||||
|
||||
if (unlikely(retval)) {
|
||||
/*
|
||||
* If we are failing, make sure the ticket doesn't have any
|
||||
* current reservations. We don't want to add this back
|
||||
* when the ticket/ transaction gets cancelled.
|
||||
*/
|
||||
internal_ticket->t_curr_res = 0;
|
||||
/* ungrant will give back unit_res * t_cnt. */
|
||||
internal_ticket->t_cnt = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Mount a log filesystem
|
||||
*
|
||||
@@ -2565,58 +2600,6 @@ restart:
|
||||
return 0;
|
||||
} /* xlog_state_get_iclog_space */
|
||||
|
||||
STATIC int
|
||||
xlog_grant_log_space(
|
||||
struct log *log,
|
||||
struct xlog_ticket *tic)
|
||||
{
|
||||
int need_bytes;
|
||||
int error = 0;
|
||||
|
||||
trace_xfs_log_grant_enter(log, tic);
|
||||
|
||||
error = xlog_grant_head_check(log, &log->l_reserve_head, tic,
|
||||
&need_bytes);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xlog_grant_add_space(log, &log->l_reserve_head.grant, need_bytes);
|
||||
xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
|
||||
trace_xfs_log_grant_exit(log, tic);
|
||||
xlog_verify_grant_tail(log);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Replenish the byte reservation required by moving the grant write head.
|
||||
*/
|
||||
STATIC int
|
||||
xlog_regrant_write_log_space(
|
||||
struct log *log,
|
||||
struct xlog_ticket *tic)
|
||||
{
|
||||
int need_bytes;
|
||||
int error = 0;
|
||||
|
||||
tic->t_curr_res = tic->t_unit_res;
|
||||
xlog_tic_reset_res(tic);
|
||||
|
||||
if (tic->t_cnt > 0)
|
||||
return 0;
|
||||
|
||||
trace_xfs_log_regrant_write_enter(log, tic);
|
||||
|
||||
error = xlog_grant_head_check(log, &log->l_write_head, tic,
|
||||
&need_bytes);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
xlog_grant_add_space(log, &log->l_write_head.grant, need_bytes);
|
||||
trace_xfs_log_regrant_write_exit(log, tic);
|
||||
xlog_verify_grant_tail(log);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The first cnt-1 times through here we don't need to
|
||||
* move the grant write head because the permanent
|
||||
* reservation has reserved cnt times the unit amount.
|
||||
@@ -3156,7 +3139,7 @@ xlog_ticket_alloc(
|
||||
int unit_bytes,
|
||||
int cnt,
|
||||
char client,
|
||||
uint xflags,
|
||||
bool permanent,
|
||||
int alloc_flags)
|
||||
{
|
||||
struct xlog_ticket *tic;
|
||||
@@ -3260,7 +3243,7 @@ xlog_ticket_alloc(
|
||||
tic->t_clientid = client;
|
||||
tic->t_flags = XLOG_TIC_INITED;
|
||||
tic->t_trans_type = 0;
|
||||
if (xflags & XFS_LOG_PERM_RESERV)
|
||||
if (permanent)
|
||||
tic->t_flags |= XLOG_TIC_PERM_RESERV;
|
||||
|
||||
xlog_tic_reset_res(tic);
|
||||
|
Reference in New Issue
Block a user