openSUSE, Ubuntu. Btrfs 사용 상 다른 점.

Clover 부트로더, rEFInd 부트로더를 사용하려다가 보니, 이 두 배포판이 Btrfs 를 사용할 때 어떻게 다르게 사용하는지를 알 수 있었다. 며칠 걸리긴 했지만, 그래도 뭔가 수수께끼를 풀어낸 듯 하여 기분은 좋다.

의문은 여기서 시작됐다. (두 배포판에서 모두 Btrfs 를 기본 파일시스템(Root 용)으로 사용했다는 전제가 있다.)
rEFInd 는, 추가 설정을 해주지 않으면 우분투를 찾지 못한다. 혹은, /boot 파티션을 따로 만들면 찾기는 하지만, 결국 부팅엔 실패한다.

‘찾는다’의 의미는 커널이미지를 탐색하는데 성공했다는 의미가 될테고, ‘부팅에 실패한다’는 @ 라는 서브볼륨을 인식하지 못했다는데 원인이 있다.

그런데, 같은 Btrfs 를 사용하고, 역시 같은 서브볼륨 @ 를 사용하지만, rEFInd 는 아무런 주저(?)없이 openSUSE 를 찾아내고, 부팅까지 시켜준다.

이 차이는 어디에서 온걸까????
이게 이 글을 시작하게 된 계기이자, 결국 주제가 되었다.


먼저, 우분투(계열)에서, 최초 설치할 때, / 디렉토리가 생성될 파티션의 파일시스템(말이 복잡하다..)을 Btrfs 로 선택하면, 우분투는 이 시스템을 이런 식으로 설정한다.

  • 선택한 파티션(ex. /dev/sda2)을 btrfs 로 포맷. (mkfs.btrfs /dev/sda2)
  • Subvolume @, @home 생성. (btrfs subvolume create <path>/@, btrfs subvolume create /@home)
  • @/ 아래에 필요한 파일 복사..
  • @home/ 아래에 사용자 홈디렉토리 생성
  • fstab 에 위 디렉토리 마운트.

fstab 내용은 이런 식이다.

# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/sda2 during installation
UUID=2417f7fb-fb7f-4c64-aa29-01a0a96d0b2e /               btrfs   defaults,subvol=@ 0       1
# /home was on /dev/sda2 during installation
UUID=2417f7fb-fb7f-4c64-aa29-01a0a96d0b2e /home           btrfs   defaults,subvol=@home 0       2

위 사실은 ‘직관’을 통해 이해할 수 있다. 어려운 내용은 없다. 서브볼륨을 만들고, 그것을 따로 마운트 한다. 서브볼륨은, 한 파일시스템 하에 서브디렉토리처럼 생성되지만, 그것을 따로 마운트할 수 있다는 점이 특징이다. Ext4 에선 이렇게 할 수가 없고, 굳이 비슷한 기능을 쓰려면 fstab 의 bind 기능을 이용해야 한다.

서브볼륨이 저렇게 (설치 중에) 생성되었단 사실은 fstab 을 봄으로써 미루어 짐작해볼 순 있다. 그러나, 설치가 끝나고 디스크로 부팅을 하면, @ 나 @home 디렉토리는 확인할 수가 없다. 그 디렉토리 자체가 / 와 /home 으로 각각 마운트 되었기 때문이다. 허나, 파일시스템 내부엔 저 디렉토리들이 실재하고 있다.

그것을 확인하기에 앞서, 서브볼륨 목록을 확인해보면,

# btrfs subvolume list -p /
ID 257 gen 31243 parent 5 top level 5 path @
ID 258 gen 31215 parent 5 top level 5 path @home

top level 5 로 생성된 @ 서브볼륨과, @home 이 있음을 알 수 있다.
그럼, 이제 @, @home ‘디렉토리’의 존재를 확인해보자.
이렇게 하려면 서브볼륨이 아닌 파티션 자체를 마운트해야 한다.

# mount /dev/sda2 /mnt
# ll /mnt
drwxr-xr-x 1 root root 250  4월 23 15:20 '@'/
drwxr-xr-x 1 root root  42  4월 10  2018 '@home'/

위와 같이, @ 와 @home 이 ‘디렉토리’로 존재함을 확인할 수 있다.

