xfs: cleanup the transaction commit path a bit
Now that the nodelaylog mode is gone we can simplify the transaction commit path a bit by removing the xfs_trans_commit_cil routine. Restoring the process flags is merged into xfs_trans_commit which already does it for the error path, and allocating the log vectors is merged into xlog_cil_format_items, which already fills them with data, thus avoiding one loop over all log items. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Ben Myers <bpm@sgi.com>
This commit is contained in:
parent
93b8a5854f
commit
0244b9603d
3 changed files with 63 additions and 99 deletions
|
@ -184,8 +184,7 @@ void xlog_iodone(struct xfs_buf *);
|
|||
struct xlog_ticket *xfs_log_ticket_get(struct xlog_ticket *ticket);
|
||||
void xfs_log_ticket_put(struct xlog_ticket *ticket);
|
||||
|
||||
void xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
struct xfs_log_vec *log_vector,
|
||||
int xfs_log_commit_cil(struct xfs_mount *mp, struct xfs_trans *tp,
|
||||
xfs_lsn_t *commit_lsn, int flags);
|
||||
bool xfs_log_item_in_current_chkpt(struct xfs_log_item *lip);
|
||||
|
||||
|
|
|
@ -159,37 +159,72 @@ xlog_cil_init_post_recovery(
|
|||
* format the regions into the iclog as though they are being formatted
|
||||
* directly out of the objects themselves.
|
||||
*/
|
||||
static void
|
||||
xlog_cil_format_items(
|
||||
struct log *log,
|
||||
struct xfs_log_vec *log_vector)
|
||||
static struct xfs_log_vec *
|
||||
xlog_cil_prepare_log_vecs(
|
||||
struct xfs_trans *tp)
|
||||
{
|
||||
struct xfs_log_vec *lv;
|
||||
struct xfs_log_item_desc *lidp;
|
||||
struct xfs_log_vec *lv = NULL;
|
||||
struct xfs_log_vec *ret_lv = NULL;
|
||||
|
||||
ASSERT(log_vector);
|
||||
for (lv = log_vector; lv; lv = lv->lv_next) {
|
||||
|
||||
/* Bail out if we didn't find a log item. */
|
||||
if (list_empty(&tp->t_items)) {
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_for_each_entry(lidp, &tp->t_items, lid_trans) {
|
||||
struct xfs_log_vec *new_lv;
|
||||
void *ptr;
|
||||
int index;
|
||||
int len = 0;
|
||||
|
||||
/* Skip items which aren't dirty in this transaction. */
|
||||
if (!(lidp->lid_flags & XFS_LID_DIRTY))
|
||||
continue;
|
||||
|
||||
/* Skip items that do not have any vectors for writing */
|
||||
lidp->lid_size = IOP_SIZE(lidp->lid_item);
|
||||
if (!lidp->lid_size)
|
||||
continue;
|
||||
|
||||
new_lv = kmem_zalloc(sizeof(*new_lv) +
|
||||
lidp->lid_size * sizeof(struct xfs_log_iovec),
|
||||
KM_SLEEP);
|
||||
|
||||
/* The allocated iovec region lies beyond the log vector. */
|
||||
new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
|
||||
new_lv->lv_niovecs = lidp->lid_size;
|
||||
new_lv->lv_item = lidp->lid_item;
|
||||
|
||||
/* build the vector array and calculate it's length */
|
||||
IOP_FORMAT(lv->lv_item, lv->lv_iovecp);
|
||||
for (index = 0; index < lv->lv_niovecs; index++)
|
||||
len += lv->lv_iovecp[index].i_len;
|
||||
IOP_FORMAT(new_lv->lv_item, new_lv->lv_iovecp);
|
||||
for (index = 0; index < new_lv->lv_niovecs; index++)
|
||||
len += new_lv->lv_iovecp[index].i_len;
|
||||
|
||||
lv->lv_buf_len = len;
|
||||
lv->lv_buf = kmem_alloc(lv->lv_buf_len, KM_SLEEP|KM_NOFS);
|
||||
ptr = lv->lv_buf;
|
||||
new_lv->lv_buf_len = len;
|
||||
new_lv->lv_buf = kmem_alloc(new_lv->lv_buf_len,
|
||||
KM_SLEEP|KM_NOFS);
|
||||
ptr = new_lv->lv_buf;
|
||||
|
||||
for (index = 0; index < lv->lv_niovecs; index++) {
|
||||
struct xfs_log_iovec *vec = &lv->lv_iovecp[index];
|
||||
for (index = 0; index < new_lv->lv_niovecs; index++) {
|
||||
struct xfs_log_iovec *vec = &new_lv->lv_iovecp[index];
|
||||
|
||||
memcpy(ptr, vec->i_addr, vec->i_len);
|
||||
vec->i_addr = ptr;
|
||||
ptr += vec->i_len;
|
||||
}
|
||||
ASSERT(ptr == lv->lv_buf + lv->lv_buf_len);
|
||||
ASSERT(ptr == new_lv->lv_buf + new_lv->lv_buf_len);
|
||||
|
||||
if (!ret_lv)
|
||||
ret_lv = new_lv;
|
||||
else
|
||||
lv->lv_next = new_lv;
|
||||
lv = new_lv;
|
||||
}
|
||||
|
||||
return ret_lv;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -622,28 +657,30 @@ xlog_cil_push(
|
|||
* background commit, returns without it held once background commits are
|
||||
* allowed again.
|
||||
*/
|
||||
void
|
||||
int
|
||||
xfs_log_commit_cil(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
struct xfs_log_vec *log_vector,
|
||||
xfs_lsn_t *commit_lsn,
|
||||
int flags)
|
||||
{
|
||||
struct log *log = mp->m_log;
|
||||
int log_flags = 0;
|
||||
int push = 0;
|
||||
struct xfs_log_vec *log_vector;
|
||||
|
||||
if (flags & XFS_TRANS_RELEASE_LOG_RES)
|
||||
log_flags = XFS_LOG_REL_PERM_RESERV;
|
||||
|
||||
/*
|
||||
* do all the hard work of formatting items (including memory
|
||||
* Do all the hard work of formatting items (including memory
|
||||
* allocation) outside the CIL context lock. This prevents stalling CIL
|
||||
* pushes when we are low on memory and a transaction commit spends a
|
||||
* lot of time in memory reclaim.
|
||||
*/
|
||||
xlog_cil_format_items(log, log_vector);
|
||||
log_vector = xlog_cil_prepare_log_vecs(tp);
|
||||
if (!log_vector)
|
||||
return ENOMEM;
|
||||
|
||||
/* lock out background commit */
|
||||
down_read(&log->l_cilp->xc_ctx_lock);
|
||||
|
@ -696,6 +733,7 @@ xfs_log_commit_cil(
|
|||
*/
|
||||
if (push)
|
||||
xlog_cil_push(log, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1324,82 +1324,6 @@ xfs_trans_committed_bulk(
|
|||
spin_unlock(&ailp->xa_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the log items and allocate log vector structures for
|
||||
* each item large enough to fit all the vectors they require.
|
||||
* Note that this format differs from the old log vector format in
|
||||
* that there is no transaction header in these log vectors.
|
||||
*/
|
||||
STATIC struct xfs_log_vec *
|
||||
xfs_trans_alloc_log_vecs(
|
||||
xfs_trans_t *tp)
|
||||
{
|
||||
struct xfs_log_item_desc *lidp;
|
||||
struct xfs_log_vec *lv = NULL;
|
||||
struct xfs_log_vec *ret_lv = NULL;
|
||||
|
||||
|
||||
/* Bail out if we didn't find a log item. */
|
||||
if (list_empty(&tp->t_items)) {
|
||||
ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_for_each_entry(lidp, &tp->t_items, lid_trans) {
|
||||
struct xfs_log_vec *new_lv;
|
||||
|
||||
/* Skip items which aren't dirty in this transaction. */
|
||||
if (!(lidp->lid_flags & XFS_LID_DIRTY))
|
||||
continue;
|
||||
|
||||
/* Skip items that do not have any vectors for writing */
|
||||
lidp->lid_size = IOP_SIZE(lidp->lid_item);
|
||||
if (!lidp->lid_size)
|
||||
continue;
|
||||
|
||||
new_lv = kmem_zalloc(sizeof(*new_lv) +
|
||||
lidp->lid_size * sizeof(struct xfs_log_iovec),
|
||||
KM_SLEEP);
|
||||
|
||||
/* The allocated iovec region lies beyond the log vector. */
|
||||
new_lv->lv_iovecp = (struct xfs_log_iovec *)&new_lv[1];
|
||||
new_lv->lv_niovecs = lidp->lid_size;
|
||||
new_lv->lv_item = lidp->lid_item;
|
||||
if (!ret_lv)
|
||||
ret_lv = new_lv;
|
||||
else
|
||||
lv->lv_next = new_lv;
|
||||
lv = new_lv;
|
||||
}
|
||||
|
||||
return ret_lv;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_trans_commit_cil(
|
||||
struct xfs_mount *mp,
|
||||
struct xfs_trans *tp,
|
||||
xfs_lsn_t *commit_lsn,
|
||||
int flags)
|
||||
{
|
||||
struct xfs_log_vec *log_vector;
|
||||
|
||||
/*
|
||||
* Get each log item to allocate a vector structure for
|
||||
* the log item to to pass to the log write code. The
|
||||
* CIL commit code will format the vector and save it away.
|
||||
*/
|
||||
log_vector = xfs_trans_alloc_log_vecs(tp);
|
||||
if (!log_vector)
|
||||
return ENOMEM;
|
||||
|
||||
xfs_log_commit_cil(mp, tp, log_vector, commit_lsn, flags);
|
||||
|
||||
current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
|
||||
xfs_trans_free(tp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Commit the given transaction to the log.
|
||||
*
|
||||
|
@ -1456,13 +1380,16 @@ xfs_trans_commit(
|
|||
xfs_trans_apply_sb_deltas(tp);
|
||||
xfs_trans_apply_dquot_deltas(tp);
|
||||
|
||||
error = xfs_trans_commit_cil(mp, tp, &commit_lsn, flags);
|
||||
error = xfs_log_commit_cil(mp, tp, &commit_lsn, flags);
|
||||
if (error == ENOMEM) {
|
||||
xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR);
|
||||
error = XFS_ERROR(EIO);
|
||||
goto out_unreserve;
|
||||
}
|
||||
|
||||
current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS);
|
||||
xfs_trans_free(tp);
|
||||
|
||||
/*
|
||||
* If the transaction needs to be synchronous, then force the
|
||||
* log out now and wait for it.
|
||||
|
|
Loading…
Reference in a new issue