On 5/7/17 10:56 AM, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > --- > io/Makefile | 4 > io/copy_file_range.c | 2 > io/encrypt.c | 1 > io/fsmap.c | 559 ++++++++++++++++++++++++++++++++++++++++++++++++++ > io/init.c | 8 + > io/io.h | 14 + > io/open.c | 21 ++ > io/pwrite.c | 2 > io/reflink.c | 4 > io/sendfile.c | 2 > man/man8/xfs_io.8 | 47 ++++ > 11 files changed, 651 insertions(+), 13 deletions(-) > create mode 100644 io/fsmap.c > > > diff --git a/io/Makefile b/io/Makefile > index 435ccff..8d3a30e 100644 > --- a/io/Makefile > +++ b/io/Makefile > @@ -99,6 +99,10 @@ ifeq ($(HAVE_MREMAP),yes) > LCFLAGS += -DHAVE_MREMAP > endif > > +ifeq ($(HAVE_GETFSMAP),yes) > +CFILES += fsmap.c > +endif > + > default: depend $(LTCOMMAND) > > include $(BUILDRULES) > diff --git a/io/copy_file_range.c b/io/copy_file_range.c > index 249c649..d1dfc5a 100644 > --- a/io/copy_file_range.c > +++ b/io/copy_file_range.c > @@ -121,7 +121,7 @@ copy_range_f(int argc, char **argv) > if (optind != argc - 1) > return command_usage(©_range_cmd); > > - fd = openfile(argv[optind], NULL, IO_READONLY, 0); > + fd = openfile(argv[optind], NULL, IO_READONLY, 0, NULL); > if (fd < 0) > return 0; > > diff --git a/io/encrypt.c b/io/encrypt.c > index d844c5e..26ab97c 100644 > --- a/io/encrypt.c > +++ b/io/encrypt.c > @@ -20,6 +20,7 @@ > #include "platform_defs.h" > #include "command.h" > #include "init.h" > +#include "path.h" > #include "io.h" > > #ifndef ARRAY_SIZE > diff --git a/io/fsmap.c b/io/fsmap.c > new file mode 100644 > index 0000000..4128fae > --- /dev/null > +++ b/io/fsmap.c > @@ -0,0 +1,559 @@ > +/* > + * Copyright (C) 2017 Oracle. All Rights Reserved. > + * > + * Author: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > + * > + * This program is free software; you can redistribute it and/or > + * modify it under the terms of the GNU General Public License > + * as published by the Free Software Foundation; either version 2 > + * of the License, or (at your option) any later version. > + * > + * This program is distributed in the hope that it would be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program; if not, write the Free Software Foundation, > + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. > + */ > +#include "platform_defs.h" > +#include "command.h" > +#include "init.h" > +#include "path.h" > +#include "io.h" > +#include "input.h" > + > +static cmdinfo_t fsmap_cmd; > +static dev_t xfs_data_dev; > + > +static void > +fsmap_help(void) > +{ > + printf(_( > +"\n" > +" prints the block mapping for an XFS filesystem" Did you want an \n" on the above line too? Seems a bit odd to have it only on the next line. (one \n is fine too, but not like this) :) > +"\n" > +" Example:\n" > +" 'fsmap -dlrv [-n nr] [startoff] [endoff]' - tabular format verbose map, including unwritten extents\n" This doesn't match the short help: + fsmap_cmd.args = _("[-v] [-n nx] [start] [end]"); or the manpage: +.BI "fsmap [ \-v ] [ \-n " nx " ] [ " start " ] [ " end " ] but getopt sez: > + while ((c = getopt(argc, argv, "dln:rv")) != EOF) { so I guess the short help & manpage need updates. Also, I don't think the "Example:" above is valid: if (dflag + lflag + rflag > 1) return command_usage(&fsmap_cmd); so the help needs to indicate that exactly 1 of -d, -l, or -r is required. > +"\n" > +" fsmap prints the map of disk blocks used by the whole filesystem.\n" > +" The map lists each extent used by the file <newbie> "the file?" what file? , as well as regions in the\n" > +" filesystem that do not have any corresponding blocks (free space).\n" > +" By default, each line of the listing takes the following form:\n" > +" extent: [startoffset..endoffset] owner startblock..endblock\n" say what "owner" means in this case? </newbie> > +" All the file offsets and disk blocks are in units of 512-byte blocks.\n" > +" -d -- query only the data device.\n" > +" -l -- query only the log device.\n" > +" -r -- query only the realtime device.\n" > +" -n -- query n extents.\n" > +" -v -- Verbose information, specify ag info. Show flags legend on 2nd -v\n" > +"\n")); > +} > + > +static int > +numlen( > + off64_t val) > +{ > + off64_t tmp; > + int len; > + > + for (len = 0, tmp = val; tmp > 0; tmp = tmp/10) > + len++; > + return (len == 0 ? 1 : len); > +} Hm, copy #3, do we still not have anywhere to put common stuff like this? > + > +#define OWNER_BUF_SZ 32 > +static const char * > +special_owner( > + __int64_t owner, > + char *buf) > +{ > + switch (owner) { > + case XFS_FMR_OWN_FREE: > + return _("free space"); > + case XFS_FMR_OWN_UNKNOWN: > + return _("unknown"); > + case XFS_FMR_OWN_FS: > + return _("static fs metadata"); > + case XFS_FMR_OWN_LOG: > + return _("journalling log"); > + case XFS_FMR_OWN_AG: > + return _("per-AG metadata"); > + case XFS_FMR_OWN_INOBT: > + return _("inode btree"); > + case XFS_FMR_OWN_INODES: > + return _("inodes"); > + case XFS_FMR_OWN_REFC: > + return _("refcount btree"); > + case XFS_FMR_OWN_COW: > + return _("cow reservation"); > + case XFS_FMR_OWN_DEFECTIVE: > + return _("defective"); > + default: > + snprintf(buf, OWNER_BUF_SZ, _("special %u:%u"), > + FMR_OWNER_TYPE(owner), FMR_OWNER_CODE(owner)); > + return buf; > + } > +} > + > +static void > +dump_map( > + unsigned long long *nr, > + struct fsmap_head *head) > +{ > + unsigned long long i; > + struct fsmap *p; > + char owner[OWNER_BUF_SZ]; > + > + for (i = 0, p = head->fmh_recs; i < head->fmh_entries; i++, p++) { > + printf("\t%llu: %u:%u [%lld..%lld]: ", i + (*nr), > + major(p->fmr_device), minor(p->fmr_device), > + (long long)BTOBBT(p->fmr_physical), > + (long long)BTOBBT(p->fmr_physical + p->fmr_length - 1)); > + if (p->fmr_flags & FMR_OF_SPECIAL_OWNER) > + printf("%s", special_owner(p->fmr_owner, owner)); > + else if (p->fmr_flags & FMR_OF_EXTENT_MAP) > + printf(_("inode %lld extent map"), > + (long long) p->fmr_owner); > + else > + printf(_("inode %lld %lld..%lld"), > + (long long)p->fmr_owner, > + (long long)BTOBBT(p->fmr_offset), > + (long long)BTOBBT(p->fmr_offset + p->fmr_length - 1)); > + printf(_(" %lld blocks\n"), > + (long long)BTOBBT(p->fmr_length)); > + } > + > + (*nr) += head->fmh_entries; > +} > + > +/* > + * Verbose mode displays: > + * extent: major:minor [startblock..endblock]: startoffset..endoffset \ > + * ag# (agoffset..agendoffset) totalbbs flags > + */ > +#define MINRANGE_WIDTH 16 > +#define MINAG_WIDTH 2 > +#define MINTOT_WIDTH 5 > +#define NFLG 7 /* count of flags */ > +#define FLG_NULL 00000000 /* Null flag */ > +#define FLG_SHARED 01000000 /* shared extent */ > +#define FLG_ATTR_FORK 00100000 /* attribute fork */ > +#define FLG_PRE 00010000 /* Unwritten extent */ > +#define FLG_BSU 00001000 /* Not on begin of stripe unit */ > +#define FLG_ESU 00000100 /* Not on end of stripe unit */ > +#define FLG_BSW 00000010 /* Not on begin of stripe width */ > +#define FLG_ESW 00000001 /* Not on end of stripe width */ These really couldn't share w/ io/bmap.c? :( (could FLG_ATTR_FORK go to the end so that it matches bmap until then?) speakinawhich, I wonder how much of this is copied from bmap, and what could be shared? I'm going to go off & look at that a bit, may have further comments. :) > diff --git a/man/man8/xfs_io.8 b/man/man8/xfs_io.8 > index 29a036c..2c956b8 100644 > --- a/man/man8/xfs_io.8 > +++ b/man/man8/xfs_io.8 > @@ -301,6 +301,53 @@ ioctl. Options behave as described in the > .BR xfs_bmap (8) > manual page. > .TP > +.BI "fsmap [ \-v ] [ \-n " nx " ] [ " start " ] [ " end " ] > +Prints the mapping of disk blocks used by an XFS filesystem. FOREIGN_OK too right? -Eric > The map > +lists each extent used by files, allocation group metadata, > +journalling logs, and static filesystem metadata, as well as any > +regions that are unused. Each line of the listings takes the > +following form: > +.PP > +.RS > +.IR extent ": " major ":" minor " [" startblock .. endblock "]: " owner " " startoffset .. endoffset " " length > +.PP > +Static filesystem metadata, allocation group metadata, btrees, > +journalling logs, and free space are marked by replacing the > +.IR startoffset .. endoffset > +with the appropriate marker. All blocks, offsets, and lengths are specified > +in units of 512-byte blocks, no matter what the filesystem's block size is. > +.BI "The optional " start " and " end " arguments can be used to constrain > +the output to a particular range of disk blocks. > +.RE > +.RS 1.0i > +.PD 0 > +.TP > +.BI \-n " num_extents" > +If this option is given, > +.B xfs_fsmap > +obtains the extent list of the file in groups of > +.I num_extents > +extents. In the absence of > +.BR \-n ", " xfs_fsmap > +queries the system for the number of extents in the filesystem and uses that > +value to compute the group size. > +.TP > +.B \-v > +Shows verbose information. When this flag is specified, additional AG > +specific information is appended to each line in the following form: > +.IP > +.RS 1.2i > +.IR agno " (" startagblock .. endagblock ") " nblocks " " flags > +.RE > +.IP > +A second > +.B \-v > +option will print out the > +.I flags > +legend. > +.RE > +.PD > +.TP > .BI "extsize [ \-R | \-D ] [ " value " ]" > Display and/or modify the preferred extent size used when allocating > space for the currently open file. If the > > -- > To unsubscribe from this list: send the line "unsubscribe linux-xfs" in > the body of a message to majordomo@xxxxxxxxxxxxxxx > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-xfs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html