여기까지가 우분투의 경우다. OpenSuse 는 이와는 전혀 다른 결과를 보여준다.


OpenSuse 는 기본 파일시스템을 Btrfs 로 설정해놓고 있다. 우분투는 기본은 Ext4 이고, 내가 Btrfs 로 선택했지만, OpenSuse 는 그렇지 않다.

@ 를 Top Level Subvolume 으로 사용하는 것도 우분투와 비슷하다. 확실하진 않으나, 우분투와 OpenSuse 만이 Btrfs 사용 시 @ 를 루트로 사용한다고 한다.
@ 에는 별 의미는 없고, 그냥 관습이라고 하는 글도 어디선가 봤는데, 아무튼 @ 자체엔 아무런 의미가 없다.

강력한, OpenSuse 의 설치프로그램에서는, 설치 전에 파일시스템 개요도를 볼 수가 있다. VBox 에서 실행한 뒤 갈무리를 해서 완전한 그림을 얻지는 못했지만, 대략 다음과 같다.

OpenSuse Btrfs File System

여기서 우분투와 판이하게 다른 점을 확인할 수 있다. 정확한 정보는 다음과 같다.

# btrfs subvolume list -p /
ID 256 gen 354 parent 5 top level 5 path @
ID 258 gen 354 parent 256 top level 256 path var
ID 259 gen 307 parent 256 top level 256 path usr/local
ID 260 gen 354 parent 256 top level 256 path tmp
ID 261 gen 272 parent 256 top level 256 path srv
ID 262 gen 354 parent 256 top level 256 path root
ID 263 gen 325 parent 256 top level 256 path opt
ID 264 gen 354 parent 256 top level 256 path home
ID 265 gen 272 parent 256 top level 256 path boot/grub2/x86_64-efi
ID 266 gen 272 parent 256 top level 256 path boot/grub2/i386-pc

@ 가 최상위에, 그 아래에 var, usr/local, home 등이 서브디렉토리/서브볼륨으로 자리 잡고 있다.

그런데??? 저기에 속하지 않은 다른 필수 디렉토리들은? 소속이 어디일까?
위의 그림에 답은 나와있지만, 우분투와 비슷한 상황이라 가정(또는 속단?)하고, 우분투와 같은 방식으로 작업을 해봤다.

# mount /dev/sda2 /mnt
# ll /mnt
drwxr-xr-x 1 root root 1828 Apr 18 21:35 bin
drwxr-xr-x 1 root root  868 Apr 23 16:30 boot
drwxr-xr-x 1 root root    0 Apr 18 21:22 dev
drwxr-xr-x 1 root root 5188 Apr 23 16:29 etc
drwxr-xr-x 1 root root   16 Apr 18 21:47 home
drwxr-xr-x 1 root root   78 Apr 18 21:46 lib
drwxr-xr-x 1 root root 3178 Apr 18 21:35 lib64
drwxr-xr-x 1 root root    0 Jan 30 08:30 mnt
drwxr-xr-x 1 root root   48 Apr 23 16:16 opt
drwxr-xr-x 1 root root    0 Apr 18 21:22 proc
drwx------ 1 root root  186 Apr 23 16:39 root
drwxr-xr-x 1 root root    0 Apr 18 21:47 run
drwxr-xr-x 1 root root 3740 Apr 23 16:31 sbin
drwxr-xr-x 1 root root    0 Jan 30 08:30 selinux
drwxr-xr-x 1 root root   38 Apr 18 21:31 srv
drwxr-xr-x 1 root root    0 Apr 18 21:22 sys
drwxrwxrwt 1 root root 1302 Apr 23 16:39 tmp
drwxr-xr-x 1 root root  104 Apr 18 21:23 usr
drwxr-xr-x 1 root root  114 Apr 18 21:49 var

어라.. 이상하다. 우분투에서는 @ 와 @home 만이 나왔었는데, 여기선 그냥 / 산하 모든 디렉토리들이 표시가 된다.

그러나 서브볼륨목록에는 틀림없이 @ 가 최상위 서브볼륨(아래에 다시 쓰겠지만, 이 표현은 잘못되었다.)으로 나타나는데.. @ 는 어디로 사라진 걸까???

이걸 알아내기까지 이틀쯤 걸렸다.
늘 그렇지만, 이번에도 답은 ArchLinux 문서(그리고 btrfs.wiki.kernel.org 문서)에 있었다. 보고도 답을 못찾은 게 문제지.

