From: Eric Blake <eblake@redhat.com>
To: Josef Bacik <josef@toxicpanda.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: [PATCH 1/2] fs: add SEEK_HOLE and SEEK_DATA flags
Date: Fri, 22 Apr 2011 05:41:47 -0600 [thread overview]
Message-ID: <4DB1697B.10606@redhat.com> (raw)
In-Reply-To: <BANLkTiknb+hzFAjpwESwMcqMVtkFc0HFQQ@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 7845 bytes --]
On 04/21/2011 07:22 PM, Josef Bacik wrote:
>> You absolutely need to match Solaris semantics, which are documented as follows:
>>
>> � If whence is SEEK_HOLE, the offset of the start of the next hole
>> greater than or equal to the supplied offset is returned. The def-
>> inition of a hole is provided near the end of the DESCRIPTION.
>>
>> Note that in that definition, SEEK_HOLE does _not_ reposition the file offset
>> (it returns the offset of the next hole, which might be at the end of the file
>> since all files have a virtual hole at the end, but leaves the position
>> unchanged). I'd have to write a test program on Solaris to see whether that
>> definition is actually true, or if it is a bug in the Solaris man page.
>
> lseek's purpose is to reposition the file position, so I'd imagine
> this is just a bug in the man page.
Confirmed that the Solaris man page is buggy and does not accurately
describe the semantics that are actually implemented. My testing showed:
lseek(fd, off, SEEK_HOLE) has four cases:
off < end, in data: repositions to the next hole as if by lseek(fd,
next_hole, SEEK_CUR); the next hole is guaranteed to exist, even if at
end of file
off < end, in hole, and later in file has data: repositions as if by
lseek(fd, off, SEEK_CUR)
off < end, in hole, and no further data in file: repositions as if by
lseek(fd, 0, SEEK_END)
off == end: fails with ENXIO
lseek(fd, off, SEEK_DATA) has four cases:
off < end, in data: repositions as if by lseek(fd, off, SEEK_CUR)
off < end, in hole, and later in file has data: repositions to the next
data as if by lseek(fd, next_data, SEEK_CUR)
off < end, in hole, and remainder of file is hold: fails with ENXIO
off == end: fails with ENXIO
Here's how I tested:
$ uname -sr
SunOS 5.10
$ cat foo.c
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <string.h>
static int
make_sparse (const char *name)
{
int fd = open (name, O_RDWR | O_CREAT | O_TRUNC, 0600);
if (fd < 0)
return fd;
printf ("creating %s\n", name);
if (write (fd, "a", 1) != 1)
goto cleanup;
if (lseek (fd, 1024*1024, SEEK_CUR) == -1)
goto cleanup;
if (write (fd, "b", 1) != 1)
goto cleanup;
if (lseek (fd, 0, SEEK_SET) != 0)
goto cleanup;
return fd;
cleanup:
close (fd);
return -1;
}
int
main (int argc, char **argv)
{
off_t off;
off_t end;
int fd = argc > 2 ? open (argv[1], O_RDONLY)
: make_sparse (argc > 1 ? argv[1] : "file");
perror(NULL);
if (fd < 0)
return 2;
printf ("fpathconf gives %ld, ENXIO is %d\n",
fpathconf (fd, _PC_MIN_HOLE_SIZE), ENXIO);
puts ("\ntesting at start");
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_DATA);
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
puts ("\ntesting at end");
errno = 0;
off = end = lseek (fd, 0, SEEK_END);
printf ("end at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, end, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, end, SEEK_DATA);
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, end - 1, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, end - 1, SEEK_DATA);
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
puts ("\ntesting at offset 1");
errno = 0;
off = lseek (fd, 1, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 1, SEEK_DATA);
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
puts ("\ntesting at offset 200000");
errno = 0;
off = lseek (fd, 200000, SEEK_HOLE);
printf ("HOLE gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 200000, SEEK_DATA);
printf ("DATA gives offset %lld, errno %d\n", (long long) off, errno);
errno = 0;
off = lseek (fd, 0, SEEK_CUR);
printf ("CUR at offset %lld, errno %d\n", (long long) off, errno);
if (close (fd))
return 3;
return 0;
}
$ ./foo
creating file
Error 0
fpathconf gives 512, ENXIO is 6
testing at start
CUR at offset 0, errno 0
HOLE gives offset 131072, errno 0
CUR at offset 131072, errno 0
DATA gives offset 0, errno 0
CUR at offset 0, errno 0
HOLE gives offset 131072, errno 0
CUR at offset 131072, errno 0
testing at end
end at offset 1048578, errno 0
HOLE gives offset -1, errno 6
CUR at offset 1048578, errno 0
DATA gives offset -1, errno 6
CUR at offset 1048578, errno 0
HOLE gives offset 1048578, errno 0
CUR at offset 1048578, errno 0
DATA gives offset 1048577, errno 0
CUR at offset 1048577, errno 0
testing at offset 1
HOLE gives offset 131072, errno 0
CUR at offset 131072, errno 0
DATA gives offset 1, errno 0
CUR at offset 1, errno 0
testing at offset 200000
HOLE gives offset 200000, errno 0
CUR at offset 200000, errno 0
DATA gives offset 1048576, errno 0
CUR at offset 1048576, errno 0
$ gtruncate -s 1M sparse
$ ./foo sparse 2
Error 0
fpathconf gives 512, ENXIO is 6
testing at start
CUR at offset 0, errno 0
HOLE gives offset 0, errno 0
CUR at offset 0, errno 0
DATA gives offset -1, errno 6
CUR at offset 0, errno 0
HOLE gives offset 0, errno 0
CUR at offset 0, errno 0
testing at end
end at offset 1048576, errno 0
HOLE gives offset -1, errno 6
CUR at offset 1048576, errno 0
DATA gives offset -1, errno 6
CUR at offset 1048576, errno 0
HOLE gives offset 1048576, errno 0
CUR at offset 1048576, errno 0
DATA gives offset -1, errno 6
CUR at offset 1048576, errno 0
testing at offset 1
HOLE gives offset 1, errno 0
CUR at offset 1, errno 0
DATA gives offset -1, errno 6
CUR at offset 1, errno 0
testing at offset 200000
HOLE gives offset 1048576, errno 0
CUR at offset 1048576, errno 0
DATA gives offset -1, errno 6
CUR at offset 1048576, errno 0
$
--
Eric Blake eblake@redhat.com +1-801-349-2682
Libvirt virtualization library http://libvirt.org
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 619 bytes --]
next prev parent reply other threads:[~2011-04-22 11:41 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-21 19:42 [PATCH 1/2] fs: add SEEK_HOLE and SEEK_DATA flags Josef Bacik
2011-04-21 19:42 ` [PATCH 2/2] Btrfs: implement our own ->llseek Josef Bacik
2011-04-21 20:45 ` [PATCH 1/2] fs: add SEEK_HOLE and SEEK_DATA flags Theodore Tso
2011-04-21 21:29 ` Sunil Mushran
2011-04-22 3:23 ` Matthew Wilcox
2011-04-21 22:28 ` Eric Blake
2011-04-22 1:22 ` Josef Bacik
2011-04-22 4:50 ` Christoph Hellwig
2011-04-22 11:28 ` Markus Trippelsdorf
2011-04-22 11:28 ` Markus Trippelsdorf
2011-04-22 11:28 ` Markus Trippelsdorf
2011-04-22 11:50 ` Eric Blake
2011-04-22 16:28 ` Sunil Mushran
2011-04-22 16:40 ` Eric Blake
2011-04-22 16:57 ` Sunil Mushran
2011-04-22 17:03 ` Eric Blake
2011-04-22 17:08 ` Sunil Mushran
2011-04-22 18:06 ` Andreas Dilger
2011-04-22 23:33 ` Sunil Mushran
2011-04-24 17:49 ` Jamie Lokier
2011-04-25 12:37 ` Eric Blake
2011-04-25 14:15 ` Jamie Lokier
2011-04-22 13:06 ` Eric Blake
2011-04-22 13:06 ` Eric Blake
2011-04-25 15:02 ` Nick Bowler
2011-04-25 15:48 ` Eric Blake
2011-04-25 15:48 ` Eric Blake
2011-04-22 11:41 ` Eric Blake [this message]
2011-04-22 4:47 ` Christoph Hellwig
2011-04-22 20:10 ` Jonathan Nieder
2011-04-22 20:49 ` Sunil Mushran
2011-04-25 3:11 ` Valdis.Kletnieks
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=4DB1697B.10606@redhat.com \
--to=eblake@redhat.com \
--cc=josef@toxicpanda.com \
--cc=linux-kernel@vger.kernel.org \
/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.