IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES

I am observing a strange problem. I have some data that needs to be flushed
to a disk file just before VSS commits the snapshot. The setup:

  1. Volume filter driver.
  2. Driver has open file handle.
  3. Driver sends FSCTL_MARK_HANDLE and locks the clusters from being moved.
  4. Driver stores files retrieval pointers in device extension.
  5. When the driver needs to read or write to/from the file, it is done via
    IoBuildSynchronousFsdRequest() IRP_MJ_READ/WRITE from/to the appropriate
    clusters on the volume below the filter (from a system thread). This is
    working flawless until:

On IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES, before sending the IRP down to the
target, the driver does one last flush (waiting for the thread to finish),
and the writes to the target device fail with c0000225. They actually start
failing shortly after IOCTL_VOLSNAP_PREPARE_FOR_SNAPSHOT; just before
IOCTL_VOLSAP_FLUSH_AND_HOLD_WRITES. Everything is moving along fine, lots
of IO occurring via the filter, and then all of a sudden, the writes begin
to fail.

I would expect the target under the filter to accept the write requests
since I have not sent the FLUSH_AND_HOLD_WRITES down yet. Isn’t that sort
of the purpose of a flush? The reason for doing the direct cluster IO is to
avoid and locking issues with the file system precisely during
FLUSH_AND_HOLD.

Am I missing something here? Shouldn’t this work?

I am observing a strange problem. I have some data that needs to be flushed
to a disk file just before VSS commits the snapshot. The setup:

  1. Volume filter driver.
  2. Driver has open file handle.
  3. Driver sends FSCTL_MARK_HANDLE and locks the clusters from being moved.
  4. Driver stores files retrieval pointers in device extension.
  5. When the driver needs to read or write to/from the file, it is done via
    IoBuildSynchronousFsdRequest() IRP_MJ_READ/WRITE from/to the appropriate
    clusters on the volume below the filter (from a system thread). This is
    working flawless until:

On IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES, before sending the IRP down to the
target, the driver does one last flush (waiting for the thread to finish),
and the writes to the target device fail with c0000225. They actually start
failing shortly after IOCTL_VOLSNAP_PREPARE_FOR_SNAPSHOT; just before
IOCTL_VOLSAP_FLUSH_AND_HOLD_WRITES. Everything is moving along fine, lots
of IO occurring via the filter, and then all of a sudden, the writes begin
to fail.

I would expect the target under the filter to accept the write requests
since I have not sent the FLUSH_AND_HOLD_WRITES down yet. Isn’t that sort
of the purpose of a flush? The reason for doing the direct cluster IO is to
avoid and locking issues with the file system precisely during
FLUSH_AND_HOLD.

Am I missing something here? Shouldn’t this work?

From MSDN:

A driver may choose to flush data while holding this IRP containing the
IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES IOCTL before passing it to lower-level
drivers. Any data flushed to the disk while holding this IOCTL before
sending the IRP to the next lower-level driver will be data available on
the resulting shadow copy.

On Wed, Jan 6, 2016 at 12:02 AM Jamey Kirby wrote:

> I am observing a strange problem. I have some data that needs to be
> flushed to a disk file just before VSS commits the snapshot. The setup:
>
> 0) Volume filter driver.
> 1) Driver has open file handle.
> 2) Driver sends FSCTL_MARK_HANDLE and locks the clusters from being moved.
> 3) Driver stores files retrieval pointers in device extension.
> 4) When the driver needs to read or write to/from the file, it is done via
> IoBuildSynchronousFsdRequest() IRP_MJ_READ/WRITE from/to the appropriate
> clusters on the volume below the filter (from a system thread). This is
> working flawless until:
>
> On IOCTL_VOLSNAP_FLUSH_AND_HOLD_WRITES, before sending the IRP down to the
> target, the driver does one last flush (waiting for the thread to finish),
> and the writes to the target device fail with c0000225. They actually start
> failing shortly after IOCTL_VOLSNAP_PREPARE_FOR_SNAPSHOT; just before
> IOCTL_VOLSAP_FLUSH_AND_HOLD_WRITES. Everything is moving along fine, lots
> of IO occurring via the filter, and then all of a sudden, the writes begin
> to fail.
>
> I would expect the target under the filter to accept the write requests
> since I have not sent the FLUSH_AND_HOLD_WRITES down yet. Isn’t that sort
> of the purpose of a flush? The reason for doing the direct cluster IO is to
> avoid and locking issues with the file system precisely during
> FLUSH_AND_HOLD.
>
> Am I missing something here? Shouldn’t this work?
>
>

Did the write requests fail in volsnap, or in ntfs driver? I think ntfs handles only IOCTL_VOLSNAP_FLUSH_*/RELEASE requests, PREPARE IOCTL shouldn’t be forwarded down to the stack.

Also when you receive file’s retrieval pointers, why do you still use IoBuildSynchronousFsd- API instead forwarding the IRP to disk’s layer?

I am maintaining a metadata file that gets updated on each write to the
disk. So, I get a write to cluster 100,000. I let the write proceed. I then
post a queued item to a system thread to update my metadata file to let me
know that cluster 100000 was written to.
My alternate solution it to update the metadata in the write path, but I
want to reduce head trashing so that I do not impose a delay in the write
path.
The PREPARE IOCTL does get sent to my volume, but that is too early.
The write fails under my volume filter (volsnap). I have no filter on top
of the FSD, only on top of the volume disk device.

On Wed, Jan 6, 2016 at 9:26 AM Petr Kurtin wrote:

> Did the write requests fail in volsnap, or in ntfs driver? I think ntfs
> handles only IOCTL_VOLSNAP_FLUSH_*/RELEASE requests, PREPARE IOCTL
> shouldn’t be forwarded down to the stack.
>
>
>
> Also when you receive file’s retrieval pointers, why do you still use
> IoBuildSynchronousFsd- API instead forwarding the IRP to disk’s layer?
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: <
> http://www.osronline.com/showlists.cfm?list=ntdev&gt;
>
> 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://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

STATUS_NOT_FOUND (0xC0000225) is a strange error to get for a write. Have you determined which driver is failing the IRP with that status? (I usually do this by setting an access breakpoint on Irp->IoStatus.Status, assuming that I can narrow things down that much)

-scott
OSR
@OSRDrivers