lkml.org 
[lkml]   [1999]   [Sep]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Race conditions in file creation in 2.3.
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#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;
}

\
 
 \ /
  Last update: 2005-03-22 13:53    [W:0.025 / U:0.220 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site