OSDN Git Service

dumpe2fs: fix 64-bit block numbers on 32-bit systems
[android-x86/external-e2fsprogs.git] / misc / filefrag.c
index 66a09e7..0583e91 100644 (file)
@@ -9,6 +9,7 @@
  * %End-Header%
  */
 
+#include "config.h"
 #ifndef __linux__
 #include <stdio.h>
 #include <stdlib.h>
@@ -46,6 +47,7 @@ int verbose = 0;
 int no_bs = 0;         /* Don't use the files blocksize, use 1K blocksize */
 int sync_file = 0;     /* fsync file before getting the mapping */
 int xattr_map = 0;     /* get xattr mapping */
+int force_bmap = 0;
 int logical_width = 12;
 int physical_width = 14;
 unsigned long long filesize;
@@ -168,32 +170,23 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents)
        struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
        int count = (sizeof(buf) - sizeof(*fiemap)) /
                        sizeof(struct fiemap_extent);
-       unsigned long long last_blk = 0;
+       unsigned long long expected = 0;
        unsigned long flags = 0;
        unsigned int i;
        static int fiemap_incompat_printed;
+       int fiemap_header_printed = 0;
        int tot_extents = 1, n = 0;
        int last = 0;
        int rc;
 
-       fiemap->fm_length = ~0ULL;
-
        memset(fiemap, 0, sizeof(struct fiemap));
 
-       if (!verbose)
-               count = 0;
-
        if (sync_file)
                flags |= FIEMAP_FLAG_SYNC;
 
        if (xattr_map)
                flags |= FIEMAP_FLAG_XATTR;
 
-       if (verbose)
-               printf(" ext %*s %*s %*s length flags\n", logical_width,
-                      "logical", physical_width, "physical",
-                      physical_width, "expected");
-
        do {
                fiemap->fm_length = ~0ULL;
                fiemap->fm_flags = flags;
@@ -208,9 +201,19 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents)
                        return rc;
                }
 
-               if (!verbose) {
-                       *num_extents = fiemap->fm_mapped_extents;
-                       goto out;
+               if (verbose && !fiemap_header_printed) {
+                       /*
+                        * No extents on first call?
+                        * Skip header and show 0 extents.
+                        */
+                       if (fiemap->fm_mapped_extents == 0) {
+                               *num_extents = 0;
+                               goto out;
+                       }
+                       printf(" ext %*s %*s %*s length flags\n", logical_width,
+                              "logical", physical_width, "physical",
+                              physical_width, "expected");
+                       fiemap_header_printed = 1;
                }
 
                /* If 0 extents are returned, then more ioctls are not needed */
@@ -225,13 +228,15 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents)
                        ext_len = fm_ext[i].fe_length >> blk_shift;
                        logical_blk = fm_ext[i].fe_logical >> blk_shift;
 
-                       if (logical_blk && phy_blk != last_blk + 1)
+                       if (logical_blk && phy_blk != expected)
                                tot_extents++;
                        else
-                               last_blk = 0;
-                       print_extent_info(&fm_ext[i], n, last_blk, blk_shift);
+                               expected = 0;
+                       if (verbose)
+                               print_extent_info(&fm_ext[i], n, expected,
+                                                 blk_shift);
 
-                       last_blk = phy_blk + ext_len - 1;
+                       expected = phy_blk + ext_len;
                        if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
                                last = 1;
                        n++;
@@ -258,7 +263,7 @@ static void frag_report(const char *filename)
 #endif
        int             bs;
        long            fd;
-       unsigned long   block, last_block = 0, numblocks, i, count;
+       unsigned long   block, last_block = 0, numblocks, i, count = 0;
        long            bpib;   /* Blocks per indirect block */
        long            cylgroups;
        int             num_extents = 0, expected;
@@ -327,7 +332,8 @@ static void frag_report(const char *filename)
                printf("File size of %s is %lld (%ld block%s, blocksize %d)\n",
                       filename, (long long) fileinfo.st_size, numblocks,
                       numblocks == 1 ? "" : "s", bs);
-       if (filefrag_fiemap(fd, int_log2(bs), &num_extents) != 0) {
+       if (force_bmap ||
+           filefrag_fiemap(fd, int_log2(bs), &num_extents) != 0) {
                for (i = 0, count = 0; i < numblocks; i++) {
                        if (is_ext2 && last_block) {
                                if (((i-EXT2_DIRECT) % bpib) == 0)
@@ -335,12 +341,14 @@ static void frag_report(const char *filename)
                                if (((i-EXT2_DIRECT-bpib) % (bpib*bpib)) == 0)
                                        last_block++;
                                if (((i-EXT2_DIRECT-bpib-bpib*bpib) %
-                                                       (bpib*bpib*bpib)) == 0)
+                                    (((__u64) bpib)*bpib*bpib)) == 0)
                                        last_block++;
                        }
                        rc = get_bmap(fd, i, &block);
                        if (block == 0)
                                continue;
+                       if (!num_extents)
+                               num_extents++;
                        count++;
                        if (last_block && (block != last_block+1) ) {
                                if (verbose)
@@ -356,8 +364,9 @@ static void frag_report(const char *filename)
                printf("%s: 1 extent found", filename);
        else
                printf("%s: %d extents found", filename, num_extents);
+       /* count, and thus expected, only set for indirect FIBMAP'd files */
        expected = (count/((bs*8)-(fsinfo.f_files/8/cylgroups)-3))+1;
-       if (is_ext2 && expected < num_extents)
+       if (is_ext2 && expected && expected < num_extents)
                printf(", perfection would be %d extent%s\n", expected,
                        (expected>1) ? "s" : "");
        else
@@ -368,7 +377,7 @@ static void frag_report(const char *filename)
 
 static void usage(const char *progname)
 {
-       fprintf(stderr, "Usage: %s [-bvsx] file ...\n", progname);
+       fprintf(stderr, "Usage: %s [-Bbvsx] file ...\n", progname);
        exit(1);
 }
 
@@ -377,8 +386,11 @@ int main(int argc, char**argv)
        char **cpp;
        int c;
 
-       while ((c = getopt(argc, argv, "bsvx")) != EOF)
+       while ((c = getopt(argc, argv, "Bbsvx")) != EOF)
                switch (c) {
+               case 'B':
+                       force_bmap++;
+                       break;
                case 'b':
                        no_bs++;
                        break;