exit(EXIT_FAILURE);
}
#else
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#ifndef _LARGEFILE64_SOURCE
#define _LARGEFILE64_SOURCE
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/ioctl.h>
+#ifdef HAVE_LINUX_FD_H
#include <linux/fd.h>
+#endif
#include <ext2fs/ext2fs.h>
#include <ext2fs/ext2_types.h>
#include <ext2fs/fiemap.h>
print_flag(&fe_flags, FIEMAP_EXTENT_SHARED, flags, "shared,");
/* print any unknown flags as hex values */
for (mask = 1; fe_flags != 0 && mask != 0; mask <<= 1) {
- char hex[6];
+ char hex[sizeof(mask) * 2 + 4]; /* 2 chars/byte + 0x, + NUL */
if ((fe_flags & mask) == 0)
continue;
print_flag(&fe_flags, mask, flags, hex);
}
- if (fm_extent->fe_logical + fm_extent->fe_length >= st->st_size)
+ if (fm_extent->fe_logical + fm_extent->fe_length >=
+ (unsigned long long) st->st_size)
strcat(flags, "eof,");
/* Remove trailing comma, if any */
static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
ext2fs_struct_stat *st)
{
- char buf[16384];
+ __u64 buf[2048]; /* __u64 for proper field alignment */
struct fiemap *fiemap = (struct fiemap *)buf;
struct fiemap_extent *fm_ext = &fiemap->fm_extents[0];
+ struct fiemap_extent fm_last;
int count = (sizeof(buf) - sizeof(*fiemap)) /
sizeof(struct fiemap_extent);
unsigned long long expected = 0;
+ unsigned long long expected_dense = 0;
unsigned long flags = 0;
unsigned int i;
int fiemap_header_printed = 0;
int rc;
memset(fiemap, 0, sizeof(struct fiemap));
+ memset(&fm_last, 0, sizeof(fm_last));
if (sync_file)
flags |= FIEMAP_FLAG_SYNC;
}
for (i = 0; i < fiemap->fm_mapped_extents; i++) {
+ expected_dense = fm_last.fe_physical +
+ fm_last.fe_length;
+ expected = fm_last.fe_physical +
+ fm_ext[i].fe_logical - fm_last.fe_logical;
if (fm_ext[i].fe_logical != 0 &&
- fm_ext[i].fe_physical != expected) {
+ fm_ext[i].fe_physical != expected &&
+ fm_ext[i].fe_physical != expected_dense) {
tot_extents++;
} else {
expected = 0;
if (verbose)
print_extent_info(&fm_ext[i], n, expected,
blk_shift, st);
-
- expected = fm_ext[i].fe_physical + fm_ext[i].fe_length;
if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
last = 1;
+ fm_last = fm_ext[i];
n++;
}
ext2fs_struct_stat *st,
unsigned long numblocks, int is_ext2)
{
- struct fiemap_extent fm_ext;
+ struct fiemap_extent fm_ext, fm_last;
unsigned long i, last_block;
- unsigned long long logical;
+ unsigned long long logical, expected = 0;
/* Blocks per indirect block */
const long bpib = st->st_blksize / 4;
int count;
+ memset(&fm_ext, 0, sizeof(fm_ext));
+ memset(&fm_last, 0, sizeof(fm_last));
if (force_extent) {
- memset(&fm_ext, 0, sizeof(fm_ext));
fm_ext.fe_flags = FIEMAP_EXTENT_MERGED;
}
- if (sync_file)
- fsync(fd);
+ if (sync_file && fsync(fd) != 0)
+ return -errno;
for (i = 0, logical = 0, *num_extents = 0, count = last_block = 0;
i < numblocks;
return rc;
if (block == 0)
continue;
- if (*num_extents == 0) {
- (*num_extents)++;
- if (force_extent) {
+
+ if (*num_extents == 0 || block != last_block + 1 ||
+ fm_ext.fe_logical + fm_ext.fe_length != logical) {
+ /*
+ * This is the start of a new extent; figure out where
+ * we expected it to be and report the extent.
+ */
+ if (*num_extents != 0 && fm_last.fe_length) {
+ expected = fm_last.fe_physical +
+ (fm_ext.fe_logical - fm_last.fe_logical);
+ if (expected == fm_ext.fe_physical)
+ expected = 0;
+ }
+ if (force_extent && *num_extents == 0)
print_extent_header();
- fm_ext.fe_physical = block * st->st_blksize;
+ if (force_extent && *num_extents != 0) {
+ print_extent_info(&fm_ext, *num_extents - 1,
+ expected, blk_shift, st);
}
- }
- count++;
- if (force_extent && last_block != 0 &&
- (block != last_block + 1 ||
- fm_ext.fe_logical + fm_ext.fe_length != logical)) {
- print_extent_info(&fm_ext, *num_extents - 1,
- (last_block + 1) * st->st_blksize,
- blk_shift, st);
- fm_ext.fe_logical = logical;
+ if (verbose && expected != 0) {
+ printf("Discontinuity: Block %llu is at %llu "
+ "(was %llu)\n",
+ fm_ext.fe_logical / st->st_blksize,
+ fm_ext.fe_physical / st->st_blksize,
+ expected / st->st_blksize);
+ }
+ /* create the new extent */
+ fm_last = fm_ext;
+ (*num_extents)++;
fm_ext.fe_physical = block * st->st_blksize;
+ fm_ext.fe_logical = logical;
fm_ext.fe_length = 0;
- (*num_extents)++;
- } else if (last_block && (block != last_block + 1)) {
- if (verbose)
- printf("Discontinuity: Block %ld is at %lu (was "
- "%lu)\n", i, block, last_block + 1);
- (*num_extents)++;
}
fm_ext.fe_length += st->st_blksize;
last_block = block;
}
-
- if (force_extent)
- print_extent_info(&fm_ext, *num_extents - 1,
- last_block * st->st_blksize, blk_shift, st);
+ if (force_extent && *num_extents != 0) {
+ if (fm_last.fe_length) {
+ expected = fm_last.fe_physical +
+ (fm_ext.fe_logical - fm_last.fe_logical);
+ if (expected == fm_ext.fe_physical)
+ expected = 0;
+ }
+ print_extent_info(&fm_ext, *num_extents - 1, expected,
+ blk_shift, st);
+ }
return count;
}
static void usage(const char *progname)
{
- fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeklsvxX] file ...\n",
+ fprintf(stderr, "Usage: %s [-b{blocksize}] [-BeksvxX] file ...\n",
progname);
exit(1);
}
char *end;
blocksize = strtoul(optarg, &end, 0);
if (end) {
+#if __GNUC_PREREQ (7, 0)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
+#endif
switch (end[0]) {
case 'g':
case 'G':
blocksize *= 1024;
- /* no break */
+ /* fall through */
case 'm':
case 'M':
blocksize *= 1024;
- /* no break */
+ /* fall through */
case 'k':
case 'K':
blocksize *= 1024;
default:
break;
}
+#if __GNUC_PREREQ (7, 0)
+#pragma GCC diagnostic pop
+#endif
}
} else { /* Allow -b without argument for compat. Remove
* this eventually so "-b {blocksize}" works */
if (optind == argc)
usage(argv[0]);
- for (cpp = argv + optind; *cpp != '\0'; cpp++) {
+ for (cpp = argv + optind; *cpp != NULL; cpp++) {
int rc2 = frag_report(*cpp);
if (rc2 < 0 && rc == 0)