]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blame - repair/xfs_repair.c
libxfs: fix root inode handling inconsistencies
[thirdparty/xfsprogs-dev.git] / repair / xfs_repair.c
CommitLineData
2bd0ea18 1/*
da23017d
NS
2 * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
3 * All Rights Reserved.
dfc130f3 4 *
da23017d
NS
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
2bd0ea18 7 * published by the Free Software Foundation.
dfc130f3 8 *
da23017d
NS
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.
dfc130f3 13 *
da23017d
NS
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
2bd0ea18
NS
17 */
18
1d7e80ee 19#include <xfs/libxlog.h>
12be365e 20#include <sys/resource.h>
2bd0ea18
NS
21#include "avl.h"
22#include "avl64.h"
23#include "globals.h"
24#include "versions.h"
25#include "agheader.h"
26#include "protos.h"
27#include "incore.h"
28#include "err_protos.h"
cb5b3ef4 29#include "prefetch.h"
3b6ac903 30#include "threads.h"
06fbdda9 31#include "progress.h"
2bd0ea18
NS
32
33#define rounddown(x, y) (((x)/(y))*(y))
34
2bd0ea18
NS
35#define XR_MAX_SECT_SIZE (64 * 1024)
36
37/*
38 * option tables for getsubopt calls
39 */
40
41/*
4af916f8 42 * -o: user-supplied override options
2bd0ea18 43 */
8b8a6b02 44static char *o_opts[] = {
2bd0ea18
NS
45#define ASSUME_XFS 0
46 "assume_xfs",
47#define PRE_65_BETA 1
48 "fs_is_pre_65_beta",
9f38f08d
MV
49#define IHASH_SIZE 2
50 "ihash",
51#define BHASH_SIZE 3
52 "bhash",
2556c98b 53#define AG_STRIDE 4
add3cb90 54 "ag_stride",
d4dd6ab5
CH
55#define FORCE_GEO 5
56 "force_geometry",
364a126c
DC
57#define PHASE2_THREADS 6
58 "phase2_threads",
2bd0ea18
NS
59 NULL
60};
61
4af916f8
BN
62/*
63 * -c: conversion options
64 */
8b8a6b02 65static char *c_opts[] = {
4af916f8
BN
66#define CONVERT_LAZY_COUNT 0
67 "lazycount",
68 NULL
69};
70
71
2556c98b
BN
72static int ihash_option_used;
73static int bhash_option_used;
12be365e 74static long max_mem_specified; /* in megabytes */
364a126c 75static int phase2_threads = 32;
2556c98b 76
2bd0ea18
NS
77static void
78usage(void)
79{
4af916f8
BN
80 do_warn(_(
81"Usage: %s [options] device\n"
82"\n"
83"Options:\n"
84" -f The device is a file\n"
85" -L Force log zeroing. Do this as a last resort.\n"
86" -l logdev Specifies the device where the external log resides.\n"
87" -m maxmem Maximum amount of memory to be used in megabytes.\n"
88" -n No modify mode, just checks the filesystem for damage.\n"
89" -P Disables prefetching.\n"
90" -r rtdev Specifies the device where the realtime section resides.\n"
91" -v Verbose output.\n"
92" -c subopts Change filesystem parameters - use xfs_admin.\n"
93" -o subopts Override default behaviour, refer to man page.\n"
94" -t interval Reporting interval in minutes.\n"
95" -d Repair dangerously.\n"
96" -V Reports version and exits.\n"), progname);
2bd0ea18
NS
97 exit(1);
98}
99
2bd0ea18
NS
100char *
101err_string(int err_code)
102{
507f4e33
NS
103 static char *err_message[XR_BAD_ERR_CODE];
104 static int done;
105
106 if (!done) {
107 err_message[XR_OK] = _("no error");
108 err_message[XR_BAD_MAGIC] = _("bad magic number");
109 err_message[XR_BAD_BLOCKSIZE] = _("bad blocksize field");
110 err_message[XR_BAD_BLOCKLOG] = _("bad blocksize log field");
4af916f8 111 err_message[XR_BAD_VERSION] = _("bad or unsupported version");
507f4e33
NS
112 err_message[XR_BAD_INPROGRESS] =
113 _("filesystem mkfs-in-progress bit set");
114 err_message[XR_BAD_FS_SIZE_DATA] =
115 _("inconsistent filesystem geometry information");
116 err_message[XR_BAD_INO_SIZE_DATA] =
117 _("bad inode size or inconsistent with number of inodes/block"),
118 err_message[XR_BAD_SECT_SIZE_DATA] = _("bad sector size");
119 err_message[XR_AGF_GEO_MISMATCH] =
120 _("AGF geometry info conflicts with filesystem geometry");
121 err_message[XR_AGI_GEO_MISMATCH] =
122 _("AGI geometry info conflicts with filesystem geometry");
123 err_message[XR_SB_GEO_MISMATCH] =
124 _("AG superblock geometry info conflicts with filesystem geometry");
125 err_message[XR_EOF] = _("attempted to perform I/O beyond EOF");
126 err_message[XR_BAD_RT_GEO_DATA] =
127 _("inconsistent filesystem geometry in realtime filesystem component");
128 err_message[XR_BAD_INO_MAX_PCT] =
129 _("maximum indicated percentage of inodes > 100%");
130 err_message[XR_BAD_INO_ALIGN] =
131 _("inconsistent inode alignment value");
132 err_message[XR_INSUFF_SEC_SB] =
133 _("not enough secondary superblocks with matching geometry");
134 err_message[XR_BAD_SB_UNIT] =
135 _("bad stripe unit in superblock");
136 err_message[XR_BAD_SB_WIDTH] =
137 _("bad stripe width in superblock");
138 err_message[XR_BAD_SVN] =
139 _("bad shared version number in superblock");
140 done = 1;
141 }
142
2bd0ea18 143 if (err_code < XR_OK || err_code >= XR_BAD_ERR_CODE)
507f4e33 144 do_abort(_("bad error code - %d\n"), err_code);
2bd0ea18
NS
145
146 return(err_message[err_code]);
147}
148
149static void
150noval(char opt, char *tbl[], int idx)
151{
507f4e33 152 do_warn(_("-%c %s option cannot have a value\n"), opt, tbl[idx]);
2bd0ea18
NS
153 usage();
154}
155
156static void
157respec(char opt, char *tbl[], int idx)
158{
159 do_warn("-%c ", opt);
160 if (tbl)
161 do_warn("%s ", tbl[idx]);
507f4e33 162 do_warn(_("option respecified\n"));
2bd0ea18
NS
163 usage();
164}
165
166static void
167unknown(char opt, char *s)
168{
507f4e33 169 do_warn(_("unknown option -%c %s\n"), opt, s);
2bd0ea18
NS
170 usage();
171}
172
173/*
174 * sets only the global argument flags and variables
175 */
8b8a6b02 176static void
2bd0ea18
NS
177process_args(int argc, char **argv)
178{
179 char *p;
180 int c;
181
182 log_spec = 0;
183 fs_is_dirty = 0;
184 verbose = 0;
185 no_modify = 0;
c781939c 186 dangerously = 0;
2bd0ea18 187 isa_file = 0;
d321ceac 188 zap_log = 0;
2bd0ea18 189 dumpcore = 0;
0f012a4c 190 full_ino_ex_data = 0;
2bd0ea18
NS
191 delete_attr_ok = 1;
192 force_geo = 0;
193 assume_xfs = 0;
194 clear_sunit = 0;
195 sb_inoalignmt = 0;
196 sb_unit = 0;
197 sb_width = 0;
198 fs_attributes_allowed = 1;
9b1d68ec 199 fs_attributes2_allowed = 1;
2bd0ea18
NS
200 fs_inode_nlink_allowed = 1;
201 fs_quotas_allowed = 1;
202 fs_aligned_inodes_allowed = 1;
203 fs_sb_feature_bits_allowed = 1;
204 fs_has_extflgbit_allowed = 1;
205 pre_65_beta = 0;
206 fs_shared_allowed = 1;
add3cb90 207 ag_stride = 0;
2556c98b 208 thread_count = 1;
06fbdda9 209 report_interval = PROG_RPT_DEFAULT;
2bd0ea18
NS
210
211 /*
212 * XXX have to add suboption processing here
213 * attributes, quotas, nlinks, aligned_inos, sb_fbits
214 */
4af916f8 215 while ((c = getopt(argc, argv, "c:o:fl:m:r:LnDvVdPt:")) != EOF) {
2bd0ea18
NS
216 switch (c) {
217 case 'D':
218 dumpcore = 1;
219 break;
220 case 'o':
221 p = optarg;
222 while (*p != '\0') {
223 char *val;
224
225 switch (getsubopt(&p, (constpp)o_opts, &val)) {
226 case ASSUME_XFS:
227 if (val)
228 noval('o', o_opts, ASSUME_XFS);
229 if (assume_xfs)
230 respec('o', o_opts, ASSUME_XFS);
231 assume_xfs = 1;
232 break;
233 case PRE_65_BETA:
234 if (val)
235 noval('o', o_opts, PRE_65_BETA);
236 if (pre_65_beta)
237 respec('o', o_opts,
238 PRE_65_BETA);
239 pre_65_beta = 1;
240 break;
9f38f08d 241 case IHASH_SIZE:
5e656dbb 242 libxfs_ihash_size = (int)strtol(val, NULL, 0);
2556c98b 243 ihash_option_used = 1;
9f38f08d
MV
244 break;
245 case BHASH_SIZE:
12be365e
BN
246 if (max_mem_specified)
247 do_abort(
248 _("-o bhash option cannot be used with -m option\n"));
5e656dbb 249 libxfs_bhash_size = (int)strtol(val, NULL, 0);
2556c98b 250 bhash_option_used = 1;
cb5b3ef4 251 break;
add3cb90 252 case AG_STRIDE:
5e656dbb 253 ag_stride = (int)strtol(val, NULL, 0);
3b6ac903 254 break;
d4dd6ab5
CH
255 case FORCE_GEO:
256 if (val)
257 noval('o', o_opts, FORCE_GEO);
258 if (force_geo)
259 respec('o', o_opts, FORCE_GEO);
260 force_geo = 1;
261 break;
364a126c
DC
262 case PHASE2_THREADS:
263 phase2_threads = (int)strtol(val, NULL, 0);
264 break;
2bd0ea18
NS
265 default:
266 unknown('o', val);
267 break;
268 }
269 }
270 break;
4af916f8
BN
271 case 'c':
272 p = optarg;
273 while (*p) {
274 char *val;
275
276 switch (getsubopt(&p, (constpp)c_opts, &val)) {
277 case CONVERT_LAZY_COUNT:
5e656dbb 278 lazy_count = (int)strtol(val, NULL, 0);
4af916f8
BN
279 convert_lazy_count = 1;
280 break;
281 default:
282 unknown('c', val);
283 break;
284 }
285 }
286 break;
2bd0ea18
NS
287 case 'l':
288 log_name = optarg;
289 log_spec = 1;
290 break;
42a564ab
ES
291 case 'r':
292 rt_name = optarg;
293 rt_spec = 1;
294 break;
2bd0ea18
NS
295 case 'f':
296 isa_file = 1;
297 break;
12be365e
BN
298 case 'm':
299 if (bhash_option_used)
300 do_abort(_("-m option cannot be used with "
301 "-o bhash option\n"));
5e656dbb 302 max_mem_specified = strtol(optarg, NULL, 0);
12be365e 303 break;
d321ceac
NS
304 case 'L':
305 zap_log = 1;
306 break;
2bd0ea18
NS
307 case 'n':
308 no_modify = 1;
309 break;
6089b6f0
NS
310 case 'd':
311 dangerously = 1;
312 break;
2bd0ea18 313 case 'v':
3b6ac903 314 verbose++;
2bd0ea18
NS
315 break;
316 case 'V':
507f4e33 317 printf(_("%s version %s\n"), progname, VERSION);
3d98fe63 318 exit(0);
cb5b3ef4 319 case 'P':
2556c98b 320 do_prefetch = 0;
3b6ac903 321 break;
06fbdda9 322 case 't':
5e656dbb 323 report_interval = (int)strtol(optarg, NULL, 0);
06fbdda9 324 break;
2bd0ea18
NS
325 case '?':
326 usage();
327 }
328 }
329
330 if (argc - optind != 1)
331 usage();
332
333 if ((fs_name = argv[optind]) == NULL)
334 usage();
335}
336
b1559967 337void __attribute__((noreturn))
2bd0ea18
NS
338do_error(char const *msg, ...)
339{
340 va_list args;
341
507f4e33 342 fprintf(stderr, _("\nfatal error -- "));
2bd0ea18
NS
343
344 va_start(args, msg);
079afa09
CH
345 vfprintf(stderr, msg, args);
346 if (dumpcore)
347 abort();
348 exit(1);
2bd0ea18
NS
349}
350
351/*
352 * like do_error, only the error is internal, no system
353 * error so no oserror processing
354 */
b1559967 355void __attribute__((noreturn))
2bd0ea18
NS
356do_abort(char const *msg, ...)
357{
358 va_list args;
359
360 va_start(args, msg);
079afa09
CH
361 vfprintf(stderr, msg, args);
362 if (dumpcore)
363 abort();
364 exit(1);
2bd0ea18
NS
365}
366
367void
368do_warn(char const *msg, ...)
369{
370 va_list args;
371
372 fs_is_dirty = 1;
373
374 va_start(args, msg);
079afa09 375 vfprintf(stderr, msg, args);
2bd0ea18
NS
376 va_end(args);
377}
378
379/* no formatting */
380
381void
382do_log(char const *msg, ...)
383{
384 va_list args;
385
386 va_start(args, msg);
079afa09 387 vfprintf(stderr, msg, args);
2bd0ea18
NS
388 va_end(args);
389}
390
8b8a6b02 391static void
2bd0ea18
NS
392calc_mkfs(xfs_mount_t *mp)
393{
394 xfs_agblock_t fino_bno;
395 int do_inoalign;
396
397 do_inoalign = mp->m_sinoalign;
398
399 /*
400 * pre-calculate geometry of ag 0. We know what it looks
401 * like because we know what mkfs does -- 3 btree roots,
402 * and some number of blocks to prefill the agfl.
403 */
404 bnobt_root = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize);
405 bcntbt_root = bnobt_root + 1;
406 inobt_root = bnobt_root + 2;
407 fino_bno = inobt_root + XFS_MIN_FREELIST_RAW(1, 1, mp) + 1;
408
d4dd6ab5 409 /*
649bfa9a
CH
410 * If the log is allocated in the first allocation group we need to
411 * add the number of blocks used by the log to the above calculation.
412 *
413 * This can happens with filesystems that only have a single
414 * allocation group, or very odd geometries created by old mkfs
415 * versions on very small filesystems.
d4dd6ab5 416 */
649bfa9a
CH
417 if (mp->m_sb.sb_logstart &&
418 XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == 0) {
419
d4dd6ab5
CH
420 /*
421 * XXX(hch): verify that sb_logstart makes sense?
422 */
423 fino_bno += mp->m_sb.sb_logblocks;
424 }
425
2bd0ea18
NS
426 /*
427 * ditto the location of the first inode chunks in the fs ('/')
428 */
5e656dbb 429 if (xfs_sb_version_hasdalign(&mp->m_sb) && do_inoalign) {
2bd0ea18
NS
430 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, roundup(fino_bno,
431 mp->m_sb.sb_unit), 0);
5e656dbb 432 } else if (xfs_sb_version_hasalign(&mp->m_sb) &&
2bd0ea18
NS
433 mp->m_sb.sb_inoalignmt > 1) {
434 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp,
435 roundup(fino_bno,
436 mp->m_sb.sb_inoalignmt),
437 0);
438 } else {
439 first_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno, 0);
440 }
441
442 ASSERT(XFS_IALLOC_BLOCKS(mp) > 0);
443
444 if (XFS_IALLOC_BLOCKS(mp) > 1)
445 last_prealloc_ino = first_prealloc_ino + XFS_INODES_PER_CHUNK;
446 else
447 last_prealloc_ino = XFS_OFFBNO_TO_AGINO(mp, fino_bno + 1, 0);
448
449 /*
450 * now the first 3 inodes in the system
451 */
452 if (mp->m_sb.sb_rootino != first_prealloc_ino) {
453 do_warn(
5d1b7f0f 454_("sb root inode value %" PRIu64 " %sinconsistent with calculated value %u\n"),
507f4e33
NS
455 mp->m_sb.sb_rootino,
456 (mp->m_sb.sb_rootino == NULLFSINO ? "(NULLFSINO) ":""),
457 first_prealloc_ino);
2bd0ea18
NS
458
459 if (!no_modify)
460 do_warn(
5d1b7f0f 461 _("resetting superblock root inode pointer to %u\n"),
2bd0ea18
NS
462 first_prealloc_ino);
463 else
464 do_warn(
5d1b7f0f 465 _("would reset superblock root inode pointer to %u\n"),
2bd0ea18
NS
466 first_prealloc_ino);
467
468 /*
469 * just set the value -- safe since the superblock
470 * doesn't get flushed out if no_modify is set
471 */
472 mp->m_sb.sb_rootino = first_prealloc_ino;
473 }
474
475 if (mp->m_sb.sb_rbmino != first_prealloc_ino + 1) {
476 do_warn(
5d1b7f0f 477_("sb realtime bitmap inode %" PRIu64 " %sinconsistent with calculated value %u\n"),
507f4e33
NS
478 mp->m_sb.sb_rbmino,
479 (mp->m_sb.sb_rbmino == NULLFSINO ? "(NULLFSINO) ":""),
480 first_prealloc_ino + 1);
2bd0ea18
NS
481
482 if (!no_modify)
483 do_warn(
5d1b7f0f 484 _("resetting superblock realtime bitmap ino pointer to %u\n"),
2bd0ea18
NS
485 first_prealloc_ino + 1);
486 else
487 do_warn(
5d1b7f0f 488 _("would reset superblock realtime bitmap ino pointer to %u\n"),
2bd0ea18
NS
489 first_prealloc_ino + 1);
490
491 /*
492 * just set the value -- safe since the superblock
493 * doesn't get flushed out if no_modify is set
494 */
495 mp->m_sb.sb_rbmino = first_prealloc_ino + 1;
496 }
497
498 if (mp->m_sb.sb_rsumino != first_prealloc_ino + 2) {
499 do_warn(
5d1b7f0f
CH
500_("sb realtime summary inode %" PRIu64 " %sinconsistent with calculated value %u\n"),
501 mp->m_sb.sb_rsumino,
502 (mp->m_sb.sb_rsumino == NULLFSINO ? "(NULLFSINO) ":""),
503 first_prealloc_ino + 2);
2bd0ea18
NS
504
505 if (!no_modify)
506 do_warn(
5d1b7f0f 507 _("resetting superblock realtime summary ino pointer to %u\n"),
2bd0ea18
NS
508 first_prealloc_ino + 2);
509 else
510 do_warn(
5d1b7f0f 511 _("would reset superblock realtime summary ino pointer to %u\n"),
2bd0ea18
NS
512 first_prealloc_ino + 2);
513
514 /*
515 * just set the value -- safe since the superblock
516 * doesn't get flushed out if no_modify is set
517 */
518 mp->m_sb.sb_rsumino = first_prealloc_ino + 2;
519 }
520
521}
522
523int
524main(int argc, char **argv)
525{
2bd0ea18
NS
526 xfs_mount_t *temp_mp;
527 xfs_mount_t *mp;
5e656dbb 528 xfs_dsb_t *dsb;
2bd0ea18
NS
529 xfs_buf_t *sbp;
530 xfs_mount_t xfs_m;
06fbdda9 531 char *msgbuf;
2bd0ea18
NS
532
533 progname = basename(argv[0]);
507f4e33
NS
534 setlocale(LC_ALL, "");
535 bindtextdomain(PACKAGE, LOCALEDIR);
536 textdomain(PACKAGE);
2bd0ea18
NS
537
538 temp_mp = &xfs_m;
539 setbuf(stdout, NULL);
540
541 process_args(argc, argv);
d321ceac 542 xfs_init(&x);
2bd0ea18 543
2556c98b
BN
544 msgbuf = malloc(DURATION_BUF_SIZE);
545
06fbdda9
MV
546 timestamp(PHASE_START, 0, NULL);
547 timestamp(PHASE_END, 0, NULL);
548
2bd0ea18
NS
549 /* do phase1 to make sure we have a superblock */
550 phase1(temp_mp);
06fbdda9 551 timestamp(PHASE_END, 1, NULL);
2bd0ea18
NS
552
553 if (no_modify && primary_sb_modified) {
507f4e33
NS
554 do_warn(_("Primary superblock would have been modified.\n"
555 "Cannot proceed further in no_modify mode.\n"
556 "Exiting now.\n"));
2bd0ea18
NS
557 exit(1);
558 }
559
560 /* prepare the mount structure */
2bd0ea18 561 memset(&xfs_m, 0, sizeof(xfs_mount_t));
75c8b434
DC
562 libxfs_buftarg_init(&xfs_m, x.ddev, x.logdev, x.rtdev);
563 sbp = libxfs_readbuf(xfs_m.m_ddev_targp, XFS_SB_DADDR,
564 1 << (XFS_MAX_SECTORSIZE_LOG - BBSHIFT), 0,
565 &xfs_sb_buf_ops);
5e656dbb 566 libxfs_sb_from_disk(&xfs_m.m_sb, XFS_BUF_TO_SBP(sbp));
2bd0ea18 567
f63fd268
DC
568 /*
569 * if the sector size of the filesystem we are trying to repair is
570 * smaller than that of the underlying filesystem (i.e. we are repairing
571 * an image), the we have to turn off direct IO because we cannot do IO
572 * smaller than the host filesystem's sector size.
573 */
574 if (isa_file) {
575 int fd = libxfs_device_to_fd(x.ddev);
576 struct xfs_fsop_geom_v1 geom = { 0 };
577
578 if (ioctl(fd, XFS_IOC_FSGEOMETRY_V1, &geom) < 0) {
579 do_warn(_("Cannot get host filesystem geometry.\n"
580 "Repair may fail if there is a sector size mismatch between\n"
581 "the image and the host filesystem.\n"));
582 geom.sectsize = BBSIZE;
583 }
584
585 if (xfs_m.m_sb.sb_sectsize < geom.sectsize) {
586 long old_flags;
587
588 old_flags = fcntl(fd, F_GETFL, 0);
589 if (fcntl(fd, F_SETFL, old_flags & ~O_DIRECT) < 0) {
590 do_warn(_(
591 "Sector size on host filesystem larger than image sector size.\n"
592 "Cannot turn off direct IO, so exiting.\n"));
593 exit(1);
594 }
595 }
596 }
5e656dbb 597 mp = libxfs_mount(&xfs_m, &xfs_m.m_sb, x.ddev, x.logdev, x.rtdev, 0);
2bd0ea18
NS
598
599 if (!mp) {
507f4e33
NS
600 fprintf(stderr,
601 _("%s: cannot repair this filesystem. Sorry.\n"),
2bd0ea18
NS
602 progname);
603 exit(1);
604 }
605 libxfs_putbuf(sbp);
2aa2e7b9 606 libxfs_purgebuf(sbp);
2bd0ea18
NS
607
608 /*
609 * set XFS-independent status vars from the mount/sb structure
610 */
611 glob_agcount = mp->m_sb.sb_agcount;
612
613 chunks_pblock = mp->m_sb.sb_inopblock / XFS_INODES_PER_CHUNK;
e0607266 614 max_symlink_blocks = libxfs_symlink_blocks(mp, MAXPATHLEN);
edf3f9d0
BN
615 inodes_per_cluster = MAX(mp->m_sb.sb_inopblock,
616 XFS_INODE_CLUSTER_SIZE(mp) >> mp->m_sb.sb_inodelog);
2bd0ea18 617
add3cb90 618 if (ag_stride) {
2556c98b 619 thread_count = (glob_agcount + ag_stride - 1) / ag_stride;
add3cb90
BN
620 thread_init();
621 }
622
2556c98b 623 if (ag_stride && report_interval) {
06fbdda9 624 init_progress_rpt();
06fbdda9
MV
625 if (msgbuf) {
626 do_log(_(" - reporting progress in intervals of %s\n"),
627 duration(report_interval, msgbuf));
06fbdda9
MV
628 }
629 }
630
2556c98b
BN
631 /*
632 * Adjust libxfs cache sizes based on system memory,
633 * filesystem size and inode count.
634 *
635 * We'll set the cache size based on 3/4s the memory minus
636 * space used by the inode AVL tree and block usage map.
637 *
638 * Inode AVL tree space is approximately 4 bytes per inode,
639 * block usage map is currently 1 byte for 2 blocks.
640 *
641 * We assume most blocks will be inode clusters.
642 *
643 * Calculations are done in kilobyte units.
644 */
645
12be365e 646 if (!bhash_option_used || max_mem_specified) {
2556c98b 647 unsigned long mem_used;
12be365e
BN
648 unsigned long max_mem;
649 struct rlimit rlim;
2556c98b
BN
650
651 libxfs_icache_purge();
652 libxfs_bcache_purge();
653 cache_destroy(libxfs_icache);
654 cache_destroy(libxfs_bcache);
655
656 mem_used = (mp->m_sb.sb_icount >> (10 - 2)) +
12be365e
BN
657 (mp->m_sb.sb_dblocks >> (10 + 1)) +
658 50000; /* rough estimate of 50MB overhead */
659 max_mem = max_mem_specified ? max_mem_specified * 1024 :
660 libxfs_physmem() * 3 / 4;
661
662 if (getrlimit(RLIMIT_AS, &rlim) != -1 &&
663 rlim.rlim_cur != RLIM_INFINITY) {
664 rlim.rlim_cur = rlim.rlim_max;
665 setrlimit(RLIMIT_AS, &rlim);
666 /* use approximately 80% of rlimit to avoid overrun */
667 max_mem = MIN(max_mem, rlim.rlim_cur / 1280);
668 } else
669 max_mem = MIN(max_mem, (LONG_MAX >> 10) + 1);
2556c98b
BN
670
671 if (verbose > 1)
5d1b7f0f
CH
672 do_log(
673 _(" - max_mem = %lu, icount = %" PRIu64 ", imem = %" PRIu64 ", dblock = %" PRIu64 ", dmem = %" PRIu64 "\n"),
12be365e
BN
674 max_mem, mp->m_sb.sb_icount,
675 mp->m_sb.sb_icount >> (10 - 2),
676 mp->m_sb.sb_dblocks,
677 mp->m_sb.sb_dblocks >> (10 + 1));
678
679 if (max_mem <= mem_used) {
2556c98b
BN
680 /*
681 * Turn off prefetch and minimise libxfs cache if
682 * physical memory is deemed insufficient
683 */
0335a835
DC
684 if (max_mem_specified) {
685 do_abort(
686 _("Required memory for repair is greater that the maximum specified\n"
687 "with the -m option. Please increase it to at least %lu.\n"),
12be365e 688 mem_used / 1024);
0335a835
DC
689 } else {
690 do_warn(
691 _("Not enough RAM available for repair to enable prefetching.\n"
692 "This will be _slow_.\n"
693 "You need at least %luMB RAM to run with prefetching enabled.\n"),
694 mem_used * 1280 / (1024 * 1024));
695 }
2556c98b
BN
696 do_prefetch = 0;
697 libxfs_bhash_size = 64;
698 } else {
12be365e
BN
699 max_mem -= mem_used;
700 if (max_mem >= (1 << 30))
701 max_mem = 1 << 30;
702 libxfs_bhash_size = max_mem / (HASH_CACHE_RATIO *
2556c98b
BN
703 (mp->m_inode_cluster_size >> 10));
704 if (libxfs_bhash_size < 512)
705 libxfs_bhash_size = 512;
706 }
707
708 if (verbose)
709 do_log(_(" - block cache size set to %d entries\n"),
710 libxfs_bhash_size * HASH_CACHE_RATIO);
711
712 if (!ihash_option_used)
713 libxfs_ihash_size = libxfs_bhash_size;
714
715 libxfs_icache = cache_init(libxfs_ihash_size,
716 &libxfs_icache_operations);
717 libxfs_bcache = cache_init(libxfs_bhash_size,
718 &libxfs_bcache_operations);
719 }
720
2bd0ea18
NS
721 /*
722 * calculate what mkfs would do to this filesystem
723 */
724 calc_mkfs(mp);
725
726 /*
c1f7a46c 727 * initialize block alloc map
2bd0ea18 728 */
c1f7a46c
BN
729 init_bmaps(mp);
730 incore_ino_init(mp);
731 incore_ext_init(mp);
732
733 /* initialize random globals now that we know the fs geometry */
734 inodes_per_block = mp->m_sb.sb_inopblock;
2bd0ea18
NS
735
736 if (parse_sb_version(&mp->m_sb)) {
737 do_warn(
507f4e33 738 _("Found unsupported filesystem features. Exiting now.\n"));
2bd0ea18
NS
739 return(1);
740 }
741
742 /* make sure the per-ag freespace maps are ok so we can mount the fs */
364a126c 743 phase2(mp, phase2_threads);
06fbdda9 744 timestamp(PHASE_END, 2, NULL);
2bd0ea18 745
2556c98b
BN
746 if (do_prefetch)
747 init_prefetch(mp);
748
2bd0ea18 749 phase3(mp);
06fbdda9 750 timestamp(PHASE_END, 3, NULL);
2bd0ea18
NS
751
752 phase4(mp);
06fbdda9 753 timestamp(PHASE_END, 4, NULL);
2bd0ea18
NS
754
755 if (no_modify)
507f4e33 756 printf(_("No modify flag set, skipping phase 5\n"));
3b6ac903 757 else {
2bd0ea18 758 phase5(mp);
3b6ac903 759 }
06fbdda9 760 timestamp(PHASE_END, 5, NULL);
2bd0ea18 761
c1f7a46c
BN
762 /*
763 * Done with the block usage maps, toss them...
764 */
765 free_bmaps(mp);
766
2bd0ea18
NS
767 if (!bad_ino_btree) {
768 phase6(mp);
06fbdda9 769 timestamp(PHASE_END, 6, NULL);
2bd0ea18
NS
770
771 phase7(mp);
06fbdda9 772 timestamp(PHASE_END, 7, NULL);
2bd0ea18
NS
773 } else {
774 do_warn(
507f4e33 775_("Inode allocation btrees are too corrupted, skipping phases 6 and 7\n"));
2bd0ea18
NS
776 }
777
0340d706 778 if (lost_quotas && !have_uquotino && !have_gquotino && !have_pquotino) {
2bd0ea18
NS
779 if (!no_modify) {
780 do_warn(
507f4e33 781_("Warning: no quota inodes were found. Quotas disabled.\n"));
2bd0ea18
NS
782 } else {
783 do_warn(
507f4e33 784_("Warning: no quota inodes were found. Quotas would be disabled.\n"));
2bd0ea18
NS
785 }
786 } else if (lost_quotas) {
787 if (!no_modify) {
788 do_warn(
507f4e33 789_("Warning: quota inodes were cleared. Quotas disabled.\n"));
2bd0ea18
NS
790 } else {
791 do_warn(
507f4e33 792_("Warning: quota inodes would be cleared. Quotas would be disabled.\n"));
2bd0ea18
NS
793 }
794 } else {
795 if (lost_uquotino) {
796 if (!no_modify) {
797 do_warn(
507f4e33
NS
798_("Warning: user quota information was cleared.\n"
799 "User quotas can not be enforced until limit information is recreated.\n"));
2bd0ea18
NS
800 } else {
801 do_warn(
507f4e33
NS
802_("Warning: user quota information would be cleared.\n"
803 "User quotas could not be enforced until limit information was recreated.\n"));
2bd0ea18
NS
804 }
805 }
806
b36eef04 807 if (lost_gquotino) {
2bd0ea18
NS
808 if (!no_modify) {
809 do_warn(
507f4e33
NS
810_("Warning: group quota information was cleared.\n"
811 "Group quotas can not be enforced until limit information is recreated.\n"));
2bd0ea18
NS
812 } else {
813 do_warn(
507f4e33
NS
814_("Warning: group quota information would be cleared.\n"
815 "Group quotas could not be enforced until limit information was recreated.\n"));
9b27bdbb
NS
816 }
817 }
818
819 if (lost_pquotino) {
820 if (!no_modify) {
821 do_warn(
822_("Warning: project quota information was cleared.\n"
823 "Project quotas can not be enforced until limit information is recreated.\n"));
824 } else {
825 do_warn(
826_("Warning: project quota information would be cleared.\n"
827 "Project quotas could not be enforced until limit information was recreated.\n"));
2bd0ea18
NS
828 }
829 }
830 }
831
2556c98b 832 if (ag_stride && report_interval)
06fbdda9 833 stop_progress_rpt();
9f38f08d 834
2bd0ea18
NS
835 if (no_modify) {
836 do_log(
507f4e33 837 _("No modify flag set, skipping filesystem flush and exiting.\n"));
3b6ac903 838 if (verbose)
06fbdda9 839 summary_report();
2bd0ea18
NS
840 if (fs_is_dirty)
841 return(1);
842
843 return(0);
844 }
845
846 /*
847 * Clear the quota flags if they're on.
848 */
849 sbp = libxfs_getsb(mp, 0);
850 if (!sbp)
507f4e33 851 do_error(_("couldn't get superblock\n"));
2bd0ea18 852
5e656dbb 853 dsb = XFS_BUF_TO_SBP(sbp);
2bd0ea18 854
342aef1e 855 if (be16_to_cpu(dsb->sb_qflags) & XFS_ALL_QUOTA_CHKD) {
5e656dbb
BN
856 do_warn(_("Note - quota info will be regenerated on next "
857 "quota mount.\n"));
342aef1e 858 dsb->sb_qflags &= cpu_to_be16(~XFS_ALL_QUOTA_CHKD);
2bd0ea18
NS
859 }
860
861 if (clear_sunit) {
862 do_warn(
507f4e33
NS
863_("Note - stripe unit (%d) and width (%d) fields have been reset.\n"
864 "Please set with mount -o sunit=<value>,swidth=<value>\n"),
5e656dbb
BN
865 be32_to_cpu(dsb->sb_unit), be32_to_cpu(dsb->sb_width));
866 dsb->sb_unit = 0;
867 dsb->sb_width = 0;
dfc130f3 868 }
2bd0ea18
NS
869
870 libxfs_writebuf(sbp, 0);
871
2556c98b
BN
872 /*
873 * Done, flush all cached buffers and inodes.
874 */
875 libxfs_bcache_flush();
876
2bd0ea18 877 libxfs_umount(mp);
d321ceac
NS
878 if (x.rtdev)
879 libxfs_device_close(x.rtdev);
880 if (x.logdev && x.logdev != x.ddev)
881 libxfs_device_close(x.logdev);
882 libxfs_device_close(x.ddev);
2bd0ea18 883
06fbdda9
MV
884 if (verbose)
885 summary_report();
507f4e33 886 do_log(_("done\n"));
4c0a98ae
BN
887 pftrace_done();
888
3b6ac903
MV
889 return (0);
890}