Whamcloud - gitweb
libext2fs: optimize ext2fs_convert_subcluster_bitmap()
[tools/e2fsprogs.git] / misc / dumpe2fs.c
index 395ea9e..5c955a9 100644 (file)
@@ -53,7 +53,7 @@ static int blocks64 = 0;
 
 static void usage(void)
 {
-       fprintf(stderr, _("Usage: %s [-bfghixV] [-o superblock=<num>] "
+       fprintf(stderr, _("Usage: %s [-bfghimxV] [-o superblock=<num>] "
                 "[-o blocksize=<num>] device\n"), program_name);
        exit(1);
 }
@@ -387,7 +387,7 @@ static void print_inline_journal_information(ext2_filsys fs)
        }
        ext2fs_file_close(journal_file);
        jsb = (journal_superblock_t *) buf;
-       if (be32_to_cpu(jsb->s_header.h_magic) != JFS_MAGIC_NUMBER) {
+       if (be32_to_cpu(jsb->s_header.h_magic) != JBD2_MAGIC_NUMBER) {
                fprintf(stderr, "%s",
                        _("Journal superblock magic number invalid!\n"));
                exit(1);
@@ -410,9 +410,9 @@ static void print_journal_information(ext2_filsys fs)
                exit(1);
        }
        jsb = (journal_superblock_t *) buf;
-       if ((jsb->s_header.h_magic != (unsigned) ntohl(JFS_MAGIC_NUMBER)) ||
+       if ((jsb->s_header.h_magic != (unsigned) ntohl(JBD2_MAGIC_NUMBER)) ||
            (jsb->s_header.h_blocktype !=
-            (unsigned) ntohl(JFS_SUPERBLOCK_V2))) {
+            (unsigned) ntohl(JBD2_SUPERBLOCK_V2))) {
                com_err(program_name, 0, "%s",
                        _("Couldn't find journal superblock magic numbers"));
                exit(1);
@@ -420,6 +420,83 @@ static void print_journal_information(ext2_filsys fs)
        e2p_list_journal_super(stdout, buf, fs->blocksize, 0);
 }
 
+static int check_mmp(ext2_filsys fs)
+{
+       int retval;
+
+       /* This won't actually start MMP on the filesystem, since fs is opened
+        * readonly, but it will do the proper activity checking for us. */
+       retval = ext2fs_mmp_start(fs);
+       if (retval) {
+               com_err(program_name, retval, _("while trying to open %s"),
+                       fs->device_name);
+               if (retval == EXT2_ET_MMP_FAILED ||
+                   retval == EXT2_ET_MMP_FSCK_ON ||
+                   retval == EXT2_ET_MMP_CSUM_INVALID ||
+                   retval == EXT2_ET_MMP_UNKNOWN_SEQ) {
+                       if (fs->mmp_buf) {
+                               struct mmp_struct *mmp = fs->mmp_buf;
+                               time_t mmp_time = mmp->mmp_time;
+
+                               fprintf(stderr,
+                                       "%s: MMP update by '%.*s%.*s' at %s",
+                                       program_name,
+                                       EXT2_LEN_STR(mmp->mmp_nodename),
+                                       EXT2_LEN_STR(mmp->mmp_bdevname),
+                                       ctime(&mmp_time));
+                       }
+                       retval = 1;
+               } else {
+                       retval = 2;
+               }
+       } else {
+               printf("%s: it is safe to mount '%s', MMP is clean\n",
+                      program_name, fs->device_name);
+       }
+
+       return retval;
+}
+
+static void print_mmp_block(ext2_filsys fs)
+{
+       struct mmp_struct *mmp;
+       time_t mmp_time;
+       errcode_t retval;
+
+       if (fs->mmp_buf == NULL) {
+               retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
+               if (retval) {
+                       com_err(program_name, retval,
+                               _("failed to alloc MMP buffer\n"));
+                       return;
+               }
+       }
+
+       retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
+       /* this is only dumping, not checking status, so OK to skip this */
+       if (retval == EXT2_ET_OP_NOT_SUPPORTED)
+               return;
+       if (retval) {
+               com_err(program_name, retval,
+                       _("reading MMP block %llu from '%s'\n"),
+                       fs->super->s_mmp_block, fs->device_name);
+               return;
+       }
+
+       mmp = fs->mmp_buf;
+       mmp_time = mmp->mmp_time;
+       printf("MMP_block:\n");
+       printf("    mmp_magic: 0x%x\n", mmp->mmp_magic);
+       printf("    mmp_check_interval: %d\n", mmp->mmp_check_interval);
+       printf("    mmp_sequence: %#08x\n", mmp->mmp_seq);
+       printf("    mmp_update_date: %s", ctime(&mmp_time));
+       printf("    mmp_update_time: %lld\n", mmp->mmp_time);
+       printf("    mmp_node_name: %.*s\n",
+              EXT2_LEN_STR(mmp->mmp_nodename));
+       printf("    mmp_device_name: %.*s\n",
+              EXT2_LEN_STR(mmp->mmp_bdevname));
+}
+
 static void parse_extended_opts(const char *opts, blk64_t *superblock,
                                int *blocksize)
 {
@@ -500,11 +577,15 @@ static void parse_extended_opts(const char *opts, blk64_t *superblock,
 int main (int argc, char ** argv)
 {
        errcode_t       retval;
+       errcode_t       retval_csum = 0;
+       const char      *error_csum = NULL;
        ext2_filsys     fs;
        int             print_badblocks = 0;
        blk64_t         use_superblock = 0;
        int             use_blocksize = 0;
        int             image_dump = 0;
+       int             mmp_check = 0;
+       int             mmp_info = 0;
        int             force = 0;
        int             flags;
        int             header_only = 0;
@@ -519,12 +600,23 @@ int main (int argc, char ** argv)
        set_com_err_gettext(gettext);
 #endif
        add_error_table(&et_ext2_error_table);
-       fprintf (stderr, "dumpe2fs %s (%s)\n", E2FSPROGS_VERSION,
-                E2FSPROGS_DATE);
-       if (argc && *argv)
-               program_name = *argv;
+       if (argc && *argv) {
+               if (strrchr(*argv, '/'))
+                       program_name = strrchr(*argv, '/') + 1;
+               else
+                       program_name = *argv;
+
+               if (strstr(program_name, "mmpstatus") != NULL) {
+                       mmp_check = 1;
+                       header_only = 1;
+               }
+       }
 
-       while ((c = getopt(argc, argv, "bfghixVo:")) != EOF) {
+       if (!mmp_check)
+               fprintf(stderr, "dumpe2fs %s (%s)\n", E2FSPROGS_VERSION,
+                       E2FSPROGS_DATE);
+
+       while ((c = getopt(argc, argv, "bfghimxVo:")) != EOF) {
                switch (c) {
                case 'b':
                        print_badblocks++;
@@ -539,7 +631,18 @@ int main (int argc, char ** argv)
                        header_only++;
                        break;
                case 'i':
-                       image_dump++;
+                       if (mmp_check)
+                               mmp_info++;
+                       else
+                               image_dump++;
+                       break;
+               case 'm':
+                       mmp_check++;
+                       header_only++;
+                       if (image_dump) {
+                               mmp_info = image_dump;
+                               image_dump = 0;
+                       }
                        break;
                case 'o':
                        parse_extended_opts(optarg, &use_superblock,
@@ -557,16 +660,18 @@ int main (int argc, char ** argv)
                        usage();
                }
        }
-       if (optind != argc - 1) {
+       if (optind != argc - 1)
                usage();
-               exit(1);
-       }
+
        device_name = argv[optind++];
-       flags = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
+       flags = EXT2_FLAG_JOURNAL_DEV_OK | EXT2_FLAG_SOFTSUPP_FEATURES |
+               EXT2_FLAG_64BITS;
        if (force)
                flags |= EXT2_FLAG_FORCE;
        if (image_dump)
                flags |= EXT2_FLAG_IMAGE_FILE;
+       if (header_only)
+               flags |= EXT2_FLAG_SUPER_ONLY;
 try_open_again:
        if (use_superblock && !use_blocksize) {
                for (use_blocksize = EXT2_MIN_BLOCK_SIZE;
@@ -579,64 +684,87 @@ try_open_again:
                        if (!retval)
                                break;
                }
-       } else
-               retval = ext2fs_open (device_name, flags, use_superblock,
-                                     use_blocksize, unix_io_manager, &fs);
-       if (retval && !(flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) {
-               flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
-               goto try_open_again;
+       } else {
+               retval = ext2fs_open(device_name, flags, use_superblock,
+                                    use_blocksize, unix_io_manager, &fs);
        }
-       if (!retval && (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS))
-               printf("%s", _("\n*** Checksum errors detected in filesystem!  Run e2fsck now!\n\n"));
        flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
+       if (retval && !retval_csum) {
+               retval_csum = retval;
+               error_csum = _("while trying to open %s");
+               goto try_open_again;
+       }
        if (retval) {
-               com_err (program_name, retval, _("while trying to open %s"),
-                        device_name);
+               com_err(program_name, retval, _("while trying to open %s"),
+                       device_name);
                printf("%s", _("Couldn't find valid filesystem superblock.\n"));
                if (retval == EXT2_ET_BAD_MAGIC)
                        check_plausibility(device_name, CHECK_FS_EXIST, NULL);
-               exit (1);
+               goto out;
        }
        fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
        if (ext2fs_has_feature_64bit(fs->super))
                blocks64 = 1;
-       if (print_badblocks) {
+       if (mmp_check) {
+               if (ext2fs_has_feature_mmp(fs->super) &&
+                   fs->super->s_mmp_block != 0) {
+                       if (mmp_info) {
+                               print_mmp_block(fs);
+                               printf("    mmp_block_number: ");
+                               print_number(fs->super->s_mmp_block);
+                               printf("\n");
+                       } else {
+                               retval = check_mmp(fs);
+                       }
+                       if (!retval && retval_csum)
+                               retval = 2;
+               } else {
+                       fprintf(stderr, _("%s: MMP feature not enabled.\n"),
+                               program_name);
+                       retval = 2;
+               }
+       } else if (print_badblocks) {
                list_bad_blocks(fs, 1);
        } else {
                if (grp_only)
                        goto just_descriptors;
-               list_super (fs->super);
+               list_super(fs->super);
                if (ext2fs_has_feature_journal_dev(fs->super)) {
                        print_journal_information(fs);
-                       ext2fs_close_free(&fs);
-                       exit(0);
+
+                       goto out_close;
                }
                if (ext2fs_has_feature_journal(fs->super) &&
                    (fs->super->s_journal_inum != 0))
                        print_inline_journal_information(fs);
+               if (ext2fs_has_feature_mmp(fs->super) &&
+                   fs->super->s_mmp_block != 0)
+                       print_mmp_block(fs);
                list_bad_blocks(fs, 0);
-               if (header_only) {
-                       ext2fs_close_free(&fs);
-                       exit (0);
-               }
+               if (header_only)
+                       goto out_close;
+
                fs->flags &= ~EXT2_FLAG_IGNORE_CSUM_ERRORS;
 try_bitmaps_again:
-               retval = ext2fs_read_bitmaps (fs);
-               if (retval && !(fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS)) {
+               retval = ext2fs_read_bitmaps(fs);
+               if (retval && !retval_csum) {
                        fs->flags |= EXT2_FLAG_IGNORE_CSUM_ERRORS;
+                       retval_csum = retval;
+                       error_csum = _("while trying to read '%s' bitmaps\n");
                        goto try_bitmaps_again;
                }
-               if (!retval && (fs->flags & EXT2_FLAG_IGNORE_CSUM_ERRORS))
-                       printf("%s", _("\n*** Checksum errors detected in bitmaps!  Run e2fsck now!\n\n"));
 just_descriptors:
                list_desc(fs, grp_only);
-               if (retval) {
-                       printf(_("\n%s: %s: error reading bitmaps: %s\n"),
-                              program_name, device_name,
-                              error_message(retval));
-               }
+       }
+out_close:
+       if (retval_csum) {
+               com_err(program_name, retval_csum, error_csum, device_name);
+               printf("%s", _("*** Run e2fsck now!\n\n"));
+               if (!retval)
+                       retval = retval_csum;
        }
        ext2fs_close_free(&fs);
        remove_error_table(&et_ext2_error_table);
-       exit (0);
+out:
+       return retval;
 }