File: logformat.c

package info (click to toggle)
xfsprogs 4.9.0+nmu1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 8,012 kB
  • ctags: 10,574
  • sloc: ansic: 110,850; sh: 3,804; makefile: 863; python: 126
file content (149 lines) | stat: -rw-r--r-- 3,808 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
/*
 * Copyright (c) 2015 Red Hat, Inc.
 * All Rights Reserved.
 *
 * 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.  See the
 * GNU General Public License for more details.
 *
 * 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 "libxfs.h"
#include "command.h"
#include "init.h"
#include "output.h"
#include "libxlog.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);
}