2007/10/30

솔라리스 UFS 화일 시스템의 최대 화일 개수와 inode의 부족

단일 디렉토리 내에서는 32767개의 디렉토리만 지원하므로, 각 디렉토리는 서브
디렉토리를 가져야만 더 많은 디렉토리를 가질 수 있고, 각 디렉토리별로 더 많은
화일을 가질 수 있게 됩니다.

단일 디렉토리에 형성할 수 있는 화일의 개수는 이론적으로 제한이 없습니다만,
inode의 개수에 제한을 받습니다. 32비트 화일 시스템에서는 최대 40억개의 inode를 (unsigned long long for 64bit, unsigned long for 32bit) 구성 하실 수 있습니다만, inode에 할당하는 블럭의 크기(디폴트는 1 inode에 2kb를 사용)에 따라 변화가 있으므로 다음과 같은 방법으로 체크하실 필요가 있습니다.
inode만 보고 싶은 경우에는
#df -F ufs -o i /

혹은 기타 다른 상황까지 보고 싶은 경우에는 fstyp 이용
# fstyp -v /dev/dsk/c0t0d0s0 | less
ufs
magic 11954 format dynamic time Tue Oct 30 13:59:33 2007
sblkno 16 cblkno 24 iblkno 32 dblkno 760
sbsize 2048 cgsize 8192 cgoffset 64 cgmask 0xffffffc0
ncg 627 size 30803962 blocks 30337448
bsize 8192 shift 13 mask 0xffffe000
fsize 1024 shift 10 mask 0xfffffc00
frag 8 shift 3 fsbtodb 1
minfree 1% maxbpg 2048 optim time
maxcontig 128 rotdelay 0ms rps 167
csaddr 760 cssize 10240 shift 9 mask 0xfffffe00
ntrak 48 nsect 128 spc 6144 ncyl 10028
cpg 16 bpg 6144 fpg 49152 ipg 5824
nindir 2048 inopb 64 nspf 2
nbfree 1748247 ndir 31696 nifree 3392581 nffree 255808
cgrotor 101 fmod 0 ronly 0 logbno 1584
version 2

.....

참고 화일 /usr/include/sys/types.h

//
// 32bit의 경우
typedef ulong_t ino_t; /* expanded inode type */
...
typedef ulong_t fsfilcnt_t; /* count of files */

// 64bit의 경우
typedef u_longlong_t ino_t; /* expanded inode type */
...
typedef u_longlong_t fsfilcnt_t; /* count of files */
//
//
inode가 부족하다고 판단이 되는 경우에는 tunefs를 통해서 inode 블럭당 사용되는 용량을
줄여서 즉, space 기준으로 최적화를 함으로써 inode를 좀 더 획득할 수 있습니다.

그러나, inode가 풍부함에서 디렉토리를 나열하거나(ls) 하는데, 오랜 시간이 걸리면서
sys% 가 증가하는 경우에는 캐쉬 테이블의 크기가 부족해지는 경우가 대부분입니다.
이런경우 일단, 가장 쉬운 workaround로는
/etc/system에 튜닝을 하실 필요가 있습니다. 단 메모리가 충분이 있어야 합니다.
튜닝 대상이 되는 시스템 변수는 ncsize이며, ufs_ninode라는 변수의 상위 개념에 해당합니다.
일단 현재 사용되는 값을 확인하기 위해서는 다음과 같은 방법을 사용합니다.
# echo "ncsize/D" | mdb -k
ncsize:
ncsize: 129700
숫자를 확인하셨으면 다음과 같이 필요한 만큼의 숫자를 결정하신 후 /etc/system에 입력합니다.
set ncsize= 1042865

또한, 디렉토리 나열을 느리지 않은데, 화일 /O(데이타를 읽거나, 쓸때)가 느리다고 판단이 되는 경우에는
다음과 같은 시스템 변수의 튜닝을 할 필요가 있습니다.
segmap_percent

설정 이전에 먼저 보는 법은 다음과 같습니다.
# echo "segmap_percent/D" | mdb -k
segmap_percent:
segmap_percent: 12

확인이 되었으면, 다음과 같이 설정을 하되, 너무 큰 값을 설정하지 않도록 주의 합니다.
이 설정은 커널이 I/O를 위해서 많은 메모리를 사전 할당하도록 하므로, 메모리 사용에 커다란
영향을 주게 됩니다.
set segmap_percent=25

와 같이 튜닝하시고 테스트후 조정하는 과정을 거쳐야 합니다.

상황에 따라서는 위 두개의 튜닝을 동시에 진행할 수 있습니다. 그럴 수록 커널 메모리의 상태를 잘 이해하고 있어야 합니다. 참고로 커널이 사용하는 메모리의 상태를 보기 위해서는 다음과 같은 명령어를 사용할 수 있습니다.

#echo "::memstat" | mdb -k ; 솔라리스 9이후 부터 가능. 메모리가 큰 장비에서는 오래 걸림.

참고로 솔라리스 10의 ZFS를 사용하면 UFS가 가지는 위와 같은 문제가 근원적으로 발생하지 않습니다.

댓글 12개:

kuh3h3 :

좋은 내용이 많군요.잘 보고 있습니다.그런데 한가지 질문을 드려도 될지? 얼마전에 솔라리스 익스프레스 커뮤니티 이디션(nv-b75a)를 깔았습니다.그런ep 넷웍에 문제가 있군요.wget 이든 firefox든 용량이 큰(대략 4.5메가 바이트 이상) 되는 파일을 받으면 4.5 메가 까지만 받고 넷웍이 작동하지 않는군요.무언가 사용자 쿼터제한이 있나 싶어 룻계정에서 해봐도 마찬가지입니다.원인이 뭘까요? 막연한 질문이지만 답변을 해주시면 감사하겠습니다.

