{
struct xlog log;
int dirty;
+ xfs_daddr_t logstart;
+ int logblocks;
+ int logversion;
+ int cycle = XLOG_INIT_CYCLE;
if (show_progress)
print_progress("Copying log");
/* clear out a clean log */
if (show_progress)
print_progress("Zeroing clean log");
- memset(iocur_top->data, 0,
- mp->m_sb.sb_logblocks * mp->m_sb.sb_blocksize);
+
+ logstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
+ logblocks = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
+ logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1;
+ if (xfs_sb_version_hascrc(&mp->m_sb))
+ cycle = log.l_curr_cycle + 1;
+
+ libxfs_log_clear(NULL, iocur_top->data, logstart, logblocks,
+ &mp->m_sb.sb_uuid, logversion,
+ mp->m_sb.sb_logsunit, XLOG_FMT, cycle);
break;
case 1:
/* keep the dirty log */
dbprintf(_("Clearing log and setting UUID\n"));
- error = libxfs_log_clear(mp->m_logdev_targp,
+ error = libxfs_log_clear(mp->m_logdev_targp, NULL,
XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
(xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
uuidp,
* Helpers to clear the log to a particular log cycle.
*/
#define XLOG_INIT_CYCLE 1
-extern int libxfs_log_clear(struct xfs_buftarg *, xfs_daddr_t, uint,
- uuid_t *, int, int, int, int);
+extern int libxfs_log_clear(struct xfs_buftarg *, char *, xfs_daddr_t,
+ uint, uuid_t *, int, int, int, int);
extern int libxfs_log_header(char *, uuid_t *, int, int, int, xfs_lsn_t,
xfs_lsn_t, libxfs_get_block_t *, void *);
memcpy((char *)p + sizeof(xlog_op_header_t), &magic, sizeof(magic));
}
-static char *next(char *ptr, int offset, void *private)
+static char *next(
+ char *ptr,
+ int offset,
+ void *private)
{
- xfs_buf_t *buf = (xfs_buf_t *)private;
+ struct xfs_buf *buf = (struct xfs_buf *)private;
- if (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset)
+ if (buf &&
+ (XFS_BUF_COUNT(buf) < (int)(ptr - XFS_BUF_PTR(buf)) + offset))
abort();
+
return ptr + offset;
}
+/*
+ * Format the log. The caller provides either a buftarg which is used to access
+ * the log via buffers or a direct pointer to a buffer that encapsulates the
+ * entire log.
+ */
int
libxfs_log_clear(
struct xfs_buftarg *btp,
+ char *dptr,
xfs_daddr_t start,
- uint length,
+ uint length, /* basic blocks */
uuid_t *fs_uuid,
int version,
- int sunit,
+ int sunit, /* bytes */
int fmt,
int cycle)
{
- xfs_buf_t *bp;
+ struct xfs_buf *bp = NULL;
int len;
xfs_lsn_t lsn;
xfs_lsn_t tail_lsn;
xfs_daddr_t blk;
xfs_daddr_t end_blk;
+ char *ptr;
- if (!btp->dev || !fs_uuid)
+ if (((btp && dptr) || (!btp && !dptr)) ||
+ (btp && !btp->dev) || !fs_uuid)
return -EINVAL;
/* first zero the log */
- libxfs_device_zero(btp, start, length);
+ if (btp)
+ libxfs_device_zero(btp, start, length);
+ else
+ memset(dptr, 0, BBTOB(length));
/*
* Initialize the log record length and LSNs. XLOG_INIT_CYCLE is a
tail_lsn = xlog_assign_lsn(cycle - 1, length - len);
/* write out the first log record */
- bp = libxfs_getbufr(btp, start, len);
- libxfs_log_header(XFS_BUF_PTR(bp), fs_uuid, version, sunit, fmt,
- lsn, tail_lsn, next, bp);
- bp->b_flags |= LIBXFS_B_DIRTY;
- libxfs_putbufr(bp);
+ ptr = dptr;
+ if (btp) {
+ bp = libxfs_getbufr(btp, start, len);
+ ptr = XFS_BUF_PTR(bp);
+ }
+ libxfs_log_header(ptr, fs_uuid, version, sunit, fmt, lsn, tail_lsn,
+ next, bp);
+ if (bp) {
+ bp->b_flags |= LIBXFS_B_DIRTY;
+ libxfs_putbufr(bp);
+ }
/*
* There's nothing else to do if this is a log reset. The kernel detects
*/
cycle--;
blk = start + len;
+ if (dptr)
+ dptr += BBTOB(len);
end_blk = start + length;
len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
lsn = xlog_assign_lsn(cycle, blk - start);
tail_lsn = xlog_assign_lsn(cycle, blk - start - len);
- bp = libxfs_getbufr(btp, blk, len);
+ ptr = dptr;
+ if (btp) {
+ bp = libxfs_getbufr(btp, blk, len);
+ ptr = XFS_BUF_PTR(bp);
+ }
/*
* Note: pass the full buffer length as the sunit to initialize
* the entire buffer.
*/
- libxfs_log_header(XFS_BUF_PTR(bp), fs_uuid, version, BBTOB(len),
- fmt, lsn, tail_lsn, next, bp);
- bp->b_flags |= LIBXFS_B_DIRTY;
- libxfs_putbufr(bp);
+ libxfs_log_header(ptr, fs_uuid, version, BBTOB(len), fmt, lsn,
+ tail_lsn, next, bp);
+ if (bp) {
+ bp->b_flags |= LIBXFS_B_DIRTY;
+ libxfs_putbufr(bp);
+ }
- len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
blk += len;
+ if (dptr)
+ dptr += BBTOB(len);
+ len = min(end_blk - blk, BTOBB(BDSTRAT_SIZE));
}
return 0;
/*
* Zero the log....
*/
- libxfs_log_clear(mp->m_logdev_targp,
+ libxfs_log_clear(mp->m_logdev_targp, NULL,
XFS_FSB_TO_DADDR(mp, logstart),
(xfs_extlen_t)XFS_FSB_TO_BB(mp, logblocks),
&sbp->sb_uuid, logversion, lsunit, XLOG_FMT, XLOG_INIT_CYCLE);
* filesystems.
*/
if (!no_modify && zap_log) {
- libxfs_log_clear(log->l_dev,
+ libxfs_log_clear(log->l_dev, NULL,
XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart),
(xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks),
&mp->m_sb.sb_uuid,
}
do_warn(_("Format log to cycle %d.\n"), new_cycle);
- libxfs_log_clear(log->l_dev, logstart, logblocks, &mp->m_sb.sb_uuid,
- logversion, mp->m_sb.sb_logsunit, XLOG_FMT, new_cycle);
+ libxfs_log_clear(log->l_dev, NULL, logstart, logblocks,
+ &mp->m_sb.sb_uuid, logversion, mp->m_sb.sb_logsunit,
+ XLOG_FMT, new_cycle);
}
int