USB Stick: korrupte Daten bei umount

Hallo,

Erstmal besteht dieses Problem schon länger. Wenn ich etwas
auf einen USB-Stick kopiere (dritt hauptsächlich bei größeren
Dateien auf) und danach das Dateisystem mit umount aushänge
und dann sofort den USB-Stick abstecke, dann sind die letzten
geschriebenen Daten immer fehlerhaft.

Also irgendwie synchronisiert Linux bei umount nicht das Dateisystem
auf den USB-Stick.

Ich habe mir als Workaround zwischenzeitlich angewöhnt, bevor ich
den USB-Stick abstecke noch den Befehl sync einzugeben und zu
warten bis der Befehl erfolgreich ausgeführt wurde.

Der Nachteil ist hier allerdings, dass alle Geräte/Dateisysteme synchronisiert werden.

Beim schnellen Überfliegen vom Kernel-Code finde ich keine betreffende
Codezeile die vorher das Dateisystem synchronisiert. Kann aber auch sein,
dass ich im Code einfach etwas übersehe. :

Auszug aus /usr/src/linux/fs/namespace.c (Linux 3.12.59/openSUSE 13.1):
Code:
SYSCALL_DEFINE2(umount, char __user *, name, int, flags)
{
    struct path path;
    struct mount *mnt;
    int retval;
    int lookup_flags = 0;

    if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW))
        return -EINVAL;

    if (!may_mount())
        return -EPERM;

    if (!(flags & UMOUNT_NOFOLLOW))
        lookup_flags |= LOOKUP_FOLLOW;

    retval = user_path_mountpoint_at(AT_FDCWD, name, lookup_flags, &path);
    if (retval)
        goto out;
    mnt = real_mount(path.mnt);
    retval = -EINVAL;
    if (path.dentry != path.mnt->mnt_root)
        goto dput_and_out;
    if (!check_mnt(mnt))
        goto dput_and_out;
    if (mnt->mnt.mnt_flags & MNT_LOCKED)
        goto dput_and_out;
    retval = -EPERM;
    if (flags & MNT_FORCE && !capable(CAP_SYS_ADMIN))
        goto dput_and_out;

    retval = do_umount(mnt, flags);
dput_and_out:
    /* we mustn't call path_put() as that would clear mnt_expiry_mark */
    dput(path.dentry);
    mntput_no_expire(mnt);
out:
    return retval;
}
Code:
static int do_umount(struct mount *mnt, int flags)
{
    struct super_block *sb = mnt->mnt.mnt_sb;
    int retval;

    retval = security_sb_umount(&mnt->mnt, flags);
    if (retval)
        return retval;

    /*
     * Allow userspace to request a mountpoint be expired rather than
     * unmounting unconditionally. Unmount only happens if:
     *  (1) the mark is already set (the mark is cleared by mntput())
     *  (2) the usage count == 1 [parent vfsmount] + 1 [sys_umount]
     */
    if (flags & MNT_EXPIRE) {
        if (&mnt->mnt == current->fs->root.mnt ||
            flags & (MNT_FORCE | MNT_DETACH))
            return -EINVAL;

        /*
         * probably don't strictly need the lock here if we examined
         * all race cases, but it's a slowpath.
         */
        br_write_lock(&vfsmount_lock);
        if (mnt_get_count(mnt) != 2) {
            br_write_unlock(&vfsmount_lock);
            return -EBUSY;
        }
        br_write_unlock(&vfsmount_lock);

        if (!xchg(&mnt->mnt_expiry_mark, 1))
            return -EAGAIN;
    }

    /*
     * If we may have to abort operations to get out of this
     * mount, and they will themselves hold resources we must
     * allow the fs to do things. In the Unix tradition of
     * 'Gee thats tricky lets do it in userspace' the umount_begin
     * might fail to complete on the first run through as other tasks
     * must return, and the like. Thats for the mount program to worry
     * about for the moment.
     */

    if (flags & MNT_FORCE && sb->s_op->umount_begin) {
        sb->s_op->umount_begin(sb);
    }

    /*
     * No sense to grab the lock for this test, but test itself looks
     * somewhat bogus. Suggestions for better replacement?
     * Ho-hum... In principle, we might treat that as umount + switch
     * to rootfs. GC would eventually take care of the old vfsmount.
     * Actually it makes sense, especially if rootfs would contain a
     * /reboot - static binary that would close all descriptors and
     * call reboot(9). Then init(8) could umount root and exec /reboot.
     */
    if (&mnt->mnt == current->fs->root.mnt && !(flags & MNT_DETACH)) {
        /*
         * Special case for "unmounting" root ...
         * we just try to remount it readonly.
         */
        if (!capable(CAP_SYS_ADMIN))
            return -EPERM;
        down_write(&sb->s_umount);
        if (!(sb->s_flags & MS_RDONLY))
            retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
        up_write(&sb->s_umount);
        return retval;
    }

    namespace_lock();
    br_write_lock(&vfsmount_lock);
    event++;

    if (!(flags & MNT_DETACH))
        shrink_submounts(mnt);

    retval = -EBUSY;
    if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) {
        if (!list_empty(&mnt->mnt_list))
            umount_tree(mnt, 1);
        retval = 0;
    }
    br_write_unlock(&vfsmount_lock);
    namespace_unlock();
    return retval;
}
 
