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