]>
Commit | Line | Data |
---|---|---|
c7a8ea47 BF |
1 | /* |
2 | * Copyright (c) 2015 Red Hat, Inc. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or | |
6 | * modify it under the terms of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it would be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | * GNU General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License | |
15 | * along with this program; if not, write the Free Software Foundation, | |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
17 | */ | |
18 | ||
19 | #include "libxfs.h" | |
20 | #include "command.h" | |
21 | #include "init.h" | |
22 | #include "output.h" | |
23 | #include "libxlog.h" | |
24 | ||
25 | #define MAX_LSUNIT 256 * 1024 /* max log buf. size */ | |
26 | ||
27 | static int | |
28 | logformat_f(int argc, char **argv) | |
29 | { | |
30 | xfs_daddr_t head_blk; | |
31 | xfs_daddr_t tail_blk; | |
32 | int logversion; | |
33 | int lsunit = -1; | |
34 | int cycle = -1; | |
35 | int error; | |
36 | int c; | |
37 | ||
38 | logversion = xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1; | |
39 | ||
40 | while ((c = getopt(argc, argv, "c:s:")) != EOF) { | |
41 | switch (c) { | |
42 | case 'c': | |
43 | cycle = strtol(optarg, NULL, 0); | |
44 | if (cycle == 0) { | |
45 | dbprintf("invalid cycle\n"); | |
46 | return -1; | |
47 | } | |
48 | break; | |
49 | case 's': | |
50 | lsunit = strtol(optarg, NULL, 0); | |
51 | /* | |
52 | * The log stripe unit must be block aligned and no | |
53 | * larger than 256k. | |
54 | */ | |
55 | if (lsunit > 1 && | |
56 | (lsunit % mp->m_sb.sb_blocksize || | |
57 | (logversion == 2 && lsunit > MAX_LSUNIT))) { | |
58 | dbprintf("invalid log stripe unit\n"); | |
59 | return -1; | |
60 | } | |
61 | break; | |
62 | default: | |
63 | dbprintf("invalid option\n"); | |
64 | return -1; | |
65 | } | |
66 | } | |
67 | ||
68 | /* | |
69 | * Check whether the log is dirty. This also determines the current log | |
70 | * cycle if we have to use it by default below. | |
71 | */ | |
72 | memset(mp->m_log, 0, sizeof(struct xlog)); | |
73 | mp->m_log->l_mp = mp; | |
74 | mp->m_log->l_dev = mp->m_logdev_targp; | |
75 | mp->m_log->l_logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); | |
76 | mp->m_log->l_logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); | |
77 | mp->m_log->l_sectBBsize = BBSIZE; | |
78 | if (xfs_sb_version_hassector(&mp->m_sb)) | |
79 | mp->m_log->l_sectBBsize <<= (mp->m_sb.sb_logsectlog - BBSHIFT); | |
80 | mp->m_log->l_sectBBsize = BTOBB(mp->m_log->l_sectBBsize); | |
81 | ||
82 | error = xlog_find_tail(mp->m_log, &head_blk, &tail_blk); | |
83 | if (error) { | |
84 | dbprintf("could not find log head/tail\n"); | |
85 | return -1; | |
86 | } | |
87 | if (head_blk != tail_blk) { | |
88 | dbprintf(_( | |
89 | "The log is dirty. Please mount to replay the log.\n")); | |
90 | return -1; | |
91 | } | |
92 | ||
93 | /* | |
94 | * Use the current cycle and/or log stripe unit if either is not | |
95 | * provided by the user. | |
96 | */ | |
97 | if (cycle < 0) | |
98 | cycle = mp->m_log->l_curr_cycle; | |
99 | if (lsunit < 0) | |
100 | lsunit = mp->m_sb.sb_logsunit; | |
101 | ||
102 | dbprintf("Formatting the log to cycle %d, stripe unit %d bytes.\n", | |
103 | cycle, lsunit); | |
104 | error = libxfs_log_clear(mp->m_logdev_targp, NULL, | |
105 | mp->m_log->l_logBBstart, | |
106 | mp->m_log->l_logBBsize, | |
107 | &mp->m_sb.sb_uuid, logversion, lsunit, | |
108 | XLOG_FMT, cycle, false); | |
109 | if (error) { | |
110 | dbprintf("error formatting log - %d\n", error); | |
111 | return error; | |
112 | } | |
113 | ||
114 | return 0; | |
115 | } | |
116 | ||
117 | static void | |
118 | logformat_help(void) | |
119 | { | |
120 | dbprintf(_( | |
121 | "\n" | |
122 | " The 'logformat' command reformats (clears) the log to the specified log\n" | |
123 | " cycle and log stripe unit. If the log cycle is not specified, the log is\n" | |
124 | " reformatted to the current cycle. If the log stripe unit is not specified,\n" | |
125 | " the stripe unit from the filesystem superblock is used.\n" | |
126 | "\n" | |
127 | )); | |
128 | } | |
129 | ||
130 | static const struct cmdinfo logformat_cmd = { | |
131 | .name = "logformat", | |
132 | .altname = NULL, | |
133 | .cfunc = logformat_f, | |
134 | .argmin = 0, | |
135 | .argmax = 4, | |
136 | .canpush = 0, | |
137 | .args = N_("[-c cycle] [-s sunit]"), | |
138 | .oneline = N_("reformat the log"), | |
139 | .help = logformat_help, | |
140 | }; | |
141 | ||
142 | void | |
143 | logformat_init(void) | |
144 | { | |
145 | if (!expert_mode) | |
146 | return; | |
147 | ||
148 | add_command(&logformat_cmd); | |
149 | } |