kuh3h3 :

그래서 일반적인 웹서핑에는 문제가 없지만 대략 4.5 메가 이상되는 파일을 받다 멈춘뒤에는 넷웍이 작동되지 않아 케이블모뎀의 전원을 내렸다 다시켜면 넷웍이 다시 작동하는 이상한 현상을 겪고 있습니다.

kuh3h3 :

제시스템은 x86이구요 넷웍카드는 레알텍 랜카드입니다. 윈도우 리눅스 등과 솔라리스를 멀티부팅 하고 있습니다

kuh3h3 :

아 마지막으로 저는 dhcp로 ip를 받고 있습니다.
넷웍 전송이 어떤 크기를 넘으면 넷웍을 정지시키는 서비스 같은게 솔라리스 익스프레스 커뮤니티 이디션에 작동하나 싶어 서비스를 살펴봐도 잘 모르겠더군요.

스마트라이프 :

4.5G가 아니고, 4.5M인가요? 글세, 다른 문제가 있는 것으로 생각됩니다. 저는 1 G 화일을 수시로 받는데요...

솔라리스에 IPQoS와 같이 프로토콜별 네트웍 용량을 조절하는 기술이 들어있긴 합니다만, 기본적으로 이것이 활성화되어 있지 않습니다. 즉, 솔라리스는 네트웍이 많이 사용된다고 해서 그것을 죽이거나 하지는 않는 것이죠.

솔라리스 자체에 문제가 있는 지를 확인하시고 싶으시면, 루프백 테스트라는 것을 해보실 수 있습니다. 즉, 해당 서버에서 해당 서버로 wget이나 ftp를 해보는 것이죠. 시스템 외부로 나가지 않으므로(즉, 네트웍을 타지 않기 때문에) 네트웍을 제외한 솔라리스와 시스템 자체적으로 건전하지를 테스트할 수 있습니다.

위 테스트에서 문제가 없는 경우 해당 애플리케이션이 동작하지 않고 서 있을때(wget이 좋은 경우입니다), pstack 으로 어떤 스택에서 멈춰있는 지를 파악하시면 문제의 핵심이 어디에 있는 지 보다 쉬워집니다.

kuh3h3 :

답변 감사합니다. 로컬 ftp 서비스를 시작한 후 4.5 메가 바이트 이상되는 파일을 ftp 와 wget 으로 받아 보았습니다.로컬에서는 문제가 없더군요. pstack으로 확인은 아직 못했습니다.svn이나 cvs로 소스를 받아올때도 마찬가지 현상이 생기는 걸로 봐선 무선 쿼터가 걸려 있는게 확실한듯 한데 어떤 종류의 쿼터가 이런 제한을 걸수 있는지 알수 없군요.멀티 부팅하고 있는 윈도우나 오픈비에스디 넷비에스디, 우분투, 업그레이드 하기전 solaris 10에서는 이런 문제가 없거든요.

kuh3h3 :

pstack을 해보았습니다.

글로 쓰기엔 너무 번거로울듯해서 스크린샷을 잡았습니다.그런 데 넷워 멈추는 파일 크기가 점점 더 작아 지네요.

http://gagemel.joa1004.com/error.png

다음은 넷웍이 멈춘후 파이어폭스에서 서핑을 시도 할때의 pstack모습입니다.

http://gagemel.joa1004.com/error2.png

kuh3h3 :

넷웍이 멈춘것은외부로 텔넷 ftp ssh ping 등도 안되는군요.

kuh3h3 :

cde 환경에선 그런 문제가 없는 걸로 봐서 nv-b75a에 설치된 그놈에 문제의 원인이 있는듯 하네요.

kuh3h3 :

그놈버젼을 올렸습니다.
JDS (Java Desktop System) Consolidation - nevada_77
http://dlc.sun.com/osol/jds/downloads/nevada_77/
혹시나 하고 재부팅한후 테스트 해보니 여전히 같은 에러네요. 그놈의 어떤 것이 이런 에러를 만들까요?

kuh3h3 :

그놈버젼을 올려도 문제가 해결안되어 좀더 살펴보니 제가 쓰는 vdsl 모뎀이 인터넷 연결에서 솔라리스 와는 안맞는듯 합니다. 그래서 이번 기회에 광랜으로 갈아버렸더니 아무문제 없군요.정말 감사합니다.

스마트라이프 :

vdsl을 사용하실때 네트웍 상태를 보실 필요가 있겠습니다. 일단 로컬로는 문제가 없는 것으로 봐서, 네트웍과 관련된 문제인 것은 확실한 것으로 여겨집니다. JDS는 일반 TCP 애플리케이션들이고, 로컬 네트웍만을 이용하기 때문에 네트웍에 문제를 야기하지는 않습니다.

제 생각에는 사용하시는 네바다 베타빌드에 새로이 추가된 tcp/ip stack이 사용하시던 vdsl과의 간섭 문제가 있는 듯 합니다. b75 이후에는 crossbow는 네트웍 카드 가상화 관련 프로젝트가 도입되어 있어서 네트웍 카드를 관장하는 드라이버가 변경되어 있습니다.
새로운 이드라이버가 vdsl 사용할 경우에 MTU를 변경해야 한다던지 혹은 collision이 많이 발생한다던지 하는 사소한 네트웍 문제를 야기시킬 수 있습니다.(아마도 버그인듯... )

캡쳐하신 애플리케이션들의 스택도 모두 tcp에서 데이타를 기다리는 펑션에서 wait하는 것으로 나오는 것으로 보건데, 이전 vdsl에서 문제를 찾아서 해결하셨다면 좋은 얘기거리가 될 수 있을 뻔 했습니다.