linux-ext4.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/4] filefrag: exit with error code on failure
@ 2013-12-17  1:05 Andreas Dilger
  2013-12-17  1:05 ` [PATCH 2/4] filefrag: improve extent flags printing Andreas Dilger
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andreas Dilger @ 2013-12-17  1:05 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4, Andreas Dilger

If an error is hit during filefrag operation, it should continue to
run if multiple files are specified on the command-line, but exit
with a non-zero value, so that callers can determine that some error
was hit during file processing, similar to tar and other utilities.

Signed-off-by: Andreas Dilger <adilger@dilger.ca>
---
 misc/filefrag.c |  102 ++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 67 insertions(+), 35 deletions(-)

diff --git a/misc/filefrag.c b/misc/filefrag.c
index a050a22..18dc1e5 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -103,12 +103,8 @@ static int get_bmap(int fd, unsigned long block, unsigned long *phy_blk)
 
 	b = block;
 	ret = ioctl(fd, FIBMAP, &b); /* FIBMAP takes pointer to integer */
-	if (ret < 0) {
-		if (errno == EPERM) {
-			fprintf(stderr, "No permission to use FIBMAP ioctl; "
-				"must have root privileges\n");
-		}
-	}
+	if (ret < 0)
+		return -errno;
 	*phy_blk = b;
 
 	return ret;
@@ -191,7 +187,6 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
 	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 = 0, n = 0;
 	int last = 0;
@@ -211,9 +206,13 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
 		fiemap->fm_extent_count = count;
 		rc = ioctl(fd, FS_IOC_FIEMAP, (unsigned long) fiemap);
 		if (rc < 0) {
-			if (errno == EBADR && fiemap_incompat_printed == 0) {
-				printf("FIEMAP failed with unsupported "
-				       "flags %x\n", fiemap->fm_flags);
+			static int fiemap_incompat_printed;
+
+			rc = -errno;
+			if (rc == -EBADR && !fiemap_incompat_printed) {
+				fprintf(stderr, "FIEMAP failed with unknown "
+						"flags %x\n",
+				       fiemap->fm_flags);
 				fiemap_incompat_printed = 1;
 			}
 			return rc;
@@ -293,8 +292,23 @@ static int filefrag_fibmap(int fd, int blk_shift, int *num_extents,
 				last_block++;
 		}
 		rc = get_bmap(fd, i, &block);
-		if (rc < 0)
+		if (rc < 0) {
+			if (rc == -EINVAL || rc == -ENOTTY) {
+				fprintf(stderr, "FIBMAP unsupported\n");
+			} else if (rc == -EPERM) {
+				static int fibmap_perm_printed;
+
+				if (!fibmap_perm_printed) {
+					fprintf(stderr, "FIBMAP requires "
+							"root privileges\n");
+					fibmap_perm_printed = 1;
+				}
+			} else {
+				fprintf(stderr, "FIBMAP error: %s",
+					strerror(errno));
+			}
 			return rc;
+		}
 		if (block == 0)
 			continue;
 		if (*num_extents == 0) {
@@ -331,7 +345,7 @@ static int filefrag_fibmap(int fd, int blk_shift, int *num_extents,
 	return count;
 }
 
-static void frag_report(const char *filename)
+static int frag_report(const char *filename)
 {
 	static struct statfs fsinfo;
 	ext2fs_struct_stat st;
@@ -342,8 +356,8 @@ static void frag_report(const char *filename)
 	int		num_extents = 1, expected = ~0;
 	int		is_ext2 = 0;
 	static dev_t	last_device;
-	unsigned int	flags;
 	int		width;
+	int		rc = 0;
 
 #if defined(HAVE_OPEN64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
 	fd = open64(filename, O_RDONLY);
@@ -351,8 +365,10 @@ static void frag_report(const char *filename)
 	fd = open(filename, O_RDONLY);
 #endif
 	if (fd < 0) {
+		rc = -errno;
 		perror("open");
-		return;
+
+		return rc;
 	}
 
 #if defined(HAVE_FSTAT64) && !defined(__OSX_AVAILABLE_BUT_DEPRECATED)
@@ -360,28 +376,34 @@ static void frag_report(const char *filename)
 #else
 	if (fstat(fd, &st) < 0) {
 #endif
+		rc = -errno;
 		close(fd);
 		perror("stat");
-		return;
+
+		return rc;
 	}
 
 	if (last_device != st.st_dev) {
 		if (fstatfs(fd, &fsinfo) < 0) {
+			rc = -errno;
 			close(fd);
 			perror("fstatfs");
-			return;
+
+			return rc;
 		}
 		if (verbose)
 			printf("Filesystem type is: %lx\n",
 			       (unsigned long) fsinfo.f_type);
 	}
 	st.st_blksize = fsinfo.f_bsize;
-	if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) < 0)
-		flags = 0;
-	if (!(flags & EXT4_EXTENTS_FL) &&
-	    ((fsinfo.f_type == 0xef51) || (fsinfo.f_type == 0xef52) ||
-	     (fsinfo.f_type == 0xef53)))
-		is_ext2++;
+	if (fsinfo.f_type == 0xef51 || fsinfo.f_type == 0xef52 ||
+	    fsinfo.f_type == 0xef53) {
+		unsigned int	flags;
+
+		if (ioctl(fd, EXT3_IOC_GETFLAGS, &flags) == 0 &&
+		    !(flags & EXT4_EXTENTS_FL))
+			is_ext2 = 1;
+	}
 
 	if (is_ext2) {
 		long cylgroups = div_ceil(fsinfo.f_blocks, fsinfo.f_bsize * 8);
@@ -414,19 +436,19 @@ static void frag_report(const char *filename)
 		       numblocks * fsinfo.f_bsize >> blk_shift,
 		       numblocks == 1 ? "" : "s", 1 << blk_shift);
 
-	if (force_bmap ||
-	    filefrag_fiemap(fd, blk_shift, &num_extents, &st) != 0) {
+	if (!force_bmap) {
+		rc = filefrag_fiemap(fd, blk_shift, &num_extents, &st);
+		expected = 0;
+	}
+
+	if (force_bmap || rc < 0) { /* FIEMAP failed, try FIBMAP instead */
 		expected = filefrag_fibmap(fd, blk_shift, &num_extents,
 					   &st, numblocks, is_ext2);
 		if (expected < 0) {
-			if (errno == EINVAL || errno == ENOTTY) {
-				fprintf(stderr, "%s: FIBMAP unsupported\n",
-					filename);
-			} else if (errno != EPERM) {
-				fprintf(stderr, "%s: FIBMAP error: %s",
-					filename, strerror(errno));
-			}
+			rc = expected;
 			goto out_close;
+		} else {
+			rc = 0;
 		}
 		expected = expected / data_blocks_per_cyl + 1;
 	}
@@ -443,6 +465,8 @@ static void frag_report(const char *filename)
 		fputc('\n', stdout);
 out_close:
 	close(fd);
+
+	return rc;
 }
 
 static void usage(const char *progname)
@@ -455,9 +479,10 @@ static void usage(const char *progname)
 int main(int argc, char**argv)
 {
 	char **cpp;
+	int rc = 0;
 	int c;
 
-	while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF)
+	while ((c = getopt(argc, argv, "Bb::eksvxX")) != EOF) {
 		switch (c) {
 		case 'B':
 			force_bmap++;
@@ -516,10 +541,17 @@ int main(int argc, char**argv)
 			usage(argv[0]);
 			break;
 		}
+	}
+
 	if (optind == argc)
 		usage(argv[0]);
-	for (cpp=argv+optind; *cpp; cpp++)
-		frag_report(*cpp);
-	return 0;
+
+	for (cpp = argv + optind; *cpp; cpp++) {
+		int rc2 = frag_report(*cpp);
+		if (rc2 < 0 && rc == 0)
+			rc = rc2;
+	}
+
+	return -rc;
 }
 #endif
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/4] filefrag: improve extent flags printing
  2013-12-17  1:05 [PATCH 1/4] filefrag: exit with error code on failure Andreas Dilger
@ 2013-12-17  1:05 ` Andreas Dilger
  2013-12-17  1:05 ` [PATCH 3/4] filefrag: reserve fields and new extent flags Andreas Dilger
  2013-12-17  1:05 ` [PATCH 4/4] filefrag: print out physical extent length if set Andreas Dilger
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Dilger @ 2013-12-17  1:05 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4, Andreas Dilger

