2016-07-30 5 views
4

내 문제는 스파 스 파일 읽기를 처리하고 파일의 범위가 주변의 일부 논리를 수행하는 위치를 이해하는 것입니다.ioctl을 FS_IOC_FIEMAP과 함께 사용하는 방법

이러한 것들을 찾아내는 직접적인 API 호출이 없기 때문에 ioctl api를 사용하기로 결정했습니다. cp 명령이 스파 스 파일을 통해 코드를 복사하여 문제를 해결하고이를 보았던 방법에 대한 아이디어를 얻었습니다.

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

그래서, 사용자 공간에서 실행 내 샘플 프로그램에서 같은 일을 시도하고 "잘못된 인수"와 그 오류를 밖으로. 내가 누락 된 부분이나 사용자 공간에서 가능한지 확실하지 않습니다. ext4 파일 시스템에서 우분투 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 파일 시스템의 상위 커널 커널 버전에서만 지원되는 것처럼 보입니다. 그래서 우리는 ioctl 방식에 의존해야했습니다. 이 저수준 프로그래밍에 익숙하지 않습니다. FIEMAP_FLAG_SYNC 플래그를 사용하면 부작용이 될 수있는 것에 대해 조언 할 수 있습니까? – Aila

+0

동기화는 성능에 큰 영향을 줄 수 있으므로 가능한 경우 피해야합니다. – pixelbeat