삽질특기생

다음에 삽질 덜하려고 만든 블로그

0%

overlayfs 버그 - xfs 사용 시 ftype=0인 경우 파일 삭제 시 인식하지 못함

문제 상황

환경 세팅 중 crio가 다음과 같은 fatal log를 출력하고 종료되었다.

1
Dec 01 18:02:54 bp-master001 crio[8263]: time="2020-12-01 18:02:54.147849982+09:00" level=fatal msg="kernel does not support overlay fs: overlay: the backing xfs filesystem is formatted without d_type support, which leads to incorrect behavior. Reformat the filesystem with ftype=1 to enable d_type support. Running without d_type is not supported.: driver not supported"

backing filesystem으로 d_type을 지원하지 않는 xfs를 사용하면 비정상적인 동작으로 이끌 수 있으니,
ftype=1로 파일시스템을 다시 포맷하여 d_type 지원을 활성화시키라는 내용이다.

관련 이슈 확인

overlayfs에서 위와 같은 상황에서 삭제된 파일이 삭제되었다고 표시되지 않는 버그가 있다고 한다.

During mount, make sure upper fs supports d_type otherwise error out.
In some instances xfs has been created with ftype=0 and there if a file on lower fs is removed, overlay leaves a whiteout in upper fs but that whiteout does not get filtered out and is visible to overlayfs users.
And reason it does not get filtered out because upper filesystem does
not report file type of whiteout as DT_CHR during iterate_dir().
So it seems to be a requirement that upper filesystem support d_type for overlayfs to work properly. Do this check during mount and fail if d_type is not supported.

버그 재현

파티션 생성

테스트를 위한 새로운 파티션을 생성한다.

1
# fdisk /dev/sdb
생성 과정
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@master ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).

Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table
Building a new DOS disklabel with disk identifier 0x4aa3c9aa.

Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-16777215, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-16777215, default 16777215):
Using default value 16777215
Partition 1 of type Linux and of size 8 GiB is set

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

xfs 생성

xfs 생성 시 ftype=0 옵션을 추가한다.
참고로 ftype=0은 crc=0도 추가해야한다.

1
# mkfs -t xfs -n ftype=0 /dev/sdb1
생성 과정
1
2
3
4
5
6
7
8
9
10
[root@master ~]# mkfs -t xfs -n ftype=0 -m crc=0 /dev/sdb1
meta-data=/dev/sdb1 isize=256 agcount=4, agsize=524224 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0, sparse=0
data = bsize=4096 blocks=2096896, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal log bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
crc=0 없이 생성한 경우
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
[root@master ~]# mkfs -t xfs -n ftype=0 /dev/sdb1
cannot disable ftype with crcs enabled
Usage: mkfs.xfs
/* blocksize */ [-b log=n|size=num]
/* metadata */ [-m crc=0|1,finobt=0|1,uuid=xxx]
/* data subvol */ [-d agcount=n,agsize=n,file,name=xxx,size=num,
(sunit=value,swidth=value|su=num,sw=num|noalign),
sectlog=n|sectsize=num
/* force overwrite */ [-f]
/* inode size */ [-i log=n|perblock=n|size=num,maxpct=n,attr=0|1|2,
projid32bit=0|1]
/* no discard */ [-K]
/* log subvol */ [-l agnum=n,internal,size=num,logdev=xxx,version=n
sunit=value|su=num,sectlog=n|sectsize=num,
lazy-count=0|1]
/* label */ [-L label (maximum 12 characters)]
/* naming */ [-n log=n|size=num,version=2|ci,ftype=0|1]
/* no-op info only */ [-N]
/* prototype file */ [-p fname]
/* quiet */ [-q]
/* realtime subvol */ [-r extsize=num,size=num,rtdev=xxx]
/* sectorsize */ [-s log=n|size=num]
/* version */ [-V]
devicename
<devicename> is required unless -d name=xxx is given.
<num> is xxx (bytes), xxxs (sectors), xxxb (fs blocks), xxxk (xxx KiB),
xxxm (xxx MiB), xxxg (xxx GiB), xxxt (xxx TiB) or xxxp (xxx PiB).
<value> is xxx (512 byte blocks).

fstab에 mount 정보 추가 및 적용

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@master ~]# vi /etc/fstab
/dev/sdb1 /root/ftype0 xfs defaults 0 0
[root@master ~]# mkdir /root/ftype0
[root@master ~]# mount -a
[root@master ~]# xfs_info /root/ftype0
meta-data=/dev/sdb1 isize=256 agcount=4, agsize=524224 blks
= sectsz=512 attr=2, projid32bit=1
= crc=0 finobt=0 spinodes=0
data = bsize=4096 blocks=2096896, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=0
log =internal bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0
(참고) root는 ftyep=1이다
1
2
3
4
5
6
7
8
9
10
[root@master ~]# xfs_info /
meta-data=/dev/mapper/centos-root isize=512 agcount=4, agsize=406016 blks
= sectsz=512 attr=2, projid32bit=1
= crc=1 finobt=0 spinodes=0
data = bsize=4096 blocks=1624064, imaxpct=25
= sunit=0 swidth=0 blks
naming =version 2 bsize=4096 ascii-ci=0 ftype=1
log =internal bsize=4096 blocks=2560, version=2
= sectsz=512 sunit=0 blks, lazy-count=1
realtime =none extsz=4096 blocks=0, rtextents=0