Improve the handling of printing extent flags in verbose mode.
For unknown flags, print out the flag value in hexadecimal.

Signed-off-by: Andreas Dilger <adilger@dilger.ca>
---
 misc/filefrag.c |   60 +++++++++++++++++++++++++++++++++----------------------
 1 files changed, 36 insertions(+), 24 deletions(-)

diff --git a/misc/filefrag.c b/misc/filefrag.c
index 18dc1e5..6289899 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -120,6 +120,15 @@ static void print_extent_header(void)
 	       "expected:");
 }
 
+static void print_flag(__u32 *flags, __u32 mask, char *buf, const char *name)
+{
+	if ((*flags & mask) == 0)
+		return;
+
+	strcat(buf, name);
+	*flags &= ~mask;
+}
+
 static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 			      unsigned long long expected, int blk_shift,
 			      ext2fs_struct_stat *st)
@@ -128,10 +137,12 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 	unsigned long long logical_blk;
 	unsigned long long ext_len;
 	unsigned long long ext_blks;
-	char flags[256] = "";
+	__u32 flags, mask;
+	char buf[256] = "";
 
+	flags = fm_extent->fe_flags;
 	/* For inline data all offsets should be in bytes, not blocks */
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
+	if (flags & FIEMAP_EXTENT_DATA_INLINE)
 		blk_shift = 0;
 
 	ext_len = fm_extent->fe_length >> blk_shift;
