/*
- * Copyright (c) 2000-2004 Silicon Graphics, Inc. All Rights Reserved.
+ * Copyright (c) 2000-2005 Silicon Graphics, Inc.
+ * All Rights Reserved.
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of version 2 of the GNU General Public License as
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation.
*
- * This program is distributed in the hope that it would be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * This program is distributed in the hope that it would be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Further, this software is distributed without any warranty that it is
- * free of the rightful claim of any third person regarding infringement
- * or the like. Any license provided herein, whether implied or
- * otherwise, applies only to this software file. Patent licenses, if
- * any, provided herein do not apply to combinations of this program with
- * other software, or any other product whatsoever.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write the Free Software Foundation, Inc., 59
- * Temple Place - Suite 330, Boston MA 02111-1307, USA.
- *
- * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
- * Mountain View, CA 94043, or:
- *
- * http://www.sgi.com
- *
- * For further information regarding this notice, see:
- *
- * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
- */
-
-/*
- * High level interface routines for log manager
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
#include "xfs.h"
-#include "xfs_macros.h"
+#include "xfs_fs.h"
#include "xfs_types.h"
-#include "xfs_inum.h"
-#include "xfs_ag.h"
-#include "xfs_sb.h"
+#include "xfs_bit.h"
#include "xfs_log.h"
+#include "xfs_inum.h"
#include "xfs_trans.h"
+#include "xfs_sb.h"
+#include "xfs_ag.h"
#include "xfs_dir.h"
+#include "xfs_dir2.h"
#include "xfs_dmapi.h"
#include "xfs_mount.h"
#include "xfs_error.h"
#include "xfs_log_priv.h"
#include "xfs_buf_item.h"
+#include "xfs_bmap_btree.h"
#include "xfs_alloc_btree.h"
+#include "xfs_ialloc_btree.h"
#include "xfs_log_recover.h"
-#include "xfs_bit.h"
-#include "xfs_rw.h"
#include "xfs_trans_priv.h"
+#include "xfs_dir_sf.h"
+#include "xfs_dir2_sf.h"
+#include "xfs_attr_sf.h"
+#include "xfs_dinode.h"
+#include "xfs_inode.h"
+#include "xfs_rw.h"
#define xlog_write_adv_cnt(ptr, len, off, bytes) \
int num_bblks);
STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes);
STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog);
-STATIC void xlog_unalloc_log(xlog_t *log);
+STATIC void xlog_dealloc_log(xlog_t *log);
STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[],
int nentries, xfs_log_ticket_t tic,
xfs_lsn_t *start_lsn,
STATIC void xlog_state_switch_iclogs(xlog_t *log,
xlog_in_core_t *iclog,
int eventual_size);
-STATIC int xlog_state_sync(xlog_t *log, xfs_lsn_t lsn, uint flags);
-STATIC int xlog_state_sync_all(xlog_t *log, uint flags);
+STATIC int xlog_state_sync(xlog_t *log,
+ xfs_lsn_t lsn,
+ uint flags,
+ int *log_flushed);
+STATIC int xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed);
STATIC void xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog);
/* local functions to manipulate grant head */
uint flags);
STATIC void xlog_ticket_put(xlog_t *log, xlog_ticket_t *ticket);
-/* local debug functions */
-#if defined(DEBUG) && !defined(XLOG_NOLOG)
+#if defined(DEBUG)
STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr);
STATIC void xlog_verify_grant_head(xlog_t *log, int equals);
STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog,
STATIC int xlog_iclogs_empty(xlog_t *log);
-#ifdef DEBUG
-int xlog_do_error = 0;
-int xlog_req_num = 0;
-int xlog_error_mod = 33;
-#endif
-
-#define XLOG_FORCED_SHUTDOWN(log) (log->l_flags & XLOG_IO_ERROR)
-
-/*
- * 0 => disable log manager
- * 1 => enable log manager
- * 2 => enable log manager and log debugging
- */
-#if defined(XLOG_NOLOG) || defined(DEBUG)
-int xlog_debug = 1;
-xfs_buftarg_t *xlog_target;
-#endif
-
#if defined(XFS_LOG_TRACE)
-
void
xlog_trace_loggrant(xlog_t *log, xlog_ticket_t *tic, xfs_caddr_t string)
{
void
xlog_trace_iclog(xlog_in_core_t *iclog, uint state)
{
- pid_t pid;
-
- pid = current_pid();
-
if (!iclog->ic_trace)
iclog->ic_trace = ktrace_alloc(256, KM_SLEEP);
ktrace_enter(iclog->ic_trace,
(void *)((unsigned long)state),
- (void *)((unsigned long)pid),
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0,
- (void *)0);
+ (void *)((unsigned long)current_pid()),
+ (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
+ (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
+ (void *)NULL, (void *)NULL, (void *)NULL, (void *)NULL,
+ (void *)NULL, (void *)NULL);
}
-
#else
#define xlog_trace_loggrant(log,tic,string)
#define xlog_trace_iclog(iclog,state)
#endif /* XFS_LOG_TRACE */
+
+static void
+xlog_ins_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
+{
+ if (*qp) {
+ tic->t_next = (*qp);
+ tic->t_prev = (*qp)->t_prev;
+ (*qp)->t_prev->t_next = tic;
+ (*qp)->t_prev = tic;
+ } else {
+ tic->t_prev = tic->t_next = tic;
+ *qp = tic;
+ }
+
+ tic->t_flags |= XLOG_TIC_IN_Q;
+}
+
+static void
+xlog_del_ticketq(struct xlog_ticket **qp, struct xlog_ticket *tic)
+{
+ if (tic == tic->t_next) {
+ *qp = NULL;
+ } else {
+ *qp = tic->t_next;
+ tic->t_next->t_prev = tic->t_prev;
+ tic->t_prev->t_next = tic->t_next;
+ }
+
+ tic->t_next = tic->t_prev = NULL;
+ tic->t_flags &= ~XLOG_TIC_IN_Q;
+}
+
+static void
+xlog_grant_sub_space(struct log *log, int bytes)
+{
+ log->l_grant_write_bytes -= bytes;
+ if (log->l_grant_write_bytes < 0) {
+ log->l_grant_write_bytes += log->l_logsize;
+ log->l_grant_write_cycle--;
+ }
+
+ log->l_grant_reserve_bytes -= bytes;
+ if ((log)->l_grant_reserve_bytes < 0) {
+ log->l_grant_reserve_bytes += log->l_logsize;
+ log->l_grant_reserve_cycle--;
+ }
+
+}
+
+static void
+xlog_grant_add_space_write(struct log *log, int bytes)
+{
+ log->l_grant_write_bytes += bytes;
+ if (log->l_grant_write_bytes > log->l_logsize) {
+ log->l_grant_write_bytes -= log->l_logsize;
+ log->l_grant_write_cycle++;
+ }
+}
+
+static void
+xlog_grant_add_space_reserve(struct log *log, int bytes)
+{
+ log->l_grant_reserve_bytes += bytes;
+ if (log->l_grant_reserve_bytes > log->l_logsize) {
+ log->l_grant_reserve_bytes -= log->l_logsize;
+ log->l_grant_reserve_cycle++;
+ }
+}
+
+static inline void
+xlog_grant_add_space(struct log *log, int bytes)
+{
+ xlog_grant_add_space_write(log, bytes);
+ xlog_grant_add_space_reserve(log, bytes);
+}
+
+
/*
* NOTES:
*
xlog_ticket_t *ticket = (xfs_log_ticket_t) xtic;
xfs_lsn_t lsn = 0;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return 0;
-#endif
-
if (XLOG_FORCED_SHUTDOWN(log) ||
/*
* If nothing was ever written, don't write out commit record.
if ((ticket->t_flags & XLOG_TIC_PERM_RESERV) == 0 ||
(flags & XFS_LOG_REL_PERM_RESERV)) {
/*
- * Release ticket if not permanent reservation or a specifc
+ * Release ticket if not permanent reservation or a specific
* request has been made to release a permanent reservation.
*/
xlog_trace_loggrant(log, ticket, "xfs_log_done: (non-permanent)");
* semaphore.
*/
int
-xfs_log_force(xfs_mount_t *mp,
- xfs_lsn_t lsn,
- uint flags)
+_xfs_log_force(
+ xfs_mount_t *mp,
+ xfs_lsn_t lsn,
+ uint flags,
+ int *log_flushed)
{
- int rval;
- xlog_t *log = mp->m_log;
+ xlog_t *log = mp->m_log;
+ int dummy;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return 0;
-#endif
+ if (!log_flushed)
+ log_flushed = &dummy;
ASSERT(flags & XFS_LOG_FORCE);
XFS_STATS_INC(xs_log_force);
- if ((log->l_flags & XLOG_IO_ERROR) == 0) {
- if (lsn == 0)
- rval = xlog_state_sync_all(log, flags);
- else
- rval = xlog_state_sync(log, lsn, flags);
- } else {
- rval = XFS_ERROR(EIO);
- }
-
- return rval;
-
+ if (log->l_flags & XLOG_IO_ERROR)
+ return XFS_ERROR(EIO);
+ if (lsn == 0)
+ return xlog_state_sync_all(log, flags, log_flushed);
+ else
+ return xlog_state_sync(log, lsn, flags, log_flushed);
} /* xfs_log_force */
/*
xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl;
int abortflg, spl;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return 0;
-#endif
cb->cb_next = NULL;
spl = LOG_LOCK(log);
abortflg = (iclog->ic_state & XLOG_STATE_IOERROR);
if (xlog_state_release_iclog(log, iclog)) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
- return(EIO);
+ return EIO;
}
return 0;
{
xlog_t *log = mp->m_log;
xlog_ticket_t *internal_ticket;
- int retval;
+ int retval = 0;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return 0;
-#endif
- retval = 0;
ASSERT(client == XFS_TRANSACTION || client == XFS_LOG);
ASSERT((flags & XFS_LOG_NOSLEEP) == 0);
mp->m_log = xlog_alloc_log(mp, log_target, blk_offset, num_bblks);
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug) {
- cmn_err(CE_NOTE, "log dev: %s", XFS_BUFTARG_NAME(log_target));
- return 0;
- }
-#endif
/*
* skip log recovery on a norecovery mount. pretend it all
* just worked.
if (readonly)
vfsp->vfs_flag &= ~VFS_RDONLY;
- error = xlog_recover(mp->m_log, readonly);
+ error = xlog_recover(mp->m_log);
if (readonly)
vfsp->vfs_flag |= VFS_RDONLY;
if (error) {
cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error);
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
return error;
}
}
error = xfs_log_unmount_write(mp);
xfs_log_unmount_dealloc(mp);
- return (error);
+ return error;
}
/*
__uint32_t pad2; /* may as well make it 64 bits */
} magic = { XLOG_UNMOUNT_TYPE, 0, 0 };
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return 0;
-#endif
-
/*
* Don't write out unmount record on read-only mounts.
* Or, if we are doing a forced umount (typically because of IO errors).
*
* Go through the motions of sync'ing and releasing
* the iclog, even though no I/O will actually happen,
- * we need to wait for other log I/O's that may already
+ * we need to wait for other log I/Os that may already
* be in progress. Do this as a separate section of
* code so we'll know if we ever get stuck here that
* we're in this odd situation of trying to unmount
void
xfs_log_unmount_dealloc(xfs_mount_t *mp)
{
- xlog_unalloc_log(mp->m_log);
+ xlog_dealloc_log(mp->m_log);
}
/*
int error;
xlog_t *log = mp->m_log;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ) {
- *start_lsn = 0;
- return 0;
- }
-#endif
if (XLOG_FORCED_SHUTDOWN(log))
return XFS_ERROR(EIO);
if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
}
- return (error);
+ return error;
} /* xfs_log_write */
int need_bytes, free_bytes, cycle, bytes;
SPLDECL(s);
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- if (!xlog_debug && xlog_target == log->l_targ)
- return;
-#endif
- /* XXXsup tmp */
if (XLOG_FORCED_SHUTDOWN(log))
return;
ASSERT(!XFS_FORCED_SHUTDOWN(mp));
needed = 1;
}
LOG_UNLOCK(log, s);
- return(needed);
+ return needed;
}
/******************************************************************************
XFS_BUF_ERROR(bp, EIO);
XFS_BUF_STALE(bp);
xfs_biodone(bp);
- return (XFS_ERROR(EIO));
+ return XFS_ERROR(EIO);
}
int size;
int xhdrs;
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- /*
- * When logbufs == 0, someone has disabled the log from the FSTAB
- * file. This is not a documented feature. We need to set xlog_debug
- * to zero (this deactivates the log) and set xlog_target to the
- * appropriate device. Only one filesystem may be affected as such
- * since this is just a performance hack to test what we might be able
- * to get if the log were not present.
- */
- if (mp->m_logbufs == 0) {
- xlog_debug = 0;
- xlog_target = log->l_targ;
- log->l_iclog_bufs = XLOG_MIN_ICLOGS;
- } else
-#endif
- {
- /*
- * This is the normal path. If m_logbufs == -1, then the
- * admin has chosen to use the system defaults for logbuffers.
- */
- if (mp->m_logbufs == -1) {
- if (xfs_physmem <= btoc(128*1024*1024)) {
- log->l_iclog_bufs = XLOG_MIN_ICLOGS;
- } else if (xfs_physmem <= btoc(400*1024*1024)) {
- log->l_iclog_bufs = XLOG_MED_ICLOGS;
- } else {
- /* 256K with 32K bufs */
- log->l_iclog_bufs = XLOG_MAX_ICLOGS;
- }
- } else
- log->l_iclog_bufs = mp->m_logbufs;
-
-#if defined(DEBUG) || defined(XLOG_NOLOG)
- /* We are reactivating a filesystem after it was inactive */
- if (log->l_targ == xlog_target) {
- xlog_target = NULL;
- xlog_debug = 1;
+ if (mp->m_logbufs <= 0) {
+ if (xfs_physmem <= btoc(128*1024*1024)) {
+ log->l_iclog_bufs = XLOG_MIN_ICLOGS;
+ } else if (xfs_physmem <= btoc(400*1024*1024)) {
+ log->l_iclog_bufs = XLOG_MED_ICLOGS;
+ } else { /* 256K with 32K bufs */
+ log->l_iclog_bufs = XLOG_MAX_ICLOGS;
}
-#endif
+ } else {
+ log->l_iclog_bufs = mp->m_logbufs;
}
/*
* Buffer size passed in from mount system call.
*/
- if (mp->m_logbsize != -1) {
+ if (mp->m_logbsize > 0) {
size = log->l_iclog_size = mp->m_logbsize;
log->l_iclog_size_log = 0;
while (size != 1) {
log->l_iclog_hsize = BBSIZE;
log->l_iclog_heads = 1;
}
- return;
+ goto done;
}
/*
if (mp->m_sb.sb_blocksize >= 16*1024) {
log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
- if (mp->m_logbufs == -1) {
+ if (mp->m_logbufs <= 0) {
switch (mp->m_sb.sb_blocksize) {
case 16*1024: /* 16 KB */
log->l_iclog_bufs = 3;
}
}
}
+
+done: /* are we being asked to make the sizes selected above visible? */
+ if (mp->m_logbufs == 0)
+ mp->m_logbufs = log->l_iclog_bufs;
+ if (mp->m_logbsize == 0)
+ mp->m_logbsize = log->l_iclog_size;
} /* xlog_get_iclog_buffer_size */
iclog, XLOG_COMMIT_TRANS))) {
xfs_force_shutdown(mp, XFS_LOG_IO_ERROR);
}
- return (error);
+ return error;
} /* xlog_commit_record */
/* move grant heads by roundoff in sync */
s = GRANT_LOCK(log);
- XLOG_GRANT_ADD_SPACE(log, roundoff, 'w');
- XLOG_GRANT_ADD_SPACE(log, roundoff, 'r');
+ xlog_grant_add_space(log, roundoff);
GRANT_UNLOCK(log, s);
/* put cycle number in every block */
XFS_BUF_BUSY(bp);
XFS_BUF_ASYNC(bp);
/*
- * Do a disk write cache flush for the log block.
- * This is a bit of a sledgehammer, it would be better
- * to use a tag barrier here that just prevents reordering.
+ * Do an ordered write for the log block.
+ *
* It may not be needed to flush the first split block in the log wrap
* case, but do it anyways to be safe -AK
*/
- if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH))
- XFS_BUF_FLUSH(bp);
+ if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
+ XFS_BUF_ORDERED(bp);
ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
if ((error = XFS_bwrite(bp))) {
xfs_ioerror_alert("xlog_sync", log->l_mp, bp,
XFS_BUF_ADDR(bp));
- return (error);
+ return error;
}
if (split) {
bp = iclog->ic_log->l_xbuf;
XFS_BUF_SET_FSPRIVATE(bp, iclog);
XFS_BUF_BUSY(bp);
XFS_BUF_ASYNC(bp);
- if (!(log->l_mp->m_flags & XFS_MOUNT_NOLOGFLUSH))
- XFS_BUF_FLUSH(bp);
+ if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
+ XFS_BUF_ORDERED(bp);
dptr = XFS_BUF_PTR(bp);
/*
* Bump the cycle numbers at the start of each block
ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
- /* account for internal log which does't start at block #0 */
+ /* account for internal log which doesn't start at block #0 */
XFS_BUF_SET_ADDR(bp, XFS_BUF_ADDR(bp) + log->l_logBBstart);
XFS_BUF_WRITE(bp);
if ((error = XFS_bwrite(bp))) {
xfs_ioerror_alert("xlog_sync (split)", log->l_mp,
bp, XFS_BUF_ADDR(bp));
- return (error);
+ return error;
}
}
- return (0);
+ return 0;
} /* xlog_sync */
/*
- * Unallocate a log structure
+ * Deallocate a log structure
*/
void
-xlog_unalloc_log(xlog_t *log)
+xlog_dealloc_log(xlog_t *log)
{
xlog_in_core_t *iclog, *next_iclog;
xlog_ticket_t *tic, *next_tic;
if ((log->l_ticket_cnt != log->l_ticket_tcnt) &&
!XLOG_FORCED_SHUTDOWN(log)) {
xfs_fs_cmn_err(CE_WARN, log->l_mp,
- "xlog_unalloc_log: (cnt: %d, total: %d)",
+ "xlog_dealloc_log: (cnt: %d, total: %d)",
log->l_ticket_cnt, log->l_ticket_tcnt);
/* ASSERT(log->l_ticket_cnt == log->l_ticket_tcnt); */
#endif
log->l_mp->m_log = NULL;
kmem_free(log, sizeof(xlog_t));
-} /* xlog_unalloc_log */
+} /* xlog_dealloc_log */
/*
* Update counters atomically now that memcpy is done.
* print out info relating to regions written which consume
* the reservation
*/
-#if defined(XFS_LOG_RES_DEBUG)
STATIC void
xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket)
{
ticket->t_res_arr_sum, ticket->t_res_o_flow,
ticket->t_res_num_ophdrs, ophdr_spc,
ticket->t_res_arr_sum +
- ticket->t_res_o_flow + ophdr_spc,
+ ticket->t_res_o_flow + ophdr_spc,
ticket->t_res_num);
for (i = 0; i < ticket->t_res_num; i++) {
- uint r_type = ticket->t_res_arr[i].r_type;
+ uint r_type = ticket->t_res_arr[i].r_type;
cmn_err(CE_WARN,
"region[%u]: %s - %u bytes\n",
i,
ticket->t_res_arr[i].r_len);
}
}
-#else
-#define xlog_print_tic_res(mp, ticket)
-#endif
/*
* Write some region out to in-core log
for (index = 0; index < nentries; ) {
if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket,
&contwr, &log_offset)))
- return (error);
+ return error;
ASSERT(log_offset <= iclog->ic_size - 1);
ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset);
xlog_state_finish_copy(log, iclog, record_cnt, data_cnt);
record_cnt = data_cnt = 0;
if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
break; /* don't increment index */
} else { /* copied entire region */
index++;
ASSERT(flags & XLOG_COMMIT_TRANS);
*commit_iclog = iclog;
} else if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
if (index == nentries)
return 0; /* we are done */
else
*commit_iclog = iclog;
return 0;
}
- return (xlog_state_release_iclog(log, iclog));
+ return xlog_state_release_iclog(log, iclog);
} /* xlog_write */
}
lsn_log = lsn_log->ic_next;
} while (lsn_log != log->l_iclog);
- return(lowest_lsn);
+ return lowest_lsn;
}
if (iclog->ic_refcnt == 1) {
LOG_UNLOCK(log, s);
if ((error = xlog_state_release_iclog(log, iclog)))
- return (error);
+ return error;
} else {
iclog->ic_refcnt--;
LOG_UNLOCK(log, s);
/* something is already sleeping; insert new transaction at end */
if (log->l_reserve_headq) {
- XLOG_INS_TICKETQ(log->l_reserve_headq, tic);
+ xlog_ins_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: sleep 1");
/*
log->l_grant_reserve_bytes);
if (free_bytes < need_bytes) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_reserve_headq, tic);
+ xlog_ins_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_grant_log_space: sleep 2");
XFS_STATS_INC(xs_sleep_logspace);
s = GRANT_LOCK(log);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
/* we've got enough space */
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w');
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'r');
+ xlog_grant_add_space(log, need_bytes);
#ifdef DEBUG
tail_lsn = log->l_tail_lsn;
/*
error_return:
if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic, "xlog_grant_log_space: err_ret");
/*
* If we are failing, make sure the ticket doesn't have any
XLOG_TIC_RESET_RES(tic);
if (tic->t_cnt > 0)
- return (0);
+ return 0;
#ifdef DEBUG
if (log->l_flags & XLOG_ACTIVE_RECOVERY)
if (ntic != log->l_write_headq) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_write_headq, tic);
+ xlog_ins_ticketq(&log->l_write_headq, tic);
xlog_trace_loggrant(log, tic,
"xlog_regrant_write_log_space: sleep 1");
log->l_grant_write_bytes);
if (free_bytes < need_bytes) {
if ((tic->t_flags & XLOG_TIC_IN_Q) == 0)
- XLOG_INS_TICKETQ(log->l_write_headq, tic);
+ xlog_ins_ticketq(&log->l_write_headq, tic);
XFS_STATS_INC(xs_sleep_logspace);
sv_wait(&tic->t_sema, PINOD|PLTWAIT, &log->l_grant_lock, s);
s = GRANT_LOCK(log);
goto redo;
} else if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_write_headq, tic);
+ xlog_del_ticketq(&log->l_write_headq, tic);
- XLOG_GRANT_ADD_SPACE(log, need_bytes, 'w'); /* we've got enough space */
+ /* we've got enough space */
+ xlog_grant_add_space_write(log, need_bytes);
#ifdef DEBUG
tail_lsn = log->l_tail_lsn;
if (CYCLE_LSN(tail_lsn) != log->l_grant_write_cycle) {
xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: exit");
xlog_verify_grant_head(log, 1);
GRANT_UNLOCK(log, s);
- return (0);
+ return 0;
error_return:
if (tic->t_flags & XLOG_TIC_IN_Q)
- XLOG_DEL_TICKETQ(log->l_reserve_headq, tic);
+ xlog_del_ticketq(&log->l_reserve_headq, tic);
xlog_trace_loggrant(log, tic, "xlog_regrant_write_log_space: err_ret");
/*
* If we are failing, make sure the ticket doesn't have any
ticket->t_cnt--;
s = GRANT_LOCK(log);
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r');
+ xlog_grant_sub_space(log, ticket->t_curr_res);
ticket->t_curr_res = ticket->t_unit_res;
XLOG_TIC_RESET_RES(ticket);
xlog_trace_loggrant(log, ticket,
return;
}
- XLOG_GRANT_ADD_SPACE(log, ticket->t_unit_res, 'r');
+ xlog_grant_add_space_reserve(log, ticket->t_unit_res);
xlog_trace_loggrant(log, ticket,
"xlog_regrant_reserve_log_space: exit");
xlog_verify_grant_head(log, 0);
s = GRANT_LOCK(log);
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: enter");
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_curr_res, 'r');
+ xlog_grant_sub_space(log, ticket->t_curr_res);
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: sub current");
*/
if (ticket->t_cnt > 0) {
ASSERT(ticket->t_flags & XLOG_TIC_PERM_RESERV);
- XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'w');
- XLOG_GRANT_SUB_SPACE(log, ticket->t_unit_res*ticket->t_cnt,'r');
+ xlog_grant_sub_space(log, ticket->t_unit_res*ticket->t_cnt);
}
xlog_trace_loggrant(log, ticket, "xlog_ungrant_log_space: exit");
/*
* We let the log lock go, so it's possible that we hit a log I/O
- * error or someother SHUTDOWN condition that marks the iclog
+ * error or some other SHUTDOWN condition that marks the iclog
* as XLOG_STATE_IOERROR before the bwrite. However, we know that
* this iclog has consistent data, so we ignore IOERROR
* flags after this point.
if (sync) {
return xlog_sync(log, iclog);
}
- return (0);
+ return 0;
} /* xlog_state_release_iclog */
* not in the active nor dirty state.
*/
STATIC int
-xlog_state_sync_all(xlog_t *log, uint flags)
+xlog_state_sync_all(xlog_t *log, uint flags, int *log_flushed)
{
xlog_in_core_t *iclog;
xfs_lsn_t lsn;
if (xlog_state_release_iclog(log, iclog))
return XFS_ERROR(EIO);
+ *log_flushed = 1;
s = LOG_LOCK(log);
if (INT_GET(iclog->ic_header.h_lsn, ARCH_CONVERT) == lsn &&
iclog->ic_state != XLOG_STATE_DIRTY)
*/
if (iclog->ic_state & XLOG_STATE_IOERROR)
return XFS_ERROR(EIO);
+ *log_flushed = 1;
} else {
int
xlog_state_sync(xlog_t *log,
xfs_lsn_t lsn,
- uint flags)
+ uint flags,
+ int *log_flushed)
{
xlog_in_core_t *iclog;
int already_slept = 0;
XFS_STATS_INC(xs_log_force_sleep);
sv_wait(&iclog->ic_prev->ic_writesema, PSWP,
&log->l_icloglock, s);
+ *log_flushed = 1;
already_slept = 1;
goto try_again;
} else {
LOG_UNLOCK(log, s);
if (xlog_state_release_iclog(log, iclog))
return XFS_ERROR(EIO);
+ *log_flushed = 1;
s = LOG_LOCK(log);
}
}
*/
if (iclog->ic_state & XLOG_STATE_IOERROR)
return XFS_ERROR(EIO);
+ *log_flushed = 1;
} else { /* just return */
LOG_UNLOCK(log, s);
}
} while (iclog != log->l_iclog);
LOG_UNLOCK(log, s);
- return (0);
+ return 0;
} /* xlog_state_sync */
*
******************************************************************************
*/
-#if defined(DEBUG) && !defined(XLOG_NOLOG)
+#if defined(DEBUG)
/*
* Make sure that the destination ptr is within the valid data region of
* one of the iclogs. This uses backup pointers stored in a different
}
}
if (clientid != XFS_TRANSACTION && clientid != XFS_LOG)
- cmn_err(CE_WARN, "xlog_verify_iclog: invalid clientid %d op 0x%p offset 0x%x", clientid, ophead, field_offset);
+ cmn_err(CE_WARN, "xlog_verify_iclog: "
+ "invalid clientid %d op 0x%p offset 0x%lx",
+ clientid, ophead, (unsigned long)field_offset);
/* check length */
field_offset = (__psint_t)
ptr += sizeof(xlog_op_header_t) + op_len;
}
} /* xlog_verify_iclog */
-#endif /* DEBUG && !XLOG_NOLOG */
+#endif
/*
* Mark all iclogs IOERROR. LOG_LOCK is held by the caller.
ic->ic_state = XLOG_STATE_IOERROR;
ic = ic->ic_next;
} while (ic != iclog);
- return (0);
+ return 0;
}
/*
* Return non-zero, if state transition has already happened.
*/
- return (1);
+ return 1;
}
/*
xlog_ticket_t *tic;
xlog_t *log;
int retval;
+ int dummy;
SPLDECL(s);
SPLDECL(s2);
log->l_flags & XLOG_ACTIVE_RECOVERY) {
mp->m_flags |= XFS_MOUNT_FS_SHUTDOWN;
XFS_BUF_DONE(mp->m_sb_bp);
- return (0);
+ return 0;
}
/*
*/
if (logerror && log->l_iclog->ic_state & XLOG_STATE_IOERROR) {
ASSERT(XLOG_FORCED_SHUTDOWN(log));
- return (1);
+ return 1;
}
retval = 0;
/*
* Force the incore logs to disk before shutting the
* log down completely.
*/
- xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC);
+ xlog_state_sync_all(log, XFS_LOG_FORCE|XFS_LOG_SYNC, &dummy);
s2 = LOG_LOCK(log);
retval = xlog_state_ioerror(log);
LOG_UNLOCK(log, s2);
}
#endif
/* return non-zero if log IOERROR transition had already happened */
- return (retval);
+ return retval;
}
STATIC int
* any language.
*/
if (iclog->ic_header.h_num_logops)
- return(0);
+ return 0;
iclog = iclog->ic_next;
} while (iclog != log->l_iclog);
- return(1);
+ return 1;
}