seeking and seekability (was: "tar tfv /dev/cd0" speedup patch)

Matthias Andree matthias.andree at gmx.de
Fri Feb 19 08:34:31 UTC 2010


Am 19.02.2010, 06:03 Uhr, schrieb Tim Kientzle <kientzle at freebsd.org>:

> Joerg Sonnenberger wrote:
>> On Thu, Feb 18, 2010 at 07:34:59PM +0100, Juergen Lock wrote:
>>>  Ok here is a new version of the patch with these things fixed and the
>>> Linux case added:  (Linux case not tested yet, and yes I did this on
>>> stable/8.)
>>  Why the check at all? Shouldn't devices that don't allow seek fail  
>> that?
>> E.g. for devices, just try to seek ahead and fallback to normal reading?
>
> That was the initial implementation in libarchive, but
> I had a number of reports of that not working for
> tape drives.  I recently dug out and connected an
> old DDS drive I had in the closet, so I should
> probably try again and see if I misunderstood
> something along the way.

I'd already written this in a private email to Tim before I came across  
this continued discussion on -hackers@, I'll paste a modified version of  
my own part:

I strongly believe that someone should really fix lseek() in FreeBSD  
outside GEOM. There is precedence, namely  
<http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/60313> and it was never  
properly fixed. The PR was closed because the actual reported problem on  
da(4) no longer occurred since FreeBSD 5 after the GEOM migration, and my  
issue was with da(4) on FreeBSD 4.

Now I'm learning that the very same bug persists through -CURRENT nearly a  
decade later: after lseek devices such as sa(4) will return "garbage" (i.  
e. from the unchanged offset) rather than failing.

It should be sorted out before 8.1.

Am I naive if I expect lseek to return (off_t)-1 with errno == ESPIPE on  
non-seekable devices?
   I'll concede that sa(4) is neither socket nor pipe nor fifo in the  
strict sense, but all share the non-seekability.

If lseek() can't know the device isn't seekable, subsequent I/O operations  
should return EIO along with a proper kernel log message for the first  
occasion per process, but that would not help applications or libarchive  
for that matter - they will need a canonical way to find out if a device  
is seekable. Unfortunately FreeBSD maps many physical block devices that  
are unbuffered to character special device nodes, so the obvious way of  
calling [f]stat() and then checking S_ISBLK(st.st_mode) will return FALSE  
even for devices that can seek.

-- 
Matthias Andree


More information about the freebsd-hackers mailing list