IRPStackSize 공간이 부족하여 발생하는 문제를 가끔 겪게 됩니다. IRP 의 기본적인 개념과 IRPStackSize 를 확인하는 방법에 대해서 아래와 같이 정리하였습니다.

I/O Request Packet(IRP)은 시스템이 I/O 요청을 처리할 때 필요한 정보를 저장하는 영역으로 Thread 가 I/O 서비스를 요청할 때 I/O Manager 는 I/O 서비스가 I/O 시스템을 통해 진행됨에 따라 그 동작을 나타내기 위해 IRP 를 생성합니다. IRP 는 Fixed header 와 하나 이상의 Stack Location 으로 구성되어 있습니다.

Fixed header
요청 유형, 요청 크기, 요청이 동기적인지 비동기적인지 여부, Buffered I/O에 대한 버퍼 포인터, 요청이 진행되면서 변경되는 상태 정보
 
Stack Location
함수 코드, 함수 관련 파라미터, 호출자(caller)의 파일 개체 포인터



IRPStackSize 매개변수는 IRP 의 Stack Location 수를 의미하며 파일 시스템에 각종 Device Driver 들이 설치되어 Attach 될 때마다 Stack 의 누적되는 깊이는 증가하게 됩니다. Windows Server 2003 의 IRPStackSize 값은 기본적으로 15 입니다. 아래 레지스트리에서 값을 지정할 수 있습니다.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters



Stack Location 값은 11 ~ 50 (0xb ~ 0x32)까지 증가 가능하며 드라이버당 1개가 증가하게 됩니다. IRPStackSize 가 설정된 값을 초과하게 될 경우 Event ID 2011 Srv 이벤트 오류에 irpstacksize 가 부족하다는 메시지가 나타나며 저장소 부족에 따른 오동작이 발생할 수 있습니다. 물론 레지스트리 변경을 통해 IRPStackSize 를 증가해 줄 수 있지만 증가한만큼 Buffer 에 대한 메모리가 소모되기 때문에 다른 문제가 발생할 수 있으므로 필요에 따라 값을 조금씩 (3 이하) 증가하여 모니터링 하는 것이 방법인 듯 합니다.


다음은 Windows XP PC 에서 로컬 디버그 모드에서 C 드라이브 Device object 에 Attach Driver 들에 대해 Device Stack 를 확인하는 방법입니다.

lkd> !driveinfo c:
Drive c:, DriveObject e1538910
    Directory Object: e1004450  Name: C:
        Target String is '\Device\HarddiskVolume1'
        Drive Letter Index is 3 (C:)
    Volume DevObj: 8254be30
    Vpb: 825e55e8  DeviceObject: 82563020
    FileSystem: \FileSystem\Ntfs


lkd> !devstack 0x82563020
  !DevObj   !DrvObj            !DevExt   ObjectName
  81f62460  \Driver\AhnFlt2K   81f62518 
  8258c3b8  \FileSystem\sr     8258c470 
> 82563020  \FileSystem\Ntfs   825630d8  // Active Stack Location


lkd> dt _device_object 82563020 stacksize
nt!_DEVICE_OBJECT
   +0x030 StackSize : 10 ''

lkd> dt _device_object 8258c3b8 stacksize
nt!_DEVICE_OBJECT
   +0x030 StackSize : 11 ''

lkd> dt _device_object 81f62460 stacksize
nt!_DEVICE_OBJECT
   +0x030 StackSize : 12 '' // 최상위 device object 의 StackSize 는 12임을 확인

lkd> !vpb 825e55e8  // Read Device 확인
Vpb at 0x825e55e8
Flags: 0x1 mounted
DeviceObject: 0x82563020
RealDevice:   0x8254be30
RefCount: 1749
Volume Label:

lkd> !devstack 0x8254be30 // 하위 Device Stack 확인
  !DevObj   !DrvObj            !DevExt   ObjectName
  825675f0  \Driver\VolSnap    825676a8 
> 8254be30  \Driver\Ftdisk     8254bee8  HarddiskVolume1
!DevNode 825e5b88 :
  DeviceInst is "STORAGE\Volume\1&30a96598&0&SignatureC7FCC7FCOffset7E00Length17611F800"
  ServiceName is "VolSnap"

lkd> !DevNode 825e5b88
DevNode 0x825e5b88 for PDO 0x8254be30
  Parent 0x825a6308   Sibling 0000000000   Child 0000000000
  InstancePath is "STORAGE\Volume\1&30a96598&0&SignatureC7FCC7FCOffset7E00Length17611F800"
  ServiceName is "VolSnap"
  TargetDeviceNotify List - f 0xe101ea00  b 0xe18fa250
  State = DeviceNodeStarted (0x308)
  Previous State = DeviceNodeEnumerateCompletion (0x30d)
  StateHistory[07] = DeviceNodeEnumerateCompletion (0x30d)
  StateHistory[06] = DeviceNodeStarted (0x308)
  StateHistory[05] = DeviceNodeStartPostWork (0x307)
  StateHistory[04] = DeviceNodeStartCompletion (0x306)
  StateHistory[03] = DeviceNodeResourcesAssigned (0x304)
  StateHistory[02] = DeviceNodeDriversAdded (0x303)
  StateHistory[01] = DeviceNodeInitialized (0x302)
  StateHistory[00] = DeviceNodeUninitialized (0x301)
  StateHistory[19] = Unknown State (0x0)
  StateHistory[18] = Unknown State (0x0)
  StateHistory[17] = Unknown State (0x0)
  StateHistory[16] = Unknown State (0x0)
  StateHistory[15] = Unknown State (0x0)
  StateHistory[14] = Unknown State (0x0)
  StateHistory[13] = Unknown State (0x0)
  StateHistory[12] = Unknown State (0x0)
  StateHistory[11] = Unknown State (0x0)
  StateHistory[10] = Unknown State (0x0)
  StateHistory[09] = Unknown State (0x0)
  StateHistory[08] = Unknown State (0x0)
  Flags (0x00000130)  DNF_ENUMERATED, DNF_IDS_QUERIED,
                      DNF_NO_RESOURCE_REQUIRED
  UserFlags (0x0000000a)  DNUF_DONT_SHOW_IN_UI, DNUF_NOT_DISABLEABLE
  CapabilityFlags (0x00000380)  SilentInstall, RawDeviceOK,
                                SurpriseRemovalOK
  DisableableDepends = 1 (including self)



DeviceTree 툴을 사용하면 Stack Size 를 쉽게 확인할 수 있습니다. (단, 운영 머신에서의 사용은 주의가 필요합니다)




[참고자료]
DeviceTree
http://www.osronline.com/article.cfm?article=97

Windows 2000 및 Windows Server 2003의 IRPStackSize 매개 변수에 대한 설명
http://support.microsoft.com/kb/285089

IRPStackSize and Clusters.
http://blogs.technet.com/b/askcore/archive/2008/01/25/irpstacksize-and-clusters.aspx


작성자 : Lai Go / 작성일자 : 2011.06.01

Posted by Lai Go