Joonas' Note

Joonas' Note

[Ubuntu] 디스크 용량이 남았는데 No space left 오류인 경우 본문

개발

[Ubuntu] 디스크 용량이 남았는데 No space left 오류인 경우

2024. 8. 10. 23:23 joonas

    최근 회사에서 우분투로 프로젝트를 빌드해야하는 일이 생겼는데, 파일 시스템과 관련하여 학부생때 공부했던 이론이 문제 해결에 도움이 된 경험이 신기해서 글로 남겨본다.

    이론과 실습, 특히나 다양한 프로그램을 주로 사용하는 우분투 환경에서는 OS, 컴퓨터 구조와 같은 수업에서 배우는 이론적인 부분은 실제 개발하는 중에 크게 마주할 일이 없을거라고 생각했다. 하지만 그런 일이 생겼다.

    발단

    동료의 컴퓨터에서 빌드 도중 No space left on device 와 같은 이유로 빌드가 중단되었다. 하지만 디스크 용량을 확인해봤을때, 용량은 분명 40GB 정도 남아있었다. (아래는 당시 상황을 재연한 모습이다.)

    $ df -h
    Filesystem      Size  Used Avail Use% Mounted on
    /dev/sda1        49G   24G   25G  49% /
    tmpfs            64M     0   64M   0% /dev
    /dev/root        49G   24G   25G  49% /pid2
    /dev/sda2       256G  6.0M   32G   1% /tmp

    분명 디스크 용량이 남아있었기 때문에, touch a.txt 와 같은 명령어로 빈 파일을 생성하려고 했는데 그마저도 막혔다.

    이 때 문제의 원인은 하나밖에 없다는 생각이 머리를 스쳤다.

    원인

    "파일을 더 생성하지 못한다는거는, inode 개수를 모두 사용한 것이 아닐까?" 라는 생각이었다.

    $ df -ih
    Filesystem    Inodes IUsed IFree IUse% Mounted on
    /dev/sda1       6.2M  6.2M     0   99% /
    tmpfs           7.9M    16  7.9M    1% /dev
    /dev/root       6.2M  666K  5.6M   11% /pid2
    /dev/sda2       800K   21K  780K    3% /io

    파일 시스템의 디스크 사용량을 확인하는 df 명령어에는 inode 를 확인하는 -i 옵션이 있다.
    위처럼 inode 를 모두 사용한 것을 확인하고는 학교에서 배우는 내용이 이렇게 쓰일 줄은 몰랐다고 생각했다.

    먼저, 우분투는 보통 ext4 파일 시스템을 사용한다.

    $ mount -l | grep ^/dev
    /dev/root on / type ext4 (ro,relatime,discard,errors=remount-ro)
    /dev/root on /nix type ext4 (ro,relatime,discard,errors=remount-ro)
    /dev/nbd47 on /repl type btrfs (rw,noatime,nobarrier,ssd,space_cache=v2,subvolid=256,subvol=/working_subv)
    /dev/root on /etc/localtime type ext4 (ro,relatime,discard,errors=remount-ro)
    ...

    ext3는 하나의 디렉토리에 최대 6만개 정도의 파일을, ext4는 최대 3만개의 파일을 가질 수 있는 것으로 기억한다.

    이번을 기회에 오랜만에 inode 구조에 대해서 다시 공부해보았다.

    inode 구조체는 아래 링크에서 직접 확인해볼 수 있다.

     

    fs.h - include/linux/fs.h - Linux source code v6.5-rc1 - Bootlin

    / include / linux / fs.h

    elixir.bootlin.com

    위 그림을 참고해보면 inode 는 실제로 디스크에 저장되는 block 을 포인터 배열로 들고 있고, 부족한 경우에는 이중/삼중 포인터로도 들고 있지만, ext4 파일 시스템의 경우 용량에 따라 사용 가능한 inode 의 개수가 이미 정해져있다.

    해결

    하나의 파일은 하나의 inode를 차지한다. 여기서 파일이란 디렉토리를 포함한다.
    여담으로, 디렉토리 역시 파일인데, vi 같은 편집기로 디렉토리를 열어보면 하위 파일의 경로가 적혀있는 텍스트 파일임을 알 수 있다.

    위와 같은 이유로, inode 를 확보하는 방법은 "최대한 많은 파일을 제거하는 것"이다.
    사용되고 있지 않는데 용량이 작은 파일을 최대한 많이 삭제하는 방법, 가장 대표적으로 캐시 파일을 지우는 것이다.

    다른 방법으로는 파일 시스템을 변경하는 법이다. ext4는 구조상 ext3 에 비해 1/2배의 inode만 사용할 수 있다.
    그렇다는것은, ext3 파일 시스템으로 디스크를 새로 포맷하면 2배의 inode 를 사용할 수 있다는 뜻이다.

    하지만 이 방법은, 포맷이 필요하기 때문에 파일을 전부 지워야하는 사태가 발생해서 실제로 적용해보기는 어려운 방법이다.

    FAT, NTFS 등의 파일 시스템은 inode 개수가 없는 것으로 알고 있는데, Ubuntu OS 와의 호환성이 좋지는 않은 것으로 알고 있어서 속도가 빠르지는 않을 것으로 예상된다.

     

    Comments