fast-cloud의 object storage인 Swift에서 replication에 대해 mount부분을 수정 하던 중 아래와 같은 문제가 발생함
can't read superblock on /dev/loop0. dmesg(1) may have more information after failed mount system call.
mount 명령어가 디스크(loop0)를 읽을려 했는데, format을 초기화 하지 않아서, 파일 시스템(ext4, xfs 등 ..)이 깔려있지 않는 상태를 나타내고 있었음
VFS (Virtual File System)
리눅스는 ext4, xfs 등.. 수많은 파일 시스템을 지원함
사용자 프로그램(python 등..)은 파일이 어떤 format인지 신경 쓰지 않고 open(), write() 등.. 함수를 사용함
이것이 가능한 이유가 VFS가 중간에 있기 때문임

즉, VFS는 커널과 실제 파일 시스템 사이의 추상화 계층임
VFS는 디스크를 관리하기 위해 4가지의 주요 객체가 있음
Superblock, inode, Dentry(Directory Entry), File 이 있음
Superblock
파일 시스템 전체의 메타데이터를 담고 있음
즉, 마운트를 할때 가장 먼저 읽히는 곳임
총 inode 수, inode 테이블, filesystem 크기, block 크기, 마지막 moount한 시간, 마지막 쓰기 시간 등..을 가지고 있음
즉, 현재 발생한 문제는 superblock이 생성되지 않아서, format(mkfs)을 하지 않았기에, superblock에서 발생한 문제임을 알 수 있음
inode
특정 파일에 대한 메타데이터를 저장함
파일 권한, 소유자(user/group), 파일 크기, 생성 시간 등..
파일이 생성될 때 만들어지며, 데이터 블록 포인터를 통해 실제 데이터의 디스크 주소록을 가지고 있음
이때 inode에는 파일 이름이 없으며, 이름은 Dentry를 통해 관리가 됨

Dentry
파일 이름을 inode number(컴퓨터가 인식하는 번호)와 연결을 해줌
디렉토리도 파일의 일종이므로, 트리 구조를 형성함
ex) /home/stack/test.txt를 찾을때
/root-dentry/home(dentry)/stack(dentry)/data.txt(dentry)
dentry들은 디스크에 별도로 저장되기 보다는, 디렉토리 파일의 내용을 읽어서, 메모리에 Dentry cache 형태로 존재함
File
메모리에만 존재하는 프로세스 전용 객체임
offset을 통해 파일의 어디를 읽고 있는지, mode를 통해 쓰기 전용인지 읽기 전용인지, 어떤 dentry(file)를 보고 있는지를 나타냄
loop device
loop driver는 device driver에서 진짜 디스크가 아닌, 파일을 디스크처럼 속이는 가상 드라이버임
즉, 파일을 block 디바이스인 척 속이는 커널 드라이버임
물리적 하드웨어 대신 논리적(파일)으로 디스크 환경을 따라할 수 있기에 Devstack이 사용하고 있음

상위 계층인 Swift/VFS/XFS가 /dev/loop0를 보고 물리적인 하드디스크가 존재하는 것 처럼 인식을 해, read/write 명령이 아닌,
block단위 명령을 내림
loop device는 해당 명령을 받고, 연결된 파일에 명령을 수행하도록 파일 시스템 명령어로 변환을 함
변환된 명령어를 하위 계층들이 받아, 실제 물리 디스크에 있는 파일에 데이터를 기록하게 됨
즉, VFS -> File System -> Block Layer -> Device Driver(Loop Driver) -> loop driver에 의해 파일 쓰기 요청으로 변환 -> VFS로 전달 -> VFS로 가서 format을 다시 확인하고 다시 아래 계층으로 이동하며, Device Driver에서 진짜 하드웨어 드라이버임 NVMe/SATA Driver에 의해 디스크에 기록됨
cf) block layer는 I/O 스케줄러 역할을 수행과, I/O Merge 역할을 수행함
문제점
해당 문제 발생한 원인은 파일 자체가 없었기에 발생한 문제임을 위에 에러 코드를 통해 확인할 수 있었음
그럼 왜 파일이 없었는지를 생각을 해보았는데..
아마 unstack.sh 후 stack.sh 같이 스택을 다시 할때 기존 연결이 끊겼을 가능성이 많았을거 같음
즉, /dev/loop0와 실제 파일 사이의 연결이 끊긴거를 말함
해당 매핑 정보는 메모리에 저장되는데 재부팅을 했기에, 날라갔을 가능성이 많음
또한 파일 자체는 디스크에 남아 있을지라도, stack.sh 재실행을 통해 실제 내용(xfs)이 날라갔을거 같음
일반적인 리눅스 환경이라면 디스크에 저장을 했기에 losetup으로 다시 연결하면 가져올 수 있지만,
devstack의 경우 기존의 데이터를 밀어버리는 특성이 있음
그래서 이를 방지하기 위해 local.conf에 아래와 같은 명령어를 설정해야함
# ex) 루프백 파일이 이미 있으면 새로 만들지 말고 재사용
SWIFT_LOOPBACK_CREATE=False
#데이터 디렉토리를 지우지 마라
REUSE_DATA=True
병목 현상
해당 파일 시스템들에 공부를 하다 보니 병목 현상이 발생하는 근본적인 이유에 대해서도 알게되었음
메타데이터 조회 API가 갑자기 느려진 현상이 여기서 알 수 있었음
1. Double Jornaling
write 병목에 의해 발생함
Swift에 파일 하나를 저장할 때 마다 메타데이터를 업데이트를 해줘야하는 상황이 계속 발생함
만약 Loop가 없었더라면, xfs -> 기록 -> 디스크 저장 이런 관계를 가졌을 거임
하지만, loop가 존재하기에 위에서 말한 loop 현상이 발생하게 됨
즉, 데이터 1개를 쓰는데 디스크 I/O는 최소 2배 이상 발생하게 되는 것임
2. Context Switch
loop Driver가 작업을 수행하기 위해 커널 작업자 스레드(kworker)에게 일을 줘야하는데, 그럴때마다 context switching이 발생하게 됨
해당 문제는 읽기와 쓰기 작업에서 모두 발생하게 됨
3. I/O Serialization
loop device는 내부의 작업자는 메타데이터 같은 갱신 작업을 순서대로 처리하고 있음
즉, 쓰기 작업은 파일 시스탬의 무결성을 위해 동시에 처리하지 못하고 있음
또한 이때 backing file(실제 데이터를 저장하는 파일)을 보호하기 위해 mutex가 걸리게 되어 지연이 많이 발생하게 됨
추가적으로, 이를 개선하기 위해 global lock을 풀었더니 backing file의 하위 레벨에서의 mutex가 다시 발생하는 상황이 발생하게 됨
backing file은 결국 단일 물리적 파일이기 때문임
'데이터 > 복기' 카테고리의 다른 글
| 미니PC 우분투 와이파이 연결 (0) | 2025.12.04 |
|---|---|
| 데이터 처리 파이프라인 프로젝트(1) (0) | 2025.11.10 |
| Neo4j 그래프 DB 속도 향상 (0) | 2025.06.27 |