Hard Link 는 어떻게 동작하는 것일까요?

Choog Yul Lee·2023년 2월 14일
0
post-thumbnail

🥗 Prologue

나는 데이터 전달을 보장하는 솔루션을 운영한다. 파일을 주고받는 단순한 요건을 처리하는데 에러가 발생했다. Target Directory에 파일이 저장되지 않는다.

"어? 왜이러지?"

🎪 System Configuration Diagram

먼저, 문제를 분석하기 위해 환경 구성을 확인한다. 정상적인 환경과 비정상적인 환경을 비교하여 차이점을 찾는다. 대부분 답은 다름에 있다.

환경 구성은 단순하다. Middleware를 통해 Endpoint는 File을 전달 받는다. 특이한 점이 있다면 2개의 다른 파일 시스템을 쓴다는 것!

  1. Middleware로 부터 파일 조각을 전달 받는다.
  2. 파일 조각을 /home/usr/temp 경로에 순차적으로 write한다.
  3. /home/usr/temp 에 파일이 전체가 write 되면 /app/dist 로 파일을 옮긴다.

/home/usr/temp/app/dist 서로 다른 파일 시스템이다.

🔑 Problem

로그를 보니 아래의 코드에서 문제가 발생했다. 임시 경로인 /home/usr/temp 에는 정상적으로 파일이 존하는데, Target Dirctory인 /app/dist는 파일이 존재하지 않는다. rename 함수를 통해 로 옮기는 부분에서 0이 아니라 -1이 리턴하면서, 파일이 정상적으로 수신되지 않은 것 처럼 보이는 것이다.

if(0 != rename(frompath, targetpath)) {
	sprintf("Error write target file")
}

🔪 Analysis

rename 함수는 <stdlib.h> C언어의 표준 라이브러리에서 제공하는 함수인데 왜 안되지? rename 함수에는 문제가 있을리 없다. 단지, 내가 모르는 부분이 있을 뿐!

🔍 How to implement rename function in C language?

rename 함수의 실제 구현을 살펴보면 로직은 매우 단순한데 아래 두개의 Step 이 전부다.

  • __link 함수를 통해 old 파일에 new라는 hard link 를 생성한다.
  • __unlink 함수를 통해 기존 hard link old 를 제거한다.

rename 함수에서 hard link가 주요한 역할을 함으로 주의 깊게 살펴보아야 할 것 같다.

int
rename (const char *old, const char *new)
{
  int save = errno;
  if (__link (old, new) < 0)
    {
      if (errno == EEXIST)
	{
	  __set_errno (save);
	  /* Race condition, required for 1003.1 conformance.  */
	  if (__unlink (new) < 0
	      || __link (old, new) < 0)
	    return -1;
	}
      else
	return -1;
    }
  if (__unlink (old) < 0)
    {
      save = errno;
      if (__unlink (new) == 0)
	__set_errno (save);
      return -1;
    }
  return 0;
}

컴퓨팅 시스템에는 파일을 위한 2개의 링크가 존재한다. 하나는 Hard Link 이고 또 다른 하나는 Soft Link 이다. 나는 이 두개를 이렇게 이해하는데,

  • Hard Link는 파일 이름으로 실제 데이터에 접근할 수 있도록 하는 것
  • Soft Link는 바로가기. 원본 파일의 이름 시스템(Hard Link?)을 가르키도록 하는 것
사실 Hard LinkInode와 관련되어 있고, Inode 대한 건 여기서 확인 할 수 있다.

'Hard Link는 파일 이름으로 실제 데이터에 접근할 수 있도록 한다.'라고 정의하면 왜 모든 파일이 적어도 하나의 Hard Link 가 존재해야 하는지 이해 수 있다. 바로, 파일 이름으로 실제 데이터(physical data)에 접근해야 하기 때문이다.

아래의 그림은 Hard Link의 동작 방법을 표현한 그림이다. 디렉터리 dirA, dirB, dirC의 파일 이름 name1, name2, name3은 Inode 12345를 가르키고 있다. Inode 12345에는 파일에 대한 내용과 그리고 Hard Link의 갯수에 대한 정보를 가지고 있다.

여기서 dirD에 파일 이름 name4로 Hard Link를 추가하면, 추가된 Hard LinkInode 12345를 가르키고 Hard Link 수를 4로 변경한다. Inode를 새로 생성하지 않는다.

반면에, Soft Link 를 생성하면 Inode가 생성된다. 그리고 Inode에 실제 파일 경로를 저장한다. 아래 그림은 Soft Link의 동작 방법을 보여준다. dirA의 파일 이름 name1은 Inode 12345를 가르키고 있다. 여기에 dirB의 name2 라는 Soft Link를 생성하면 새로운 Inode 13579가 생성된다. Inode 13579는 실제 파일(physical data)의 /dirA/name 의 경로를 가르킨다.

dirA에 있는 name1 파일을 삭제하면, dirB에 있는 Soft Link 파일 name2는 존재하지 않는 파일 경로를 가리키 때문에 액세스할 때 오류가 발생한다.

Hard Link에는 제약 사항이 존재한다.

  • Hard Link는 디렉토리에 생성할 수 없다.
  • Hard Link는 같은 파일 시스템에서 사용가능하다. 그 대신 Soft Link를 사용해야 한다.
  • 하나의 파일에 대한 Hard Link의 최대 개수는 232 이다.

🌠 How to Solve the Problem

Hard Link에 대해 공부하다 보니 문제 발생 원인이 명확하게 보인다.

Hard Link 제약사항System Configuration Diagram을 보면 내가 운영하는 솔루션이 Hard Link의 제약사항을 위반 하고 있음을 알 수 있다.

Hard Link는 같은 파일 시스템에서 사용가능하다.

/home/usr/temp/app/dist 은 서로 다른 파일 시스템이기 때문에 문제가 발생하는 것이다.

문제의 해결법은 두가지 이다.

첫째, rename 함수를 사용하지 않는 것
둘째, Target Directory 와 Temp Directory를 같은 파일 시스템으로 변경하는 것

팀원들과 협의 끝에 나는 두 번째 방법을 선택해 수정했다.

🍰 Epilogue

일을 하면 할 수록 운영체제와 컴퓨터 구조론과 같은 Computer Sicence이 지식이 필요함을 느낀다. 다 필요한 것들인데 대학에서 공부 할 때는 왜 이리 쓸모 없게 느껴졌을까?

🛰️ Reference Site

0개의 댓글