Question

Quelle est la bonne façon de renommer un fichier dans durablement un système de fichiers POSIX? Plus précisément au sujet de se demander sur les Opérations fsyncs répertoires . (Si cela dépend de l'OS / FS, je demande à propos de Linux et ext3 / ext4).

Remarque : il y a d'autres questions sur StackOverflow sur renomme durables, mais AFAICT ils ne traitent pas fsync-ment les répertoires (qui est ce qui compte pour moi - je ne suis pas modifier même les données de fichiers ).

J'ai actuellement (en Python):

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

Questions spécifiques :

  • Est-ce implicitement fsync le répertoire source? Ou pourrais-je finir avec le fichier apparaître dans les deux répertoires après un cycle de puissance (ce qui signifie que je dois vérifier le nombre de liens dur et effectuer manuellement la récupération), à savoir qu'il est impossible de garantir une opération de déplacement durable atomique?
  • Si je fsync le répertoire source au lieu de le répertoire de destination, sera également implicitement que fsync le répertoire de destination?
  • Y at-il des outils de test connexes utiles / débogage / apprentissage (injecteurs de défaut, les outils d'introspection, les systèmes de fichiers, etc simulacres.)?

Merci à l'avance.

Était-ce utile?

La solution

POSIX définit que le fonction de changement de nom doit être atomique .

Donc, si vous renommez (A, B), en aucun cas vous ne devez jamais voir un état avec le fichier dans les deux répertoires ou ni répertoire. Il y aura toujours exactement un, peu importe ce que vous faites avec fsync () ou si le système se bloque.

Mais cela ne résout pas le problème de se assurer que l'opération Rename () est durable. Posix répond à cette question :

  

Si la constante symbolique _POSIX_SYNCHRONIZED_IO est définie, la fonction fsync () doit forcer toutes les opérations d'entrée / sortie actuellement en file d'attente associés au fichier indiqué par descripteur de fichier fildes à l'état d'achèvement d'entrée / sortie synchronisée. Toutes les opérations d'E / S sont complétés tel que défini pour l'achèvement de l'intégrité des fichiers E / S synchronisé.

Donc, si vous fsync () un répertoire, les opérations de changement de nom en attente doivent être transférés sur le disque au moment où ce rendement. fsync () soit le répertoire devrait être suffisant, car atomicité de l'opération Rename (), il faudrait que les changements synchronisés des deux répertoires atomiquement.

Enfin, contrairement à la demande dans le billet de blog mentionné dans une autre réponse, la justification de ce qui explique ce qui suit:

  

La fonction fsync () est destiné à forcer une écriture physique de données à partir du cache de la mémoire tampon, et pour assurer que, après un arrêt du système ou d'un autre défaut que toutes les données jusqu'au moment de l'appel fsync () est inscrite sur la disque. Étant donné que les concepts de « tampon cache », « plantage du système », « écriture physique » et « stockage non volatile » ne sont pas définis ici, le libellé doit être plus abstraite.

Un système qui prétendait être conforme aux spécifications POSIX et considéré comme un comportement correct (c.-à-pas un bug ou une défaillance du matériel) pour compléter un fsync () et ne persistera pas ces changements à travers un plantage du système devrait être délibérément se faisant passer par rapport à la spécification.

(mis à jour avec re info supplémentaire: Linux spécifique de comportement par rapport à-portable)

Autres conseils

Malheureusement, la réponse de Dave est erroné.

Tous les systèmes POSIX pourrait même avoir un stockage durable. Et s'ils le font, il est encore « permis » d'être aspergés après un plantage du système. Pour ces systèmes, une fsync no-op () est logique, et comme fsync () est explicitement autorisé par POSIX. Il est également juridique pour que le fichier soit récupérable dans l'ancien répertoire, le nouveau répertoire, les deux, ou tout autre endroit. Posix ne fait aucune garantie pour le plantage du système ou de récupération du système de fichiers.

La vraie question devrait être:

Comment faire un changement de nom durable sur les systèmes supportant cette via l'API Posix?

Vous devez faire un fsync () sur les deux, la source et répertoire de destination, parce que le minimum les fsync () s sont censés faire est persistent comment répertoire source ou la destination devrait ressembler.

Est-ce qu'un fsync (destdirfd) implicitement fsync le répertoire source?

  • Posix en général: non, rien implique que
  • ext3 / 4: Je ne sais pas si les deux changements à la source et la destination dir finissent dans la même transaction dans le journal. Si elles le font, ils obtiennent les deux Commited ensemble.

Ou pourrais-je finir avec le fichier apparaître dans les deux répertoires après un cycle d'alimentation ( « crash »), à savoir qu'il est impossible de garantir une opération de déplacement durable atomique?

  • Posix en général: aucune garantie, mais vous êtes censé fsync () les deux répertoires, ce qui pourrait ne pas être durable atomique
  • ext3 / 4: combien fsync () vous minimalement besoin dépend du montage des options. Par exemple. si elle est montée avec « DirSync » vous n'avez pas besoin de ces deux fsync () s. Tout au plus vous avez besoin à la fois fsync () s, mais je suis presque sûr que l'on est assez (alors atomique durable).

Si je fsync le répertoire source au lieu du répertoire de destination, sera également implicitement que fsync le répertoire de destination?

  • Posix: pas
  • ext3 / 4: Je crois vraiment à la fois finissent dans la même transaction, il n'a pas d'importance qui d'entre eux vous fsync ()
  • noyaux plus ext3: (si elles ne sont pas dans la même transaction) une mise en œuvre pas si optimale a fait beaucoup trop sur la synchronisation fsync (), je parie qu'il a commis toutes les transactions qui sont venus avant. Et oui, une mise en œuvre normale serait d'abord le lier à la destination, puis retirez-le de la source. Ainsi, le fsync (srcdirfd) déclencherait l'fsync () de la destination ainsi.
  • ext4 / ext3 dernière: si elles ne sont pas dans la même transaction, vous pourriez être en mesure de les synchroniser complètement indépendamment (pour faire les deux)

Y at-il des outils de test connexes utiles / débogage / apprentissage (injecteurs de défaut, les outils d'introspection, maquettes, etc systèmes de fichiers.)?

Pour un vrai accident, non. Soit dit en passant, un vrai accident va au-delà du point de vue du noyau. Le matériel peut modifier l'ordre écrit (et ne parviennent pas à tout écriture), corrompt le système de fichiers. Ext4 est mieux préparé contre cela, car elle permet Barries d'écriture (options de montage) par défaut (ext3 ne fonctionne pas) et peut détecter la corruption avec checksums de journal (également une option de montage).

Et pour apprendre: savoir si les changements sont liés en quelque sorte dans la revue! :-P

La réponse à votre question va dépendre beaucoup du système d'exploitation spécifique utilisé, le type de système de fichiers utilisé et si la source et dest sont sur le même appareil ou non.

Je commence par lire la page de manuel de changement de nom (2) sur la plate-forme que vous utilisez.

Il me semble que vous essayez de faire le travail du système de fichiers. Si vous déplacez un fichier du noyau et du système de fichiers sont responsables de l'opération atomique et la récupération faute, pas votre code.

Quoi qu'il en soit, cet article semble répondre à vos questions concernant fsync: http://blogs.gnome.org/ alexl / 2009/03/16 / ext4-vs-fsync-my-take /

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top