[PATCH] xfs_io: add fiemap -s flag to print number of extents

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



FS_IOC_FIEMAP has an option to return total number of extents
without copying each one of them. This could be pretty handy for
checking if large file is heavily fragmented. The same can be done
with calling FS_IOC_FIEMAP and counting lines with wc but
FS_IOC_FIEMAP is limited to ~76mil extents (FIEMAP_MAX_EXTENTS). The
other option is FS_IOC_FSGETXATTR which is much faster than
iterating through all extents, but it doesn't include holes.

Signed-off-by: Andrey Albershteyn <aalbersh@xxxxxxxxxx>
---
 io/fiemap.c | 27 +++++++++++++++++++++++----
 1 file changed, 23 insertions(+), 4 deletions(-)

diff --git a/io/fiemap.c b/io/fiemap.c
index b41f71bfd027..d4e55a82f6db 100644
--- a/io/fiemap.c
+++ b/io/fiemap.c
@@ -42,6 +42,13 @@ fiemap_help(void)
 "\n"));
 }
 
+static void
+print_total(
+	   struct fiemap	*fiemap)
+{
+	printf("Extents total: %d\n", fiemap->fm_mapped_extents);
+}
+
 static void
 print_hole(
 	   int		foff_w,
@@ -223,9 +230,11 @@ fiemap_f(
 	int		done = 0;
 	int		lflag = 0;
 	int		vflag = 0;
+	int		sflag = 0;
 	int		fiemap_flags = FIEMAP_FLAG_SYNC;
 	int		c;
 	int		i;
+	int		ext_arr_size = 0;
 	int		map_size;
 	int		ret;
 	int		cur_extent = 0;
@@ -242,7 +251,7 @@ fiemap_f(
 
 	init_cvtnum(&fsblocksize, &fssectsize);
 
-	while ((c = getopt(argc, argv, "aln:v")) != EOF) {
+	while ((c = getopt(argc, argv, "aln:sv")) != EOF) {
 		switch (c) {
 		case 'a':
 			fiemap_flags |= FIEMAP_FLAG_XATTR;
@@ -253,6 +262,9 @@ fiemap_f(
 		case 'n':
 			max_extents = atoi(optarg);
 			break;
+		case 's':
+			sflag++;
+			break;
 		case 'v':
 			vflag++;
 			break;
@@ -285,8 +297,9 @@ fiemap_f(
 		range_end = start_offset + length;
 	}
 
-	map_size = sizeof(struct fiemap) +
-		(EXTENT_BATCH * sizeof(struct fiemap_extent));
+	if (!sflag)
+		ext_arr_size = (EXTENT_BATCH * sizeof(struct fiemap_extent));
+	map_size = sizeof(struct fiemap) + ext_arr_size;
 	fiemap = malloc(map_size);
 	if (!fiemap) {
 		fprintf(stderr, _("%s: malloc of %d bytes failed.\n"),
@@ -302,7 +315,8 @@ fiemap_f(
 		fiemap->fm_flags = fiemap_flags;
 		fiemap->fm_start = last_logical;
 		fiemap->fm_length = range_end - last_logical;
-		fiemap->fm_extent_count = EXTENT_BATCH;
+		if (!sflag)
+			fiemap->fm_extent_count = EXTENT_BATCH;
 
 		ret = ioctl(file->fd, FS_IOC_FIEMAP, (unsigned long)fiemap);
 		if (ret < 0) {
@@ -313,6 +327,11 @@ fiemap_f(
 			return 0;
 		}
 
+		if (sflag) {
+			print_total(fiemap);
+			goto out;
+		}
+
 		/* No more extents to map, exit */
 		if (!fiemap->fm_mapped_extents)
 			break;
-- 
2.44.1





[Index of Archives]     [XFS Filesystem Development (older mail)]     [Linux Filesystem Development]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux RAID]     [Linux SCSI]


  Powered by Linux