Purtroppo la risposta di Dave è sbagliata.
Non tutti i sistemi POSIX possono anche avere una memoria duratura. E se lo fanno, è ancora "permesso" di essere hosed dopo un crash del sistema. Per quei sistemi un fsync() no-op ha senso, e tale fsync() è esplicitamente permesso sotto POSIX. È anche legale che il file sia recuperabile nella vecchia directory, nella nuova directory, in entrambi o in qualsiasi altra posizione. POSIX non fornisce garanzie per arresti anomali del sistema o ripristini del file system.
La vera domanda dovrebbe essere:
come fare una ridenominazione di lunga durata sui sistemi che supportano che tramite l'API POSIX?
Hai bisogno di fare un fsync() su entrambi, fonte e directory di destinazione, perché il minimo quelli fsync) s sono tenuti a fare (è persistono come directory di origine o di destinazione dovrebbe essere simile.
Fa un fsync (destdirfd) anche implicitamente fsync alla directory di origine?
- POSIX in generale: no, niente implica che
- ext3/4: Non sono sicuro se sia i cambiamenti di origine e di destinazione dir finiscono nella stessa transazione nella rivista. Se lo fanno, vengono entrambi commessi insieme.
Oppure potrei finire con il file mostrando in entrambe le directory dopo un ciclo di alimentazione (“crash”), vale a dire che è impossibile garantire un'operazione di spostamento durevolmente atomica?
- POSIX in generale: non ci sono garanzie, ma si suppone che fsync() entrambe le directory, che potrebbe non essere atomica-resistente
- ext3/4: come fsync (molto), è minimamente necessario dipende le opzioni di montaggio. Per esempio. se montato con "dirsync" non hai bisogno di nessuno di questi due fsync() s. Al massimo hai bisogno di entrambi i fsync() s, ma sono quasi sicuro che ne è sufficiente uno (quindi resistente all'atomico).
Se si esegue il fsync della directory di origine anziché della directory di destinazione, anche questo fsync implicherà la directory di destinazione?
- POSIX: no
- ext3/4: Credo davvero entrambi finiscono nella stessa transazione, quindi non importa quale di essi si fsync()
- vecchio kernel ext3: (se non sono nella stessa transazione) alcune implementazioni non così ottimali hanno fatto troppa sincronizzazione su fsync(), scommetto che ha commesso tutte le transazioni precedenti. E sì, un'implementazione normale dovrebbe prima collegarla alla destinazione e quindi rimuoverla dalla fonte. Quindi il fsync (srcdirfd) attiverà anche il fsync() della destinazione.
- ext4/ultime ext3: se non sono nella stessa transazione, si potrebbe essere in grado di sincronizzare in modo completamente indipendente (in modo da fare entrambe le cose)
Esistono relativi strumenti di testing/debugging/apprendimento utili (iniettori di errori, strumenti di introspezione, file system simulati, ecc.)?
Per un vero incidente, no. A proposito, un vero crash va oltre il punto di vista del kernel. L'hardware potrebbe riordinare le scritture (e non riuscire a scrivere tutto), corrompendo il filesystem. Ext4 è meglio preparato contro questo, perché abilita le barriere di scrittura (opzioni di mount) per impostazione predefinita (ext3 non lo fa) e può rilevare il danneggiamento con checksum del journal (anche un'opzione di mount).
E per l'apprendimento: scopri se entrambe le modifiche sono in qualche modo collegate nel diario! :-P
Il ragionamento qui è molto sbagliato. - La "atomicità" di rename(), ad esempio, si riferisce al "newpath", sotto il quale dovrebbe essere il vecchio file (se ce n'era uno) o il file rinominato, senza nessuno stato intermedio (come visto da altri processi) . –
Robert lo ha sottolineato, il nome è "atomico" rispetto all'assegnazione di un nuovo inode al nome, se il nuovo inode punta a dati non aggiornati o non è definito da POSIX. – ArekBulski