AcquireForModWrite/ReleaseForModWrite

My FSD does not implement a AcquireForModWrite/ReleaseForModWrite routines.

Recently we have been testing large file copy transfers from a Windows NFS product. I’m pretty sure this product only lives in user space, listens on the typical NFS ports, and translates NFS protocols into local writes.

Come in this morning after doing a weekend long test and my writes appeared to be hung. I fired up ProcMon and I saw a ton of calls into my virtual drive from System for
FASTIO_ACQUIRE_FOR_MOD_WRITE. All of these calls were getting a CANT WAIT code and it never stopped. Reading a nice little NTInsider article, it appears we are OK since we use the standard NT locking mechanism (ExAcquireResourceXXXX on Fcb->Header.Resource) A lot of this code is duplicated from CDFS btw.

In any case, the thing I see as bizzare is the offset reported by ProcMon for FASTIO_ACQUIRE_FOR_MOD_WRITE. On 64-bit Machines, its 18,446,737,888,987,347,952 and on 32-bit Machines its 9,702,377,320,705,244,344.
Is this wrong or is MPW just saying it wants access to the whole file? Looks like a bit flipped negative to me.

If this is OK then, I can’t figure why the CANT WAIT happened. We don’t allow FAST IO for any writes, so should I just implement those callbacks and return STATUS_INVALID_DEVICE_REQUEST?

It’s relatively rare for a standard load to ever cause the mod writer to
fire - there is a test in IFSTEST which seems to do it, but that’s about it.
Also, AFAIK (and I’ll happily be contradicted) the last MS supported
(writeable) filesystem which didn’t have the modwriter calls was retired
some time prior to Win2K, so it could be that Modwriter can adapated to
expect these calls (I must admit that I always implement them out of sheer
habit).

When you say:

[call for] FASTIO_ACQUIRE_FOR_MOD_WRITE. All of these calls were getting a
CANT WAIT code

Do you mean that the OS (not you) is converting the lack of implementation
into that? As I am sure you know, that status is the (non documented) one
that the FSDs use to tell the modwriter that now is a really bad time to be
doing a modwrite (“Not now, Mommy’s busy”). If that’s the case then it
feels like either a bug or a gap in the documentation.

Again, its just habit but I hate relying on the structural black magic that
is ADVANCED_FCB_HEADER, so I’d bite the bullet and implement the locking
calls (return STATUS_SUCCESS by the way since you want things to carry on).
You might prefer to implement the calls via
FsRtlRegisterFileSystemFilterCallbacks (yes an FSD can call this).

I can guarantee that you do *not* have to implement the FastIO Write calls…

/Rod

wrote in message news:xxxxx@ntfsd…

My FSD does not implement a AcquireForModWrite/ReleaseForModWrite routines.

Recently we have been testing large file copy transfers from a Windows NFS
product.
I’m pretty sure this product only lives in user space, listens on the
typical NFS ports,
and translates NFS protocols into local writes.

Come in this morning after doing a weekend long test and my writes appeared
to be
hung. I fired up ProcMon and I saw a ton of calls into my virtual drive
from System for
FASTIO_ACQUIRE_FOR_MOD_WRITE. All of these calls were getting a CANT WAIT
code and it never stopped. Reading a nice little NTInsider article, it
appears we are
OK since we use the standard NT locking mechanism (ExAcquireResourceXXXX
on
Fcb->Header.Resource) A lot of this code is duplicated from CDFS btw.

In any case, the thing I see as bizzare is the offset reported by ProcMon
for FASTIO_ACQUIRE_FOR_MOD_WRITE. On 64-bit Machines, its
18,446,737,888,987,347,952 and on 32-bit Machines its
9,702,377,320,705,244,344. Is this wrong or is MPW just saying
it wants access to the whole file? Looks like a bit flipped negative to me.

If this is OK then, I can’t figure why the CANT WAIT happened. We don’t
allow FAST IO for any writes, so should I just implement those callbacks
and return STATUS_INVALID_DEVICE_REQUEST?

> Do you mean that the OS (not you) is converting the lack of implementation into that?

Yes, that’s exactly right.

I’m not sure what is causing the mod writer to fire. This O/S is W2K8, and I’ve seen it fire on both 32-bit and 64-bit versions (Its not R2 either.) But I know it only fires with a larger file (multi MB). I tried taking the NFS app out of it and simply generating a large file using my own data generator, which uses CreateFile and doesn’t MMAP explicitly, and get the exact same behavior. What’s equally weird is, shouldn’t I see it issuing an IRP for WriteFile from System? I see it acquire the lock, then release the lock with nothing in between. However, after releasing it, System calls SetEndOfFileInformationFile.

In any case, I’m now looking to implement the callbacks but am slightly fuzzy on what I need to do. I compared our Write functions to FastFat from the latest DDK and we acquire locks in pretty much the same way, but none of the examples implement those 2 callbacks. And we differ where our AcquireFcbForLazyWrite acquires the PagingIO resource exclusively.

On top of that, when should I return STATUS_CANT_WAIT? Those other callbacks have a Wait param. Should I try to acquire the resource exclusively on my own, but don’t ever block, so if it fails, I return STATUS_CANT_WAIT?

I just tried implementing the function both ways, i.e. acquiring the PagingIo resource exclusive and shared, and returning STATUS_CANT_WAIT if I can’t acquire the resource immediately. In the exclusive case, at the end of the write of file I see a AcquireForCcFlush (another callback we don’t implement) call, followed by indefinite amount of Acquire(Release)ForModWrite and no actual WriteFile. In the shared case, it worked for a few files, but eventually at the end of the file I then see again an indefinite amount of Acquire(Release)ForModWrite. I then tried implementing AcquireForCcFlush/ReleaseForCcFlush and got a complete deadlock.

I’ll have to sort this out, but is there any advice on how and which resources I need to acquire? I have Nagar’s book, but there aren’t any examples for these two functions.

> On top of that, when should I return STATUS_CANT_WAIT? Those other callbacks have a Wait

param. Should I try to acquire the resource exclusively on my own, but don’t ever block, so if it fails, I
return STATUS_CANT_WAIT?

Yes.

I think this is how most FSD locking calls work.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com