Whamcloud - gitweb
Make e2fsck uninit block group aware
[tools/e2fsprogs.git] / e2fsck / unix.c
index 950e2d4..7b662e4 100644 (file)
@@ -52,8 +52,6 @@ extern int optind;
 #include "../version.h"
 
 /* Command line options */
-static int swapfs;
-static int normalize_swapfs;
 static int cflag;              /* check disk */
 static int show_version_only;
 static int verbose;
@@ -71,7 +69,7 @@ int journal_enable_debug = -1;
 static void usage(e2fsck_t ctx)
 {
        fprintf(stderr,
-               _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
+               _("Usage: %s [-panyrcdfvtDFV] [-b superblock] [-B blocksize]\n"
                "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
                "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
                "\t\t[-E extended-options] device\n"),
@@ -260,6 +258,7 @@ static void check_if_skip(e2fsck_t ctx)
        long next_check;
        int batt = is_on_batt();
        int defer_check_on_battery;
+       time_t lastcheck;
 
        profile_get_boolean(ctx->profile, "options",
                            "defer_check_on_battery", 0, 1, 
@@ -267,15 +266,19 @@ static void check_if_skip(e2fsck_t ctx)
        if (!defer_check_on_battery)
                batt = 0;
 
-       if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
-           cflag || swapfs)
+       if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag)
                return;
        
+       lastcheck = fs->super->s_lastcheck;
+       if (lastcheck > ctx->now)
+               lastcheck -= ctx->time_fudge;
        if ((fs->super->s_state & EXT2_ERROR_FS) ||
            !ext2fs_test_valid(fs))
                reason = _(" contains a file system with errors");
        else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
                reason = _(" was not cleanly unmounted");
+       else if (check_backup_super_block(ctx))
+               reason = _(" primary superblock features different from backup");
        else if ((fs->super->s_max_mnt_count > 0) &&
                 (fs->super->s_mnt_count >=
                  (unsigned) fs->super->s_max_mnt_count)) {
@@ -285,8 +288,7 @@ static void check_if_skip(e2fsck_t ctx)
                             (unsigned) fs->super->s_max_mnt_count*2))
                        reason = 0;
        } else if (fs->super->s_checkinterval &&
-                  ((ctx->now - fs->super->s_lastcheck) >= 
-                   fs->super->s_checkinterval)) {
+                  ((ctx->now - lastcheck) >= fs->super->s_checkinterval)) {
                reason = _(" has gone %u days without being checked");
                reason_arg = (ctx->now - fs->super->s_lastcheck)/(3600*24);
                if (batt && ((ctx->now - fs->super->s_lastcheck) < 
@@ -556,7 +558,9 @@ static void parse_extended_opts(e2fsck_t ctx, const char *opts)
                       "and may take an argument which\n"
                       "is set off by an equals ('=') sign.  "
                        "Valid extended options are:\n"
-                      "\tea_ver=<ea_version (1 or 2)>\n\n"), stderr);
+                       "\tea_ver=<ea_version (1 or 2)>\n"
+                       "\tuninit_groups\n"
+                       "\tinit_groups\n\n"), stderr);
                exit(1);
        }
 }
@@ -730,20 +734,6 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                case 'N':
                        ctx->device_name = optarg;
                        break;
-#ifdef ENABLE_SWAPFS
-               case 's':
-                       normalize_swapfs = 1;
-               case 'S':
-                       swapfs = 1;
-                       break;
-#else
-               case 's':
-               case 'S':
-                       fprintf(stderr, _("Byte-swapping filesystems "
-                                         "not compiled in this version "
-                                         "of e2fsck\n"));
-                       exit(1);
-#endif
                case 'k':
                        keep_bad_blocks++;
                        break;
@@ -755,8 +745,9 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
        if (optind != argc - 1)
                usage(ctx);
        if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
-           !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
+           !cflag && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
                ctx->options |= E2F_OPT_READONLY;
+
        ctx->io_options = strchr(argv[optind], '?');
        if (ctx->io_options) 
                *ctx->io_options++ = 0;
@@ -790,15 +781,6 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                }
                close(fd);
        }
-#ifdef ENABLE_SWAPFS
-       if (swapfs) {
-               if (cflag || bad_blocks_file) {
-                       fprintf(stderr, _("Incompatible options not "
-                                         "allowed when byte-swapping.\n"));
-                       exit(FSCK_USAGE);
-               }
-       }
-#endif
        if (cflag && bad_blocks_file) {
                fprintf(stderr, _("The -c and the -l/-L options may "
                                  "not be both used at the same time.\n"));
@@ -844,7 +826,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
        }
 #ifdef CONFIG_JBD_DEBUG
        jbd_debug = getenv("E2FSCK_JBD_DEBUG");
-       if (jbd_debug)
+       if (jbd_debug) {
                res = sscanf(jbd_debug, "%d", &journal_enable_debug);
                if (res != 1) {
                        fprintf(stderr,
@@ -852,6 +834,7 @@ static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
                                jbd_debug);
                        exit (1);
                }
+       }
 #endif
        return 0;
 
@@ -863,7 +846,7 @@ sscanf_err:
 
 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;
@@ -878,6 +861,7 @@ int main (int argc, char *argv[])
        int flags, run_result;
        int journal_size;
        int sysval, sys_page_size = 4096;
