Btrfs Snapshot, CoW, inode, Hard/Symbolic Link.

이 글은 그저 내가 이해할 수 있게끔 정리한 내용이므로, 객관성은 전혀 보장돼 있지 않다.

서버를 이전(?)하면서, Btrfs snapshot 기능을 사용해보려고 한다. 방법은 어렵지 않지만, 늘 그렇듯, 배경 지식이 궁금해졌다. (이래서 난 돈을 못번다. ‘결과’만 내면 되는데, 뭔 잘난 척을 하느라, 이리 저리 끙끙대고 있는지..)

Btrfs Snapshot 은 CoW 기능을 활용한 방식이다. 그럼, CoW 는 뭘까?
CoW 는, 결국 ‘공간’을 낭비를 줄이기 위해 고안된 기술이다.
위키피디아 초반에 이런 설명이 있다.

If a resource is duplicated but not modified, it is not necessary to create a new resource; the resource can be shared between the copy and the original. 

Wikipedia

예를 들어, A 라는 파일을 B 라는 파일로 ‘복사’ 했다고 가정한다. A 와 B 는 복사시점부터, 어느 한 파일이 변경되기 전까지는 동일하기에, 굳이 동일한 내용을 중복하여 저장해놓을 필요는 없다.

동일한 내용을 ‘중복’하여 저장해 놓을 필요가 없다는 건 또 뭔 소린가?
이를 이해하기 위해선, inode 에 대해 알 필요가 있다.

역시나, 위키피디아에는 이렇게 설명되어있다.

Each inode stores the attributes and disk block location(s) of the object’s data. File-system object attributes may include metadata (times of last change, access, modification), as well as owner and permission data.

Wikipedia

파일이 하나 생성되면, 그 파일은 크게 두가지 정보를 갖게 된다. 하나는 이름, 또 다른 하나는 inode. inode 에는 파일의 특성(Attr.)과 파일이 실제 저장된 주소(disk block location) 이 저장된다.

다시 위의 CoW 로 가서, ‘동일한 내용을 중복하여 저장해 놓을 필요가 없다.’ 를 다시 살펴보자면 이렇다.

파일 A 를 파일 B 로, CoW 기술을 사용해 복사했다. 이 때, 파일 A 가 갖고 있던 두가지 정보는 새로 설정이 된다. 일단 파일명이 ‘A’ 에서 ‘B’ 로, 새로 바뀐다.
inode 역시 새로 만들어진다. (이건 아래에서 ls 명령으로 간단히 확인할 수 있다.)
그러나!!!
복사한 시점에서, 파일 A 와 파일 B 가 가리키는 disk block location 은 같다.
이게 중요한 점이다.

물론, 파일 A 또는 B 의 내용이 바뀌게 되면, 파일 B 는 새로운 디스크 공간을 할당받게 된다.

이렇게 함으로써, 용량을 적게 차지하면서도 모든 파일을 복사(Backup)할 수 있는 환경이 마련된다.
왜 용량이 적어질까? 이전에 복사한 파일들과 비교해서, ‘실제로 변경된’ 파일만 저장공간에 기록하기 때문이다.
변경되지 않은 파일은, ‘그냥 거기 그대로 있음’이란 정보만으로 충분하다.
(다만, 불의의 사고로 인해, 원래 저장공간이 손실된다면?? 여기에 대한 답은 아직 못찾았다.)


이를 시험해보기 위해, Hard Link, Symbolic Link 개념과 연계해서 아래 예를 만들어보았다.

먼저 file_A.orig 를 만든다. 그리고, cp 명령으로 이 파일을 복사한다.
그리고, ls -li 로 이 두 파일을 살펴본다.

$ ls -li
합계 60K
3145 -rw-rw-r-- 1 nemoneon nemoneon 19K 2019-05-28 15:14 file_A.orig
3146 -rw-rw-r-- 1 nemoneon nemoneon 19K 2019-05-28 15:14 file_B.cp

첫번째 열이 바로 inode(ls -i)이고, 이걸 보면 두 파일은 완전히 별개임을 알 수 있다. (물론.. inode 만으로는 같은 데이터 저장공간을 쓰고 있는지까지는 알 수가 없지만.)

다음은, file_A.orig 로, CoW 를 기능을 써서 복사본을 만들어(cp –reflink) 보겠다.

$ ls -li
합계 60K
3145 -rw-rw-r-- 1 nemoneon nemoneon 19K 2019-05-28 15:14 file_A.orig
3146 -rw-rw-r-- 1 nemoneon nemoneon 19K 2019-05-28 15:14 file_B.cp
3147 -rw-rw-r-- 1 nemoneon nemoneon 19K 2019-05-28 15:14 file_C.CoW

–reflink 에는 auto 와 always 두가지 선택사항이 있는데, 그냥 –reflink 를 하게되면 always 가 되는 듯 하다.
이 내용은 Archlinux 문서에 나와 있는데, 사실, CoW 로 만들어진 건지, 아니면 진짜 복사본인지는 어떻게 확인해야 하는 지 알 수가 없었다. 아무튼.. 뭐 그렇다고 한다.
Archlinux 문서에 따르면, 그냥 cp 를 하면 진짜 복사본(Actual Copy)이 만들어지고, CoW 로 복사를 하기 위해서는 –reflink 를 사용하라고 한다.

