"Rolling My Own IRP" - Is this the way to go?

Hi Everyone -

I have an FSD that causes a usermode service to actually perform the write
request for a file. When the system gets busy, I deadlock, because I’m
holding up the MPW thread, and the usermode app can’t write. It’s because
cache is full and the system is trying to flush everything.

So, after some discussion in this newsgroup, I decided to roll my own irp
and complete the original IRP with SUCCESS. Then my own IRP comes in on
another thread and all should be ok, unless there’s a failure. It was
suggested that I can inform the system that this failure occured by doing
IoRaiseHardError. I’ve gotten “ryo.zip” and examined it, but it is a
little different because it doesn’t use a usermode service.

Ok fine. BUT, It dawned on me that when I complete the original IRP, the
system will free the MDL associated with it, so I can’t expect it to be
around for my own IRP to use.

Am I correct in thinking that I must get a new buffer, copy the original
buffer into it, alloc a MDL and stuff that into my new IRP->Mdl? Is this
the best (only?) way to get around this thread-deadlock issue?

Thanks for your comments/suggestions.

Regards,

Greg

If you are trying to *not* block the MPW thread and to simply queue the
request of the write to a user mode thread for the write, then just
re-allocate the buffer, along with some context information, and post
this to the asynchronous thread which will pass it to the user service.
Then you can allow the MPW thread to complete.

There maybe a bit of confusion here though. What is the user service
doing when it gets a request, via an inverted IOCtl interface I assume,
to flush a buffer? Does it call the WriteFile(), or equivalent, API?

Pete

Peter Scott
xxxxx@KernelDrivers.com
http://www.KernelDrivers.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Greg Pearce
Sent: Wednesday, September 04, 2002 9:11 AM
To: File Systems Developers
Subject: [ntfsd] “Rolling My Own IRP” - Is this the way to go?

Hi Everyone -

I have an FSD that causes a usermode service to actually
perform the write request for a file. When the system gets
busy, I deadlock, because I’m holding up the MPW thread, and
the usermode app can’t write. It’s because cache is full and
the system is trying to flush everything.

So, after some discussion in this newsgroup, I decided to
roll my own irp and complete the original IRP with SUCCESS.
Then my own IRP comes in on another thread and all should be
ok, unless there’s a failure. It was suggested that I can
inform the system that this failure occured by doing
IoRaiseHardError. I’ve gotten “ryo.zip” and examined it, but
it is a little different because it doesn’t use a usermode service.

Ok fine. BUT, It dawned on me that when I complete the
original IRP, the system will free the MDL associated with
it, so I can’t expect it to be around for my own IRP to use.

Am I correct in thinking that I must get a new buffer, copy
the original buffer into it, alloc a MDL and stuff that into
my new IRP->Mdl? Is this the best (only?) way to get around
this thread-deadlock issue?

Thanks for your comments/suggestions.

Regards,

Greg


You are currently subscribed to ntfsd as:
xxxxx@KernelDrivers.com To unsubscribe send a blank email to
%%email.unsub%%

Hi Pete!

Thanks for the reply - Yes, the communications between the FSD and the
usermode service is an inverted IOCtl interface. The usermode service
tries to do WriteFile() to write the flushed data.

TIA

Greg

Peter -

Thanks for pointing out the (now, to me) obvious. I don’t need to Roll My
Own Irp - I’ll complete it before sending the usermode service the
request.

I wish there was a better way to tell the user that there was an error
after the fact, besides IoRaiseHardError - but If this is what I must do,
then so be it.

Thanks again!

Greg

Greg,
A question I would have is why don’t you flush the data from kernel mode? Still queue it to an async worker but avoid the user service all together.

Of course, there may be other reasons why you are doing it this way.

Pete

Pete -

I wish I could do that; but our usermode thingy writes the data out in a
special format so it can eventually be written to our special hardware.
It’s a pain, but it had to be done this way.

I’ve got this thing mostly coded now - I’ll see what happens today!
Thanks for you help!

Regards,

Greg

Hi Pete (and anyone else),

If I make a copy of an IRP then complete the original, can I rely on the
FileObject pointer still being good, or should I create another file
object and use that instead?

Thanks - Greg

Hi Pete (and everyone else),

> If I make a copy of an IRP then complete the original,
> can I rely on the FileObject pointer still being good,
> or should I create another file object and use that instead?

I forgot to add that my copy of the IRP wont be re-dispatched by IO Mgr -
I’ll post it to one of my worker threads, process it, then free it myself.

Regards,

Greg

If you are only saving the buffer contents, along with some context information, then you shouldn’t need to make an entirely new irp, should you?