@@ -140,34 +151,35 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 	physical_blk = fm_extent->fe_physical >> blk_shift;
 
 	if (expected)
-		sprintf(flags, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
+		sprintf(buf, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
 			physical_width, expected >> blk_shift);
 	else
-		sprintf(flags, "%.*s  ", physical_width, "                   ");
-
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNKNOWN)
-		strcat(flags, "unknown,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_DELALLOC)
-		strcat(flags, "delalloc,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_ENCRYPTED)
-		strcat(flags, "encrypted,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_NOT_ALIGNED)
-		strcat(flags, "not_aligned,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_INLINE)
-		strcat(flags, "inline,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_DATA_TAIL)
-		strcat(flags, "tail_packed,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_UNWRITTEN)
-		strcat(flags, "unwritten,");
-	if (fm_extent->fe_flags & FIEMAP_EXTENT_MERGED)
-		strcat(flags, "merged,");
+		sprintf(buf, "%.*s  ", physical_width, "                   ");
+
+	print_flag(&flags, FIEMAP_EXTENT_UNKNOWN, buf, "unknown,");
+	print_flag(&flags, FIEMAP_EXTENT_DELALLOC, buf, "delalloc,");
+	print_flag(&flags, FIEMAP_EXTENT_DATA_ENCRYPTED, buf, "encrypted,");
+	print_flag(&flags, FIEMAP_EXTENT_NOT_ALIGNED, buf, "not_aligned,");
+	print_flag(&flags, FIEMAP_EXTENT_DATA_INLINE, buf, "inline,");
+	print_flag(&flags, FIEMAP_EXTENT_DATA_TAIL, buf, "tail_packed,");
+	print_flag(&flags, FIEMAP_EXTENT_UNWRITTEN, buf, "unwritten,");
+	print_flag(&flags, FIEMAP_EXTENT_MERGED, buf, "merged,");
+	print_flag(&flags, FIEMAP_EXTENT_LAST, buf, "last,");
+	/* Print unknown flags in hex format.  Known flags are already printed
+	 * above and will have their bit cleared from "flags". */
+	for (mask = 1; flags != 0 && mask != 0; mask <<= 1) {
+		char hex[6];
+
+		sprintf(hex, "%04x,", mask);
+		print_flag(&flags, mask, buf, hex);
+	}
 
 	if (fm_extent->fe_logical + fm_extent->fe_length >= (__u64) st->st_size)
-		strcat(flags, "eof,");
+		strcat(buf, "eof,");
 
 	/* Remove trailing comma, if any */
-	if (flags[0])
-		flags[strlen(flags) - 1] = '\0';
+	if (buf[0])
+		buf[strlen(buf) - 1] = '\0';
 
 	printf(ext_fmt, cur_ex, logical_width, logical_blk,
 	       logical_width, logical_blk + ext_blks,
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 3/4] filefrag: reserve fields and new extent flags
  2013-12-17  1:05 [PATCH 1/4] filefrag: exit with error code on failure Andreas Dilger
  2013-12-17  1:05 ` [PATCH 2/4] filefrag: improve extent flags printing Andreas Dilger
@ 2013-12-17  1:05 ` Andreas Dilger
  2013-12-17  1:05 ` [PATCH 4/4] filefrag: print out physical extent length if set Andreas Dilger
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Dilger @ 2013-12-17  1:05 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4, Andreas Dilger

Reserve the FIEMAP_EXTENT_DATA_COMPRESSED flag to allow reporting
extents with physical length different than logical length.  This
also sets the FIEMAP_EXTENT_ENCODED flag to indicate that the data
cannot be accessed directly.  This adds a new fe_phys_length field
to struct fiemap_extent which specifies the physical extent length
in bytes when DATA_COMPRESSED is set.  Linux 3.14 and later kernels
will fill out the fe_phys_length field, but in older kernels the
contents are undefined (though typically zero).

Reserve the FIEMAP_EXTENT_NET flag, which indicates that the data
is on a network filesystem.  This also sets FIEMAP_EXTENT_ENCODED
flag to indicate the data cannot be accessed directly.

Print out these flags in filefrag if detected.

Signed-off-by: Andreas Dilger <adilger@dilger.ca>
---
 lib/ext2fs/fiemap.h |   14 ++++++++++----
 misc/filefrag.c     |    2 ++
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/lib/ext2fs/fiemap.h b/lib/ext2fs/fiemap.h
index 30bf555..df973da 100644
--- a/lib/ext2fs/fiemap.h
+++ b/lib/ext2fs/fiemap.h
@@ -17,15 +17,17 @@ struct fiemap_extent {
 	__u64 fe_physical; /* physical offset in bytes for the start
 			    * of the extent from the beginning of the disk */
 	__u64 fe_length;   /* length in bytes for this extent */
-	__u64 fe_reserved64[2];
+	__u64 fe_phys_length; /* physical length in bytes for this extent,
+			       * undefined if DATA_COMPRESSED not set */
+	__u64 fe_reserved64;
 	__u32 fe_flags;    /* FIEMAP_EXTENT_* flags for this extent */
 	__u32 fe_reserved[3];
 };
 
 struct fiemap {
-	__u64 fm_start;		/* logical offset (inclusive) at
+	__u64 fm_start;		/* logical offset in bytes (inclusive) at
 				 * which to start mapping (in) */
-	__u64 fm_length;	/* logical length of mapping which
+	__u64 fm_length;	/* logical length in bytes of mapping which
 				 * userspace wants (in) */
 	__u32 fm_flags;		/* FIEMAP_FLAG_* flags for request (in/out) */
 	__u32 fm_mapped_extents;/* number of extents that were mapped (out) */
@@ -51,8 +53,10 @@ struct fiemap {
 						    * Sets EXTENT_UNKNOWN. */
 #define FIEMAP_EXTENT_ENCODED		0x00000008 /* Data can not be read
 						    * while fs is unmounted */
+#define FIEMAP_EXTENT_DATA_COMPRESSED	0x00000040 /* Data is compressed by fs.
+						    * Sets EXTENT_ENCODED. */
 #define FIEMAP_EXTENT_DATA_ENCRYPTED	0x00000080 /* Data is encrypted by fs.
-						    * Sets EXTENT_NO_BYPASS. */
+						    * Sets EXTENT_ENCODED. */
 #define FIEMAP_EXTENT_NOT_ALIGNED	0x00000100 /* Extent offsets may not be
 						    * block aligned. */
 #define FIEMAP_EXTENT_DATA_INLINE	0x00000200 /* Data mixed with metadata.
@@ -64,5 +68,7 @@ struct fiemap {
 #define FIEMAP_EXTENT_MERGED		0x00001000 /* File does not natively
 						    * support extents. Result
 						    * merged for efficiency. */
+#define FIEMAP_EXTENT_NET		0x80000000 /* Data stored remotely.
+						    * Sets EXTENT_ENCODED. */
 
 #endif /* _LINUX_FIEMAP_H */
diff --git a/misc/filefrag.c b/misc/filefrag.c
index 6289899..7096abb 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -158,12 +158,14 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 
 	print_flag(&flags, FIEMAP_EXTENT_UNKNOWN, buf, "unknown,");
 	print_flag(&flags, FIEMAP_EXTENT_DELALLOC, buf, "delalloc,");
+	print_flag(&flags, FIEMAP_EXTENT_DATA_COMPRESSED, buf, "compressed,");
 	print_flag(&flags, FIEMAP_EXTENT_DATA_ENCRYPTED, buf, "encrypted,");
 	print_flag(&flags, FIEMAP_EXTENT_NOT_ALIGNED, buf, "not_aligned,");
 	print_flag(&flags, FIEMAP_EXTENT_DATA_INLINE, buf, "inline,");
 	print_flag(&flags, FIEMAP_EXTENT_DATA_TAIL, buf, "tail_packed,");
 	print_flag(&flags, FIEMAP_EXTENT_UNWRITTEN, buf, "unwritten,");
 	print_flag(&flags, FIEMAP_EXTENT_MERGED, buf, "merged,");
+	print_flag(&flags, FIEMAP_EXTENT_NET, buf, "net,");
 	print_flag(&flags, FIEMAP_EXTENT_LAST, buf, "last,");
 	/* Print unknown flags in hex format.  Known flags are already printed
 	 * above and will have their bit cleared from "flags". */
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 4/4] filefrag: print out physical extent length if set
  2013-12-17  1:05 [PATCH 1/4] filefrag: exit with error code on failure Andreas Dilger
  2013-12-17  1:05 ` [PATCH 2/4] filefrag: improve extent flags printing Andreas Dilger
  2013-12-17  1:05 ` [PATCH 3/4] filefrag: reserve fields and new extent flags Andreas Dilger
@ 2013-12-17  1:05 ` Andreas Dilger
  2 siblings, 0 replies; 4+ messages in thread
From: Andreas Dilger @ 2013-12-17  1:05 UTC (permalink / raw)
  To: tytso; +Cc: linux-ext4, Andreas Dilger

Rename fe_length to be fe_logi_length to distinguish it from the
fe_phys_length field.

If the extent's physical length is different from its logical length
(if FIEMAP_EXTENT_DATA_COMPRESSED is set) then use the fe_phys_length
for the physical length.  If FIEMAP_EXTENT_DATA_COMPRESSED is unset,
then continue to use fe_logi_length for the extent length, but set
fe_phys_length = fe_logi_length to simplify the rest of the code.

Signed-off-by: Andreas Dilger <adilger@dilger.ca>
---
 lib/ext2fs/fiemap.h |    2 +-
 misc/filefrag.c     |   62 +++++++++++++++++++++++++++++++++++++--------------
 2 files changed, 46 insertions(+), 18 deletions(-)

diff --git a/lib/ext2fs/fiemap.h b/lib/ext2fs/fiemap.h
index df973da..3cf32f7 100644
--- a/lib/ext2fs/fiemap.h
+++ b/lib/ext2fs/fiemap.h
@@ -16,7 +16,7 @@ struct fiemap_extent {
 			    * the extent from the beginning of the file */
 	__u64 fe_physical; /* physical offset in bytes for the start
 			    * of the extent from the beginning of the disk */
-	__u64 fe_length;   /* length in bytes for this extent */
+	__u64 fe_logi_length; /* logical length in bytes for this extent */
 	__u64 fe_phys_length; /* physical length in bytes for this extent,
 			       * undefined if DATA_COMPRESSED not set */
 	__u64 fe_reserved64;
diff --git a/misc/filefrag.c b/misc/filefrag.c
index 7096abb..6cefaf4 100644
--- a/misc/filefrag.c
+++ b/misc/filefrag.c
@@ -133,10 +133,14 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 			      unsigned long long expected, int blk_shift,
 			      ext2fs_struct_stat *st)
 {
-	unsigned long long physical_blk;
-	unsigned long long logical_blk;
-	unsigned long long ext_len;
-	unsigned long long ext_blks;
+	unsigned long long logical_blk;	/* logical starting block of file */
+	unsigned long long logical_len;	/* logical length of extent in blocks */
+	unsigned long long logical_unit;/* logical length to end of extent, may
+					 * not be logical_len-1 if extent isn't
+					 * aligned to requested block size */
+	unsigned long long physical_blk;/* physical starting block in LUN */
+	unsigned long long physical_len;/* physical length of extent in blocks*/
+	unsigned long long physical_unit;/* physical length to end of extent */
 	__u32 flags, mask;
 	char buf[256] = "";
 
@@ -145,10 +149,20 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 	if (flags & FIEMAP_EXTENT_DATA_INLINE)
 		blk_shift = 0;
 
-	ext_len = fm_extent->fe_length >> blk_shift;
-	ext_blks = (fm_extent->fe_length - 1) >> blk_shift;
 	logical_blk = fm_extent->fe_logical >> blk_shift;
-	physical_blk = fm_extent->fe_physical >> blk_shift;
+	logical_len = fm_extent->fe_logi_length >> blk_shift;
+	logical_unit = (fm_extent->fe_logi_length - 1) >> blk_shift;
+	if (flags & FIEMAP_EXTENT_UNKNOWN) {
+		physical_blk = 0;
+		physical_len = 0;
+		physical_unit = 0;
+	} else {
+		/* FIEMAP_EXTENT_DATA_COMPRESSED was checked by caller
+		 * and fixed up fe_phys_length if unset. */
+		physical_blk = fm_extent->fe_physical >> blk_shift;
+		physical_len = fm_extent->fe_phys_length >> blk_shift;
+		physical_unit = (fm_extent->fe_phys_length - 1) >> blk_shift;
+	}
 
 	if (expected)
 		sprintf(buf, ext_fmt == hex_fmt ? "%*llx: " : "%*llu: ",
@@ -176,7 +190,8 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 		print_flag(&flags, mask, buf, hex);
 	}
 
-	if (fm_extent->fe_logical + fm_extent->fe_length >= (__u64) st->st_size)
+	if (fm_extent->fe_logical + fm_extent->fe_logi_length >=
+	    (__u64)st->st_size)
 		strcat(buf, "eof,");
 
 	/* Remove trailing comma, if any */
@@ -184,10 +199,10 @@ static void print_extent_info(struct fiemap_extent *fm_extent, int cur_ex,
 		buf[strlen(buf) - 1] = '\0';
 
 	printf(ext_fmt, cur_ex, logical_width, logical_blk,
-	       logical_width, logical_blk + ext_blks,
+	       logical_width, logical_blk + logical_unit,
 	       physical_width, physical_blk,
-	       physical_width, physical_blk + ext_blks,
-	       ext_len, flags);
+	       physical_width, physical_blk + physical_unit,
+	       logical_len, buf);
 }
 
 static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
@@ -250,18 +265,29 @@ static int filefrag_fiemap(int fd, int blk_shift, int *num_extents,
 				if (!tot_extents)
 					tot_extents = 1;
 			}
+
+			/* If DATA_COMPRESSED is set, then the logical and
+			 * physical extent lengths are different and the
+			 * fe_phys_length field is known to be valid.
+			 * Kernels older than 3.14 did not set fe_phys_length,
+			 * so do that here to simplify the rest of the code. */
+			if (!(fm_ext[i].fe_flags &
+			      FIEMAP_EXTENT_DATA_COMPRESSED))
+				fm_ext[i].fe_phys_length =
+					fm_ext[i].fe_logi_length;
+
 			if (verbose)
 				print_extent_info(&fm_ext[i], n, expected,
 						  blk_shift, st);
-
-			expected = fm_ext[i].fe_physical + fm_ext[i].fe_length;
+			expected = fm_ext[i].fe_physical +
+				   fm_ext[i].fe_phys_length;
 			if (fm_ext[i].fe_flags & FIEMAP_EXTENT_LAST)
 				last = 1;
 			n++;
 		}
 
 		fiemap->fm_start = (fm_ext[i - 1].fe_logical +
-				    fm_ext[i - 1].fe_length);
+				    fm_ext[i - 1].fe_logi_length);
 	} while (last == 0);
 
 	*num_extents = tot_extents;
@@ -335,20 +361,22 @@ static int filefrag_fibmap(int fd, int blk_shift, int *num_extents,
 		count++;
 		if (force_extent && last_block != 0 &&
 		    (block != last_block + 1 ||
-		     fm_ext.fe_logical + fm_ext.fe_length != logical)) {
+		     fm_ext.fe_logical + fm_ext.fe_logi_length != logical)) {
 			print_extent_info(&fm_ext, *num_extents - 1,
 					  (last_block + 1) * st->st_blksize,
 					  blk_shift, st);
 			fm_ext.fe_logical = logical;
 			fm_ext.fe_physical = block * st->st_blksize;
-			fm_ext.fe_length = 0;
+			fm_ext.fe_logi_length = 0;
+			fm_ext.fe_phys_length = 0;
 			(*num_extents)++;
 		} else if (verbose && last_block && (block != last_block + 1)) {
 			printf("Discontinuity: Block %ld is at %lu (was %lu)\n",
 			       i, block, last_block + 1);
 			(*num_extents)++;
 		}
-		fm_ext.fe_length += st->st_blksize;
+		fm_ext.fe_logi_length += st->st_blksize;
+		fm_ext.fe_phys_length += st->st_blksize;
 		last_block = block;
 	}
 
-- 
1.7.3.4


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-12-17  1:15 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-12-17  1:05 [PATCH 1/4] filefrag: exit with error code on failure Andreas Dilger
2013-12-17  1:05 ` [PATCH 2/4] filefrag: improve extent flags printing Andreas Dilger
2013-12-17  1:05 ` [PATCH 3/4] filefrag: reserve fields and new extent flags Andreas Dilger
2013-12-17  1:05 ` [PATCH 4/4] filefrag: print out physical extent length if set Andreas Dilger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).