简体   繁体   English

如何在linux中使用ioctl(原始分区)正确刷新磁盘缓存

[英]How to properly flush disk cache using ioctl (raw partition) in linux

I am trying to use ioctl to make sure changes written directly to the volume are hitting the disk. 我正在尝试使用ioctl来确保直接写入卷的更改正在访问磁盘。 fsync() obviously not available in raw partition. fsync()显然在原始分区中不可用。 sync() is horrible solution too (in order to flush 64MB, i need entire life time to wait in sync) sync()也是一个可怕的解决方案(为了冲洗64MB,我需要整个生命时间等待同步)

so.. here is what i am trying to do - getting errno 25. 所以..这就是我想要做的事情 - 得到错误25。

/dev/sda3 is a raw unmounted partition on ssd drive / dev / sda3是ssd驱动器上的原始卸载分区

open(_fd, "/dev/sda3", ...)
pwritev(_fd, ...)

ioctl(_fd, BLKFLSBUF, 0)   <== errno = 25. 

Ubuntu 14.04, c Ubuntu 14.04,c

Note: 注意:

hdparm -W 0 /dev/sda3

fails on : Inappropriate ioctl for device. 失败:对设备不适当的ioctl。

how can I find the suitable flushing method for my ssd ? 如何为我的ssd找到合适的冲洗方法?

I cannot duplicate ioctl(fd, BLKFLSBUF) errors in Ubuntu 14.04.4 LTS on x86_64 using 4.2.0-42-generic kernel. 我不能使用4.2.0-42泛型内核在x86_64上的Ubuntu 14.04.4 LTS中复制ioctl(fd, BLKFLSBUF)错误。

I tested both full block devices, and individual partitions on them. 我测试了两个完整的块设备,以及它们上的各个分区。 Could you try the following minimal test program? 你能试试下面的最小测试程序吗?

Save the following as eg block-flush.c : 保存以下内容,例如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;
}

Compile it using 使用编译它

gcc -Wall -O2 block-flush.c -o block-flush

and run it (as root), specifying the partition(s) or block device(s) at the command line: 并运行它(以root身份),在命令行指定分区或块设备:

sudo ./block-flush /dev/sda3

For me, this outputs /dev/sdxN: Flushed. 对我来说,这输出/dev/sdxN: Flushed. for unmounted partitions, as well as the disks ( /dev/sdx ) themselves. 对于未安装的分区,以及磁盘( /dev/sdx )本身。 (Also, adding fdatasync(descriptor) before the ioctl() does not change anything, and it too succeeds without any errors.) (另外,在ioctl( fdatasync(descriptor)之前添加fdatasync(descriptor)不会改变任何东西,并且它也会成功而没有任何错误。)

Also, I happened to test this using an external USB SATA docking station and a "loud" 3.5" drive (such docks needing external power; USB power not being sufficient for these larger drives with spinning platters). I could easily hear that the ioctl() does access the physical device, so it is not a no-op (and, again, the minimal test program never reported any failures in my tests). After closing the descriptor, the disk is also quiescent until the disk or partitions are opened for further accesses. Of course, these observations are only valid for USB-connected hard drives, and only on this particular kernel and hardware architecture, but in my opinion, it does indicate that the ioctl(descriptor, BLKFLSBUF); should work for unmounted partitions and full block devices, in the expected manner. 此外,我碰巧使用外部USB SATA扩展坞和“响亮的”3.5“驱动器(这种扩展需要外部电源; USB电源不足以满足这些带有旋转盘片的大型驱动器)进行测试。我很容易听到ioctl ()确实访问物理设备,所以它不是无操作(并且,最小的测试程序再次没有报告我的测试中的任何失败)。关闭描述符后,磁盘也是静止的,直到磁盘或分区是当然,这些观察仅适用于USB连接的硬盘驱动器,并且只适用于这种特定的内核和硬件架构,但在我看来,它确实表明ioctl(descriptor, BLKFLSBUF);应该适用于未预装的分区和完整的块设备,以预期的方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM