On Wed, Apr 10, 2019 at 11:59:47AM +0200, Karel Zak wrote: > On Wed, Apr 10, 2019 at 04:12:20PM +0800, zhenwei pi wrote: > > Add fiemap to dump file extent mappings. Typically we can recognize a > > file is sparse or not. > > It's good idea to export FIEMAP to command line, but it seems we > already have xfs_io and filefrag. > > The command filefrag seems pretty usable and with "-e" it provides > exactly the same output like your "fiemap" tool. > > The problem I see is that filefrag is in e2fsprogs package. It would > be better to have it in some more generic package and FS independent > package. > > Maybe we can do another move from e2fsprogs to util-linux. Ted, your > opinion? Looking at the filefrag code the only ext specific part I can identify is checking for non-extent based inode and changing the output slightly as well as taking direct/indirect mapping block layout into consideration in case FIBMAP is used. Other than that it's purely generic and non ext[234] specific code that can easily live in util-linux and personally I do not think I'd miss it :) -Lukas > > Karel > > > # filefrag -e /var/log/wtmp > Filesystem type is: ef53 > File size of /var/log/wtmp is 9032064 (2206 blocks of 4096 bytes) > ext: logical_offset: physical_offset: length: expected: flags: > 0: 0.. 0: 11567426.. 11567426: 1: > 1: 1.. 190: 11730944.. 11731133: 190: 11567427: > 2: 191.. 380: 11732109.. 11732298: 190: 11731134: > 3: 381.. 570: 11731883.. 11732072: 190: 11732299: > 4: 571.. 633: 11731501.. 11731563: 63: 11732073: > 5: 634.. 761: 11731584.. 11731711: 128: 11731564: > 6: 762.. 763: 11731198.. 11731199: 2: 11731712: > 7: 764.. 764: 11732073.. 11732073: 1: 11731200: > 8: 765.. 955: 11731200.. 11731390: 191: 11732074: > 9: 956.. 1145: 11732705.. 11732894: 190: 11731391: > 10: 1146.. 1254: 11733137.. 11733245: 109: 11732895: > 11: 1255.. 1444: 11732895.. 11733084: 190: 11733246: > 12: 1445.. 1824: 11733246.. 11733625: 380: 11733085: > 13: 1825.. 2014: 11737497.. 11737686: 190: 11733626: > 14: 2015.. 2205: 11896890.. 11897080: 191: 11737687: last,eof > /var/log/wtmp: 15 extents found > > > > > > For example: > > #./fiemap /var/log/syslog /var/log/syslog.2.gz > > File /var/log/syslog has 19 extent(s): > > Logical Physical Length Flag > > 0: 0000000000000000 00000010d63a8000 0000000000001000 0000 > > 1: 0000000000001000 00000010d63c4000 0000000000001000 0000 > > 2: 0000000000002000 00000010d63d6000 0000000000001000 0000 > > 3: 0000000000003000 00000010d723e000 0000000000001000 0000 > > 4: 0000000000004000 000000076c377000 0000000000001000 0000 > > 5: 0000000000005000 00000010d550f000 0000000000001000 0000 > > 6: 0000000000006000 00000010d7290000 0000000000001000 0000 > > 7: 0000000000007000 00000010d57c9000 0000000000001000 0000 > > 8: 0000000000008000 00000010d57f5000 0000000000001000 0000 > > 9: 0000000000009000 000000076d6b3000 0000000000001000 0000 > > 10: 000000000000a000 00000010d558d000 0000000000001000 0000 > > 11: 000000000000b000 00000010d77ff000 0000000000001000 0000 > > 12: 000000000000c000 00000010d67fb000 0000000000001000 0000 > > 13: 000000000000d000 00000010d73fc000 0000000000001000 0000 > > 14: 000000000000e000 00000005d2bb2000 0000000000001000 0000 > > 15: 000000000000f000 00000007705a1000 0000000000001000 0000 > > 16: 0000000000010000 0000000c8bf10000 0000000000010000 0000 > > 17: 0000000000020000 0000001070020000 0000000000060000 0000 > > 18: 0000000000080000 00000011aa580000 0000000000014000 0001 > > > > File /var/log/syslog.2.gz has 1 extent(s): > > Logical Physical Length Flag > > 0: 0000000000000000 0000000995c40000 0000000000023000 0001 > > > > Signed-off-by: zhenwei pi <pizhenwei@xxxxxxxxxxxxx> > > --- > > AUTHORS | 1 + > > configure.ac | 3 + > > misc-utils/Makemodule.am | 5 ++ > > misc-utils/fiemap.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++ > > 4 files changed, 164 insertions(+) > > create mode 100644 misc-utils/fiemap.c > > > > diff --git a/AUTHORS b/AUTHORS > > index d7dbbd6..a0cecf7 100644 > > --- a/AUTHORS > > +++ b/AUTHORS > > @@ -20,6 +20,7 @@ AUTHORS (merged projects & commands): > > fallocate: Eric Sandeen <sandeen@xxxxxxxxxx> > > Karel Zak <kzak@xxxxxxxxxx> > > Matěj Cepl <mcepl@xxxxxxxxxx> > > + fiemap: zhenwei pi <pizhenwei@xxxxxxxxxxxxx> > > fincore: Masatake YAMATO <yamato@xxxxxxxxxx> > > findmnt: Karel Zak <kzak@xxxxxxxxxx> > > flock: H. Peter Anvin <hpa@xxxxxxxxx> > > diff --git a/configure.ac b/configure.ac > > index bbf07db..ccb1a12 100644 > > --- a/configure.ac > > +++ b/configure.ac > > @@ -1769,6 +1769,9 @@ UL_REQUIRES_LINUX([fincore]) > > UL_REQUIRES_BUILD([fincore], [libsmartcols]) > > AM_CONDITIONAL([BUILD_FINCORE], [test "x$build_fincore" = xyes]) > > > > +UL_BUILD_INIT([fiemap], [yes]) > > +AM_CONDITIONAL([BUILD_FIEMAP], [test "x$build_fiemap" = xyes]) > > + > > UL_BUILD_INIT([fsfreeze], [check]) > > UL_REQUIRES_LINUX([fsfreeze]) > > AM_CONDITIONAL([BUILD_FSFREEZE], [test "x$build_fsfreeze" = xyes]) > > diff --git a/misc-utils/Makemodule.am b/misc-utils/Makemodule.am > > index f56a819..8bdc6fa 100644 > > --- a/misc-utils/Makemodule.am > > +++ b/misc-utils/Makemodule.am > > @@ -228,3 +228,8 @@ hardlink_CFLAGS += $(PCRE_CFLAGS) > > endif > > dist_man_MANS += misc-utils/hardlink.1 > > endif > > + > > +if BUILD_FIEMAP > > +usrbin_exec_PROGRAMS += fiemap > > +fiemap_SOURCES = misc-utils/fiemap.c > > +endif > > diff --git a/misc-utils/fiemap.c b/misc-utils/fiemap.c > > new file mode 100644 > > index 0000000..b77eb14 > > --- /dev/null > > +++ b/misc-utils/fiemap.c > > @@ -0,0 +1,155 @@ > > +/* > > + * Copyright (C) 2019 zhenwei pi <pizhenwei@xxxxxxxxxxxxx> > > + * > > + * This file may be redistributed under the terms of the GNU Public > > + * License. > > + */ > > +#include <stdlib.h> > > +#include <stdio.h> > > +#include <string.h> > > +#include <unistd.h> > > +#include <fcntl.h> > > +#include <getopt.h> > > +#include <sys/ioctl.h> > > +#include <linux/fs.h> > > + > > +#include "c.h" > > +#include "nls.h" > > +#include "closestream.h" > > + > > +#ifdef FS_IOC_FIEMAP > > +#include <linux/fiemap.h> > > + > > +static struct fiemap *read_fiemap(int fd) > > +{ > > + struct fiemap *fiemap; > > + int extents_size; > > + > > + fiemap = (struct fiemap *)malloc(sizeof(struct fiemap)); > > + if (fiemap == NULL) > > + err(EXIT_FAILURE, _("malloc")); > > + > > + memset(fiemap, 0, sizeof(struct fiemap)); > > + > > + fiemap->fm_start = 0; > > + fiemap->fm_length = ~0; > > + fiemap->fm_flags = 0; > > + fiemap->fm_extent_count = 0; > > + fiemap->fm_mapped_extents = 0; > > + > > + /* count how many extents there are */ > > + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) > > + err(EXIT_FAILURE, _("fiemap ioctl() failed")); > > + > > + /* read in the extents */ > > + extents_size = sizeof(struct fiemap_extent) * > > + (fiemap->fm_mapped_extents); > > + > > + /* resize fiemaps for all extents */ > > + fiemap = (struct fiemap *)realloc(fiemap, sizeof(struct fiemap) + > > + extents_size); > > + if (fiemap == NULL) > > + err(EXIT_FAILURE, _("realloc for extents memory")); > > + > > + memset(fiemap->fm_extents, 0, extents_size); > > + fiemap->fm_extent_count = fiemap->fm_mapped_extents; > > + fiemap->fm_mapped_extents = 0; > > + > > + if (ioctl(fd, FS_IOC_FIEMAP, fiemap) < 0) { > > + err(EXIT_FAILURE, _("ioctl() FS_IOC_FIEMAP failed")); > > + return NULL; > > + } > > + > > + return fiemap; > > +} > > + > > +static void show_fiemap(struct fiemap *fiemap, char *filename) > > +{ > > + unsigned int i = 0; > > + > > + printf("File %s has %d extent(s):\n", filename, > > + fiemap->fm_mapped_extents); > > + printf("#\tLogical Physical Length Flag\n"); > > + for (i = 0; i < fiemap->fm_mapped_extents; i++) { > > + printf("%d:\t%-16.16llx %-16.16llx %-16.16llx %-4.4x\n", i, > > + fiemap->fm_extents[i].fe_logical, > > + fiemap->fm_extents[i].fe_physical, > > + fiemap->fm_extents[i].fe_length, > > + fiemap->fm_extents[i].fe_flags); > > + } > > + > > + printf("\n"); > > +} > > + > > +static void __attribute__((__noreturn__)) usage(void) > > +{ > > + FILE *out = stdout; > > + > > + fputs(USAGE_HEADER, out); > > + fprintf(out, _(" %s <file>...\n"), program_invocation_short_name); > > + > > + fputs(USAGE_SEPARATOR, out); > > + exit(EXIT_SUCCESS); > > +} > > + > > +int main(int argc, char **argv) > > +{ > > + int c; > > + static const struct option longopts[] = { > > + { "version", no_argument, NULL, 'V' }, > > + { "help", no_argument, NULL, 'h' }, > > + { NULL, 0, NULL, 0 }, > > + }; > > + > > + setlocale(LC_ALL, ""); > > + bindtextdomain(PACKAGE, LOCALEDIR); > > + textdomain(PACKAGE); > > + atexit(close_stdout); > > + > > + while ((c = getopt_long (argc, argv, "Vh", longopts, NULL)) != -1) { > > + switch (c) { > > + case 'V': > > + printf(UTIL_LINUX_VERSION); > > + return EXIT_SUCCESS; > > + > > + case 'h': > > + usage(); > > + > > + default: > > + errtryhelp(EXIT_FAILURE); > > + } > > + } > > + > > + if (optind == argc) { > > + warnx(_("no file specified")); > > + errtryhelp(EXIT_FAILURE); > > + } > > + > > + for ( ; optind < argc; optind++) { > > + int fd = 0; > > + > > + fd = open(argv[optind], O_RDONLY); > > + if (fd < 0) { > > + err(EXIT_FAILURE, _("open file failed")); > > + } else { > > + struct fiemap *fiemap = NULL; > > + > > + fiemap = read_fiemap(fd); > > + if (fiemap != NULL) { > > + show_fiemap(fiemap, argv[optind]); > > + free(fiemap); > > + } > > + close(fd); > > + } > > + } > > + > > + return 0; > > +} > > +#else > > +int main(int argc, char **argv) > > +{ > > + err(EXIT_FAILURE, _("FS_IOC_FIEMAP not supported")); > > + > > + return 0; > > +} > > +#endif > > -- > > 2.7.4 > > > > -- > Karel Zak <kzak@xxxxxxxxxx> > http://karelzak.blogspot.com