먼저, 우분투와 같이 파티션 전체(이 표현이 잘못되었을 가능성도 있다.)를 마운트하려면, 이렇게 해줘야 한다.

# mount /dev/sda2 /mnt -o subvol=/
또는, (아래 방법이 개념을 이해하는데 더 적합하다.)
# mount /dev/sda2 /mnt -o subvolid=5
# ll /mnt
drwxr-xr-x 1 root root 160 Apr 19 10:11 @

드디어 @ 를 찾아냈다. 뒤지고 뒤진 끝에, StackExchange 에서 실마리를 찾았다.

똑같이 파티션 자체(/dev/sda2)를 마운트 했는데, 그 결과는 완전히 달랐다. ( 우분투에서는 @ 와 @home 이 표시. OpenSuse 에선 / 산하 모든 디렉토리들이 표시)

이유를 알고나면 당연한 건데, 다른 결과에 당황했던 이유는, Default Subvolume 이라는 개념을 전혀 이해하지 못했기 때문이다.

다음은, 우분투가 설치된 파티션과, OpenSuse 가 설치된 파티션을 /mnt 아래에 마운트 하고 btrfs subvolume get-default 명령을 내린 결과다.

# btrfs subvolume get-default /mnt/ubuntu/ 
ID 5 (FS_TREE) 
# btrfs subvolume get-default /mnt/openSuse/ 
ID 256 gen 479 top level 5 path @

우분투 파티션에는 Default Subvolume 이 FS_TREE(btrfs root)로 지정되어 있고, OpenSuse 파티션에는 @ 로 지정되어 있다.

그리고, ArchLinux 문서에는 이런 내용이 있다.

  • ‘Each Btrfs file system has a top-level subvolume with ID 5. It can be mounted as / (by default), or another subvolume can be mounted instead. Subvolumes can be moved around in the filesystem and are rather identified by their id than their path.’
  • ‘The default sub-volume is mounted if no subvol= mount option is provided.’
  • ‘Changing the default subvolume with btrfs subvolume set-default will make the top level of the filesystem inaccessible, except by use of the subvol=/ or subvolid=5 mount options’

위 긴 내용을 정리하자면 이렇다. 아래는, Btrfs 서브볼륨에 대한 기본 정의가 된다.

* Btrfs Subvolume; Default subvolume.

Btrfs 에는, (보이지는 않지만) ID5 를 가진 최상위 (서브)볼륨이 존재한다. 위에 있는 내용을 다시 한번 보고, 의미를 파악해보겠다.

# btrfs subvolume list -p /
ID 256 gen 354 parent 5 top level 5 path @
ID 258 gen 354 parent 256 top level 256 path var
ID 259 gen 307 parent 256 top level 256 path usr/local
ID 260 gen 354 parent 256 top level 256 path tmp
ID 261 gen 272 parent 256 top level 256 path srv
ID 262 gen 354 parent 256 top level 256 path root
ID 263 gen 325 parent 256 top level 256 path opt
ID 264 gen 354 parent 256 top level 256 path home
ID 265 gen 272 parent 256 top level 256 path boot/grub2/x86_64-efi
ID 266 gen 272 parent 256 top level 256 path boot/grub2/i386-pc

위에서 이 목록을 잘못 해석했었다. @ 를, ‘top level id 5 를 갖는다’라고 표현했었는데, 이게 잘못됐다. 근본부터가 잘못됐으니, 이후 해석이 맞을 리가 없다.

  • ID 256 : @ 의 ID 가 256 이라는 의미.
  • gen 354 : Generation ID 라는데, 의미는 모르겠다.
  • parent 5 : 현재 서브볼륨의 부모의 ID. 즉, @ 는 최상위 볼륨(ID 5) 의 자식이다.
  • top level 5 : (확실하지는 않지만) parent 와 같은 뜻으로 보인다.

parent/top level 의 의미를 확실히 알아내지는 못했지만, 해석하는덴 별 문제가 없다.

@ 는, 보이지 않는 ID 5 의 첫번째 자식이다. @ 의 ID 는 256 이지, 5 가 아니다.
ID 5 는, 최상위 서브볼륨(volume root directory)이 갖고 있다.

