Ich kann nicht ioctl(fd, BLKFLSBUF)
Fehler in Ubuntu 14.04.4 LTS auf x86_64 mit 4.2.0-42-generischen Kernel duplizieren.
Ich testete sowohl Vollblock-Geräte, und einzelne Partitionen auf ihnen. Könnten Sie das folgende minimale Testprogramm versuchen?
Speichern Sie das Folgende wie z. block flush.c:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
int arg, descriptor, result;
if (argc < 2 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s BLOCK-DEVICE-OR-PARTITION ...\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
for (arg = 1; arg < argc; arg++) {
do {
descriptor = open(argv[arg], O_RDWR);
} while (descriptor == -1 && errno == EINTR);
if (descriptor == -1) {
const int cause = errno;
fprintf(stderr, "%s: Cannot open device: %s [%d].\n", argv[arg], strerror(cause), cause);
return EXIT_FAILURE;
}
errno = 0;
result = ioctl(descriptor, BLKFLSBUF);
if (result && errno) {
const int cause = errno;
fprintf(stderr, "%s: Cannot flush device: %s [%d].\n", argv[arg], strerror(cause), cause);
return EXIT_FAILURE;
} else
if (result)
fprintf(stderr, "%s: Flush returned %d.\n", argv[arg], result);
else
if (errno) {
const int cause = errno;
fprintf(stderr, "%s: Flush returned zero, but with error: %s [%d]. Ignored.\n", argv[arg], strerror(cause), cause);
}
result = close(descriptor);
if (result == -1) {
const int cause = errno;
fprintf(stderr, "%s: Error closing device: %s [%d].\n", argv[arg], strerror(cause), cause);
return EXIT_FAILURE;
}
fprintf(stderr, "%s: Flushed.\n", argv[arg]);
}
return EXIT_SUCCESS;
}
kompilieren
gcc -Wall -O2 block-flush.c -o block-flush
verwenden und ausführen (root), in der die Partition (en) oder Block-Vorrichtung (en) in der Befehlszeile:
sudo ./block-flush /dev/sda3
für mich gibt diese /dev/sdxN: Flushed.
für post Partitionen sowie die Scheiben (/dev/sdx
) selbst. (Auch das Hinzufügen von fdatasync(descriptor)
vor dem ioctl() ändert nichts, und es gelingt auch ohne Fehler.)
Auch das habe ich zufällig mit einer externen USB-SATA-Dockingstation und einem "lauten" 3,5 "Laufwerk zu testen (Solche Docks benötigen externe Stromversorgung; die USB-Stromversorgung reicht für diese größeren Laufwerke mit rotierenden Platten nicht aus.) Ich könnte leicht hören, dass das ioctl() auf das physische Gerät zugreift, also kein No-Op ist (und wiederum das (Das minimale Testprogramm hat in meinen Tests keine Fehler gemeldet.) Nach dem Schließen des Deskriptors ist die Festplatte auch so lange inaktiv, bis die Festplatte oder die Partitionen für weitere Zugriffe geöffnet werden.Natürlich gelten diese Beobachtungen nur für USB-verbundene Festplatten auf dieser speziellen Kernel-und Hardware-Architektur, aber meiner Meinung nach, zeigt es, dass die ioctl(descriptor, BLKFLSBUF);
sollte für unmounted partiti arbeiten Ons und Full-Block-Geräte, in der erwarteten Weise.
Verwendet direkte I/O oder/dev/rohe eine Option? –
Was meinst du, * "fsync() offensichtlich nicht in rohen Partition" *? 'fsync (_fd)' und 'fdatasync (_fd)' sollten den Inhalt auf das zugrunde liegende Gerät übertragen, auch wenn '_fd' auf ein Block-Gerät verweist. Das eigentliche Flushing erfolgt durch [fs/block_dev.c: blkdev_fsync()] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/block_dev.c# n368) (über [fs/sync.c: fdatasync()] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/fs/sync.C# n230) → do_fsync() → vfs_fsync() → vfs_fsync_range(), dann blkdev_fsync() über die file_operations-Struktur). –
@MarkPlotnick - Ich öffne/dev/sda3. nicht/dev/roh. Ich nahm eine andere Maschine, wo hdparam -W 0 arbeitete. Trotzdem schlägt ioctl mit errno = 25 fehl. Also meine Frage ist - kann ich ioctl BLKFLSHBUF auf/dev/sdxN verwenden? – Adi