Monday, March 31, 2008

Optimizing I/O Performance

간단하다. User space에서 할 수 있는 최적화란, 물리적인 블럭 순으로 I/O 작업을 요청하는 것이다. 이렇게 하기 위해 세가지 방법이 있는데,
  • 파일 경로를 보고 정렬해주는 방법 (단순하나, 별로...)
  • inode 번호를 보고 정렬해주기 (fragmentation 경우 별로이나, 대부분 이 방식을 쓴다.)
  • physical block 순으로 정렬하기 (다 좋은데 root 권한이 있어야 한다.)

inode 번호 대로 정렬하는 것은 stat() system call을 통해 사용할 수 있다.



#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

int get_inode(int fd)
{
struct stat buf;
int ret;

ret = fstat(fd, &buf);

if (ret < 0) {
perror("stat");
return -1;
}

return buf.st_ino;
}

physical block 순으로 정렬하기 위해서는 ioctl() system call을 사용한다. 아래처럼 FIBMAP을 주면 해당하는 논리 블럭의 physical block 번호를 block에 넣어준다.


#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <linux/fs.h>

int get_inode(int fd)
{
struct stat buf;
int ret;

ret = fstat(fd, &buf);

if (ret < 0) {
perror("stat");
return -1;
}

return buf.st_blocks;
}

int get_block(int fd, int logical_block)
{
if (ioctl(fd, FIBMAP, &logical_block) < 0) {
perror ("ioctl"); return -1;
}

return logical_block;
}

앞서 봤던 inode 값을 리턴하는 함수에서 buf.st_ino를 buf.st_blocks로 바꾸면 논리 블럭 갯수를 반환한다. 예를 들어 어떤 파일이 8개의 논리 블로으로 구성되어 8을 리턴했으면 이 파일은 0~7번의 논리 블럭을 가지고 있는 것이다. 그래서 이 0~7번을 ioctl 함수를 통해 각각에 대한 physical block의 번호를 받을 수 있고 이 값을 가지고 I/O 요청을 최적화할 수 있다.

3 comments:

  1. FIBMAP은 LBN나 PBN를 알려주지 못합니다. 단지 해당 파티션의 파일시스템의 첫번째 block으로 부터 몇번째 block인지만 알려 줄 뿐이지요. LBA는 디스크 기준으로 몇번째 섹터인가인데 앞으 경우와 매치가 되지 않습니다. FIBMAP의 이름 자체도 File Inode BitMAP이 아닐까 생각해 봅니다.

    ReplyDelete
  2. FIB이 PBN을 알려주는 것이 아니라, ioctl에 FIB값을 주면 FIB-PBN 맵에서 찾아 해당하는 PBN을 넘겨주는 것으로 기록한 것인데요, ioctl을 통해 구한 PBN이 Physical Block Number가 아니라면 Robert Love에게 메일을 보내봐야겠군요 :)

    ReplyDelete
  3. 아, 다시 살펴보니 Jae-hyeok님 말씀이 맞는것 같네요(!). Love가 'physical block number'라고 썼는데, 파일 시스템에서의 block number를 통해 물리적인 layout을 가늠할 수 있다는 의미로 사용한 것 같네요. 'physical block order'가 낫겠네요.

    ReplyDelete