If you must allocate a new irp, then you need to reference the fileobject so it isn’t closed while you are using it. Remember that after a cleanup is issued on a fileobject, only limited request types can be issued using it, namely read/write requests.

Pete

Pete -

Oh wow! - I’ll have to increment the reference count on the file object -
I hadn’t thought of that…

I think I do need to make a copy of the IRP and post it to my own worker
thread, because my worker thread will pull an IRP out of the queue to pass
back into the write routine when it gets dispatched.

I’m thinking that I need to queue the NEW IRP to my worker thread, then
complete the original IRP AND return to the OS from my driver. This is
because it would still be running in the context of the MPW thread if I
complete the orig. irp prior to calling my user-mode service.

Am I correct in this thinking?

A newbie, still confused…

Thanks!

Greg

My point is that if you are just passing a buffer along with the filename, say, then you don’t need to allocate a new irp. Simply allocate a structure and ‘queue’ this to your worker which, in turn, will pass it to your user service.

I used the filename above assuming that your user service is obtaining a handle in some manner but this could be whatever you are using to access the file from the user service.

Hope this helps,

Pete

Hi everyone -

Thanks Pete, for helping get my FSD past the deadlock. I’ve done
basically what you have suggested by creating my own IRP (if it the MPW
thread calling), then queueing the new one to my FSPDispatch routine.
This works great, except for one nagging problem.

I can’t figure out how to use IoRaiseInformationalHardError to tell the
application if there is an error. I save the callers thread address, then
if I get an error, I make this call. It pops up a window, but doesn’t
stop the application from continuing to write. In this case the
application in Explorer.

IoRaiseInformationalHardError wants the thread address of the thread that
should receive the error, no? I tried getting this address (using
PsGetCurrentThread) Several different ways. I saved the MPW thread
address, (this didn’t make sense to me, but I tried it anyway), and I
tried saving the original write request IRP’s thread address (the one that
gets written to cache), and I tried saving the thread’s address that
issued the open for the write, all to no avail.

Which thread address should I save to give back?

Thanks and regards,

Greg

I forgot to add this:

To prevent this deadlock, When I complete the original MPW IRP and return,
should I complete it with status_success, and fill in the info field with
the number of bytes (that will be) written, or should it be
status_pending, with info field eq to zero?

How’s that for a run-on sentence!

Thanks again

Greg

With status_success and the corrent length in the info field. That is if you want to. If you return a failure, you will see the popup.

Pete

Pete,

I do complete the IRP with status_success and the amount to be written,
but how do I get the application that generated the write request to stop
with IoRaiseInformationalHardError? I don’t know which thread to send the
error to.

When my IRP is processed in my worker thread, the original thread may be
long gone!

Thanks

Greg

I’m not sure what you’re trying to accomplish here, but you could suspend or terminate all of the threads of the offending process. You can get the list of threads belonging to a process from either the performance data or an undocumented system call, NtQuerySystemInformation.

-----Original Message-----
From: Greg Pearce [mailto:xxxxx@filetek.com]
Sent: Wednesday, September 11, 2002 1:35 PM
To: File Systems Developers
Subject: [ntfsd] RE: “Rolling My Own IRP” - Is this the way to go?

Pete,

I do complete the IRP with status_success and the amount to be written,
but how do I get the application that generated the write request to stop
with IoRaiseInformationalHardError? I don’t know which thread to send the
error to.

When my IRP is processed in my worker thread, the original thread may be
long gone!

Thanks

Greg


You are currently subscribed to ntfsd as: xxxxx@inin.com
To unsubscribe send a blank email to %%email.unsub%%

Such are the issues when dealing with failures on delayed writes. By the
time the paging write occurs, the original owner may be gone.

One suggestion is to have your user service post a dialog since it is in
user mode and it does know if the final write fails or not. I would
recommend also using direct to media IO from the user service to
minimize additional points of failure.

Pete

Peter Scott
xxxxx@KernelDrivers.com
www.KernelDrivers.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Greg Pearce
Sent: Wednesday, September 11, 2002 12:35 PM
To: File Systems Developers
Subject: [ntfsd] RE: “Rolling My Own IRP” - Is this the way to go?

Pete,

I do complete the IRP with status_success and the amount to be written,
but how do I get the application that generated the write request to
stop
with IoRaiseInformationalHardError? I don’t know which thread to send
the
error to.

When my IRP is processed in my worker thread, the original thread may be
long gone!

Thanks

Greg


You are currently subscribed to ntfsd as: xxxxx@KernelDrivers.com
To unsubscribe send a blank email to %%email.unsub%%