Whamcloud - gitweb
git://git.whamcloud.com
/
tools
/
e2fsprogs.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
| inline |
side by side
ext2fs: Handle internal journal over 2^32 bytes
[tools/e2fsprogs.git]
/
e2fsck
/
unix.c
diff --git
a/e2fsck/unix.c
b/e2fsck/unix.c
index
e39afdd
..
a43f0c9
100644
(file)
--- a/
e2fsck/unix.c
+++ b/
e2fsck/unix.c
@@
-101,9
+101,9
@@
static void show_stats(e2fsck_t ctx)
{
ext2_filsys fs = ctx->fs;
ext2_ino_t inodes, inodes_used;
- blk_t blocks, blocks_used;
- int dir_links;
- int num_files, num_links;
+ blk
64
_t blocks, blocks_used;
+
unsigned
int dir_links;
+
unsigned
int num_files, num_links;
int frag_percent_file, frag_percent_dir, frag_percent_total;
int i, j;
@@
-113,9
+113,9
@@
static void show_stats(e2fsck_t ctx)
inodes = fs->super->s_inodes_count;
inodes_used = (fs->super->s_inodes_count -
fs->super->s_free_inodes_count);
- blocks =
fs->super->s_blocks_count
;
- blocks_used = (
fs->super->s_blocks_count
-
-
fs->super->s_free_blocks_count
);
+ blocks =
ext2fs_blocks_count(fs->super)
;
+ blocks_used = (
ext2fs_blocks_count(fs->super)
-
+
ext2fs_free_blocks_count(fs->super)
);
frag_percent_file = (10000 * ctx->fs_fragmented) / inodes_used;
frag_percent_file = (frag_percent_file + 5) / 10;
@@
-129,7
+129,7
@@
static void show_stats(e2fsck_t ctx)
frag_percent_total = (frag_percent_total + 5) / 10;
if (!verbose) {
- printf(_("%s: %u/%u files (%0d.%d%% non-contiguous), %
u/%
u blocks\n"),
+ printf(_("%s: %u/%u files (%0d.%d%% non-contiguous), %
llu/%ll
u blocks\n"),
ctx->device_name, inodes_used, inodes,
frag_percent_total / 10, frag_percent_total % 10,
blocks_used, blocks);
@@
-163,7
+163,8
@@
static void show_stats(e2fsck_t ctx)
fputc('\n', stdout);
}
- printf (P_("%8u block used (%2.2f%%)\n", "%8u blocks used (%2.2f%%)\n",
+ printf (P_("%8llu block used (%2.2f%%)\n",
+ "%8llu blocks used (%2.2f%%)\n",
blocks_used), blocks_used, 100.0 * blocks_used / blocks);
printf (P_("%8u bad block\n", "%8u bad blocks\n",
ctx->fs_badblocks_count), ctx->fs_badblocks_count);
@@
-230,9
+231,9
@@
static void check_mount(e2fsck_t ctx)
if (!ctx->interactive)
fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
printf(_("\n\n\007\007\007\007WARNING!!! "
- "
Running e2fsck on a mounted filesystem may cause
\n"
- "
SEVERE
filesystem damage.\007\007\007\n\n"));
- cont = ask_yn(_("Do you really want to continue"),
-1
);
+ "
The filesystem is mounted. If you continue you ***WILL***
\n"
+ "
cause ***SEVERE***
filesystem damage.\007\007\007\n\n"));
+ cont = ask_yn(_("Do you really want to continue"),
0
);
if (!cont) {
printf (_("check aborted.\n"));
exit (0);
@@
-291,8
+292,13
@@
static void check_if_skip(e2fsck_t ctx)
long next_check;
int batt = is_on_batt();
int defer_check_on_battery;
+ int broken_system_clock;
time_t lastcheck;
+ profile_get_boolean(ctx->profile, "options", "broken_system_clock",
+ 0, 0, &broken_system_clock);
+ if (ctx->flags & E2F_FLAG_TIME_INSANE)
+ broken_system_clock = 1;
profile_get_boolean(ctx->profile, "options",
"defer_check_on_battery", 0, 1,
&defer_check_on_battery);
@@
-302,6
+308,9
@@
static void check_if_skip(e2fsck_t ctx)
if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag)
return;
+ if (ctx->options & E2F_OPT_JOURNAL_ONLY)
+ goto skip;
+
lastcheck = fs->super->s_lastcheck;
if (lastcheck > ctx->now)
lastcheck -= ctx->time_fudge;
@@
-320,11
+329,12
@@
static void check_if_skip(e2fsck_t ctx)
if (batt && (fs->super->s_mnt_count <
(unsigned) fs->super->s_max_mnt_count*2))
reason = 0;
- } else if (fs->super->s_checkinterval && (ctx->now < lastcheck)) {
+ } else if (!broken_system_clock && fs->super->s_checkinterval &&
+ (ctx->now < lastcheck)) {
reason = _(" has filesystem last checked time in the future");
if (batt)
reason = 0;
- } else if (fs->super->s_checkinterval &&
+ } else if (
!broken_system_clock &&
fs->super->s_checkinterval &&
((ctx->now - lastcheck) >=
((time_t) fs->super->s_checkinterval))) {
reason = _(" has gone %u days without being checked");
@@
-339,18
+349,19
@@
static void check_if_skip(e2fsck_t ctx)
fputs(_(", check forced.\n"), stdout);
return;
}
- printf(_("%s: clean, %u/%u files, %
u/%
u blocks"), ctx->device_name,
+ printf(_("%s: clean, %u/%u files, %
llu/%ll
u blocks"), ctx->device_name,
fs->super->s_inodes_count - fs->super->s_free_inodes_count,
fs->super->s_inodes_count,
- fs->super->s_blocks_count - fs->super->s_free_blocks_count,
- fs->super->s_blocks_count);
+ ext2fs_blocks_count(fs->super) -
+ ext2fs_free_blocks_count(fs->super),
+ ext2fs_blocks_count(fs->super));
next_check = 100000;
if (fs->super->s_max_mnt_count > 0) {
next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
if (next_check <= 0)
next_check = 1;
}
- if (fs->super->s_checkinterval &&
+ if (
!broken_system_clock &&
fs->super->s_checkinterval &&
((ctx->now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
next_check = 1;
if (next_check <= 5) {
@@
-364,6
+375,7
@@
static void check_if_skip(e2fsck_t ctx)
printf(_(" (check in %ld mounts)"), next_check);
}
fputc('\n', stdout);
+skip:
ext2fs_close(fs);
ctx->fs = NULL;
e2fsck_free_context(ctx);
@@
-586,6
+598,18
@@
static void parse_extended_opts(e2fsck_t ctx, const char *opts)
} else if (strcmp(token, "fragcheck") == 0) {
ctx->options |= E2F_OPT_FRAGCHECK;
continue;
+ } else if (strcmp(token, "journal_only") == 0) {
+ if (arg) {
+ extended_usage++;
+ continue;
+ }
+ ctx->options |= E2F_OPT_JOURNAL_ONLY;
+ } else if (strcmp(token, "discard") == 0) {
+ ctx->options |= E2F_OPT_DISCARD;
+ continue;
+ } else if (strcmp(token, "nodiscard") == 0) {
+ ctx->options &= ~E2F_OPT_DISCARD;
+ continue;
} else {
fprintf(stderr, _("Unknown extended option: %s\n"),
token);
@@
-601,6
+625,9
@@
static void parse_extended_opts(e2fsck_t ctx, const char *opts)
"Valid extended options are:\n"), stderr);
fputs(("\tea_ver=<ea_version (1 or 2)>\n"), stderr);
fputs(("\tfragcheck\n"), stderr);
+ fputs(("\tjournal_only\n"), stderr);
+ fputs(("\tdiscard\n"), stderr);
+ fputs(("\tnodiscard\n"), stderr);
fputc('\n', stderr);
exit(1);
}
@@
-659,6
+686,7
@@
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
ctx->program_name = *argv;
else
ctx->program_name = "e2fsck";
+
while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
switch (c) {
case 'C':
@@
-730,7
+758,7
@@
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
/* What we do by default, anyway! */
break;
case 'b':
- res = sscanf(optarg, "%u", &ctx->use_superblock);
+ res = sscanf(optarg, "%
ll
u", &ctx->use_superblock);
if (res != 1)
goto sscanf_err;
ctx->flags |= E2F_FLAG_SB_SPECIFIED;
@@
-744,7
+772,14
@@
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
goto sscanf_err;
break;
case 'j':
- ctx->journal_name = string_copy(ctx, optarg, 0);
+ ctx->journal_name = blkid_get_devname(ctx->blkid,
+ optarg, NULL);
+ if (!ctx->journal_name) {
+ com_err(ctx->program_name, 0,
+ _("Unable to resolve '%s'"),
+ optarg);
+ fatal_error(ctx, 0);
+ }
break;
case 'P':
res = sscanf(optarg, "%d", &ctx->process_inode_size);
@@
-789,8
+824,23
@@
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
return 0;
if (optind != argc - 1)
usage(ctx);
- if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
- !cflag && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
+ if ((ctx->options & E2F_OPT_NO) &&
+ (ctx->options & E2F_OPT_COMPRESS_DIRS)) {
+ com_err(ctx->program_name, 0,
+ _("The -n and -D options are incompatible."));
+ fatal_error(ctx, 0);
+ }
+ if ((ctx->options & E2F_OPT_NO) && cflag) {
+ com_err(ctx->program_name, 0,
+ _("The -n and -c options are incompatible."));
+ fatal_error(ctx, 0);
+ }
+ if ((ctx->options & E2F_OPT_NO) && bad_blocks_file) {
+ com_err(ctx->program_name, 0,
+ _("The -n and -l/-L options are incompatible."));
+ fatal_error(ctx, 0);
+ }
+ if (ctx->options & E2F_OPT_NO)
ctx->options |= E2F_OPT_READONLY;
ctx->io_options = strchr(argv[optind], '?');
@@
-802,7
+852,6
@@
static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
argv[optind]);
fatal_error(ctx, 0);
}
- ctx->filesystem_name = string_copy(ctx, ctx->filesystem_name, 0);
if (extended_opts)
parse_extended_opts(ctx, extended_opts);
@@
-890,12
+939,43
@@
sscanf_err:
exit (1);
}
+static errcode_t try_open_fs(e2fsck_t ctx, int flags, io_manager io_ptr,
+ ext2_filsys *ret_fs)
+{
+ errcode_t retval;
+
+ *ret_fs = NULL;
+ if (ctx->superblock && ctx->blocksize) {
+ retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
+ flags, ctx->superblock, ctx->blocksize,
+ io_ptr, ret_fs);
+ } else if (ctx->superblock) {
+ int blocksize;
+ for (blocksize = EXT2_MIN_BLOCK_SIZE;
+ blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
+ if (*ret_fs) {
+ ext2fs_free(*ret_fs);
+ *ret_fs = NULL;
+ }
+ retval = ext2fs_open2(ctx->filesystem_name,
+ ctx->io_options, flags,
+ ctx->superblock, blocksize,
+ io_ptr, ret_fs);
+ if (!retval)
+ break;
+ }
+ } else
+ retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
+ flags, 0, 0, io_ptr, ret_fs);
+ return retval;
+}
+
static const char *my_ver_string = E2FSPROGS_VERSION;
static const char *my_ver_date = E2FSPROGS_DATE;
int main (int argc, char *argv[])
{
- errcode_t retval = 0, orig_retval = 0;
+ errcode_t retval = 0,
retval2 = 0,
orig_retval = 0;
int exit_value = FSCK_OK;
ext2_filsys fs = 0;
io_manager io_ptr;
@@
-903,10
+983,12
@@
int main (int argc, char *argv[])
const char *lib_ver_date;
int my_ver, lib_ver;
e2fsck_t ctx;
+ blk_t orig_superblock;
struct problem_context pctx;
int flags, run_result;
int journal_size;
int sysval, sys_page_size = 4096;
+ int old_bitmaps;
__u32 features[3];
char *cp;
@@
-939,10
+1021,7
@@
int main (int argc, char *argv[])
}
reserve_stdio_fds();
-#ifdef RESOURCE_TRACK
init_resource_track(&ctx->global_rtrack, NULL);
-#endif
-
if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
my_ver_date);
@@
-972,36
+1051,26
@@
restart:
#endif
io_ptr = unix_io_manager;
flags = EXT2_FLAG_NOFREE_ON_ERROR;
+ profile_get_boolean(ctx->profile, "options", "old_bitmaps", 0, 0,
+ &old_bitmaps);
+ if (!old_bitmaps)
+ flags |= EXT2_FLAG_64BITS;
if ((ctx->options & E2F_OPT_READONLY) == 0)
flags |= EXT2_FLAG_RW;
if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0)
flags |= EXT2_FLAG_EXCLUSIVE;
- if (ctx->superblock && ctx->blocksize) {
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, ctx->superblock, ctx->blocksize,
- io_ptr, &fs);
- } else if (ctx->superblock) {
- int blocksize;
- for (blocksize = EXT2_MIN_BLOCK_SIZE;
- blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
- if (fs)
- ext2fs_free(fs);
- retval = ext2fs_open2(ctx->filesystem_name,
- ctx->io_options, flags,
- ctx->superblock, blocksize,
- io_ptr, &fs);
- if (!retval)
- break;
- }
- } else
- retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
- flags, 0, 0, io_ptr, &fs);
+ retval = try_open_fs(ctx, flags, io_ptr, &fs);
+
if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
!(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
((retval == EXT2_ET_BAD_MAGIC) ||
(retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
- ((retval == 0) && ext2fs_check_desc(fs)))) {
+ ((retval == 0) && (retval2 = ext2fs_check_desc(fs))))) {
+ if (retval2 == ENOMEM) {
+ retval = retval2;
+ goto failure;
+ }
if (fs->flags & EXT2_FLAG_NOFREE_ON_ERROR) {
ext2fs_free(fs);
fs = NULL;
@@
-1011,11
+1080,22
@@
restart:
ctx->program_name,
retval ? _("Superblock invalid,") :
_("Group descriptors look bad..."));
+ orig_superblock = ctx->superblock;
get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
if (fs)
ext2fs_close(fs);
orig_retval = retval;
- goto restart;
+ retval = try_open_fs(ctx, flags, io_ptr, &fs);
+ if ((orig_retval == 0) && retval != 0) {
+ if (fs)
+ ext2fs_close(fs);
+ com_err(ctx->program_name, retval,
+ "when using the backup blocks");
+ printf(_("%s: going back to original "
+ "superblock\n"), ctx->program_name);
+ ctx->superblock = orig_superblock;
+ retval = try_open_fs(ctx, flags, io_ptr, &fs);
+ }
}
}
if (((retval == EXT2_ET_UNSUPP_FEATURE) ||
@@
-1031,6
+1111,7
@@
restart:
if (features[0] || features[1] || features[2])
goto print_unsupp_features;
}
+failure:
if (retval) {
if (orig_retval)
retval = orig_retval;
@@
-1054,6
+1135,8
@@
restart:
else if (retval == EBUSY)
printf(_("Filesystem mounted or opened exclusively "
"by another program?\n"));
+ else if (retval == ENOENT)
+ printf(_("Possibly non-existent device?\n"));
#ifdef EROFS
else if (retval == EROFS)
printf(_("Disk write-protected; use the -n option "
@@
-1081,9
+1164,9
@@
restart:
__u32 blocksize = EXT2_BLOCK_SIZE(fs->super);
int need_restart = 0;
- pctx.errcode = ext2fs_get_device_size(ctx->filesystem_name,
- blocksize,
- &ctx->num_blocks);
+ pctx.errcode = ext2fs_get_device_size
2
(ctx->filesystem_name,
+
blocksize,
+
&ctx->num_blocks);
/*
* The floppy driver refuses to allow anyone else to
* open the device if has been opened with O_EXCL;
@@
-1095,9
+1178,9
@@
restart:
ext2fs_close(fs);
need_restart++;
pctx.errcode =
- ext2fs_get_device_size(ctx->filesystem_name,
- blocksize,
- &ctx->num_blocks);
+ ext2fs_get_device_size
2
(ctx->filesystem_name,
+
blocksize,
+
&ctx->num_blocks);
}
if (pctx.errcode == EXT2_ET_UNIMPLEMENTED)
ctx->num_blocks = 0;
@@
-1138,6
+1221,12
@@
restart:
if (isspace(*cp) || *cp == ':')
*cp = '_';
+ ehandler_init(fs->io);
+
+ if ((ctx->mount_flags & EXT2_MF_MOUNTED) &&
+ !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER))
+ goto skip_journal;
+
/*
* Make sure the ext3 superblock fields are consistent.
*/
@@
-1185,6
+1274,7
@@
restart:
}
}
+skip_journal:
/*
* Check for compatibility with the feature sets. We need to
* be more stringent than ext2fs_open().
@@
-1249,8
+1339,6
@@
print_unsupp_features:
if (ctx->blocks_per_page == 0)
ctx->blocks_per_page = 1;
- ehandler_init(fs->io);
-
if (ctx->superblock)
set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
ext2fs_mark_valid(fs);
@@
-1258,6
+1346,7
@@
print_unsupp_features:
if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
fatal_error(ctx, 0);
check_if_skip(ctx);
+ check_resize_inode(ctx);
if (bad_blocks_file)
read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
else if (cflag)
@@
-1285,7
+1374,8
@@
print_unsupp_features:
* find the default journal size.
*/
if (sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS)
- journal_size = sb->s_jnl_blocks[16] >> 20;
+ journal_size = (sb->s_jnl_blocks[15] << (32 - 20)) |
+ (sb->s_jnl_blocks[16] >> 20);
else
journal_size = -1;
@@
-1295,7
+1385,7
@@
print_unsupp_features:
if (ctx->flags & E2F_FLAG_JOURNAL_INODE) {
if (fix_problem(ctx, PR_6_RECREATE_JOURNAL, &pctx)) {
if (journal_size < 1024)
- journal_size = ext2fs_default_journal_size(
fs->super->s_blocks_count
);
+ journal_size = ext2fs_default_journal_size(
ext2fs_blocks_count(fs->super)
);
if (journal_size < 0) {
fs->super->s_feature_compat &=
~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
@@
-1387,12
+1477,16
@@
no_journal:
} else
sb->s_state &= ~EXT2_VALID_FS;
sb->s_mnt_count = 0;
- sb->s_lastcheck = ctx->now;
+ if (!(ctx->flags & E2F_FLAG_TIME_INSANE))
+ sb->s_lastcheck = ctx->now;
+ memset(((char *) sb) + EXT4_S_ERR_START, 0,
+ EXT4_S_ERR_LEN);
ext2fs_mark_super_dirty(fs);
}
}
- if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
+ if ((run_result & E2F_FLAG_CANCEL) == 0 &&
+ sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
!(ctx->options & E2F_OPT_READONLY)) {
retval = ext2fs_set_gdt_csum(ctx->fs);
if (retval) {
@@
-1403,11
+1497,9
@@
no_journal:
}
e2fsck_write_bitmaps(ctx);
-#ifdef RESOURCE_TRACK
io_channel_flush(ctx->fs->io);
- if (ctx->options & E2F_OPT_TIME)
- print_resource_track(NULL, &ctx->global_rtrack, ctx->fs->io);
-#endif
+ print_resource_track(ctx, NULL, &ctx->global_rtrack, ctx->fs->io);
+
ext2fs_close(fs);
ctx->fs = NULL;
free(ctx->journal_name);