2016-07-30 3 views
4

私の問題は、ファイルの読み込みを処理し、ファイルのエクステントがどこかのロジックを実行する場所であることを理解することです。ioctlをFS_IOC_FIEMAPで使用する方法

これらの問題を解決するための直接的な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; 
    } 

答えて

3

あなたが適切ioctl()を呼び出す前fiemap_buf.fパラメータを設定していないとして、EINVALFS_IOC_FIEMAP要求識別子のサポート自体からよりfiemap無効な内容から来ている可能性があります。例えば

、(カーネルから)ioctl_fiemap()は、FIEMAP_MAX_EXTENTSよりも大きいかどうかを判断し、その場合に-EINVALを戻すためにfiemap.fm_extent_countを評価します。 fiemapでメモリリセットもパラメータ化も実行されていないため、これは問題の根本原因になります。あなたが参照さcoreutilsコードから、それはioctl()を呼び出す前にfiemapの正しいパラメータ化を実行することを

注:あなたは副作用を持っているFIEMAP_FLAG_SYNCに合格することを確認する必要がよう

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; 
+1

作業中の映画マップを初期化する!どうもありがとうございました! – Aila

1

注fiemapは推奨されません。 lseek()、SEEK_DATAおよびSEEK_HOLEインターフェースが推奨されますが、ファイル・システムによっては、未書き込みのエクステント(割り当てられたゼロ)を穴として表します。

+0

提案していただきありがとうございます。 lseekでSEEK_DATAとSEEK_HOLEを試しましたが、xfsファイルシステム用のより高いlinuxカーネルバージョンからのみサポートされているようです。ですから、ioctlの方法に頼らざるを得ませんでした。私はこの低レベルのプログラミングには少し馴染んでいますが、FIEMAP_FLAG_SYNCフラグの副作用となるものについてアドバイスできますか? – Aila

+0

同期には大きなパフォーマンスの影響があり、可能な場合は避ける必要があります – pixelbeat

関連する問題