]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/xfs_repair.c
Allow swab.h to be used in -pedantic c++ build environments.
[thirdparty/xfsprogs-dev.git] / repair / xfs_repair.c
CommitLineData
2bd0ea18 1/*
9b27bdbb 2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. All Rights Reserved.
dfc130f3 3 *
2bd0ea18
NS
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
dfc130f3 7 *
2bd0ea18
NS
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
dfc130f3 11 *
2bd0ea18
NS
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
dfc130f3 18 *
2bd0ea18
NS
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
dfc130f3 22 *
2bd0ea18
NS
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
dfc130f3
RC
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
2bd0ea18
NS
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
31 */
32
1d7e80ee 33#include <xfs/libxlog.h>
2bd0ea18
NS
34#include "avl.h"
35#include "avl64.h"
36#include "globals.h"
37#include "versions.h"
38#include "agheader.h"
39#include "protos.h"
40#include "incore.h"
41#include "err_protos.h"
42
43#define rounddown(x, y) (((x)/(y))*(y))
44
45extern void phase1(xfs_mount_t *);
d321ceac 46extern void phase2(xfs_mount_t *);
2bd0ea18
NS
47extern void phase3(xfs_mount_t *);
48extern void phase4(xfs_mount_t *);
49extern void phase5(xfs_mount_t *);
50extern void phase6(xfs_mount_t *);
51extern void phase7(xfs_mount_t *);
52extern void incore_init(xfs_mount_t *);
53
54#define XR_MAX_SECT_SIZE (64 * 1024)
55
56/*
57 * option tables for getsubopt calls
58 */
59
60/*
61 * -o (user-supplied override options)
62 */
63
64char *o_opts[] = {
65#define ASSUME_XFS 0
66 "assume_xfs",
67#define PRE_65_BETA 1
68 "fs_is_pre_65_beta",
69 NULL
70};
71
72static void
73usage(void)
74{
507f4e33
NS
75 do_warn(
76_("Usage: %s [-nLvV] [-o subopt[=value]] [-l logdev] [-r rtdev] devname\n"),
2bd0ea18
NS
77 progname);
78 exit(1);
79}
80
2bd0ea18
NS
81char *
82err_string(int err_code)
83{
507f4e33
NS
84 static char *err_message[XR_BAD_ERR_CODE];
85 static int done;
86
87 if (!done) {
88 err_message[XR_OK] = _("no error");
89 err_message[XR_BAD_MAGIC] = _("bad magic number");
90 err_message[XR_BAD_BLOCKSIZE] = _("bad blocksize field");
91 err_message[XR_BAD_BLOCKLOG] = _("bad blocksize log field");
92 err_message[XR_BAD_VERSION] = _("bad version number");
93 err_message[XR_BAD_INPROGRESS] =
94 _("filesystem mkfs-in-progress bit set");
95 err_message[XR_BAD_FS_SIZE_DATA] =
96 _("inconsistent filesystem geometry information");
97 err_message[XR_BAD_INO_SIZE_DATA] =
98 _("bad inode size or inconsistent with number of inodes/block"),
99 err_message[XR_BAD_SECT_SIZE_DATA] = _("bad sector size");
100 err_message[XR_AGF_GEO_MISMATCH] =
101 _("AGF geometry info conflicts with filesystem geometry");
102 err_message[XR_AGI_GEO_MISMATCH] =
103 _("AGI geometry info conflicts with filesystem geometry");
104 err_message[XR_SB_GEO_MISMATCH] =
105 _("AG superblock geometry info conflicts with filesystem geometry");
106 err_message[XR_EOF] = _("attempted to perform I/O beyond EOF");
107 err_message[XR_BAD_RT_GEO_DATA] =
108 _("inconsistent filesystem geometry in realtime filesystem component");
109 err_message[XR_BAD_INO_MAX_PCT] =
110 _("maximum indicated percentage of inodes > 100%");
111 err_message[XR_BAD_INO_ALIGN] =
112 _("inconsistent inode alignment value");
113 err_message[XR_INSUFF_SEC_SB] =
114 _("not enough secondary superblocks with matching geometry");
115 err_message[XR_BAD_SB_UNIT] =
116 _("bad stripe unit in superblock");
117 err_message[XR_BAD_SB_WIDTH] =
118 _("bad stripe width in superblock");
119 err_message[XR_BAD_SVN] =
120 _("bad shared version number in superblock");
121 done = 1;
122 }
123
2bd0ea18 124 if (err_code < XR_OK || err_code >= XR_BAD_ERR_CODE)
507f4e33 125 do_abort(_("bad error code - %d\n"), err_code);
2bd0ea18
NS
126
127 return(err_message[err_code]);
128}
129
130static void
131noval(char opt, char *tbl[], int idx)
132{
507f4e33 133 do_warn(_("-%c %s option cannot have a value\n"), opt, tbl[idx]);
2bd0ea18
NS
134 usage();
135}
136
137static void
138respec(char opt, char *tbl[], int idx)
139{
140 do_warn("-%c ", opt);
141 if (tbl)
142 do_warn("%s ", tbl[idx]);
507f4e33 143 do_warn(_("option respecified\n"));
2bd0ea18
NS
144 usage();
145}
146
147static void
148unknown(char opt, char *s)
149{
507f4e33 150 do_warn(_("unknown option -%c %s\n"), opt, s);
2bd0ea18
NS
151 usage();
152}
153
154/*
155 * sets only the global argument flags and variables
156 */
157void
158process_args(int argc, char **argv)
159{
160 char *p;
161 int c;
162
163 log_spec = 0;
164 fs_is_dirty = 0;
165 verbose = 0;
166 no_modify = 0;
c781939c 167 dangerously = 0;
2bd0ea18 168 isa_file = 0;
d321ceac 169 zap_log = 0;
2bd0ea18
NS
170 dumpcore = 0;
171 full_backptrs = 0;
172 delete_attr_ok = 1;
173 force_geo = 0;
174 assume_xfs = 0;
175 clear_sunit = 0;
176 sb_inoalignmt = 0;
177 sb_unit = 0;
178 sb_width = 0;
179 fs_attributes_allowed = 1;
9b1d68ec 180 fs_attributes2_allowed = 1;
2bd0ea18
NS
181 fs_inode_nlink_allowed = 1;
182 fs_quotas_allowed = 1;
183 fs_aligned_inodes_allowed = 1;
184 fs_sb_feature_bits_allowed = 1;
185 fs_has_extflgbit_allowed = 1;
186 pre_65_beta = 0;
187 fs_shared_allowed = 1;
188
189 /*
190 * XXX have to add suboption processing here
191 * attributes, quotas, nlinks, aligned_inos, sb_fbits
192 */
2c794e6e 193 while ((c = getopt(argc, argv, "o:fl:r:LnDvVd")) != EOF) {
2bd0ea18
NS
194 switch (c) {
195 case 'D':
196 dumpcore = 1;
197 break;
198 case 'o':
199 p = optarg;
200 while (*p != '\0') {
201 char *val;
202
203 switch (getsubopt(&p, (constpp)o_opts, &val)) {
204 case ASSUME_XFS:
205 if (val)
206 noval('o', o_opts, ASSUME_XFS);
207 if (assume_xfs)
208 respec('o', o_opts, ASSUME_XFS);
209 assume_xfs = 1;
210 break;
211 case PRE_65_BETA:
212 if (val)
213 noval('o', o_opts, PRE_65_BETA);
214 if (pre_65_beta)
215 respec('o', o_opts,
216 PRE_65_BETA);
217 pre_65_beta = 1;
218 break;
219 default:
220 unknown('o', val);
221 break;
222 }
223 }
224 break;
225 case 'l':
226 log_name = optarg;
227 log_spec = 1;
228 break;
42a564ab
ES
229 case 'r':
230 rt_name = optarg;
231 rt_spec = 1;
232 break;
2bd0ea18
NS
233 case 'f':
234 isa_file = 1;
235 break;
d321ceac
NS
236 case 'L':
237 zap_log = 1;
238 break;
2bd0ea18
NS
239 case 'n':
240 no_modify = 1;
241 break;
6089b6f0
NS
242 case 'd':
243 dangerously = 1;
244 break;
2bd0ea18
NS
245 case 'v':
246 verbose = 1;
247 break;
248 case 'V':
507f4e33 249 printf(_("%s version %s\n"), progname, VERSION);
3d98fe63 250 exit(0);
2bd0ea18
NS
251 case '?':
252 usage();
253 }
254 }
255
256 if (argc - optind != 1)
257 usage();
258
259 if ((fs_name = argv[optind]) == NULL)
260 usage();
261}
262
263void
264do_msg(int do_abort, char const *msg, va_list args)
265{
266 vfprintf(stderr, msg, args);
267
268 if (do_abort) {
269 if (dumpcore)
270 abort();
271 exit(1);
272 }
273}
274
275void
276do_error(char const *msg, ...)
277{
278 va_list args;
279
507f4e33 280 fprintf(stderr, _("\nfatal error -- "));
2bd0ea18
NS
281
282 va_start(args, msg);
283 do_msg(1, msg, args);
284}
285
286/*
287 * like do_error, only the error is internal, no system
288 * error so no oserror processing
289 */
290void
291do_abort(char const *msg, ...)
292{
293 va_list args;
294
295 va_start(args, msg);
296 do_msg(1, msg, args);
297}
298
299void
300do_warn(char const *msg, ...)
301{
302 va_list args;
303
304 fs_is_dirty = 1;
305
306 va_start(args, msg);
307 do_msg(0, msg, args);
308 va_end(args);
309}
310
311/* no formatting */
312
313void
314do_log(char const *msg, ...)
315{
316 va_list args;
317
318 va_start(args, msg);
319 do_msg(0, msg, args);
320 va_end(args);
321}
322
323void
324calc_mkfs(xfs_mount_t *mp)
325{
326 xfs_agblock_t fino_bno;
327 int do_inoalign;
328
329 do_inoalign = mp->m_sinoalign;
330
331 /*
332 * pre-calculate geometry of ag 0. We know what it looks
333 * like because we know what mkfs does -- 3 btree roots,
334 * and some number of blocks to prefill the agfl.
335 */
336 bnobt_root = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize);
337 bcntbt_root = bnobt_root + 1;
338 inobt_root = bnobt_root + 2;
339 fino_bno = inobt_root + XFS_MIN_FREELIST_RAW(1, 1, mp) + 1;
340
341 /*
342 * ditto the location of the first inode chunks in the fs ('/')
343 */
344 if (XFS_SB_VERSION_HASDALIGN(&mp->m_sb) && do_inoalign) {
345 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, roundup(fino_bno,
346 mp->m_sb.sb_unit), 0);
dfc130f3 347 } else if (XFS_SB_VERSION_HASALIGN(&mp->m_sb) &&
2bd0ea18
NS
348 mp->m_sb.sb_inoalignmt > 1) {
349 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp,
350 roundup(fino_bno,
351 mp->m_sb.sb_inoalignmt),
352 0);
353 } else {
354 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno, 0);
355 }
356
357 ASSERT(XFS_IALLOC_BLOCKS(mp) > 0);
358
359 if (XFS_IALLOC_BLOCKS(mp) > 1)
360 last_prealloc_ino = first_prealloc_ino + XFS_INODES_PER_CHUNK;
361 else
362 last_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno + 1, 0);
363
364 /*
365 * now the first 3 inodes in the system
366 */
367 if (mp->m_sb.sb_rootino != first_prealloc_ino) {
368 do_warn(
507f4e33
NS
369_("sb root inode value %llu %sinconsistent with calculated value %lu\n"),
370 mp->m_sb.sb_rootino,
371 (mp->m_sb.sb_rootino == NULLFSINO ? "(NULLFSINO) ":""),
372 first_prealloc_ino);
2bd0ea18
NS
373
374 if (!no_modify)
375 do_warn(
507f4e33 376 _("resetting superblock root inode pointer to %lu\n"),
2bd0ea18
NS
377 first_prealloc_ino);
378 else
379 do_warn(
507f4e33 380 _("would reset superblock root inode pointer to %lu\n"),
2bd0ea18
NS
381 first_prealloc_ino);
382
383 /*
384 * just set the value -- safe since the superblock
385 * doesn't get flushed out if no_modify is set
386 */
387 mp->m_sb.sb_rootino = first_prealloc_ino;
388 }
389
390 if (mp->m_sb.sb_rbmino != first_prealloc_ino + 1) {
391 do_warn(
507f4e33
NS
392_("sb realtime bitmap inode %llu %sinconsistent with calculated value %lu\n"),
393 mp->m_sb.sb_rbmino,
394 (mp->m_sb.sb_rbmino == NULLFSINO ? "(NULLFSINO) ":""),
395 first_prealloc_ino + 1);
2bd0ea18
NS
396
397 if (!no_modify)
398 do_warn(
507f4e33 399 _("resetting superblock realtime bitmap ino pointer to %lu\n"),
2bd0ea18
NS
400 first_prealloc_ino + 1);
401 else
402 do_warn(
507f4e33 403 _("would reset superblock realtime bitmap ino pointer to %lu\n"),
2bd0ea18
NS
404 first_prealloc_ino + 1);
405
406 /*
407 * just set the value -- safe since the superblock
408 * doesn't get flushed out if no_modify is set
409 */
410 mp->m_sb.sb_rbmino = first_prealloc_ino + 1;
411 }
412
413 if (mp->m_sb.sb_rsumino != first_prealloc_ino + 2) {
414 do_warn(
507f4e33 415_("sb realtime summary inode %llu %sinconsistent with calculated value %lu\n"),
c689c5aa
ES
416 mp->m_sb.sb_rsumino,
417 (mp->m_sb.sb_rsumino == NULLFSINO ? "(NULLFSINO) ":""),
418 first_prealloc_ino + 2);
2bd0ea18
NS
419
420 if (!no_modify)
421 do_warn(
507f4e33 422 _("resetting superblock realtime summary ino pointer to %lu\n"),
2bd0ea18
NS
423 first_prealloc_ino + 2);
424 else
425 do_warn(
507f4e33 426 _("would reset superblock realtime summary ino pointer to %lu\n"),
2bd0ea18
NS
427 first_prealloc_ino + 2);
428
429 /*
430 * just set the value -- safe since the superblock
431 * doesn't get flushed out if no_modify is set
432 */
433 mp->m_sb.sb_rsumino = first_prealloc_ino + 2;
434 }
435
436}
437
438int
439main(int argc, char **argv)
440{
2bd0ea18
NS
441 xfs_mount_t *temp_mp;
442 xfs_mount_t *mp;
443 xfs_sb_t *sb;
444 xfs_buf_t *sbp;
445 xfs_mount_t xfs_m;
446
447 progname = basename(argv[0]);
507f4e33
NS
448 setlocale(LC_ALL, "");
449 bindtextdomain(PACKAGE, LOCALEDIR);
450 textdomain(PACKAGE);
2bd0ea18
NS
451
452 temp_mp = &xfs_m;
453 setbuf(stdout, NULL);
454
455 process_args(argc, argv);
d321ceac 456 xfs_init(&x);
2bd0ea18
NS
457
458 /* do phase1 to make sure we have a superblock */
459 phase1(temp_mp);
460
461 if (no_modify && primary_sb_modified) {
507f4e33
NS
462 do_warn(_("Primary superblock would have been modified.\n"
463 "Cannot proceed further in no_modify mode.\n"
464 "Exiting now.\n"));
2bd0ea18
NS
465 exit(1);
466 }
467
468 /* prepare the mount structure */
d321ceac 469 sbp = libxfs_readbuf(x.ddev, XFS_SB_DADDR, 1, 0);
2bd0ea18
NS
470 memset(&xfs_m, 0, sizeof(xfs_mount_t));
471 sb = &xfs_m.m_sb;
46eca962 472 libxfs_xlate_sb(XFS_BUF_PTR(sbp), sb, 1, XFS_SB_ALL_BITS);
2bd0ea18 473
d321ceac 474 mp = libxfs_mount(&xfs_m, sb, x.ddev, x.logdev, x.rtdev, 0);
2bd0ea18
NS
475
476 if (!mp) {
507f4e33
NS
477 fprintf(stderr,
478 _("%s: cannot repair this filesystem. Sorry.\n"),
2bd0ea18
NS
479 progname);
480 exit(1);
481 }
482 libxfs_putbuf(sbp);
483
484 /*
485 * set XFS-independent status vars from the mount/sb structure
486 */
487 glob_agcount = mp->m_sb.sb_agcount;
488
489 chunks_pblock = mp->m_sb.sb_inopblock / XFS_INODES_PER_CHUNK;
490 max_symlink_blocks = howmany(MAXPATHLEN - 1, mp->m_sb.sb_blocksize);
491 inodes_per_cluster = XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog;
492
493 /*
494 * calculate what mkfs would do to this filesystem
495 */
496 calc_mkfs(mp);
497
498 /*
499 * check sb filesystem stats and initialize in-core data structures
500 */
501 incore_init(mp);
502
503 if (parse_sb_version(&mp->m_sb)) {
504 do_warn(
507f4e33 505 _("Found unsupported filesystem features. Exiting now.\n"));
2bd0ea18
NS
506 return(1);
507 }
508
509 /* make sure the per-ag freespace maps are ok so we can mount the fs */
510
d321ceac 511 phase2(mp);
2bd0ea18
NS
512
513 phase3(mp);
514
515 phase4(mp);
516
517 if (no_modify)
507f4e33 518 printf(_("No modify flag set, skipping phase 5\n"));
2bd0ea18
NS
519 else
520 phase5(mp);
521
522 if (!bad_ino_btree) {
523 phase6(mp);
524
525 phase7(mp);
526 } else {
527 do_warn(
507f4e33 528_("Inode allocation btrees are too corrupted, skipping phases 6 and 7\n"));
2bd0ea18
NS
529 }
530
b36eef04 531 if (lost_quotas && !have_uquotino && !have_gquotino) {
2bd0ea18
NS
532 if (!no_modify) {
533 do_warn(
507f4e33 534_("Warning: no quota inodes were found. Quotas disabled.\n"));
2bd0ea18
NS
535 } else {
536 do_warn(
507f4e33 537_("Warning: no quota inodes were found. Quotas would be disabled.\n"));
2bd0ea18
NS
538 }
539 } else if (lost_quotas) {
540 if (!no_modify) {
541 do_warn(
507f4e33 542_("Warning: quota inodes were cleared. Quotas disabled.\n"));
2bd0ea18
NS
543 } else {
544 do_warn(
507f4e33 545_("Warning: quota inodes would be cleared. Quotas would be disabled.\n"));
2bd0ea18
NS
546 }
547 } else {
548 if (lost_uquotino) {
549 if (!no_modify) {
550 do_warn(
507f4e33
NS
551_("Warning: user quota information was cleared.\n"
552 "User quotas can not be enforced until limit information is recreated.\n"));
2bd0ea18
NS
553 } else {
554 do_warn(
507f4e33
NS
555_("Warning: user quota information would be cleared.\n"
556 "User quotas could not be enforced until limit information was recreated.\n"));
2bd0ea18
NS
557 }
558 }
559
b36eef04 560 if (lost_gquotino) {
2bd0ea18
NS
561 if (!no_modify) {
562 do_warn(
507f4e33
NS
563_("Warning: group quota information was cleared.\n"
564 "Group quotas can not be enforced until limit information is recreated.\n"));
2bd0ea18
NS
565 } else {
566 do_warn(
507f4e33
NS
567_("Warning: group quota information would be cleared.\n"
568 "Group quotas could not be enforced until limit information was recreated.\n"));
9b27bdbb
NS
569 }
570 }
571
572 if (lost_pquotino) {
573 if (!no_modify) {
574 do_warn(
575_("Warning: project quota information was cleared.\n"
576 "Project quotas can not be enforced until limit information is recreated.\n"));
577 } else {
578 do_warn(
579_("Warning: project quota information would be cleared.\n"
580 "Project quotas could not be enforced until limit information was recreated.\n"));
2bd0ea18
NS
581 }
582 }
583 }
584
585 if (no_modify) {
586 do_log(
507f4e33 587 _("No modify flag set, skipping filesystem flush and exiting.\n"));
2bd0ea18
NS
588 if (fs_is_dirty)
589 return(1);
590
591 return(0);
592 }
593
594 /*
595 * Clear the quota flags if they're on.
596 */
597 sbp = libxfs_getsb(mp, 0);
598 if (!sbp)
507f4e33 599 do_error(_("couldn't get superblock\n"));
2bd0ea18
NS
600
601 sb = XFS_BUF_TO_SBP(sbp);
602
46eca962 603 if (sb->sb_qflags & (XFS_UQUOTA_CHKD|XFS_OQUOTA_CHKD)) {
2bd0ea18 604 do_warn(
507f4e33 605 _("Note - quota info will be regenerated on next quota mount.\n"));
46eca962 606 sb->sb_qflags &= ~(XFS_UQUOTA_CHKD|XFS_OQUOTA_CHKD);
2bd0ea18
NS
607 }
608
609 if (clear_sunit) {
610 do_warn(
507f4e33
NS
611_("Note - stripe unit (%d) and width (%d) fields have been reset.\n"
612 "Please set with mount -o sunit=<value>,swidth=<value>\n"),
2bd0ea18
NS
613 sb->sb_unit, sb->sb_width);
614 sb->sb_unit = 0;
615 sb->sb_width = 0;
dfc130f3 616 }
2bd0ea18
NS
617
618 libxfs_writebuf(sbp, 0);
619
620 libxfs_umount(mp);
d321ceac
NS
621 if (x.rtdev)
622 libxfs_device_close(x.rtdev);
623 if (x.logdev && x.logdev != x.ddev)
624 libxfs_device_close(x.logdev);
625 libxfs_device_close(x.ddev);
2bd0ea18 626
507f4e33 627 do_log(_("done\n"));
2bd0ea18
NS
628
629 return(0);
630}