Also KDE zeigt mir an wann ich meinen Stick abziehen darf. GNOME macht das auch und für XFCE und LXDE behaupte ich das jetzt auch mal. Wenn du über ein Terminal mountest kann man ja "sync && umount xyz" eingeben.

Sync kann man als Mount-Option übergeben dadurch werden die Daten nicht zwischengespeichert und direkt geschrieben. Was aber zu einer geringeren Lebensdauer führen soll.

mount -o sync

Wenn du das "schick" haben willst füge es einer udev rule hinzu:

udev – wiki.archlinux.de
 
Soweit ich informiert bin, ruft umount sync auf, bevor das Dateisystem ausgehängt wird.
Siehe: https://groups.google.com/forum/#!topic/comp.os.linux.development.apps/8QDlM7hw0pE

Du musst natürlich in der shell warten, bis das kommando durchgelaufen ist. Wenn der Stick eine LED hat, würde ich auch warten, bis sie nicht mehr blinkt.
Hast du schon gecheckt, ob der Stick schuld ist? Vielleicht hat er einfach ein paar kaputte Sektoren.

Andere Frage: welches Dateisystem verwendest du?
 
Danke für die Antworten!

Also KDE zeigt mir an wann ich meinen Stick abziehen darf. GNOME macht das auch und für XFCE und LXDE behaupte ich das jetzt auch mal.
Unter KDE funktioniert das Auswerfen bei mir auch ohne Datenverlust.
Wenn du über ein Terminal mountest kann man ja "sync && umount xyz" eingeben.
Eigentlich ist der Befehl sync vor umount nicht das Problem. Es ist IMHO ein Schönheitsfehler. :rolleyes:
[...]
Was aber zu einer geringeren Lebensdauer führen soll.
[...]
Dieses Verhalten (also ohne die Mountoption) ist aber sinvoll. Es kommt manchmal vor, dass ich eine Datei aus einem Archiv (zip, etc.) benötige. Dann entpacke ich meistens die Datei auf dem Stick und kopiere sie dann wo anders hin. Danach lösche ich die entpackten Dateien. Kann der Kernel also im Arbeitsspeicher belassen, braucht die Daten nicht auf den Stick schreiben, weil sie kurz danach sowieso gelöscht werden...
Soweit ich informiert bin, ruft umount sync auf, bevor das Dateisystem ausgehängt wird.
Siehe: https://groups.google.com/forum/#!topic/comp.os.linux.development.apps/8QDlM7hw0pE
Danke, das habe ich auch schon gelesen. Aber anscheinend macht mein Kernel das nicht.
Du musst natürlich in der shell warten, bis das kommando durchgelaufen ist. Wenn der Stick eine LED hat, würde ich auch warten, bis sie nicht mehr blinkt.
Auf die erfolgreiche Ausführung des Befehls warte ich natürlich. Auch wenn der USB-Stick eine LED hat, achte ich darauf.
Hast du schon gecheckt, ob der Stick schuld ist? Vielleicht hat er einfach ein paar kaputte Sektoren.
Kann ich ausschließen. Tritt bei allen auf die ich habe. Unter Windows funktionieren sie problemlos.
Andere Frage: welches Dateisystem verwendest du?
FAT32 - Ich würde zwar ein anderes Dateisystem bevorzugen, muss aber mit Windows Daten austauschen können. Darf bei den Windows Rechnern keinen Dateisystemtreiber (z.B.: ext4) installieren.

Naja, vielleicht erledigt sich das Problem von selber wenn ich eine neuere Distribution mit neueren Kernel installiere. openSUSE 13.1 ist ja auch schon etwas älter...
 
Mount

Hallo


ich selbst mounte und unmounte USB-Sticks nur im Terminal und benutze selbst bei fat32 oder ntfs nie sync als Zusatzoption und habe keine Probleme damit. Debian-Sid. kernel 4.6.0-1, amd64, wmaker.

Ich würde den Stick erstmal komplettt neuformieren.

mfg
schwedenmann
 
Abhängig vom Dateisystem kannst du in der fstab, oder beim mount-befehl angeben keinen Puffer zu verwenden, zB nodelalloc für ext4.