Btrfs Wiki 의 Subvolumes 항목에 이에 대한 얘기가 나와있다. (봐도 잘 이해는 안되지만..)

내가 쓰면서도 뭔 말을 하는 건지 많이 헷갈리지만..

Btrfs Subvolume 에는, Default-Subvolume 이 있는데, 이 설정이 우분투/OpenSuse 가 다름을 위에서 이미 확인했다. 이게 다르기 때문에, 일반 마운트를 했을 때 결과가 달리 나왔다.

Set Default 설정

위에 옮겨놓은 ArchLinux 내용을 정리하면 아래와 같다.

mount(또는 fstab) 시에, subvol 을 명시하지 않으면, Default Subvolume 이 마운트된다.
Default Subvolume 을 정의하지 않았다면, 기본값은 Volume Root (파일시스템 최상위 디렉토리라 할 수 있다.)가 된다.

우분투는 Default Subvolume 을 따로 정의하지 않았다. 위에서 get-default 로 나온 FS_TREE 는 Volume root 를 의미한다. 따라서, /dev/sda2 를 마운트했을 때 @ 와 @home 을 볼 수 있었다.

반면, OpenSuse 는 @ 를 Default Subvolume 으로 명시했다. 따라서 get default 결과로 ID 256/top level 5 path @ 가 반환되었다.
Default Subvolume 이 정의되어 있으니, subvol 없이 마운트를 하면, subvol @ 가 마운트된다.
이럴 경우, 파일 시스템(ID 5) 전체를 마운트하려면, subvolid=5 (또는 subvol=/) 를 사용한다.

mount /dev/sda2 /mnt -o subvolid=5

subvol=/ 도 같은 뜻이다. 다만, / 가 디렉토리 구조의 / 와 같아서 약간 헷갈리는 면이 있다. (현재 디렉토리 구조의 / 는 @ 라고 볼 수 있기에.)
외우고, 이해하기에는 subvolid=5 가 낫다. 최상위 서브볼륨은 ID 5 를 가지고 있고, 그 최상위를 마운트한다고 생각하면 이해가 빠르리라.


그리하여, Set Default 설정은 어떻게 하나?
일단, Btrfs 시스템을 마운트 해야 한다. 꼭 subvolid=5 를 줘서 마운트할 필요는 없고, 어떤 서브볼륨이든 하나라도 마운트가 되어 있으면 된다.

예를 들어, 다음과 같은 구조를 갖는 Btrfs 가 있다고 하자.

# btrfs subvolume list /mnt/setdefault 
ID 257 gen 8 top level 5 path top
ID 258 gen 8 top level 257 path top/top-1st
ID 259 gen 14 top level 5 path top2
ID 260 gen 17 top level 259 path top2/top2-1st
ID 261 gen 11 top level 260 path top2-1st-1st

사실, 먼저 마운트를 했어야 했는데, 마운트는 저 중에 ID 258 을 마운트 했다. 258 을 마운트하면, 운영체제 디렉토리 구조에선 ID 260 은 보이지 않는다. (mount /dev/sdc1 /mnt/setdefault/ -o subvolid=258)
cd /mnt/setdefault 하면 아무 것도 없는 빈 디렉토리만 보인다.
그러나, 그 상태에서도 btrfs subvolume 관련 명령은 작동한다.

아무튼, Btrfs subvolume 명령을 사용하기 위해선, 꼭 subvolid=5 를 사용해서 Volume Root 전체를 마운트할 필요는 없다. (경우에 따라선 이게 필요할 때도 있는 모양이다. Snapshot 이나 삭제를 할 때)
서브볼륨 일부만 마운트를 해도, get-default, set-default 명령은 제대로 동작한다.

Set Default 명령은 다음과 같이 사용한다.

 btrfs subvolume set-default subvolume-id <Btrfs 마운트 경로>

위의 경우, ID 260 을 디폴트로 지정하고 싶다면 다음과 같이 한다.

btrfs subvolume set-default 260 /mnt/setdefault

그리고 확인.

# btrfs subvolume get-default /mnt/setdefault
ID 260 gen 14 top level 259 path top2/top2-1st

이러면 쓰고자 했던 내용을 다 쓴 셈이 되나..?
일단은 여기까지. 다시 읽고 수정하기로.

3 Comments

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