Re: splice() and file offsets

From: Jens Axboe
Date: Mon Jul 10 2006 - 10:18:38 EST


On Mon, Jul 10 2006, Michael Kerrisk wrote:
> Jens,
>
> > > I'm still not clear here. Let me phrase my question another way:
> > > why is it that the presence or absence of off_out affects whether
> > > or not splice() changes the current file offset for fd_out?
> >
> > The logic is simple - either you don't give an explicit offset, and the
> > current position is used and updated. Or you give an offset, and the
> > current position is ignored (not read, not updated).
>
> Yes, I understand what the code is doing, but *why* do
> things this way? (To put things another way: why not *always
> have splice() update the file offset?) I realise there may be
> some good reason for this, and if there is, it will go into the
> man page!

The good reason is why update the current position? I just told the
kernel to ignore the current position and use the given offset, why
would I bother updating the current position? The whole point of
providing an offset is to ignore the current position.

I must say I cannot understand why you are confused or find this
illogical, it makes perfect sense to me.

> > > > It's identical to how sendfile() works.
> > >
> > > But it isn't: sendfile() never changes the file offset
> > > of its 'in_fd'.
> >
> > Ehm, yes it does. Would you expect the app to do an appropriate lseek()
> > on every sendfile() call?
>
> No! It does not! See the sendfile.2 man page: "sendfile()
> does not modify the current file offset of in_fd."

I didn't read the man page, I read the source. And it clearly updates
the file offset, in fact the actual sendfile portion is just a supplied
actor to the generic page cache read functions.

> (You had me worried -- I just now went and *tested*
> the operation of sendfile().) The app does not need to
> do an lseek() call because the 'offset' argument is *always*
> updated with the new "virtual" offset. This is part of why I
> am disturbed/confused: sendfile() always updates its 'offset'
> argument and *never* changes the file offset; splice() only
> does that if its 'offset' argument is non-NULL.

Maybe you didn't understand me correctly. Basically what sys_sendfile()
ends up doing is:

if (offset_given)
ppos = &offset_given;
else
ppos = &in_fd->current_position;

ppos is always updated. sendfile() behaves as I described, it updates
ppos which is _EITHER_ the supplied offset _OR_ the current file offset.
You said that sendfile() never changes in in_fd offset, which is clearly
false as it always updates it if you don't pass in an offset. If you do
pass in an offset, that and only that is changed. The lseek() comment of
course applied to the case where you _don't_ give an explicit offset and
the current position is used.

If you don't believe me, read the source and do another test app.
splice() behaves identically, as previously stated.

--
Jens Axboe

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/