FILE_NO_INTERMEDIATE_BUFFERING & IRP_SYNCHRONOUS_PAGING_IO flags

Hello.

I’m working on minifilter driver. I’m interested in IOs to/from HDD with IRP_NOCACHE flag set on (I use this flag, because I’m not interested in IOs to/from cache manager).

Few days ago I noticed strange behaviour on one of my setups with Windows 2012R2, about which I want to ask you guys.

The scenario is:

  1. Create empty file in cached directory with name file1.txt
  2. xcopy file0.txt file1.txt /E /J /Y
    Important is that /J parameter force xcopy to work in unbuffered mode.
    File0.txt is existing file.

I observe requests which comes to file1.txt in step 2 of the scenario which I wrote and something weird happen:

  1. Post IRP_MJ_CREATE callback comes with Data->Iopb-Parameters.Create.Options flag FILE_NO_INTERMEDIATE_BUFFERING (which looks correct, because we write in unbuffered mode to this file)
  2. Pre IRP_MJ_WRITE callback comes with offset X and length Y with IRP_NOCACHE flag and buffer full of “valid” data (which also looks correct)
  3. Post IRP_MJ_WRITE callback comes with Data->IoStatus.Status == STATUS_SUCCESS and Data->IoStatus.Information == Y (so it looks like this data was correctly written into HDD)
  4. Pre IRP_MJ_WRITE callback comes with offset X and length Y/2 with IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO flags and buffer full of zeroes (for me this data doesn’t look correct)
  5. Post IRP_MJ_WRITE callback comes with Data->IoStatus.Status == STATUS_SUCCESS and Data->IoStatus.Information == Y/2 (so it looks like this data was correctly written into HDD)
    In next steps there?s no more writes (with IRP_NOCACHE flag) to area between offset X and length Y/2, but when I check file on HDD I have valid data in this area (so there?s no zeroes).

Buffer which I wrote about comes from Data->Iopb->Parameters.Write.Writebuffer or when it’s NULL from MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Write.MdlAddress).

It looks for me like a strange behavior. I?m not sure if I understand correctly, but I thought that IRP_SYNCHRONOUS_PAGING_IO comes when OS flush data from Windows Cache, but here we use unbuffered mode, so there shouldn?t be any data in Windows Cache, if I understand correctly.

I also try to do similar operations but without /J parameter in xcopy. It that case during Post IRP_MJ_CREATE callback flag FILE_NO_INTERMEDIATE_BUFFERING is not set and pre IRP_MJ_WRITE callback with IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO contains “valid” data.
So it looks like this issue only happen when we use unbuffered mode in userspace.

So I want to ask you, if this is something normal or this case is more complicated (maybe I should check also more flags to be sure, etc.).
I also want to know how should I handle data like that, should I treat them as “valid” or not.

Do you still see the same thing (namely step 4) if you restart the machine
between creating the file and xcopy-ing it (so to make sure there is no
cached view of the file around) ? I’m wondering if the tool you’re using to
create the file initializes the cache for it so then what you’re seeing in
step 4 is some sort of coherency flush ?

Thanks,
Alex.

On Mon, Jul 14, 2014 at 6:39 AM, wrote:

> Hello.
>
> I’m working on minifilter driver. I’m interested in IOs to/from HDD with
> IRP_NOCACHE flag set on (I use this flag, because I’m not interested in IOs
> to/from cache manager).
>
> Few days ago I noticed strange behaviour on one of my setups with Windows
> 2012R2, about which I want to ask you guys.
>
> The scenario is:
> 1. Create empty file in cached directory with name file1.txt
> 2. xcopy file0.txt file1.txt /E /J /Y
> Important is that /J parameter force xcopy to work in unbuffered mode.
> File0.txt is existing file.
>
> I observe requests which comes to file1.txt in step 2 of the scenario
> which I wrote and something weird happen:
> 1. Post IRP_MJ_CREATE callback comes with
> Data->Iopb-Parameters.Create.Options flag FILE_NO_INTERMEDIATE_BUFFERING
> (which looks correct, because we write in unbuffered mode to this file)
> 2. Pre IRP_MJ_WRITE callback comes with offset X and length Y with
> IRP_NOCACHE flag and buffer full of “valid” data (which also looks correct)
> 3. Post IRP_MJ_WRITE callback comes with Data->IoStatus.Status ==
> STATUS_SUCCESS and Data->IoStatus.Information == Y (so it looks like this
> data was correctly written into HDD)
> 4. Pre IRP_MJ_WRITE callback comes with offset X and length Y/2 with
> IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO flags and buffer full
> of zeroes (for me this data doesn’t look correct)
> 5. Post IRP_MJ_WRITE callback comes with Data->IoStatus.Status ==
> STATUS_SUCCESS and Data->IoStatus.Information == Y/2 (so it looks like this
> data was correctly written into HDD)
> In next steps there?s no more writes (with IRP_NOCACHE flag) to area
> between offset X and length Y/2, but when I check file on HDD I have valid
> data in this area (so there?s no zeroes).
>
> Buffer which I wrote about comes from
> Data->Iopb->Parameters.Write.Writebuffer or when it’s NULL from
> MmGetSystemAddressForMdlSafe(Data->Iopb->Parameters.Write.MdlAddress).
>
> It looks for me like a strange behavior. I?m not sure if I understand
> correctly, but I thought that IRP_SYNCHRONOUS_PAGING_IO comes when OS flush
> data from Windows Cache, but here we use unbuffered mode, so there
> shouldn?t be any data in Windows Cache, if I understand correctly.
>
> I also try to do similar operations but without /J parameter in xcopy. It
> that case during Post IRP_MJ_CREATE callback flag
> FILE_NO_INTERMEDIATE_BUFFERING is not set and pre IRP_MJ_WRITE callback
> with IRP_NOCACHE, IRP_PAGING_IO, IRP_SYNCHRONOUS_PAGING_IO contains “valid”
> data.
> So it looks like this issue only happen when we use unbuffered mode in
> userspace.
>
> So I want to ask you, if this is something normal or this case is more
> complicated (maybe I should check also more flags to be sure, etc.).
> I also want to know how should I handle data like that, should I treat
> them as “valid” or not.
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

I didn’t try to restart machine between creating file and xcopy into this file. I tried to made some pause between this two steps.

When I made short pause (5 or 20 seconds) the issue was the same.

When I made longer pause (50 seconds) it looks like that issue was gone (there was no more writes with IRP_SYNCHRONOUS_PAGING_IO after create with FILE_NO_INTERMEDIATE_BUFFERING flag).