Hello there,
I’m toying with a Dokan-based user-mode file system. While chasing the performance, I noticed a thing in driver implementation I considered “possibly optimizable”. Goes like this: the driver queues incoming IRPs and returns STATUS_PENDING for them. User mode component calls DeviceIoControl to retrieve pending requests (then handles them and calls another DeviceIoControls which complete original IRPs). Such a call itself yields IRP which also gets queued (to different queue). Then there is dedicated thread which just looks into those queues and if it finds content in both (i.e. pending request and request retrieval request) it completes the request retrieval request, filling it with appropriate incoming request details along the way. And I’m thinking: why do I need the thread here? Can’t I just check queues’ status as part of either incoming request or retrieval request processing, and complete the retrieval request from there if possible?
And so I set out to implement this change… and ended up disappointed:
- my (several concurrent) user mode worker threads call IoDeviceControl and I get a bunch of retieval requests queued
- then I force a request IRP to see it paired with a retrieval request queued; this request gets completed via IoCompleteRequest, BUT
- the user-mode DeviceIoControl call doesn’t complete

I spent brief time with this in the office, eliminated some potential issues (completing the IRP within a lock scope, completing it and then returning STATUS_PENDING etc.), but ended up empty handed. So I gave up and decided I’d live with the thread. Then I spent an evening with Google and documentation and I still don’t know what the issue is - be it a fundamental misunderstanding of the concept on my end (aka it has to be done via thread because of X) or some other obvious thing I missed. I realized I didn’t discuss the case with verifier yet, so that’s going to be my next stop, but any help/input/whatever would be appreciated!
Thanks,
L.
So, IoCompleteRequest is called for the IRP (the master original one), but umode does not see it completed?
If yes - try to look at the IRP state using !irpfind and !irp
–
Maxim S. Shatskih
Microsoft MVP on File System And Storage
xxxxx@storagecraft.com
http://www.storagecraft.com
wrote in message news:xxxxx@ntfsd…
> Hello there,
>
> I’m toying with a Dokan-based user-mode file system. While chasing the performance, I noticed a thing in driver implementation I considered “possibly optimizable”. Goes like this: the driver queues incoming IRPs and returns STATUS_PENDING for them. User mode component calls DeviceIoControl to retrieve pending requests (then handles them and calls another DeviceIoControls which complete original IRPs). Such a call itself yields IRP which also gets queued (to different queue). Then there is dedicated thread which just looks into those queues and if it finds content in both (i.e. pending request and request retrieval request) it completes the request retrieval request, filling it with appropriate incoming request details along the way. And I’m thinking: why do I need the thread here? Can’t I just check queues’ status as part of either incoming request or retrieval request processing, and complete the retrieval request from there if possible?
>
> And so I set out to implement this change… and ended up disappointed:
> - my (several concurrent) user mode worker threads call IoDeviceControl and I get a bunch of retieval requests queued
> - then I force a request IRP to see it paired with a retrieval request queued; this request gets completed via IoCompleteRequest, BUT
> - the user-mode DeviceIoControl call doesn’t complete 
>
> I spent brief time with this in the office, eliminated some potential issues (completing the IRP within a lock scope, completing it and then returning STATUS_PENDING etc.), but ended up empty handed. So I gave up and decided I’d live with the thread. Then I spent an evening with Google and documentation and I still don’t know what the issue is - be it a fundamental misunderstanding of the concept on my end (aka it has to be done via thread because of X) or some other obvious thing I missed. I realized I didn’t discuss the case with verifier yet, so that’s going to be my next stop, but any help/input/whatever would be appreciated!
>
> Thanks,
> L.
>
Hi Maxim,
thanks a lot for the advice - I’ll give it a try tomorrow hopefully!
Kind regards,
L.
To close this one out: the problem was merely my coding error. I had to reimplement the change since I reverted my initial version and did other changes afterwards, and the rewritten version works fine.
L.