GlusterFS/코드 분석/xlator/shard

From PGWiki

개요

shard(sharding, 샤딩) xlator는 기존의 스트라이프(stripe) xlator의 개선으로서, 설정된 블록 크기에 따라 파일을 쪼개서 각 브릭으로 분배하는 기능을 수행한다. 이러한 기능은 GlusterFS의 어떤 파일이 한 브릭의 가용량을 초과하는 경우에 입출력을 할 수 없는 문제점을 개선할 수 있기 때문에 VDI나 고화질 미디어 처리와 같은 대용량 파일을 처리하는 환경에 있어 반드시 필요한 기능이다.

자료 구조

shard_priv_t

xlators/features/shard/src/shard.h
175 typedef struct shard_priv {
176         uint64_t block_size;
177         uuid_t dot_shard_gfid;
178         inode_t *dot_shard_inode;
179         gf_lock_t lock;
180         int inode_count;
181         struct list_head ilist_head;
182 } shard_priv_t;
  • block_size
    샤딩될 단위 블록 크기를 기록한다.
  • dot_shard_gfid
    shard xlator의 UUID를 기록한다.
  • dot_shard_inode
    shard xlator는 샤딩된 블록들을 각 브릭의 .shard 디렉터리 아래에 저장하는데, 이 디렉터리의 아이노드 정보를 기록한다.
  • lock
    잠금 정보를 나타내는 gf_lock_t 자료형으로서, 이 자료형의 배타적 접근을 위해 사용된다.
  • inode_count
    shard xlator는 파일을 block_size에 정해진 크기만큼 나누어서 기록하게 되는데, 이렇게 나누어진 각 파일들에 대한 아이노드 정보를 연결 리스트로 관리하게 되며, 이 연결 리스트를 구성하는 원소들의 개수를 나타낸다.
  • ilist_head
    나누어진 각 파일들에 대한 아이노드들의 연결 리스트

init

xlators/features/shard/src/shard.c
4966 int
4967 init (xlator_t *this)
4968 {
4969         int           ret  = -1;
4970         shard_priv_t *priv = NULL;
4971 
4972         if (!this) { 
4973                 gf_msg ("shard", GF_LOG_ERROR, 0, SHARD_MSG_NULL_THIS,
4974                         "this is NULL. init() failed");
4975                 goto out;
4976         } 
4977 
4978         if (!this->parents) {
4979                 gf_msg (this->name, GF_LOG_ERROR, 0, SHARD_MSG_INVALID_VOLFILE,
4980                         "Dangling volume. Check volfile");
4981                 goto out;
4982         } 
4983 
4984         if (!this->children || this->children->next) { 
4985                 gf_msg (this->name, GF_LOG_ERROR, 0, SHARD_MSG_INVALID_VOLFILE,
4986                         "shard not configured with exactly one sub-volume. "
4987                         "Check volfile");
4988                 goto out;
4989         } 
4990 
4991         priv = GF_CALLOC (1, sizeof (shard_priv_t), gf_shard_mt_priv_t);
4992         if (!priv)
4993                 goto out;
4994 
4995         GF_OPTION_INIT ("shard-block-size", priv->block_size, size_uint64, out);
4996 
4997         this->local_pool = mem_pool_new (shard_local_t, 128);
4998         if (!this->local_pool) { 
4999                 ret = -1;
5000                 goto out;
5001         }                                                                               
5002         gf_uuid_parse (SHARD_ROOT_GFID, priv->dot_shard_gfid);
5003 
5004         this->private = priv;
5005         LOCK_INIT (&priv->lock);
5006         INIT_LIST_HEAD (&priv->ilist_head);
5007         ret = 0;
5008 out:
5009         if  (ret) { 
5010                 GF_FREE (priv);
5011                 mem_pool_destroy (this->local_pool);
5012         } 
5013 
5014         return ret;
5015 
5016 }

shard xlator는 모든 xlator가 그러하듯이 init() 함수를 통해 초기화가 시작된다.

  • 4984
    shard xlator는 xlator들의 방향성 그래프(Directed Graph) 상에서 단일 서브볼륨(브릭)에 대해서만 존재해야 하기 때문에 이를 위한 검사를 수행한다.
  • 4991
    xlator 별로 내부적으로 사용하는 데이터인 priv를 위한 메모리 공간을 할당한다.
  • 4995
    샤딩할 단위 블록 크기를 나타내는 설정 값인 shard-block-size를 초기화한다.
    실제로 여기에서 값이 할당되는 것은 아님을 주의하자.
  • 4997
    xlator 별로 지역적으로 할당되는 메모리 풀인 local_pool을 할당한다.
    mem_pool_new() 함수의 두번째 매개변수는 요청된 메모리 풀의 크기를 나타내지만, 현재는 사용되지 않고 있다.
  • 5002
    shard xlator의 UUID를 priv->dot_shard_gfid에 변환하여 저장한다. SHARD_ROOT_GFID는 이 코드와 같은 위치에 있는 shard.h에 다음과 같이 정의되어 있다.
    123 #define SHARD_ROOT_GFID "be318638-e8a0-4c6d-977d-7a937aa84806"
    
  • 5004-5006
    this->private이 앞서 초기화한 priv을 가리키도록 한다.
    또한 잠금 정보(priv->lock)와 아이노드 연결 리스트 헤더(priv->ilist_head)를 초기화한다.

fini

FOPs

