Re: [PATCH 1/9] xfs_io: support the new getfsmap ioctl

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

 



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(&copy_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



[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