Das alles hat auch nix mit dem Kernel zu tun sondern mit den Treibern vom Dateisystem.
Gruß

Fluffy
 
sync() ist ein Systemcall, der beim Beenden des unmount-Befehls nicht zwingend bereits fertig sein muss. Will man sichergehen, dass sync() und syncfs() durchgelaufen sind, sollte man warten, bis der Befehl

Code:
awk '{print $9}' /sys/block/<device>/stat

eine 0 ausgibt. Erst dann kann der Stick sicher entfernt werden.
 
echo "if [`awk '{print $9}' /sys/block/sdX/stat` -eq 0]; do echo 'fertig'; done" >> forksumount.sh

Besser? [emoji1]
 
echo "if [`awk '{print $9}' /sys/block/sdX/stat` -eq 0]; do echo 'fertig'; done" >> forksumount.sh

Besser? [emoji1]

Nicht wirklich, da USB-Sticks nicht immer mit dem gleichen Device im System eingehängt werden. Wenn man schon ein Skript erstellt, weil man mit Zahlen nichts anfangen kann und unbedingt ein Wort als Output braucht, sollte das Skript zumindest in der Lage sein einen Parameter entgegenzunehmen, mit dem man das Device angeben kann. sdX sollte also mindestens durch $1 ersetzt werden und es sollte überprüft werden, ob $1 überhaupt angegeben wurde. Und schon hast du unnötigen Overhead. Wobei man dieses Skript durchaus ansich als unnötigen Overhead bezeichnen kann. ;)
 
Ist zwar ein bischen Offtopic, aber ich würde meine Skripte nicht mit dennen des OS vermischen, wenn ich neu installieren muss, oder migriere ist es schwer meine Arbeit im nachhinein zu finden, und zu sichern. PATH=$PATH:/home/lama0815/bin ist da schon eher von Vorteil, oder /root/bin/ je nachdem wie weit man alles separieren will.
Gruß

Fluffy
 
Das ist tatsächlich eher eine Frage der persönlichen Präferenzen. Jemand, der Software von anderen Autoren prinzipiell nicht am Paketmanager vorbei installiert, hat zumeist keine Daten mehr in /usr/local rumliegen. Dadurch ist die Ordnerstruktur dort optimal für die selbst geschriebene Software geeignet, vor allem wenn man dann auch mal komplexere Tools mit eigenen Libs oder Klassendateien hat. Unter Umständen können auch Fragen des Datenschutzes eine Rolle spielen. Ich verwalte z.B. diverse Systeme, wo /home mit noexec-Flag gemountet ist, damit die User dort eben nicht jeden löchrigen Mist installieren können. Verhindert (sofern auch die tmp-Verzeichnisse noexec sind) auch das Einschleusen von Bots/Trojanern durch Useraktionen. Auch gibt es Systeme, wo die Home-Verzeichnisse nicht von einem (H)IDS untersucht werden dürfen, da das gegen den Datenschutz verstösst. Man kann dort also nicht überwachen ob Skripte nicht ggf. durch Schadsoftware ausgetauscht wurden. Oder Skripte sollen für mehrere User bereitgestellt werden. Dann ist /home/username der denkbar schlechteste Ort für solche Skripte. Es gibt also einige Punkte, die dagegen sprechen, dass man Software in /home ablegt, egal ob das nun Skripte oder kompilierte Programme mit eigenen Libs usw. sind. Daher bin ich persönlich der Meinung, dass /usr/local genau der Ort ist, wo Software hingehört, die nicht aus der Paketverwaltung kommt.

Nachtrag: Wenn man neu installieren muss, sollte man seine Skripte bereits in einer (externen) Versionsverwaltung haben.
 
wenn ich neu installieren muss, oder migriere ist es schwer meine Arbeit im nachhinein zu finden, und zu sichern.
Fluffy

Also vorweg möchte ich anmerken, dass die "Schönheitskorrektur" mit dem Script nicht gaaanz so ernst gemeint war [emoji6]

Unabhängig davon ob /home oder /usr/local/bin kommt es da doch eher darauf an, dass man seinen persönlichen bzw. Unternehmens Vorgaben treu bleibt. Dann weiß man wo man seine Daten findet. Wenn man sie breit im System verstreut muss man eben buchführen [emoji12]
Auf meiner privaten Kiste habe ich das auch unter /home/nichtLama0815/programme und teilweise unter /usr/local. Das sind die einzigen zwei lokationen, die ich gleich komplett so sichern kann.

Bitmunchers Ansatz übernehme ich mal so und möchte nur hinzufügen, dass in solch einem Szenario /home nicht optimal wäre wenn die dort gehorteten Programme mehreren Usern zugänglich gemacht werden sollen.
 
Zurück
Oben