No space left on device or exceeds fs.inotify.max_user_watches 에러

ny0011·2022년 9월 16일
0
No space left on device or exceeds fs.inotify.max_user_watches

직역하면 디스크 용량이 없거나 fs.inotify.max_user_watches를 초과했다는 뜻이다

그런데 디스크 용량이 아직 남았는데도 에러가 발생한다면
fs.inotify.max_user_watches를 초과했다는 말이다

그럼 fs.inotify.max_user_watches란 뭘까?

뜻만 간단하게 보면
fs : file system
inotify : 파일이 변경됨을 감지하는 시스템
max_user_watches : 사용자가 watch할 수 있는 최대값..?

구글링해보니 아래 커밋을 찾을 수 있었다
https://github.com/torvalds/linux/commit/0eeca28300df110bd6ed54b31193c83b87921443

inotify는 dnotify의 부족한 부분을 개선한 시스템

커밋 내의 문서를 보니 3가지 sys call을 설정해두면 동작한다고 되어 있다.

inotify 사용 단계
1) inotify 인스턴스를 초기화

int fd = inotify_init ();

변경 이벤트는 "watch"로 감지가 되는데
watch는 (object,mask) 묶음으로 되어 있고
object : file이나 directory
mask : 1 bit 마스킹용(0 or 1로 set). 어플리케이션이 알고 싶어하는 inotify event

watch descriptor(wd)가 watch를 참조함

watch는 file의 경로를 받아서 추가함
directory에 있는 watch는 디렉터리 안 파일의 이벤트를 리턴할 것임

watch를 추가하는 방법

int wd = inotify_add_watch (fd, path, mask);

많은 파일을 추가하는 방법

for each file to watch {
		int wd = inotify_add_watch (fd, file, mask);
}

새 mask를 전달하면 기존 watch를 업데이트 할 수 있음

이제 코드를 보면
include/linux/sysctl.h 파일에 아래 설정이 추가돼있음

/* CTL_INOTIFY names: */
enum
{
	INOTIFY_MAX_USER_DEVICES=1,	/* max number of inotify device instances per user */
	INOTIFY_MAX_USER_WATCHES=2,	/* max number of inotify watches per user */
	INOTIFY_MAX_QUEUED_EVENTS=3	/* Max number of queued events per inotify device instance */
};

INOTIFY_MAX_USER_WATCHES : user 당 inotify watch의 최대값
-> 파일이 변경됨을 감지하는 watch의 최대치를 제한해둠

그리고 아래 커밋을 보면 최대치를 늘렸다고 되어 있다.
https://github.com/torvalds/linux/commit/92890123749bafc317bbfacbe0a62ce08d78efb7

inotify를 새로 만들었을 당시(2005년!)에는 inotify.max_user_watches의 기본값을 8192로 설정해뒀지만 15년이 지난 2020년에 보니 이 값이 너무 작은 것 같은 느낌이 든다~ 라고 되어 있다.

그리고 inotify.max_user_watches 의 크기를 range (8192, 1048576)로 설정해 주소 지정 가능한 메모리의 1%를 넘지 않게 설정한다고 되어 있었다.

Modeled after the epoll.max_user_watches behavior to adjust the default
value according to the amount of addressable memory available, make
inotify.max_user_watches behave in a similar way to make it use no more
than 1% of addressable memory within the range [8192, 1048576].

inotify가 차지하는 memory 양을 측정하는 방법
inotify_inode_mark + 2*(struct inode 크기)

struct inode 크기는 구글링해보니 ext4 inode records 크기는 256B, inode struct 크기는 160 B가 기본값이라고 한다.
https://docs.kernel.org/filesystems/ext4/dynamic.html#inode-size

근데 inotify_inode_mark가 뭔지 모르겠음..
어쨌든 128GB 이상 메모리를 가진 64bit 시스템은 inotify.max_user_watches 값을 최대 1048576까지 지정할 수 있음.

We estimate the amount of memory used by inotify mark to size of
inotify_inode_mark plus two times the size of struct inode (we double
the inode size to cover the additional filesystem private inode part).

That means that a 64-bit system with 128GB or more memory will likely
have the maximum value of 1048576 for inotify.max_user_watches. This
default should be big enough for most use cases.

대충 비례식을 세워서 내 메모리 값을 알면 inotify.max_user_watches 값을 변경해주면 될 것 같다
64GB 메모리 -> 524288

내 컴퓨터의 fs.inotify.max_user_watches 값을 영구적으로 변경해주자

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

0개의 댓글