2016-07-30 40 views
4

我的問題是處理稀疏文件讀取並理解文件的範圍在哪裏執行某些邏輯。如何使用帶有FS_IOC_FIEMAP的ioctl

因爲沒有直接的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,它很可能是EINVAL從比從FS_IOC_FIEMAP請求標識符支持本身fiemap內容無效的到來。

例如,ioctl_fiemap()(從內核)會,以確定它是否比FIEMAP_MAX_EXTENTS更大,在這種情況下返回-EINVAL評估fiemap.fm_extent_count。由於在fiemap上沒有執行存儲器復位和參數設置,這很可能是問題的根本原因。

要注意,從coreutils代碼你引用,它調用ioctl()之前執行的fiemap正確的參數:不建議

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

初始化fiemap工作!非常感謝你! – Aila

1

注意fiemap,你必須確保通過FIEMAP_FLAG_SYNC它有副作用。 lseek(),SEEK_DATA和SEEK_HOLE接口是推薦的接口,不過請注意,取決於文件系統,將會將未寫入的擴展區(分配的零)表示爲空洞。

+0

感謝您的建議。我們用lseek嘗試了SEEK_DATA和SEEK_HOLE,但是它看起來只能從比我們所在的版本更高的Linux內核版本來支持xfs文件系統。所以,我們不得不訴諸於ioctl的方式。我對這個低級編程有點新意,你能否就FIEMAP_FLAG_SYNC標誌的副作用提出建議? – Aila

+0

同步可能會有較大的性能影響,應儘可能避免 – pixelbeat

相關問題