Re: What protects f_pos?

From: David Wragg (dpw@doc.ic.ac.uk)
Date: Mon Nov 13 2000 - 10:22:56 EST


"David Schwartz" <davids@webmaster.com> writes:
> Suppose you had a multithreaded program that used a
> configuration file with a group of fixed-length blocks indicating what
> work it had to do. Each thread read a block from the file and then did
> the work. One might think that there's no need to protect the file
> descriptor with a mutex.

I don't think that this will work, due to a separate non-atomicity
issue with f_pos. The generic file read and write implementations do
not atomically update f_pos. They read f_pos to determine the file
offset to use, then manipulate the page cache (possibly sleeping on
I/O), and only then set f_pos to the appropriate updated value. So
the example you suggest, with two threads, could do something like:

          Thread 1 Thread 2

   sys_read(fd, buf1, len)

      off = file->f_pos sys_read(fd, buf2, len)

         read to buf1 off = file->f_pos

    file->f_pos = off + len read to buf2

                                        file->f_pos = off + len

So both threads read the same block, and f_pos only gets incremented
once.

(Pipes and sockets are a different matter, of course.)

2.2 has the same issue, since although the BKL is held, it will get
dropped if one of the threads sleeps on I/O. (Earlier Linux versions
might well have the same issue, but I don't have the source around to
check.)

POSIX doesn't seem to bar this behaviour. From 6.4.1.2:

    On a regular file or other file capable of seeking, read() shall
    start at a position in the file given by the file offset
    associated with fildes. Before successful return from read(), the
    file offset shall be incremented by the number of bytes actually
    read.

Which is exactly what Linux does. I can't find text anywhere else in
POSIX.1 that strengthens that condition for the case of multiple
processes/threads reading from the same file. I'll try to find out
what the Austin Group has to say about this.

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



This archive was generated by hypermail 2b29 : Wed Nov 15 2000 - 21:00:23 EST