Write is not atomic?
Hi,
The Linux manual page for write(2) says:
The adjustment of the file offset and the write operation are performed as an atomic step.
This is apparently an extension to POSIX, which says
This volume of IEEE Std 1003.1-2001 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control.
The following fragment of code
int fd;
fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666);
fork();
write(fd, "Ouille", 6);
close(fd);produces "OuilleOuille", as expected, on ext4 on two machines running Linux 3.2 AMD64. However, over XFS on an old Pentium III at 500 MHz running 2.6.32, it produces just "Ouille" roughly once in three times.
Sorry for not being able to give more test cases, but I cannot easily change either the filesystem or the kernel on the Pentium server.
-- Juliusz Chroboczek
P.S. I'll appreciate being copied with any replies.
Quoted 13 lines · Juliusz Chroboczek
Hi,
The Linux manual page for write(2) says:
The adjustment of the file offset and the write operation are performed as an atomic step.
This is apparently an extension to POSIX, which says
This volume of IEEE Std 1003.1-2001 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control.
Quoted 6 lines
The following fragment of code
int fd; fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666); fork(); write(fd, "Ouille", 6);
You don't check return code here, does write succeed at all?
Quoted 5 lines
close(fd);produces "OuilleOuille", as expected, on ext4 on two machines running Linux 3.2 AMD64. However, over XFS on an old Pentium III at 500 MHz running 2.6.32, it produces just "Ouille" roughly once in three times.
Does it ever produce e.g. OuOuilleille (as this is what atomicity is about here)?
Signature · 2 lines
Thanks. -- Max
Quoted 1 line
You don't check return code here, does write succeed at all?
Yes, both writes return 6.
Quoted 1 line
Does it ever produce e.g. OuOuilleille
No.
Quoted 1 line
(as this is what atomicity is about here)?
I was referring to the claim that under Linux writing and adjusting the file offset are performed as an atomic step, not to the atomicity of the write operation itself.
-- Juliusz
Quoted 6 lines · Juliusz Chroboczek
Hi,
The Linux manual page for write(2) says:
The adjustment of the file offset and the write operation are performed as an atomic step.
That's wrong. The file offset update is not synchronised at all with the write, and for a shared fd the update will race.
Quoted 5 lines
This is apparently an extension to POSIX, which says
This volume of IEEE Std 1003.1-2001 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control.
This is how Linux behaves.
Quoted 11 lines
The following fragment of code
int fd; fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666); fork(); write(fd, "Ouille", 6); close(fd);produces "OuilleOuille", as expected, on ext4 on two machines running Linux 3.2 AMD64. However, over XFS on an old Pentium III at 500 MHz running 2.6.32, it produces just "Ouille" roughly once in three times.
ext4, on 3.6:
$ for i in `seq 0 10000`; do ./a.out ; cat /mnt/scratch/foo ; echo ; done | sort |uniq -c
39 Ouille
9962 OuilleOuille
$XFS, on the same kernel, hardware and block device:
$ for i in `seq 0 10000`; do ./a.out ; cat /mnt/scratch/foo ; echo ; done | sort |uniq -c
40 Ouille
9961 OuilleOuille
$So both filesystems behave according to the POSIX definition of concurrent writes....
Cheers,
Dave.
Signature · 2 lines
Dave Chinner [email protected]
Quoted 10 lines · Dave Chinner
Quoted 6 lines · Juliusz Chroboczek
Hi,
The Linux manual page for write(2) says:
The adjustment of the file offset and the write operation are performed as an atomic step.
That's wrong. The file offset update is not synchronised at all with the write, and for a shared fd the update will race.
That's what O_APPEND or pread/pwrite are for.
Quoted 15 lines
Quoted 5 lines
This is apparently an extension to POSIX, which says
This volume of IEEE Std 1003.1-2001 does not specify behavior of concurrent writes to a file from multiple processes. Applications should use some form of concurrency control.
This is how Linux behaves.
Quoted 7 lines
The following fragment of code
int fd; fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666); fork(); write(fd, "Ouille", 6); close(fd);
can be replaced with:
int fd;
fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, 0666);
fork();
write(fd, "Ouille", 6);
close(fd);or:
int fd;
fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666);
pid_t pid = fork();
pwrite(fd, "Ouille", 6, strlen("Ouille")*(pid == 0));
close(fd);(both code fragments untested)
Phil.
Quoted 10 lines · Philippe Troin
Quoted 8 lines · Dave Chinner
Quoted 7 lines · Juliusz Chroboczek
The following fragment of code
int fd; fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC, 0666); fork(); write(fd, "Ouille", 6); close(fd);
Quoted 7 lines
can be replaced with:
int fd; fd = open("exemple", O_CREAT | O_WRONLY | O_TRUNC | O_APPEND, 0666); fork(); write(fd, "Ouille", 6); close(fd);
Fails the same way as the original. I guess O_APPEND doesn't work this way for writes to the shared file descriptor.
Signature · 2 lines
Thanks. -- Max
Hello,
Quoted 4 lines · Juliusz Chroboczek
The Linux manual page for write(2) says:
The adjustment of the file offset and the write operation are performed as an atomic step.
This seems out of context.
Over here write(2) reads:
If the file was open(2)ed with O_APPEND, the file offset is first set to the end of the file before writing. The adjustment of the file offset and the write operation are performed as an atomic step.
Sounds different, doesn't it?
Hth,
Jochen.
Quoted 8 lines
This seems out of context.
If the file was open(2)ed with
O_APPEND, the file offset is first set to the end of the file before writing. The adjustment of the file offset and the write operation are performed as an atomic step.Sounds different, doesn't it?
Yes, it does -- thanks for the clarification. (And thanks to Dave for the interesting tests.)
Sorry for the confusion,
-- Juliusz