FltWriteFile returns STATUS_FILE_LOCK_CONFLICT

Hi all,
I should explain a part of my design because it might be related to the error.

in precreate depending on the file content I may decide to reparse to another file or not.

in prewrite depending on the new file content I might decide to write to the reparsed file (let the write to complete with no interference) or write to original file handle before reparse and complete the request preventing it from writing to the reparsed file.

*The handle to the original file was created before reparse using FltCreateFile and passed trough ecp and streamhandle context to prewrite.

I can reference the filObject and read the content using FltReadFile but I can’t have a successful call to FltWriteFile in precreate neither in postCreate.

can someone guide me what the problem can be?

let me add that I only operate on non cached IOs

You indicate you are performing these requests in pre and post create
yet you point out that you are only operating on non-cached IO? Are you
issuing the FltWriteFile() requests as non-cached requests? Or are you
issuing them in the context of a non-cached IO in pre write?

Lock_Conflict can arise when you are attempting to forward a paging IO
to a different file that, for some reason, has an active resource lock
taken on it. Are you propagating the same flags for the IO in
FltWriteFile as you receive in the original request such as paging and
non-cached?

Pete


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

------ Original Message ------
From: xxxxx@yahoo.com
To: “Windows File Systems Devs Interest List”
Sent: 2/11/2017 5:18:12 AM
Subject: [ntfsd] FltWriteFile returns STATUS_FILE_LOCK_CONFLICT

>Hi all,
>I should explain a part of my design because it might be related to the
>error.
>
>in precreate depending on the file content I may decide to reparse to
>another file or not.
>
>in prewrite depending on the new file content I might decide to write
>to the reparsed file (let the write to complete with no interference)
>or write to original file handle before reparse and complete the
>request preventing it from writing to the reparsed file.
>
>*The handle to the original file was created before reparse using
>FltCreateFile and passed trough ecp and streamhandle context to
>prewrite.
>
>I can reference the filObject and read the content using FltReadFile
>but I can’t have a successful call to FltWriteFile in precreate neither
>in postCreate.
>
>can someone guide me what the problem can be?
>
>—
>NTFSD is sponsored by OSR
>
>
>MONTHLY seminars on crash dump analysis, WDF, Windows internals and
>software drivers!
>Details at http:
>
>To unsubscribe, visit the List Server section of OSR Online at
>http:</http:></http:>

Calling FltWriteFile on paging path is not a great idea. The Memory Manager(MM) of Cache Manager(CC) acquires file locks( usually ERESOURCE(s) via file system callbacks or directly from FCB header ) before issuing a paging IRP that the filter observes as a write request. So your filter initiates IO with file locks/resources being held. This scenario is prone to deadlocks and errors.

Hi Peter, thanks for the answer.

You indicate you are performing these requests in pre and post create
yet you point out that you are only operating on non-cached IO?

where I said :

I can reference the filObject and read the content using FltReadFile but I can’t
have a successful call to FltWriteFile in precreate neither in postCreate.

I mistakenly typed preCreate and postCreate! I do this in preWrite and postWrite.

My bad. sorry for that.

Are you propagating the same flags for the IO in FltWriteFile as you receive in the original request
such as paging and non-cached?

I have tested this matter against different situations. I filter out paging and cached IO in callback processing first. Also I skip IOs with no context present which means I only perform FltWriteFile on files I previously reparsed in preCreate. I called FltWriteFile with flag FLTFL_IO_OPERATION_DO_NOT_UPDATE_BYTE_OFFSET | FLTFL_IO_OPERATION_NON_CACHED
which is what you asked. it resulted to lock error(0xC0000054) but removing NON_CACHED flag removed the error. However I think I observed lock error with NON_CACHED removed as well. but I’m not sure about the later.

read this again if necessary.

in precreate depending on the file content I may decide to reparse to another
file or not.
in prewrite depending on the new file content I might decide to write to the
reparsed file (let the write to complete with no interference) or write to
original file before reparse and complete the request preventing it from
writing to the reparsed file.

Hi Slava, thanks for your answer as well.

I observed what you are saying trying to write to the same file in paging write callbackes caused to deadlock. But please note that my problem is a little different.
I am not writing to the file object in passed in PCFLT_RELATED_OBJECTS. I want to write to another file object.
please read this scenario again if necessary :

in precreate depending on the file content I may decide to reparse to another
file or not.

in prewrite depending on the new file content I might decide to write to the
reparsed file (let the write to complete with no interference) or write to
original file handle before reparse and complete the request preventing it from
writing to the reparsed file.

*The handle to the original file was created before reparse using FltCreateFile
and passed trough ecp and streamhandle context to prewrite.

I can reference the filObject and read the content using FltReadFile but I can’t
have a successful call to FltWriteFile in preWrite neither in postWrite.

BTW, I am not familiar with this locks at all. Can someone point me to some text to read?

Writing to another file object is what I was taking about. Your design violates a locking hierarchy. Practically you are doing the following

AcquireResourcesForFileA(); <- this is done by MM or CC via FSD callbacks
{
// a paging write is issued and received by a filter
FltWriteFile()
{
//
// in FSD dispatch
//
AcquireResourcesForFileB(); <– this is done by FSD
{
// Change file data and metadata
}
ReleaseResourcesForFileB();
}
}
ReleaseResourcesForFileA();

Google for AcquireForModWrite , AcquireForCcFlush and CACHE_MANAGER_CALLBACKS . In short, these are calbacks to a file system driver to maintain a correct locking hierarchy. They are required because the Memory Manager(MM) and Cache Manager(CC) are file system clients as they call file system dispatch routines to flush modified pages and in the same time file system is a client of MM and CC as it calls them for cached read/write, cleanup, set-file-size, PnP processing.

thanks for the details and reference Slava.
I will study more

A small question, are these locks applicable to writes only or the same situation exists for read as well?

Yes, there are read callbacks also. The idea, as I said, is to allow a file system driver to acquire resources in callback so CC or MM can maintain a locking hierarchy for file system and MM/CC locks.

There are two scenarios for both read and write requests

  • MM/CC calls FSD
  • FSD calls MM/CC

Without callbacks the former acquires MM/CC resources before FSD resources while the latter acquires FSD resources before MM/CC ones. The callbacks were introduced to allow FSD to acquire resources before MM/CC acquires their own resources in the first scenario.

@Slava,

I am reading and writing (to/from different file) with non cached flag in the pre operation of a callback for a non cached read and write.

It is implemented and works with no problem.

I think it should not work as you stated it won’t. Did I miss understand your answers or you believe it should not work yet?

You are taking things too literally.

You were warned that your solution might violate FSD locking hierarchy( and actually it does ).

Non cached read/write is a trap that makes you believe you are on a safe path. FSD is not obliged to process non-cached I/O in any way different from cached I/O. Only paging I/O makes the difference.

You can only safely initiate recursive IO to a paging file.

You can ship your driver as is if it passed your tests but be prepared to receive complaints from the customers with deadlocks on recursive IO.

Thanks for the clarification.