Re: Race conditions in file creation in 2.3.

Manfred Spraul (manfreds@colorfullife.com)
Sun, 05 Sep 1999 14:53:08 +0200


This is a multi-part message in MIME format.
--------------2F4894000232D3AC1662AC76
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Alan wrote:
> I think the error is coming from open() from the error message cp issued.

Yes, but it's open(O_TRUNC).

I could reproduce a bug with the attached c-program.
Just start ~ 10 processes and wait [amd-K6 200, scsi, ext2 disk]

The bug could be caused by the missing synchronization of truncate() and
write()
This is a known problem since ~2.3.7. [neither O_APPEND, nor i_size nor
f_pos are synchronized]

Unfortunately, it seems difficult to fix it properly:

1) affected files:
several places outside VFS access i_sem directly: [at least]
+ fs/nfsd/vfs.c
+ arch/*/kernel/sys_*.c
+ drivers/char/tty_io.c

2) different types of files have completely different synchronzation
requirements, so I think flags should be added to VFS which sync calls
are required.

+ pipes: nothing, even parallel read()/write() calls to the same filp
must not block in VFS [the pipe could use O_NONBLOCK]
linux-2.2 uses a dirty hack: fs/pipe.c knows that sys_write() called
down(i_sem), and pipe.c calls up().

+ e.g. raw-io: everything can run parallel _except_ parallel
sys_read()/sys_write() calls to the same filp [flip->f_pos!]. No
restrictions on parallel sys_pread()/sys_pwrite(). Note that this cannot
be implemented in raw.c, because raw.c does not know whether sys_read()
or sys_pread() was called.

+ normal files: parallel, non-overlapping read/write calls are possible[
overlapping writes violate NfsV2]. Truncate can run in parallel with
read()/write() if these calls don't access the area between [old-EOF,
new-EOF].
Even Windows 95 allow this level or parallelity for some files, this
should be possible under Linux as well.

+ everything else: I'd call down() before calling f_ops->read()/write(),
I don't know if all character devices can handle parallel read()/write()
calls. If they can handle it, then they should set appopriate flags.

--
	Manfred
--------------2F4894000232D3AC1662AC76
Content-Type: text/plain; charset=us-ascii;
 name="opentest.cpp"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="opentest.cpp"

#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <fcntl.h>

static char buffer[81930];

extern "C" int main( int argc, char *argv[] ) { printf("opentest <test file>\n"); if(argc != 2) { printf(" Invalid parameters.\n"); return 1; } for (;;) { int handle;

handle = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC, 0600); if(handle==-1) { printf("open failed: %d.\n",errno); return 1; } write(handle, buffer, 81930); write(handle, buffer, 81930); write(handle, buffer, 81930); write(handle, buffer, 81930); write(handle, buffer, 81930); write(handle, buffer, 81930); close(handle); unlink(argv[1]); } return 0; }

--------------2F4894000232D3AC1662AC76--

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