Atomare Dateioperationen

08/03/2010 - 12:17 von Markus Raab | Report spam
Hallo!

Gibt es eine atomare (ohne Locks) Möglichkeit (Konfigurations-)dateien
upzudaten? Dabei soll ausgeschlossen sein, dass Änderungen die vom User in
dieser Datei gemacht werden verloren geht.

Selbst sed -i schafft es nicht wirklich:

open("file", O_RDONLY) = 3 #original_file
open("./sedEfnADp", O_RDWR|O_CREAT|O_EXCL, 0600) = 4 #open temporary_file
fcntl(4, F_GETFL) = 0x8002 (flags O_RDWR|O_LARGEFILE)
fstat(4, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
lseek(4, 0, SEEK_CUR) = 0
fchmod(4, 0100644) = 0
fchown(4, 500, 100) = 0
fstat(3, {st_mode=S_IFREG|0644, st_size=9, ...}) = 0

Hier wird (oder könnte) geschaut werden ob sich die originale Datei
veràndert hat.

read(3, "ein test"..., 4096) = 9
write(4, "ein kein test"..., 14) = 14
read(3, ""..., 4096) = 0
close(3) = 0

Allerdings könnte bis hier die original Datei noch veràndert[0] werden.
Diese Änderungen würden dann nach den nàchsten Befehl verloren gehen:

rename("./sedEfnADp", "file") = 0

Es würde auch nichts nützen ein stat() direkt vor dem rename()
durchzuführen. Selbst in dieser Zeitspanne (zwischen den zwei syscalls)
könnte die Datei veràndert werden.

Wie man es lösen könnte um das ganze atomar zu machen, wàre ein swap() für
Dateien. Weil dann könnte man im darauf-*folgenden* Befehl überprüfen ob
sich bei der original-Datei etwas veràndert[0] hat.

Der Ablauf wàre dann folgendermaßen:

...
close(3) = 0
swap("./sedEfnADp", "file") = 0

stat("./sedEfnAD", {st_mode=S_IFREG|0644, st_size=9, ...}) = 0

Sollte der Modifikationszeitstempel nicht mehr der originalen Datei "file"
entsprechen, so wurde sie veràndert.

Im schlimmsten Fall würde man einen Konflikt entdecken, obwohl der Benutzer
bereits von den richtigen Datei ausgegangen ist. (Falls die gesamte
Verànderung[0] zwischen swap und stat erfolgt ist.)

Da es diesen Syscall afaik nicht gibt, welche Lösungen könnte man da noch
nehmen? Warum ist diese bei sed -i nicht implementiert?

Der Ansatz mit rename ist ja grundsàtzlich mal nicht schlecht. Er garantiert
zumindest einmal das konsistente Dateien entstehen.

mfg Markus


[0] damit meine ich, es wird ein open(), write() und close() durchgeführt.

http://www.markus-raab.org | Leben ist das Einatmen der Zukunft. --
-o) | Pierre Leroux
Kernel 2.6.24-1-a /\ |
on a x86_64 _\_v |
 

Lesen sie die antworten

#1 Rolf Magnus
13/03/2010 - 18:33 | Warnen spam
Markus Raab wrote:

Es würde auch nichts nützen ein stat() direkt vor dem rename()
durchzuführen. Selbst in dieser Zeitspanne (zwischen den zwei syscalls)
könnte die Datei veràndert werden.

Wie man es lösen könnte um das ganze atomar zu machen, wàre ein swap() für
Dateien. Weil dann könnte man im darauf-*folgenden* Befehl überprüfen ob
sich bei der original-Datei etwas veràndert[0] hat.

Der Ablauf wàre dann folgendermaßen:

...
close(3) = 0
swap("./sedEfnADp", "file") = 0

stat("./sedEfnAD", {st_mode=S_IFREG|0644, st_size=9, ...}) = 0

Sollte der Modifikationszeitstempel nicht mehr der originalen Datei "file"
entsprechen, so wurde sie veràndert.



Sie kann aber vor dem swap von einem Programm geöffnet worden und danach
noch immer offen sein und beliebig viel spàter noch veràndert und dann
geschlossen werden. Diese Änderungen gehen sowieso verloren. Du gewinnst
also eigentlich nur den kurzen Zeitraum zwischen dem close und dem
rename/swap.

Der Ansatz mit rename ist ja grundsàtzlich mal nicht schlecht. Er
garantiert zumindest einmal das konsistente Dateien entstehen.



Das ist die übliche Methode dafür.

Ähnliche fragen