NACK haven't noticed that FIEMAP also doesn't count holes ignore On 2024-09-03 11:37:30, Andrey Albershteyn wrote: > 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 > -- - Andrey