Jak trwale zmienić nazwę pliku w POSIX?

Jaki jest prawidłowy sposób trwałej zmiany nazwy pliku w systemie plików POSIX? W szczególności zastanawiasz się nad fsync w katalogach . (Jeśli to zależy od OS / FS, pytam o Linuksa i ext3 / ext4).

Notatka: są inne pytania na temat StackOverflow o trwałe zmiany nazw, ale AFAICT nie odnoszą się do fsync-ing katalogów (co jest dla mnie ważne - nawet nie modyfikuję danych plików).

Aktualnie mam (w Python): {]}

dstdirfd = open(dstdirpath, O_DIRECTORY|O_RDONLY)
rename(srcdirpath + '/' + filename, dstdirpath + '/' + filename)
fsync(dstdirfd)

Pytania szczegółowe :

  • czy to również domyślnie fsync katalog źródłowy? A może skończę z tym, że plik pojawi się w obu katalogach po cyklu zasilania (czyli musiałbym sprawdzić twardą liczbę linków i ręcznie wykonać odzyskiwanie), czyli nie da się zagwarantować trwałej operacji atomic move?
  • Jeśli i fsync katalogu źródłowego zamiast katalogu docelowego, będzie to również domyślnie fsync katalog docelowy?
  • czy są jakieś przydatne powiązane narzędzia do testowania/debugowania/uczenia się (wtryskiwacze błędów, narzędzia do introspekcji, makiety systemów plików itp.)?
Z góry dzięki.
Author: Yang, 2010-09-22

4 answers

POSIX definiuje, że funkcja rename musi być atomowa:

Http://pubs.opengroup.org/onlinepubs/009695399/functions/rename.html

Więc jeśli zmienisz nazwę (A, B), pod żadnym pozorem nie powinieneś widzieć stanu z plikiem w obu katalogach lub w żadnym katalogu. Zawsze będzie dokładnie jeden, bez względu na to, co zrobisz z fsync() lub czy system ulegnie awarii.

Ale to nie rozwiązuje problemu upewnienia się, że operacja rename () jest trwałe. POSIX odpowiada na to pytanie:

Jeśli zdefiniowano _POSIX_SYNCHRONIZED_IO, funkcja fsync() wymusi wszystkie aktualnie kolejkowane operacje We/Wy związane z plikiem wskazanym przez deskryptor pliku fildes do zsynchronizowanego stanu zakończenia We/Wy. Wszystkie operacje We/Wy są wykonywane zgodnie z definicją dla zakończenia integralności synchronizowanego pliku We / Wy.

