4

私の問題は、スパースファイルの読み取りに対処し、ファイルのエクステントがどこにあるのかを理解し、その周りで何らかのロジックを実行することです。

これらを把握するための直接の API 呼び出しがないため、ioctl api を使用してこれを行うことにしました。私は cp コマンドがスパース ファイルのコピーの問題をコードを調べて処理する方法からアイデアを得て、最終的にこれを確認しました。

https://github.com/coreutils/coreutils/blob/df88fce71651afb2c3456967a142db0ae4bf9906/src/extent-scan.c#L112

そのため、ユーザー空間で実行しているサンプル プログラムで同じことを実行しようとすると、「引数が無効です」というエラーが発生します。何が欠けているのか、またはこれがユーザー空間から可能かどうかはわかりません。ext4 ファイル システムの ubuntu 14.04 で実行しています。これは、これらの要求モードをサポートするデバイス ドライバーの問題でしょうか?

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/fcntl.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <linux/fs.h>
    #include "fiemap.h" //This is from https://github.com/coreutils/coreutils/blob/df88fce71651afb2c3456967a142db0ae4bf9906/src/fiemap.h

    int main(int argc, char* argv[]) {

        int input_fd;

        if(argc != 2){
            printf ("Usage: ioctl file1");
            return 1;
        }

        /* Create input file descriptor */
        input_fd = open (argv [1], O_RDWR);
        if (input_fd < 0) {
                perror ("open");
                return 2;
        }

        union { struct fiemap f; char c[4096]; } fiemap_buf;
        struct fiemap *fiemap = &fiemap_buf.f;
        int s = ioctl(input_fd, FS_IOC_FIEMAP, fiemap);

        if (s == 0) {
            printf("ioctl success\n");
        } else {
            printf("ioctl failure\n");
            char * errmsg = strerror(errno);
            printf("error: %d %s\n", errno, errmsg);
        }

        /* Close file descriptors */
        close (input_fd);

        return s;
    }
4

2 に答える 2

3

fiemap_buf.fを呼び出す前にパラメータを適切に設定していないため、 がリクエスト識別子サポート自体からではなく、無効なコンテンツから来てioctl()いる可能性があります。EINVALfiemapFS_IOC_FIEMAP

たとえば、ioctl_fiemap()(カーネルからの) は、fiemap.fm_extent_countより大きいかどうかを判断するために を評価し、その場合はFIEMAP_MAX_EXTENTS戻り-EINVALます。でメモリのリセットもパラメータ化も実行されていないためfiemap、これが問題の根本原因である可能性が非常に高くなります。

参照したコードから、を呼び出す前にcoreutils正しいパラメーター化を実行することに注意してください。fiemapioctl()

  fiemap->fm_start = scan->scan_start;
  fiemap->fm_flags = scan->fm_flags;
  fiemap->fm_extent_count = count;
  fiemap->fm_length = FIEMAP_MAX_OFFSET - scan->scan_start;
于 2016-07-30T02:05:11.630 に答える
1

副作用のある FIEMAP_FLAG_SYNC を必ず渡す必要があるため、fiemap はお勧めしません。lseek()、SEEK_DATA、および SEEK_HOLE インターフェイスが推奨されますが、ファイル システムによっては、書き込まれていないエクステント (割り当てられたゼロ) がホールとして表現されることに注意してください。

于 2016-07-30T19:39:27.633 に答える