Skip to content

Commit

Permalink
xfs: split and cleanup xfs_log_reserve
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Christoph Hellwig authored and Ben Myers committed Feb 23, 2012
1 parent 42ceedb commit 9006fb9
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 170 deletions.
265 changes: 124 additions & 141 deletions fs/xfs/xfs_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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:
*
Expand Down Expand Up @@ -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
*
Expand Down Expand Up @@ -2565,58 +2600,6 @@ xlog_state_get_iclog_space(xlog_t *log,
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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
12 changes: 2 additions & 10 deletions fs/xfs/xfs_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,6 @@ static inline xfs_lsn_t _lsn_cmp(xfs_lsn_t lsn1, xfs_lsn_t lsn2)
*/
#define XFS_LOG_REL_PERM_RESERV 0x1

/*
* Flags to xfs_log_reserve()
*
* XFS_LOG_PERM_RESERV: Permanent reservation. When writes are
* performed against this type of reservation, the reservation
* is not decreased. Long running transactions should use this.
*/
#define XFS_LOG_PERM_RESERV 0x2

/*
* Flags to xfs_log_force()
*
Expand Down Expand Up @@ -172,8 +163,9 @@ int xfs_log_reserve(struct xfs_mount *mp,
int count,
struct xlog_ticket **ticket,
__uint8_t clientid,
uint flags,
bool permanent,
uint t_type);
int xfs_log_regrant(struct xfs_mount *mp, struct xlog_ticket *tic);
int xfs_log_unmount_write(struct xfs_mount *mp);
void xfs_log_unmount(struct xfs_mount *mp);
int xfs_log_force_umount(struct xfs_mount *mp, int logerror);
Expand Down
2 changes: 1 addition & 1 deletion fs/xfs/xfs_log_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ extern void xlog_pack_data(xlog_t *log, xlog_in_core_t *iclog, int);

extern kmem_zone_t *xfs_log_ticket_zone;
struct xlog_ticket *xlog_ticket_alloc(struct log *log, int unit_bytes,
int count, char client, uint xflags,
int count, char client, bool permanent,
int alloc_flags);


Expand Down
11 changes: 4 additions & 7 deletions fs/xfs/xfs_trace.h
Original file line number Diff line number Diff line change
Expand Up @@ -826,17 +826,14 @@ DEFINE_EVENT(xfs_loggrant_class, name, \
TP_ARGS(log, tic))
DEFINE_LOGGRANT_EVENT(xfs_log_done_nonperm);
DEFINE_LOGGRANT_EVENT(xfs_log_done_perm);
DEFINE_LOGGRANT_EVENT(xfs_log_reserve);
DEFINE_LOGGRANT_EVENT(xfs_log_umount_write);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_enter);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_error);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_sleep);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake);
DEFINE_LOGGRANT_EVENT(xfs_log_grant_wake_up);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_enter);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_write_error);
DEFINE_LOGGRANT_EVENT(xfs_log_reserve);
DEFINE_LOGGRANT_EVENT(xfs_log_reserve_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_enter);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_exit);
DEFINE_LOGGRANT_EVENT(xfs_log_regrant_reserve_sub);
Expand Down
Loading

0 comments on commit 9006fb9

Please sign in to comment.