blob: 3374c29b2aa7cd10e67ff3f9bca124a78fbea918 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2015 Red Hat, Inc.
* All Rights Reserved.
*/
#include "libxfs.h"
#include "command.h"
#include "init.h"
#include "output.h"
#include "libxlog.h"
#include "logformat.h"
#define MAX_LSUNIT 256 * 1024 /* max log buf. size */
static int
logformat_f(int argc, char **argv)
{
xfs_daddr_t head_blk;
xfs_daddr_t tail_blk;
int logversion;
int lsunit = -1;
int cycle = -1;
int error;
int c;
logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1;
while ((c = getopt(argc, argv, "c:s:")) != EOF) {
switch (c) {
case 'c':
cycle = strtol(optarg, NULL, 0);
if (cycle == 0) {
dbprintf("invalid cycle\n");
return -1;
}
break;
case 's':
lsunit = strtol(optarg, NULL, 0);
/*
* The log stripe unit must be block aligned and no
* larger than 256k.
*/
if (lsunit > 1 &&
(lsunit % mp->m_sb.sb_blocksize ||
(logversion == 2 && lsunit > MAX_LSUNIT))) {
dbprintf("invalid log stripe unit\n");
return -1;
}
break;
default:
dbprintf("invalid option\n");
return -1;
}
}
/*
* Check whether the log is dirty. This also determines the current log
* cycle if we have to use it by default below.
*/
memset(mp->m_log, 0, sizeof(struct xlog));
mp->m_log->l_mp = mp;
mp->m_log->l_dev = mp->m_logdev_targp;
mp->m_log->l_logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks);
mp->m_log->l_logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart);
mp->m_log->l_sectBBsize = BBSIZE;
if (xfs_sb_version_hassector(&mp->m_sb))
mp->m_log->l_sectBBsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT);
mp->m_log->l_sectBBsize = BTOBB(mp->m_log->l_sectBBsize);
error = xlog_find_tail(mp->m_log, &head_blk, &tail_blk);
if (error) {
dbprintf("could not find log head/tail\n");
return -1;
}
if (head_blk != tail_blk) {
dbprintf(_(
"The log is dirty. Please mount to replay the log.\n"));
return -1;
}
/*
* Use the current cycle and/or log stripe unit if either is not
* provided by the user.
*/
if (cycle < 0)
cycle = mp->m_log->l_curr_cycle;
if (lsunit < 0)
lsunit = mp->m_sb.sb_logsunit;
dbprintf("Formatting the log to cycle %d, stripe unit %d bytes.\n",
cycle, lsunit);
error = -libxfs_log_clear(mp->m_logdev_targp, NULL,
mp->m_log->l_logBBstart,
mp->m_log->l_logBBsize,
&mp->m_sb.sb_uuid, logversion, lsunit,
XLOG_FMT, cycle, false);
if (error) {
dbprintf("error formatting log - %d\n", error);
return error;
}
return 0;
}
static void
logformat_help(void)
{
dbprintf(_(
"\n"
" The 'logformat' command reformats (clears) the log to the specified log\n"
" cycle and log stripe unit. If the log cycle is not specified, the log is\n"
" reformatted to the current cycle. If the log stripe unit is not specified,\n"
" the stripe unit from the filesystem superblock is used.\n"
"\n"
));
}
static const struct cmdinfo logformat_cmd = {
.name = "logformat",
.altname = NULL,
.cfunc = logformat_f,
.argmin = 0,
.argmax = 4,
.canpush = 0,
.args = N_("[-c cycle] [-s sunit]"),
.oneline = N_("reformat the log"),
.help = logformat_help,
};
void
logformat_init(void)
{
if (!expert_mode)
return;
add_command(&logformat_cmd);
}
static void
print_logres(
int i,
struct xfs_trans_res *res)
{
dbprintf(_("type %d logres %u logcount %d flags 0x%x\n"),
i, res->tr_logres, res->tr_logcount, res->tr_logflags);
}
static int
logres_f(
int argc,
char **argv)
{
struct xfs_trans_res resv;
struct xfs_trans_res *res;
struct xfs_trans_res *end_res;
int i;
res = (struct xfs_trans_res *)M_RES(mp);
end_res = (struct xfs_trans_res *)(M_RES(mp) + 1);
for (i = 0; res < end_res; i++, res++)
print_logres(i, res);
libxfs_log_get_max_trans_res(mp, &resv);
print_logres(-1, &resv);
return 0;
}
static void
logres_help(void)
{
dbprintf(_(
"\n"
" The 'logres' command prints information about all log reservation types.\n"
" This includes the reservation space, the intended transaction roll count,\n"
" and the reservation flags, if any.\n"
"\n"
));
}
static const struct cmdinfo logres_cmd = {
.name = "logres",
.altname = NULL,
.cfunc = logres_f,
.argmin = 0,
.argmax = 0,
.canpush = 0,
.args = NULL,
.oneline = N_("dump log reservations"),
.help = logres_help,
};
void
logres_init(void)
{
add_command(&logres_cmd);
}