reg[0].i_len = sizeof(magic);
XLOG_VEC_SET_TYPE(®[0], XLOG_REG_TYPE_UNMOUNT);
- error = xfs_log_reserve(mp, 600, 1, &tic, XFS_LOG, 0, 0);
+ error = xfs_log_reserve(mp, 600, 1, &tic,
+ XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE);
if (!error) {
/* remove inited flag */
((xlog_ticket_t *)tic)->t_flags = 0;
} else {
LOG_UNLOCK(log, s);
}
- if (tic)
+ if (tic) {
+ xlog_trace_loggrant(log, tic, "unmount rec");
+ xlog_ungrant_log_space(log, tic);
xlog_state_put_ticket(log, tic);
+ }
} else {
/*
* We're already in forced_shutdown mode, couldn't
SPLDECL(s);
int needed = 0, gen;
xlog_t *log = mp->m_log;
- bhv_vfs_t *vfsp = XFS_MTOVFS(mp);
- if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) ||
- (vfsp->vfs_flag & VFS_RDONLY))
+ if (!xfs_fs_writable(mp))
return 0;
s = LOG_LOCK(log);
*/
l = iclog->ic_log;
+ /*
+ * If the ordered flag has been removed by a lower
+ * layer, it means the underlyin device no longer supports
+ * barrier I/O. Warn loudly and turn off barriers.
+ */
+ if ((l->l_mp->m_flags & XFS_MOUNT_BARRIER) && !XFS_BUF_ORDERED(bp)) {
+ l->l_mp->m_flags &= ~XFS_MOUNT_BARRIER;
+ xfs_fs_cmn_err(CE_WARN, l->l_mp,
+ "xlog_iodone: Barriers are no longer supported"
+ " by device. Disabling barriers\n");
+ xfs_buftrace("XLOG_IODONE BARRIERS OFF", bp);
+ }
+
/*
* Race to shutdown the filesystem if we see an error.
*/
} else if (iclog->ic_state & XLOG_STATE_IOERROR) {
aborted = XFS_LI_ABORTED;
}
+
+ /* log I/O is always issued ASYNC */
+ ASSERT(XFS_BUF_ISASYNC(bp));
xlog_state_done_syncing(iclog, aborted);
- if (!(XFS_BUF_ISASYNC(bp))) {
- /*
- * Corresponding psema() will be done in bwrite(). If we don't
- * vsema() here, panic.
- */
- XFS_BUF_V_IODONESEMA(bp);
- }
+ /*
+ * do not reference the buffer (bp) here as we could race
+ * with it being freed after writing the unmount record to the
+ * log.
+ */
+
} /* xlog_iodone */
/*
/*
* Return size of each in-core log record buffer.
*
- * Low memory machines only get 2 16KB buffers. We don't want to waste
- * memory here. However, all other machines get at least 2 32KB buffers.
- * The number is hard coded because we don't care about the minimum
- * memory size, just 32MB systems.
+ * All machines get 8 x 32KB buffers by default, unless tuned otherwise.
*
* If the filesystem blocksize is too large, we may need to choose a
* larger size since the directory code currently logs entire blocks.
int size;
int xhdrs;
- 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;
- }
- } else {
+ if (mp->m_logbufs <= 0)
+ log->l_iclog_bufs = XLOG_MAX_ICLOGS;
+ else
log->l_iclog_bufs = mp->m_logbufs;
- }
/*
* Buffer size passed in from mount system call.
goto done;
}
- /*
- * Special case machines that have less than 32MB of memory.
- * All machines with more memory use 32KB buffers.
- */
- if (xfs_physmem <= btoc(32*1024*1024)) {
- /* Don't change; min configuration */
- log->l_iclog_size = XLOG_RECORD_BSIZE; /* 16k */
- log->l_iclog_size_log = XLOG_RECORD_BSHIFT;
- } else {
- log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; /* 32k */
- log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
- }
+ /* All machines use 32KB buffers by default. */
+ log->l_iclog_size = XLOG_BIG_RECORD_BSIZE;
+ log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT;
/* the default log size is 16k or 32k which is one header sector */
log->l_iclog_hsize = BBSIZE;
*iclogp = (xlog_in_core_t *)
kmem_zalloc(sizeof(xlog_in_core_t), KM_SLEEP);
iclog = *iclogp;
- iclog->hic_data = (xlog_in_core_2_t *)
- kmem_zalloc(iclogsize, KM_SLEEP);
-
iclog->ic_prev = prev_iclog;
prev_iclog = iclog;
+
+ bp = xfs_buf_get_noaddr(log->l_iclog_size, mp->m_logdev_targp);
+ if (!XFS_BUF_CPSEMA(bp))
+ ASSERT(0);
+ XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
+ XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
+ XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
+ iclog->ic_bp = bp;
+ iclog->hic_data = bp->b_addr;
+
log->l_iclog_bak[i] = (xfs_caddr_t)&(iclog->ic_header);
head = &iclog->ic_header;
INT_SET(head->h_fmt, ARCH_CONVERT, XLOG_FMT);
memcpy(&head->h_fs_uuid, &mp->m_sb.sb_uuid, sizeof(uuid_t));
- bp = xfs_buf_get_empty(log->l_iclog_size, mp->m_logdev_targp);
- XFS_BUF_SET_IODONE_FUNC(bp, xlog_iodone);
- XFS_BUF_SET_BDSTRAT_FUNC(bp, xlog_bdstrat_cb);
- XFS_BUF_SET_FSPRIVATE2(bp, (unsigned long)1);
- iclog->ic_bp = bp;
iclog->ic_size = XFS_BUF_SIZE(bp) - log->l_iclog_hsize;
iclog->ic_state = XLOG_STATE_ACTIVE;
} else {
iclog->ic_bwritecnt = 1;
}
- XFS_BUF_SET_PTR(bp, (xfs_caddr_t) &(iclog->ic_header), count);
+ XFS_BUF_SET_COUNT(bp, count);
XFS_BUF_SET_FSPRIVATE(bp, iclog); /* save for later */
XFS_BUF_ZEROFLAGS(bp);
XFS_BUF_BUSY(bp);
}
#endif
next_iclog = iclog->ic_next;
- kmem_free(iclog->hic_data, log->l_iclog_size);
kmem_free(iclog, sizeof(xlog_in_core_t));
iclog = next_iclog;
}
}
cb = iclog->ic_callback;
- while (cb != 0) {
+ while (cb) {
iclog->ic_callback_tail = &(iclog->ic_callback);
iclog->ic_callback = NULL;
LOG_UNLOCK(log, s);
/* perform callbacks in the order given */
- for (; cb != 0; cb = cb_next) {
+ for (; cb; cb = cb_next) {
cb_next = cb->cb_next;
cb->cb_func(cb->cb_arg, aborted);
}
loopdidcallbacks++;
funcdidcallbacks++;
- ASSERT(iclog->ic_callback == 0);
+ ASSERT(iclog->ic_callback == NULL);
if (!(iclog->ic_state & XLOG_STATE_IOERROR))
iclog->ic_state = XLOG_STATE_DIRTY;
iclog = iclog->ic_next;
} while (first_iclog != iclog);
- if (repeats && (repeats % 10) == 0) {
+
+ if (repeats > 5000) {
+ flushcnt += repeats;
+ repeats = 0;
xfs_fs_cmn_err(CE_WARN, log->l_mp,
- "xlog_state_do_callback: looping %d", repeats);
+ "%s: possible infinite loop (%d iterations)",
+ __FUNCTION__, flushcnt);
}
} while (!ioerrors && loopdidcallbacks);
}
#endif
+ flushcnt = 0;
if (log->l_iclog->ic_state & (XLOG_STATE_ACTIVE|XLOG_STATE_IOERROR)) {
flushcnt = log->l_flushcnt;
log->l_flushcnt = 0;
#else
/* When we debug, it is easier if tickets are cycled */
ticket->t_next = NULL;
- if (log->l_tail != 0) {
+ if (log->l_tail) {
log->l_tail->t_next = ticket;
} else {
- ASSERT(log->l_freelist == 0);
+ ASSERT(log->l_freelist == NULL);
log->l_freelist = ticket;
}
log->l_tail = ticket;
s = LOG_LOCK(log);
icptr = log->l_iclog;
for (i=0; i < log->l_iclog_bufs; i++) {
- if (icptr == 0)
+ if (icptr == NULL)
xlog_panic("xlog_verify_iclog: invalid ptr");
icptr = icptr->ic_next;
}