(z http://pubs.opengroup.org/onlinepubs/009695399/functions/fsync.html )

Więc jeśli fsync () katalog oczekujący operacji zmiany nazwy musi zostać przesłany na dysk w czasie, który zostanie zwrócony. fsync () każdego z katalogów powinno być wystarczające, ponieważ atomiczność operacji rename () wymagałaby, aby zmiany obu katalogów były synchronizowane atomicznie.

Wreszcie, w przeciwieństwie do twierdzenia we wpisie na blogu wspomnianym w innej odpowiedzi, uzasadnienie tego wyjaśnia co następuje:

Funkcja fsync() ma wymusić fizyczny zapis danych z w celu zapewnienia, że po awarii systemu lub innej awarii wszystkie dane do czasu wywołania fsync() są zapisywane na dysku. Ponieważ pojęcia "bufor cache", "awaria systemu"," zapis fizyczny "i" nieulotna pamięć masowa " nie są tutaj zdefiniowane, sformułowanie musi być bardziej abstrakcyjne.

System, który twierdził, że jest zgodny ze standardem POSIX i który uważał za poprawne zachowanie (tzn. nie błąd lub awarię sprzętu), aby zakończyć fsync() i nie utrzymywać tych zmian przez awarię systemu musiałby być celowo błędnie przedstawiając się w odniesieniu do spec.

[[0]} (aktualizacja z dodatkowymi informacjami re: Linux-specific vs. portable behavior)
 14
Author: Dave Pacheco,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-27 19:06:38

Niestety odpowiedź Dave ' a jest błędna.

Nie wszystkie systemy POSIX mogą mieć nawet trwałą pamięć. A jeśli tak, to nadal jest "dozwolone", aby być hos po awarii systemu. Dla tych systemów nieużywana fsync() ma sens, a taka fsync () jest jawnie dozwolona w ramach POSIX. Legalne jest również odzyskiwanie pliku w starym katalogu, nowym katalogu lub w dowolnej innej lokalizacji. POSIX nie gwarantuje awarii systemu ani odzyskiwania systemu plików.

The prawdziwe pytanie powinno brzmieć:

Jak zrobić trwałą zmianę nazwy na systemach, które obsługują ją za pośrednictwem interfejsu POSIX API?

Musisz wykonać fsync()w obu katalogach źródłowych i, ponieważ minimum, jakie powinny wykonać fsync (), to utrzymywanie tego, jak powinien wyglądać katalog źródłowy lub docelowy.

Czy fsync (destdirfd) również domyślnie fsync katalog źródłowy?

  • ogólnie POSIX: nie, nic nie implikuje że
  • ext3 / 4: nie jestem pewien, czy obie zmiany katalogu źródłowego i docelowego kończą się w tej samej transakcji w dzienniku. Jeśli tak się stanie, oboje zostaną razem zaangażowani.

A może w końcu plik pojawi się w obu katalogach po cyklu zasilania ("crash"), tzn. nie da się zagwarantować trwałej operacji atomic move?

  • ogólnie POSIX: brak gwarancji, ale powinieneś fsync () oba katalogi, które mogą nie być atomic-durable
  • ext3 / 4: ile fsync() potrzebujesz w minimalnym stopniu zależy od opcji montowania. Np. jeśli zamontowane z "dirsync" nie potrzebujesz żadnego z tych dwóch fsync () s. co najwyżej potrzebujesz obu fsync () s, ale jestem prawie pewien, że jeden wystarczy (wtedy Atomic-durable).

Jeśli fsync katalogu źródłowego zamiast katalogu docelowego, to również domyślnie fsync katalogu docelowego?

  • POSIX: Nie
  • ext3/4: naprawdę wierzę, że oba kończą się w tej samej transakcji, więc nie ma znaczenia, który z nich fsync ()
  • starsze jądra ext3: (jeśli nie są w tej samej transakcji) jakaś niezbyt optymalna implementacja wykonała zbyt dużą synchronizację na fsync(), założę się, że zatwierdziła każdą transakcję, która była wcześniej. I tak, normalna implementacja najpierw połączy ją z miejscem docelowym, a następnie usunie ze źródła. Tak więc fsync (srcdirfd) uruchomi również fsync () miejsca docelowego.
  • ext4 / najnowszy ext3: jeśli nie są w tej samej transakcji, możesz być w stanie całkowicie zsynchronizować je niezależnie (tak jak obie)

Czy są jakieś przydatne powiązane narzędzia do testowania/debugowania/uczenia się (wtryskiwacze błędów, narzędzia do introspekcji, makiety systemów plików itp.)?

Dla prawdziwego wypadku, nie. Nawiasem mówiąc, prawdziwa awaria wykracza poza punkt widzenia jądra. Sprzęt może zmienić kolejność zapisów (i nie napisać wszystkiego), powodując uszkodzenie systemu plików. Ext4 jest lepiej przygotowany na to, ponieważ domyślnie włącza blokady zapisu (opcje montowania) (ext3 nie) i może wykrywać uszkodzenia za pomocą sum kontrolnych dziennika (również opcja montowania).

I do nauki: dowiedz się, czy obie zmiany są jakoś powiązane w dzienniku! :- P

 12
Author: Robert Siemer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-15 19:59:08

Odpowiedź na twoje pytanie będzie zależeć w dużej mierze od konkretnego używanego systemu operacyjnego, typu używanego systemu plików oraz tego, czy źródło i dest znajdują się na tym samym urządzeniu, czy nie.

Zacznę od przeczytania strony podręcznika Zmień nazwę(2) na używanej platformie.

 -1
Author: Tom Pinckney,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-12 17:59:45

Wydaje mi się, że próbujesz wykonać zadanie systemu plików. Jeśli przenosisz plik, jądro i system plików są odpowiedzialne za działanie atomowe i odzyskiwanie błędów, a nie twój kod.

W każdym razie, ten artykuł wydaje się odpowiadać na twoje pytania dotyczące fsync: http://blogs.gnome.org/alexl/2009/03/16/ext4-vs-fsync-my-take/

 -4
Author: SpliFF,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-13 05:14:46