여기서 확인해볼 수 있는 사항은, 아무튼 inode 가 모두 다르다는 점. 즉, 세 파일은 모두 독립해서 존재하는 파일이다.
다만, Btrfs CoW 기능에 의해서, file_A.orig 와 file_B.CoW 는 복사 시점에서는 같은 공간을 점유하고 있지만, 어떤 파일이든 수정이 이뤄지게 되면, 새 영역을 할당받고 디스크 공간을 차지하게 된다는 점을 기억해야 한다.
(이 부분을, 즉 어떤 공간을 사용하는지에 대해선 확인할 길이 없다. 간단히 찾아봤지만, 방법은 모르겠다.)

여기까지는 CoW 에 대한 정리였고, 다음은 좀 더 눈에 보이고, 더욱 와 닿는, Link(Hard/Symbolic)에 대해 정리해보도록 한다.

file_A.orig 를 Hard Link 로 file_D.hlk 로 만들고, Symbolic Link file_E.sym 로 만들었다.

$ ls -li
합계 116
3145 -rw-rw-r-- 2 nemoneon nemoneon 18532 2019-05-28 15:14 file_A.orig
3146 -rw-rw-r-- 1 nemoneon nemoneon 18532 2019-05-28 15:14 file_B.cp
3157 -rw-rw-r-- 1 nemoneon nemoneon 53108 2019-05-28 15:21 file_C.CoW
3145 -rw-rw-r-- 2 nemoneon nemoneon 18532 2019-05-28 15:14 file_D.hlk
3158 lrwxrwxrwx 1 nemoneon nemoneon    11 2019-05-28 15:34 file_E.sym -> file_A.orig

file_C.CoW 는 inode(3147 ➙ 3157) 가 달라졌다. 파일 크기가 달라진 것으로 확인되지만, 이건 이 파일을 변경했기 때문이다.

file_A.orig 와 그의 Hard Link 인 file_D.hlk 를 보면, inode 가 3158 로 동일함을 알 수 있다. 그리고, 파일 권한 바로 오른쪽 열에 있는 숫자가 2로 바뀌었음을 볼 수 있다.
이건, 이 파일(파일명이 아니라, 파일이 가리키고 있는 데이터 블럭이라고 해야 좀 더 정확하겠다.)의 Hard Link 가 ‘2개’임을 뜻한다.
즉, file_A.orig 와 file_D.hlk 모두 같은 데이터 블럭을 가리키고 있다. 따라서, 두 파일은 결국 동일하다.

만약, file_D.hlk 에 수정이 가해진다면?

ls -li        
합계 140
3145 -rw-rw-r-- 2 nemoneon nemoneon 30195 2019-05-28 15:42 file_A.orig
3146 -rw-rw-r-- 1 nemoneon nemoneon 18532 2019-05-28 15:14 file_B.cp
3157 -rw-rw-r-- 1 nemoneon nemoneon 53108 2019-05-28 15:21 file_C.CoW
3145 -rw-rw-r-- 2 nemoneon nemoneon 30195 2019-05-28 15:42 file_D.hlk
3158 lrwxrwxrwx 1 nemoneon nemoneon    11 2019-05-28 15:34 file_E.sym -> file_A.orig

file_D.hlk 를 수정했더니, file_A.orig 의 파일크기도 같이 변했지만, inode 는 그대로다. 즉, 두 파일은 완전히 동일한 파일이라는게 증명이 됐다.

여기서, 늘 헷갈리는 점 한가지.
두 파일 중 하나를 지우면 어떻게 되나? 나머지도 지워지나?

하드 링크 중 어느 파일을 하나를 지우더라도, 원본에는 영향을 미치지 않는다.
하드든 심볼릭이든, 말 그대로 연결점(Link)이기 때문에, 최후의 하나를 지우기 전까지는 원본은 그냥 남아있게 된다.

Symbolic Link 는 Hard Link 와 거의 같은데, Hard Link 가 디렉토리를 연결하지 못하는 단점을 보완하고 있다.
위에서 보듯, Sym. Link 는 inode 도 다르고, ls 에서 표현되는 방법도 다르다. ls 에선 원본 파일이 무엇인지를 보여준다.
일상에서 사용하는 ‘링크’는 심볼릭 링크를 뜻한다.

이쯤에서 내 나름대로 정의.

  • Hard Link 는 inode 가 동일하고, 실제 데이터 블럭을 직접 가리킨다.
  • Symbolic Link 는, 실제 데이터 블럭을 가리키는 게 아니고, 원본 파일명을 가리킨다.

여러 하드 링크 중, 하나를 삭제하면 그냥 그 파일만 지워진다. 다른 연결 파일들엔 영향이 없다. (그냥 다른 이름의 파일을 하나 만들었다고 생각하면 쉽다.)
심볼릭 링크도 비슷한데, 큰 차이점이 하나 있다. (심볼릭 링크를 지운다고 해서 원본 파일이 지워지진 않는다.)


대충 정리는 했는데..
어째 좀 많이 부족한 듯한 느낌이 강하게 드는군.

One Comment

안녕하세요. 글 남겨주셔서 고맙습니다.