Dateisystem-Wahnsinn der Woche
Wir hatten’s hier ja schon öfters von mancher Beklopptheit von Dateisystemen. Hier ist ne neue:
Es gibt Dinge im MSDOS/VFAT-Dateisystem, die ich selbst als alter Hase und nach über 20 Jahren Gebrauch noch nicht mitgekriegt habe.
Ich wollte meine Musik-Sammlung (ein großer Haufen MP3-Dateien) auf meine Fritzbox (mit eingestecktem USB-Stick) kopieren, damit der eingebaute DLNA-Streamer das an neumodische Geräte liefern kann. Das ist an sich nicht neu, das mache ich schon seit ca. 2 Jahren (mit einer Pause zwischendrin, weil die Fritzbox mal mit einer Firmware-Änderung zwischenzeitlich ein Problem mit der Indizierung von Dateien hatte). Bisher halt nur so testweise mal rüberkopiert. Ging – abgesehen von besagtem Fritzbox-Problem – immer tadellos.
Nun sollte es mehr sein, und die Sache sollte systematisch laufen. Also: Fritzbox per smb als Windows-Share gemounted und per rsync die Daten von meinem Rechner draufkopiert. Hab ich mir so schön und einfach vorgestellt, nachdem rsync ja auch schon seit (gefühlt?) weit über einem Jahrzehnt eines meiner geliebtesten Tools ist und hammerhart stabil arbeitet. Ging auch schön und einfach, aber nur beim ersten Mal.
Ab dem zweiten Kopieren jedoch versuchte rsync immer wieder, manche der Dateien erneut zu kopieren. Manche, nicht alle. Und das, obwohl sie eigentlich schon da waren, und gerade das zu erkennen und ein erneutes Überschreiben zu unterdrücken ist ja (ein) Sinn und Zweck von rsync. Warum geht das hier nicht, und insbesondere, warum geht es erstens nur manchmal nicht und zweitens immer bei denselben Dateien?
Sowohl cmp -l als auch ein ls -l zeigten an, daß die Datei unverändert und auch mit dem richtigen Dateinamen angekommen war. Warum also meinte rsync, sie jedesmal neu schreiben zu müssen?
Des Rätsels garstige Lösung:
Manche der kopierten Dateien waren auf dem Zielsystem stets eine Sekunde älter als auf dem Quellsystem. Deshalb war rsync jedesmal der Meinung, daß die auf dem Quellsystem neuer ist und daher neuen Kopierens bedürfe. Was man nicht gleich sieht, weil ein ls -l die Zeit nur in Stunde:Minute anzeigt. Man braucht entweder die Option –full-time oder irgendein anderes Hilfsmittel (lstat aus Skriptsprache, filetest aus tcsh oder sowas) um die Zeit sekundengenau anzuzeigen. Da sieht man dann die Differenz.
Aber woher kommt die? Ich dachte erst, es hätte was mit der Fritzbox oder dem SMB-Protokoll bzw. dessen Implementierung zu tun. Weit gefehlt. Wie so häufig liegt die Lösung in der man-Seite. Hier der zu rsync, als ich danach suchte, ob es da einen Toleranz-Wert gibt, den man einstellen kann. Es gibt ihn tatsächlich, die Option heißt –modify-window=1 (oder anderer Wert). Und siehe da, als Erklärung steht da genau mein Problem:
When comparing two timestamps, rsync treats the timestamps as being equal if they differ by no more than the modify-window value. This is normally 0 (for an exact match), but you may find it useful to set this to a larger value in some situations. In particular, when transferring to or from an MS Windows FAT filesystem (which represents times with a 2-second resolution), –modify-window=1 is useful (allowing times to differ by up to 1 second).
Jau. Immer wenn die Dateien im Quellsystem eine ungerade M-Time hatten, kam auf dem Zielsystem die nächstniedrigere gerade Zeit an, also war die Kopie dann eine Sekunde älter. Und die Option löst genau dieses Problem.
Herrje. Warum ist mir das in >20 Jahren noch nie aufgefallen? So’n Scheiß!
Nachtrag: Je mehr ich drüber nachdenke, desto mehr komme ich drauf, daß ich das schon mal wußte aber wieder vergessen habe. Ich habe mir irgendwann mal vor langer, langer Zeit für forensische Zwecke in Programm geschrieben, das ein MSDOS-Dateisystem auflistete, und da bin ich auch schon mal an der Zeitdarstellung vorbeigekommen. Ist aber ewig lang her. Und solche Details vergisst man dann eben irgendwann wieder, wenn man sie nicht ab und zu mal braucht…
19 Kommentare (RSS-Feed)
Schreib’s in Dein Blog, damit Du in 20 Jahren weißt, was das mit den komischen Sekunden in FAT/FAT32 auf sich hatte. 🙂
So geht’s mir übrigens auch. Sachen die ich schon vor Jahren mal ausklabüsert hatte, brauch ich manchmal wieder, hab aber meist ein Problem damit, mich zu erinnert, was genau das Problem oder die Lösung war. Man wird halt alt. .-)
Und die Umstellung mit Sommer-/ Winterzeit funktioniert?
IIRC hatte ich da auch schon mal Probleme beim Synchronisieren von Dateien – FAT speichert als Uhrzeit wohl Local Time ohne Zeitzone.
Hm, vielleicht ist das letzte Bit eines FAT-Timestamps ein Flag und gehört nicht zur Anzahl der Sekunden? Vielleicht ein Carry Flag? Dann würde es für arithmetische Operationen durch right shift entfernt, es ergäben sich dann immer gerade Anzahlen.
Ich habe da aber keine Ahnung, nur mal geraten. So alt, wie FAT schon ist, würden mich derart esoterische Bitfelder nicht wirklich wundern.
Ach was, nee, die wollten einfach Platz sparen. Carry Flags gibt es in Prozessoren, die werden aber nicht in Daten gespeichert. Und die sind oben und nicht unten.
Das eingesparte Bit war damals 🙂 ein Kompromiss unter vielen, die man auf dem Ur-PC eingegangen ist. Die Unix-Dateisysteme haben auch erst Subsekunden-Zeitstempel bekommen, als die Rechner der Entwickler so schnell wurden, dass make nicht mehr funktionierte. Ob nun eine Sekunde Auflösung oder zwei Sekunden, ein Kompromiss ist beides. Dass FAT sehr erfolgreich war und bis heute überlebt hat, kann man Microsoft nicht zum Vorwurf machen.
Sag ich ja auch gar nicht. Zumal eine Granularität von genau 1 Sekunde ja nun auch letztlich willkürlich ist.
Es ist aber eben eine Stolperfalle, weil man von einer kulturell und gewohnheitsmäßig vorgegebenen Granularität ausgeht, obwohl die Granularität nicht einheitlich, sondern im Endeffekt Dateisystemabhängig ist und es damit eine genau Synchronisierung bzw. „Gleichheit” von Dateien dateisystemübergreifend nicht geben kann. Insofern ist es nur konsequent und richtig, das wie bei rsync mit Toleranzen zu machen.
Zur allgemeinen Info & in diesem Zusammenhang, das Windowsdingens robocopy stolpert auf die gleiche Weise, dort ist der Parameter /FFT nötig — mit zwei Sekunden Granularität.
😉
Vergleicht rsync dann tatsächlich auf exakt oder nur auf eine Sekunde genau ? Inzwischen sind ja Subsekundenzeitstempel üblich, werden aber fast nie sauber reproduziert.
Inzwischen scheint es von Windows 7 zu Windows 7 zu funktionieren, aber da es ja unterschiedliche Zeitauflösungen in Dateisystemen gibt und auch die Übertragungsprotokolle nicht immer Subsekunden unterstützen, hatte ich bisher oft genullte Subsekunden bei der Übertragung von einem Rechner auf den anderen. Auch tar und zip kenne ich als Zeitstempelverfälscher.
Weiß ich nicht, müßt ich jetzt auch erst nachlesen oder ausprobieren. Da die Toleranzgrenze in Sekunden angegeben wird und rsync für vieles gedacht ist, würde ich zunächst mal Sekunden vermuten.
Ich verwende bei Backups eigentlich immer die Option –times (bzw. -t) von rsync. Damit sollen die Zeitstempel beim kopieren von Quelle zum Ziel eigentlich (lt. man-Page) beibehalten werden. Klappt das mit der Fritzbox etwa nicht? Oder habe ich das Problem falsch verstanden?
@Michael: Du hast das Problem nicht verstanden.
Wenn das Zielsystem ein DOS/FAT-Filesystem ist (und das ist es auf dem USB-Stick, der in der Fritzbox steckt), dann kann es die Uhrzeit nur mit einer Granularität von 2 Sekunden speichern. Das unterste Bit der Uhrzeit in Sekunden wird abgeschnitten.
Ist eine Datei im Quellsystem von 16:30:21 und wird (egal ob nun mit cp -a oder rsync -t oder womit auch immer) auf das Zielsystem kopiert, dann kopiert die Software erst die Datei und setzt dann mit utime das gewünschte Datum (man 2 utime). Dabei versucht die Software zwar das Datum auf 16:30:21 zu setzen und das Betriebssystem meldet Erfolg, beim nächsten Lesen steht die Datei aber auf 16:30:20, weil das Dateisystem eben nur 30 Zustände pro Minute unterstützt. Also glaubt rsync beim nächsten Mal, daß die Datei auf dem Quellsystem neuer wäre als die auf dem Zielsystem (bzw. das Datum korrigiert werden muß) und kopiert sie erneut.
Interessant. Ich wusste zwar, dass FAT da ein Bit einspart, aber wäre nie drauf gekommen, dass das zu so einem merkwürdigen Verhalten führen kann.
Hab mal überlegt, ob der Dateisystemtreiber vielleicht lieber auf- als abrunden sollte, aber letztendlich wäre das kontextabhängig besser oder auch schlechter. So gesehen ist die –modify-window-Option die sauberste Lösung. Vielleicht sollte diese Option per Default auf 1 gestellt sein? Für die meisten Anwendungen dürfte das reichen, und FAT ist ja nicht gerade ein seltenes Dateisystem – wahrscheinlich verärgert man mit –modify-window=1 weniger Leute als mit –modify-window=0. Aber zumindest wäre es nett, wenn rsync bei kleinen Zeitunterschieden eine Warnung auf stderr bringen würde.
Noch eine Anmerkung zur Dateisystemzeitauflösung.
Ich habe früher mal mit OS-9/68k geschafft. Das hatte nur minutengenaue Zeitauflösung. Das war nicht so problematisch Ende der 80er, als Übersetzungszeiten durchaus in diesem Bereich lagen.
Mitte der 90 wurde das dann recht nervig, weil ein unmodifiziertes Make unbrauchbar wurde. Schneller CPU’s und insbesondere bezahlbare Festplatten hatten diese Grenze geknackt.
Heutzutage gibt es zwar auch Fälle, in denen Make mehr macht, als notwendig, aber vervielfachte Subsekundenaktionen stören nicht so sehr, wie vervielfachte 10-20 Sekünder.
Seltsamerweise gibt es unter Unix (und auch in NFS, SMB usw.) diverse Systemaufrufe, die einem zu einer Datei das Dateisystem liefern, die Blockgröße, die Größe der Partition,und,und,und, jedoch (meines Wissens) keinen Aufruf, der einem die Granularität der Dateizeiten angibt, damit sich make, rsync usw. darauf einstellen könnten. Eine echte Lücke.
Platz zu sparen war tatsächlich der Grund. FAT speichert bei Zeit und Datum jeweils Stunde, Minute und Sekunden sowie Jahr (zweistellig, Y2k lässt grüßen ;-), Monat und Tag. Dabei werden für die einzelnen Teile nur soviel Bits wie unbedingt nötig verwendet. Für das Datum braucht man 16Bit, was wunderbar in zwei Bytes passt. Für eine sekundengenaue Zeit-Auflösung wären aber 17 Bit nötig gewesen. Um wegen des einen Bits nicht noch ein ganzes Byte verschenken zu müssen, wurde die 2-Sekunden-Auflösung gewählt (ein kompletter Directory-Eintrag hat übrigens nur 32 Bytes).
Aus heutiger Sicht ist das natürlich komplett widersinnig, aber die ersten IBM-PCs hatten noch ein Kassetteninterface; Mitte der 1980er wurden sie typischerweise mit einem 360kByte-Diskettenlaufwerk verkauft. Da ist die Knauserei zumindest nachvollziehbar.
Naja, ich finde eher, das Problem liegt darin, dass die FritzBox nur das FAT Filesystem unterstützt. Wenn NTFS oder eines der Linux-Filesysteme gäbe es eine brauchbare Granularität und auch sonst wäre es besser.
@Uwe: Das Problem ist ja nicht die Granularität an sich, sondern daß man die Unterschiede kennen und wissen muß, daß es anders ist. Erst dann, wenn ich davon weiß, hätte ich einen Grund, das entsprechende Dateisystem zu wählen. Dann aber ist die entsprechende Option von rsync das leichtere Mittel. Ausgangspunkt ist einfach, daß man es erst einmal wissen muß.
@Uwe
Fritzboxen unterstützen ext2/ext3 entweder von Haus aus (bei neueren Modellen) oder per patch (z.B. freetz) bei älteren Modellen.
Aber das ist ja hier nicht das Problem. Über diese Granularität von FAT und dem Problem mit rsync bin ich auch schon vor Jahren gestolpert. und hat mich erstmal Stundenlanges Suchen gekostet, wo der Fehler liegt, bis ich irgendwann über die Sekunden im FAT-FS gestolpert bin.
Dasselbe Problem hat man übrigens auch, wenn man eine Windows-Sicherung auf USB-festplatten mit Robocopy machen will, und der Hersteller so “nett” war, die Platte mit FAT vorzuformattieren (Gängige Windows-Versionen weigern sich, TB-Platten mit FAT32 zu formattieren).
Die rsync – manpage hat den Tag gerettet. Überrascht? Bei all ihren Macken sind die Unix-Tools mehr als Produkte: Sie sind Teil eines externen, kollektiven Gedächtnisses. Man kann schliesslich nicht alles selber im Kopf behalten. Die rsync-manpage war sozusagen der Fremdschlüssel.