+       __u32 features[3];
        
        clear_problem_context(&pctx);
 #ifdef MTRACE
@@ -909,7 +893,7 @@ int main (int argc, char *argv[])
        reserve_stdio_fds();
        
 #ifdef RESOURCE_TRACK
-       init_resource_track(&ctx->global_rtrack);
+       init_resource_track(&ctx->global_rtrack, NULL);
 #endif
 
        if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
@@ -939,7 +923,7 @@ restart:
 #else
        io_ptr = unix_io_manager;
 #endif
-       flags = 0;
+       flags = EXT2_FLAG_NOFREE_ON_ERROR;
        if ((ctx->options & E2F_OPT_READONLY) == 0)
                flags |= EXT2_FLAG_RW;
        if ((ctx->mount_flags & EXT2_MF_MOUNTED) == 0)
@@ -968,6 +952,10 @@ restart:
            ((retval == EXT2_ET_BAD_MAGIC) ||
             (retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
             ((retval == 0) && ext2fs_check_desc(fs)))) {
+               if (fs->flags & EXT2_FLAG_NOFREE_ON_ERROR) {
+                       ext2fs_free(fs);
+                       fs = NULL;
+               }
                if (!fs || (fs->group_desc_count > 1)) {
                        printf(_("%s: %s trying backup blocks...\n"),
                               ctx->program_name, 
@@ -980,6 +968,19 @@ restart:
                        goto restart;
                }
        }
+       if (((retval == EXT2_ET_UNSUPP_FEATURE) ||
+            (retval == EXT2_ET_RO_UNSUPP_FEATURE)) &&
+           fs && fs->super) {
+               sb = fs->super;
+               features[0] = (sb->s_feature_compat & 
+                              ~EXT2_LIB_FEATURE_COMPAT_SUPP);
+               features[1] = (sb->s_feature_incompat & 
+                              ~EXT2_LIB_FEATURE_INCOMPAT_SUPP);
+               features[2] = (sb->s_feature_ro_compat & 
+                              ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP);
+               if (features[0] || features[1] || features[2])
+                       goto print_unsupp_features;
+       }
        if (retval) {
                if (orig_retval)
                        retval = orig_retval;
@@ -1135,15 +1136,26 @@ restart:
         * Check for compatibility with the feature sets.  We need to
         * be more stringent than ext2fs_open().
         */
-       if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
-           (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
-               com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
-                       "(%s)", ctx->device_name);
-               goto get_newer;
-       }
-       if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
-               com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
-                       "(%s)", ctx->device_name);
+       features[0] = sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP;
+       features[1] = sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP;
+       features[2] = (sb->s_feature_ro_compat & 
+                      ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP);
+print_unsupp_features:
+       if (features[0] || features[1] || features[2]) {
+               int     i, j;
+               __u32   *mask = features, m;
+
+               fprintf(stderr, _("%s has unsupported feature(s):"), 
+                       ctx->filesystem_name);
+
+               for (i=0; i <3; i++,mask++) {
+                       for (j=0,m=1; j < 32; j++, m<<=1) {
+                               if (*mask & m)
+                                       fprintf(stderr, " %s", 
+                                               e2p_feature2string(i, m));
+                       }
+               }
+               putc('\n', stderr);
                goto get_newer;
        }
 #ifdef ENABLE_COMPRESSION
@@ -1199,21 +1211,6 @@ restart:
                read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
                fatal_error(ctx, 0);
-#ifdef ENABLE_SWAPFS
-       if (normalize_swapfs) {
-               if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
-                   ext2fs_native_flag()) {
-                       fprintf(stderr, _("%s: Filesystem byte order "
-                               "already normalized.\n"), ctx->device_name);
-                       fatal_error(ctx, 0);
-               }
-       }
-       if (swapfs) {
-               swap_filesys(ctx);
-               if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
-                       fatal_error(ctx, 0);
-       }
-#endif
 
        /*
         * Mark the system as valid, 'til proven otherwise
@@ -1249,6 +1246,7 @@ restart:
                        if (journal_size < 0) {
                                fs->super->s_feature_compat &=
                                        ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
+                               fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
                                com_err(ctx->program_name, 0, 
                                        _("Couldn't determine journal size"));
                                goto no_journal;
@@ -1288,6 +1286,10 @@ no_journal:
        }
        if (run_result & E2F_FLAG_ABORT)
                fatal_error(ctx, _("aborted"));
+       if (check_backup_super_block(ctx)) {
+               fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
+               ext2fs_mark_super_dirty(fs);
+       }
 
 #ifdef MTRACE
        mtrace_print("Cleanup");
@@ -1337,17 +1339,21 @@ no_journal:
                }
        }
 
+       if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
+           !(ctx->options & E2F_OPT_READONLY))
+               ext2fs_set_gdt_csum(ctx->fs);
+
        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
        ext2fs_close(fs);
        ctx->fs = NULL;
        free(ctx->filesystem_name);
        free(ctx->journal_name);
 
-#ifdef RESOURCE_TRACK
-       if (ctx->options & E2F_OPT_TIME)
-               print_resource_track(NULL, &ctx->global_rtrack);
-#endif
        e2fsck_free_context(ctx);
        remove_error_table(&et_ext2_error_table);
        remove_error_table(&et_prof_error_table);