파일 삭제 후 동작 확인

overlay 디렉토리에서 lower 디렉토리에 있는 파일을 삭제한 뒤 조회하면, 삭제했던 파일이 비정상적으로 조회된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@master ftype0]# mkdir overlay-test overlay-test/lower overlay-test/upper overlay-test/workdir overlay-test/overlay
[root@master ftype0]# cd overlay-test/
[root@master overlay-test]# touch lower/lower
[root@master overlay-test]# mount -t overlay -o lowerdir=/root/ftype0/overlay-test/lower,\
> upperdir=/root/ftype0/overlay-test/upper,workdir=/root/ftype0/overlay-test/workdir \
> none /root/ftype0/overlay-test/overlay
[root@master overlay-test]# ls -al overlay/
합계 0
drwxr-xr-x. 1 root root 6 12월 5 02:05 .
drwxr-xr-x. 6 root root 58 12월 5 02:05 ..
-rw-r--r--. 1 root root 0 12월 5 02:05 lower
[root@master overlay-test]# rm overlay/lower
rm: remove 일반 빈 파일 `overlay/lower'? y
[root@master overlay-test]# ls -al overlay/
ls: cannot access overlay/lower: 그런 파일이나 디렉터리가 없습니다
합계 0
drwxr-xr-x. 1 root root 18 12월 5 02:06 .
drwxr-xr-x. 6 root root 58 12월 5 02:05 ..
??????????? ? ? ? ? ? lower
(참고) 정상 시나리오 - ftype=1인 디렉토리에서 overlayfs 동작 확인

삭제된 파일이 조회되지 않는다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@master ~]# mkdir overlay-test overlay-test/lower overlay-test/upper overlay-test/workdir overlay-test/overlay
[root@master ~]# cd overlay-test/
[root@master overlay-test]# touch lower/lower
[root@master overlay-test]# mount -t overlay -o lowerdir=/root/overlay-test/lower,\
> upperdir=/root/overlay-test/upper,workdir=/root/overlay-test/workdir \
> none /root/overlay-test/overlay
[root@master overlay-test]# ls -al overlay/
합계 0
drwxr-xr-x. 1 root root 6 12월 5 02:01 .
drwxr-xr-x. 6 root root 62 12월 5 02:01 ..
-rw-r--r--. 1 root root 0 12월 5 02:01 lower
[root@master overlay-test]# rm overlay/lower
rm: remove 일반 빈 파일 `overlay/lower'? y
[root@master overlay-test]# ls -al overlay/
합계 0
drwxr-xr-x. 1 root root 19 12월 5 02:02 .
drwxr-xr-x. 6 root root 62 12월 5 02:01 ..

유관 프로젝트의 대처

레드햇의 경우 xfs 파일시스템을 사용할 때 주의 사항을 문서에 명시되어있고,
Docker 역시 overlayfs storage driver를 사용할 때 주의 사항이 공식 홈페이지에 명시되어있다.

이러한 버그가 알려져있기 때문에, docker와 cri-o에서는 앞서 소개했었던 fatal log 내용처럼 사전에 확인하는 과정을 추가한 것으로 보인다.

결론

overlayfs의 backing filesystem으로 xfs 파일 시스템을 사용할 때는, xfs 포맷 시 ftype=1을 반드시 추가하자.