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