Inconsistency between lseek(SEEK_HOLE) and lseek(SEEK_DATA)

Konstantin Belousov kostikbel at
Mon Feb 1 19:40:25 UTC 2016

On Mon, Feb 01, 2016 at 11:22:18AM -0800, Maxim Sobolev wrote:
> Well, it's still seems to be quite obscure. At the very least, the lseek(2)
> manual page needs to reflect that. Right now it says:
> [...]
>      [ENXIO]            For SEEK_DATA, there are no more data regions past
> the
>                         supplied offset.  For SEEK_HOLE, there are no more
>                         holes past the supplied offset.
> Which is not true, the SEEK_HOLE would return st_size when there are no
> more holes past the supplied offset, not ENXIO. It is also interesting that
> somehow empty file is a special case as well. Both SEEK_HOLE and SEEK_DATA
> return -1 on those. Anybody who programs to that document would probably
> get as confused as myself.
> However, having said that, our cousin Linux behaves the same - i.e. returns
> EOF+1 on SEEK_HOLE and -1 on SEEK_DATA, and does the same for empty files,
> so at least we are consistent with that.

Actually, since you referred to the man page for lseek(2), which seems to
be copied from the Solaris man page:
The existence of a hole at the end of every data region allows for easy
programming and implies that a virtual hole exists at the end of the

And, the text you quoted, does not imply that the call must return ENXIO
at the EOF for hole.  It only allows the call to do it, but other language
makes this unreasonable.

Note that it is Solaris, not Linux, which implementation of the SEEK_HOLE
and SEEK_DATA is the arbitration sample for the behavior.  We got it with
the ZFS import.  Our UFS implementation, and whatever Linux does, are only
reimplementation without clean documentation, and were done by observing
ZFS behaviour.

More information about the freebsd-fs mailing list