shard_lookup

  • SHARD_ENTRY_FOP_CHECK()
  • 메모리 풀로부터 메모리 할당
  • loc_copy()
  • local->xattr_req가 매개 변수로 들어온 확장 속성 요청(xattr_req) 혹은 새로운 사전을 가리키도록 설정
  • shard_inode_ctx_get_block_size()를 호출하여 블록 크기 얻기
  • 현재 호출 프레임 상에서 첫번째 자식 xlator(FIRST_CHILD(this))의 검색 연산(FIRST_CHILD(this)->fops->lookup)을 호출하며, 콜백으로 shard_lookup_cbk()을 호출하는 STACK_WIND() 매크로 함수 호출

shard_open

  • 첫번째 자식 xlator(FIRST_CHILD(this))의 열기 연산(FIRST_CHILD(this)->fops->open)을 호출 스택 상의 다음 요소로 하며, shard_open_cbk()를 콜백으로 하는 STACK_WIND()를 호출한다.

shard_flush

  • 첫번째 자식 xlator의 플러시 연산(FIRST_CHILD(this)->fops->flush)을 호출 스택 상의 다음 요소로 하며, shard_flush_cbk()를 콜백으로 하는 STACK_WIND()를 호출한다.

shard_fsync

  • 첫번째 자식 xlator의 동기화 연산(FIRST_CHILD(this)->fops->fsync)을 호출 스택 상의 다음 요소로 하며, shard_fsync_cbk()를 콜백으로 하는 STACK_WIND()를 호출한다.

shard_stat

  • 위치 정보가 기록하고 있는 아이노드 정보의 유형(loc->inode->ia_type)이 디렉터리 혹은 링크인 경우 첫번째 자식 xlator의 stat 연산(FIRST_CHILD(this)->fops->stat)을 호출 스택 상의 다음 요소로 하며, shard_stat_cbk()를 콜백으로 하는 STACK_WIND()를 호출하고 즉시 0을 반환한다.
  • shard_inode_ctx_get_block_size()를 호출하여 해당 아이노드에 대한 블록 크기를 얻는다.
  • 호출 프레임의 로컬 데이터로 사용하기 위한 메모리를 로컬 메모리 풀로부터 할당 받아 local에 기록 한다.
  • 현재 호출 프레임의 로컬 데이터가 local을 가리키도록 한다.
  • loc_copy()를 호출하여 위치 정보(loc)를 로컬 데이터의 위치 정보(local->loc)에 복사한다.
  • 로컬 데이터의 확장 속성(local->xattr_req)가 매개 변수로 들어온 확장 속성 요청(xattr_req) 혹은 새로운 사전을 가리키도록 설정한다.
  • SHARD_MD_READ_FOP_INIT_REQ_DICT() 매크로 함수를 호출
  • 첫번째 자식 xlator의 stat 연산(FIRST_CHILD(this)->fops->stat)을 호출 스택 상의 다음 요소로 하며, shard_common_stat_cbk()를 콜백으로 하는 STACK_WIND()를 호출한다.

shard_fstat

  • 위치 정보가 기록하고 있는 아이노드 정보의 유형(loc->inode->ia_type)이 디렉터리 혹은 링크인 경우 첫번째 자식 xlator의 stat 연산(FIRST_CHILD(this)->fops->stat)을 호출 스택 상의 다음 요소로 하며, shard_fstat_cbk()를 콜백으로 하는 STACK_WIND()를 호출하고 즉시 0을 반환한다.
  • shard_inode_ctx_get_block_size()를 호출하여 해당 아이노드에 대한 블록 크기를 얻는다.
  • 현재 xlator의 아이노드 테이블(this->itable)이 NULL이라면 매개 변수로 넘겨 받은 파일 기술자의 아이노드가 가리키는 아이노드 테이블(fd->inode->table)을 가리키도록 한다.
  • 호출 프레임의 로컬 데이터로 사용하기 위한 메모리를 로컬 메모리 풀로부터 할당 받아 local에 기록 한다.
  • 현재 호출 프레임의 로컬 데이터가 local을 가리키도록 한다.
  • loc_copy()를 호출하여 위치 정보(loc)를 로컬 데이터의 위치 정보(local->loc)에 복사한다.
  • 로컬 데이터의 핸들러(local->handler)가 shard_post_fstat_handler()를 가리키도록 한다.
  • 로컬 데이터의 파일 기술자(local->fd)가 매개 변수로 넘겨 받은 파일 기술자(fd)를 가리키도록 한다.
    이 과정에서 fd_ref(fd)를 호출하여 해당 파일 기술자의 참조 계수를 증가시킨다.
  • 로컬 데이터의 확장 속성(local->xattr_req)가 매개 변수로 들어온 확장 속성 요청(xattr_req) 혹은 새로운 사전을 가리키도록 설정한다.
  • SHARD_MD_READ_FOP_INIT_REQ_DICT() 매크로 함수를 호출
  • 첫번째 자식 xlator의 fstat 연산(FIRST_CHILD(this)->fops->fstat)을 호출 스택 상의 다음 요소로 하며, shard_common_stat_cbk()를 콜백으로 하는 STACK_WIND()를 호출한다.

shard_getxattr

shard_fgetxattr

shard_readv

shard_writev

shard_truncate

shard_ftruncate

shard_setxattr

shard_fsetxattr

shard_setattr

shard_fsetattr

shard_removexattr

shard_fremovexattr

shard_fallocate

shard_discard

shard_zerofill

shard_readdir

shard_readdirp

shard_create

shard_mknod

shard_link

shard_unlink

shard_rename

shard_seek

Callbacks

shard_forget

shard_release

shard_releasedir

바깥 고리