From: Mark Tinguely <tinguely@sgi.com>
To: Eric Sandeen <sandeen@sandeen.net>
Cc: xfs@oss.sgi.com
Subject: Re: [PATCH] xfs_io: add the lseek() SEEK_DATA/SEEK_HOLE support
Date: Wed, 21 Aug 2013 11:52:32 -0500 [thread overview]
Message-ID: <5214F050.7060402@sgi.com> (raw)
In-Reply-To: <5214EAAC.80800@sandeen.net>
On 08/21/13 11:28, Eric Sandeen wrote:
> On 8/21/13 9:14 AM, Mark Tinguely wrote:
>>
>> This patch started as an xfstest to test Jeff's advanced seek_data features. The C code we had for that feature was deemed as an xfs_io feature.
>
> *nod*
>
> Forgive me for looking more carefully now than then, sorry.
>
> Argh, and for missing that you're already on V5, I missed
> the previous reviews. Well, I did find at least one speling eror,
> so there's that. But more below...
only 1?
>
>> On 08/20/13 18:07, Eric Sandeen wrote:
>>> On 8/16/13 3:54 PM, Mark Tinguely wrote:
>>>
>>>> Add the lseek SEEK_DATA/SEEK_HOLE support into xfs_io.
>>>> The result from the lseek() call will be printed to the output.
>>>> For example:
>>>>
>>>> xfs_io> lseek -h 609k
>>>> Type Offset
>>>> hole 630784
>>>
>>> HOLE not hole, I guess. ;)
>>>
>>> I was going to say that's a lot of verbosity for a single output,
>>> but I guess the other options might have many lines, so I suppose
>>> it makes sense.
>>>
>>> (I was just thinking about what xfstests might need to do to filter
>>> & parse output...)
>>
>> parsing is a bear because there are multiple correct answers.
>> There is always a legal hole at EOF and that if SEEK_HOLE is not implemented that is the answer they give.
>>
>> Different versions of XFS seek_data code will give different answer to the same test depending on what is supported in that version.
>>
>>>
>>>> Signed-off-by: Mark Tinguely<tinguely@sgi.com>
>>>> ---
>>>> Not trying to be difficult. Dave wanted the single hole/data/hole and data
>>>> seperated from the recursive loop, but doing it that way is basically unrolling
>>>> the loop into a if-then-else and is really terrible. If this is still not
>>>> acceptable, then we can throw this feature into /dev/null.
>>>>
>>>> configure.ac | 1
>>>> include/builddefs.in | 1
>>>> io/Makefile | 5 +
>>>> io/init.c | 1
>>>> io/io.h | 6 +
>>>> io/seek.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>> m4/package_libcdev.m4 | 15 ++++
>>>> man/man8/xfs_io.8 | 35 +++++++++
>>>> 8 files changed, 251 insertions(+)
>>>>
>>>> Index: b/configure.ac
>>>> ===================================================================
>>>> --- a/configure.ac
>>>> +++ b/configure.ac
>>>> @@ -110,6 +110,7 @@ AC_HAVE_GETMNTINFO
>>>> AC_HAVE_FALLOCATE
>>>> AC_HAVE_FIEMAP
>>>> AC_HAVE_PREADV
>>>> +AC_HAVE_SEEK_DATA
>>>> AC_HAVE_SYNC_FILE_RANGE
>>>> AC_HAVE_BLKID_TOPO($enable_blkid)
>>>> AC_HAVE_READDIR
>>>> Index: b/include/builddefs.in
>>>> ===================================================================
>>>> --- a/include/builddefs.in
>>>> +++ b/include/builddefs.in
>>>> @@ -102,6 +102,7 @@ HAVE_GETMNTINFO = @have_getmntinfo@
>>>> HAVE_FALLOCATE = @have_fallocate@
>>>> HAVE_FIEMAP = @have_fiemap@
>>>> HAVE_PREADV = @have_preadv@
>>>> +HAVE_SEEK_DATA = @have_seek_data@
>>>> HAVE_SYNC_FILE_RANGE = @have_sync_file_range@
>>>> HAVE_READDIR = @have_readdir@
>>>>
>>>> Index: b/io/Makefile
>>>> ===================================================================
>>>> --- a/io/Makefile
>>>> +++ b/io/Makefile
>>>> @@ -85,6 +85,11 @@ CFILES += readdir.c
>>>> LCFLAGS += -DHAVE_READDIR
>>>> endif
>>>>
>>>> +ifeq ($(HAVE_SEEK_DATA),yes)
>>>> +LCFLAGS += -DHAVE_SEEK_DATA
>>>> +CFILES += seek.c
>>>
>>> see below; we should unconditionally compile, but conditionally
>>> locally define SEEK_DATA / SEEK_HOLE
>>>
>>
>> It was put in to check if SEEK_DATA is supported.
>>
>> Yes, it expects the user headers to reflect what the kernel is capable of doing.
>
> well, especially on a development system, the installed headers may not
> reflect or match the running kernel.
>
> So even if system headers don't have SEEK_DATA it, the running kernel may
> still be capable of it, right?
>
> We've done similar things for i.e. fallocate PUNCH_HOLE.
>
>> If you don't want it, then it will be removed.
>
> I think it makes sense to build it& locally define if necessary.
> On my RHEL6 root w/ an upstream devel kernel seek.c wouldn't have
> built, even though it'd have worked perfectly w/ a local define.
>
yes, needed anyway if removing linux/fs.h
>>>> +endif
>>>> +
>>>> default: depend $(LTCOMMAND)
>>>>
>>>> include $(BUILDRULES)
>>>> Index: b/io/init.c
>>>> ===================================================================
>>>> --- a/io/init.c
>>>> +++ b/io/init.c
>>>> @@ -64,6 +64,7 @@ init_commands(void)
>>>> help_init();
>>>> imap_init();
>>>> inject_init();
>>>> + seek_init();
>>>> madvise_init();
>>>> mincore_init();
>>>> mmap_init();
>>>> Index: b/io/io.h
>>>> ===================================================================
>>>> --- a/io/io.h
>>>> +++ b/io/io.h
>>>> @@ -108,6 +108,12 @@ extern void quit_init(void);
>>>> extern void shutdown_init(void);
>>>> extern void truncate_init(void);
>>>>
>>>> +#ifdef HAVE_SEEK_DATA
>>>> +extern void seek_init(void);
>>>> +#else
>>>> +#define seek_init() do { } while (0)
>>>> +#endif
>>>
>>> this can go when we unconditionally compile it in
>>>
>>>> +
>>>> #ifdef HAVE_FADVISE
>>>> extern void fadvise_init(void);
>>>> #else
>>>> Index: b/io/seek.c
>>>> ===================================================================
>>>> --- /dev/null
>>>> +++ b/io/seek.c
>>>> @@ -0,0 +1,187 @@
>>>> +/*
>>>> + * Copyright (c) 2013 SGI
>>>> + * All Rights Reserved.
>>>> + *
>>>> + * 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.
>>>> + *
>>>> + * 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<libxfs.h>
>>>
>>> hm, including this clashes w/ the min() define in io/init.h,
>>> which is maybe a separate problem down the line, but libxfs.h
>>> isn't required anyway for this file, so I'd just drop this include.
>>>
>>>> +#include<linux/fs.h>
>>
>> I think the previous review had a problem with this header which should be removed.
>
> oh yeah, Dave did ask (now that I'm caught up with the last 4 reviews) :(
>
> And yeah it builds fine w/o either libxfs.h or linux/fs.h, so I'd just yank
> 'em both.
>
yes, I missed them from Dave's review - my mistake.
>>>> +
>>>> +#include<sys/uio.h>
>>>> +#include<xfs/xfs.h>
>>>> +#include<xfs/command.h>
>>>> +#include<xfs/input.h>
>>>> +#include<ctype.h>
>>>> +#include "init.h"
>>>> +#include "io.h"
>>>
>>> #ifndef HAVE_SEEK_DATA
>>> #define SEEK_DATA 3 /* seek to the next data */
>>> #define SEEK_HOLE 4 /* seek to the next hole */
>>> #endif
>>>
>>>> +
>>>> +static cmdinfo_t seek_cmd;
>>>> +
>>>> +static void
>>>> +seek_help(void)
>>>> +{
>>>> + printf(_(
>>>> +"\n"
>>>> +" returns the next hole and/or data offset at or after the specified offset\n"
>>>> +"\n"
>>>> +" Example:\n"
>>>> +" 'seek -d 512' - offset of data at or following offset 512\n"
>>>> +" 'seek -a -r 0' - offsets of all data and hole in entire file\n"
>>>> +"\n"
>>>> +" Returns the offset of the next data and/or hole. There is an implied hole\n"
>>>> +" at the end of file.
>>>
>>> is this expected, given the hole at the end of the file? This is for a single
>>> non-sparse file:
>>>
>>> xfs_io> seek -ar 0
>>> Type offset
>>> DATA 0
>>> HOLE 3022
>>> DATA EOF
>>>
>>> That last line doesn't make sense, does it?
>>
>> Parsing is the reason the entry is there so the output always has
>> consistent ending entry - some queries that is the only answer (or
>> now no message) no biggy one way or the other.
>
> Hm, ok, clearly you've thought about this more than I have.
> It just surprised me...
>
> So let me just think out loud here w/ examples.
>
> For a 1M 100% nonsparse file we get:
>
> # io/xfs_io -c "seek -ar 0" alldata
> Type offset
> DATA 0
> HOLE 1048576
or this could be HOLE EOF depends on the version.
> DATA EOF
>
> For a 1M 100% sparse file (i_size and no blocks at all) we get:
>
> # io/xfs_io -c "seek -ar 0" allsparse
> Type offset
> HOLE 0
> DATA EOF
>
> For a 1M file w/ only the first 512k w/ data, then hole,
> we get:
>
> # io/xfs_io -c "seek -ar 0" endhole
> Type offset
> DATA 0
> HOLE 524288
> DATA EOF
>
> For a 1M file w/ 512k of hole and then 512k w/ data, we get:
>
> # io/xfs_io -c "seek -ar 0" starthole
> Type offset
> HOLE 0
> DATA 524288
> HOLE 1048576
> DATA EOF
>
> So in each case, the "DATA EOF" at the end seems odd to me.
>
> And in each case above, the output is unique w/o the EOF flag
> anwyway, right?
... or we will get "HOLE EOF"
There are different versions of XFS seek_data and they will
detect/report the start of data and holes differently so output parsing
will be a bear. The existing C code sends the 2 different value numbers
that could be reported.
The later, advance dirty page detection is more fine tuned. Jeff and I
had C tests for this feature that I turned into a xfstest; it was
suggested that the C test become xfs_io call, and then 5 versions later,
we have this ...
>
> I'm probably missing it; in what cases is the EOF record
> useful? It just seems beyond the scope of SEEK_HOLE/SEEK_DATA.
> (i.e. EOF is SEEK_END)
>
> If the EOF is really helpful, maybe it is possible instead to do something like:
>
> # io/xfs_io -c "seek -ar 0" starthole
> Type offset
> HOLE 0
> DATA 524288
> EOF 1048575
> HOLE 1048576
>
> That makes more intuitive sense to me if you really need the EOF
> record, but I dunno, what do you think?
>
I can drop the table header.
We can leave off the implied eof - there will be cases where there is no
entries.
>>>
>>>> If the specified offset is past end of file, or there\n"
>>>> +" is no data past the specied offset, EOF is returned.\n"
>>>
>>> "specified"
>>>
>>>> +" -a -- return the next data and hole starting at the specified offset.\n"
>>>> +" -d -- return the next data starting at the specified offset.\n"
>>>> +" -h -- return the next hole starting at the specified offset.\n"
>>>> +" -r -- return all remaining type(s) starting at the specified offset.\n"
>>>> +"\n"));
>>>> +}
>>>> +
>>>> +#define SEEK_DFLAG (1<< 0)
>>>> +#define SEEK_HFLAG (1<< 1)
>>>> +#define SEEK_RFLAG (1<< 2)
>>>> +#define DATA 0
>>>> +#define HOLE 1
>>>> +
>>>> +struct seekinfo {
>>>> + char *name;
>>>> + int seektype;
>>>> + int mask;
>>>> +} seekinfo[] = {
>>>> + {"DATA", SEEK_DATA, SEEK_DFLAG},
>>>> + {"HOLE", SEEK_HOLE, SEEK_HFLAG}
>>>
>>> I guess "DATA" doesn't get replaced by "0" ? Sorry, I failed cpp 101.
>>> It prints the right thing so I guess not. ;)
>>>
>>
>> :) no the defines are subscripts = see "current ="
>
> I did see that, I just wasn't sure if it'd replace it in literal
> strings, but apparently not.
>
nope, strings are safe - did Coverity complain?
>>
>>>> +};
>>>> +
>>>> +void
>>>> +seek_output(
>>>> + char *type,
>>>> + off64_t offset)
>>>> +{
>>>> + if (offset == -1) {
>>>> + if (errno == ENXIO)
>>>> + printf("%s EOF\n", type);
>>>> + else
>>>> + printf("%s ERR %d\n", type, errno);
>>>> + } else
>>>> + printf("%s %ld\n", type, offset);
>
> one more; for 32-bit systems I think this should be
>
> printf("%s %lld\n", type, (long long)offset);
>
> to avoid a warning; that's what i.e. the pwrite printf's do.
>
okay, thanks.
>>>> +}
>>>> +
>>>> +static int
>>>> +seek_f(
>>>> + int argc,
>>>> + char **argv)
>>>> +{
>>>> + off64_t offset, result;
>>>> + size_t fsblocksize, fssectsize;
>>>> + int flag;
>>>> + int current; /* specify data or hole */
>>>> + int c;
>>>> +
>>>> + flag = 0;
>>>> + init_cvtnum(&fsblocksize,&fssectsize);
>>>> +
>>>> + while ((c = getopt(argc, argv, "adhr")) != EOF) {
>>>> + switch (c) {
>>>> + case 'a':
>>>> + flag |= (SEEK_HFLAG | SEEK_DFLAG);
>>>> + break;
>>>> + case 'd':
>>>> + flag |= SEEK_DFLAG;
>>>> + break;
>>>> + case 'h':
>>>> + flag |= SEEK_HFLAG;
>>>> + break;
>>>> + case 'r':
>>>> + flag |= SEEK_RFLAG;
>>>> + break;
>>>> + default:
>>>> + return command_usage(&seek_cmd);
>>>> + }
>>>> + }
>>>> + /* must have hole or data specified and an offset */
>
> super-nitpick, extra tab before the comment.
>
not a problem.
>>>> + if (!(flag& (SEEK_DFLAG | SEEK_HFLAG)) ||
>>>> + optind != argc - 1)
>>>> + return command_usage(&seek_cmd);
>>>> +
>>>> + offset = cvtnum(fsblocksize, fssectsize, argv[optind]);
>>>
>>> need to error check that:
>>>
>>> xfs_io> seek -a 8x8
>>> Type offset
>>> HOLE EOF
>>>
>>
>> Some version of XFS seek_data will treat it as a 0, but okay.
>
> but I mean the error from cvtnum, if you don't give it a valid string;
> nothing to do w/ seek_data ...
>
duh me. okay.
> Thanks,
> -Eric
Thanks.
--Mark.
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2013-08-21 16:52 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-08-16 20:54 [PATCH] xfs_io: add the lseek() SEEK_DATA/SEEK_HOLE support Mark Tinguely
2013-08-20 21:26 ` Rich Johnston
2013-08-20 23:07 ` Eric Sandeen
2013-08-21 14:14 ` Mark Tinguely
2013-08-21 16:28 ` Eric Sandeen
2013-08-21 16:52 ` Mark Tinguely [this message]
2013-08-21 18:31 ` Eric Sandeen
2013-08-21 19:20 ` Mark Tinguely
2013-08-21 19:37 ` Eric Sandeen
2013-08-21 19:55 ` Eric Sandeen
2013-08-21 19:58 ` Mark Tinguely
[not found] <20121022213759.033667921@sgi.com>
2012-10-22 21:38 ` Mark Tinguely
2012-10-22 23:29 ` Dave Chinner
2012-10-23 14:08 ` Mark Tinguely
2012-10-23 12:22 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5214F050.7060402@sgi.com \
--to=tinguely@sgi.com \
--cc=sandeen@sandeen.net \
--cc=xfs@oss.sgi.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.