DokanOptions.MountManager: Bad interaction between ProjFS and Dokan

76 views
Skip to first unread message

Hans Olav Norheim

unread,
Jun 24, 2021, 5:22:47 PM6/24/21
to Dokan
[For some reason my replies to the other thread are automatically deleted so starting a new thread.]

When using DokanOptions.MountManager and a mount point (not a drive letter), there's a bad interaction between PrjFlt (ProjFS's filter driver) and Dokan. Specifically, when PrjFlt is attached to a volume, SET_REPARSE_POINT calls from dokan1.sys fails and the reparse point is not attached. The following is visible in Event Viewer:

SendDirectoryFsctl - ZwFsControlFile Code 900AC on "\??\C:\DokanMirror" failed

I am not sure if the bug is in ProjFS or Dokan. Liryna, would you be able to take a look and we can escalate to the ProjFS maintainers if necessary (I have contacts and can help with that).

Here are full repro instructions:

1. Create a clean Windows 10 VM using Quick create in Hyper-V.
2. Enable ProjFS: Enable-WindowsOptionalFeature -Online -FeatureName Client-ProjFS -NoRestart
3. Install latest Dokan.
4. Make target and mirror directories: 
    mkdir C:\DokanTarget
    mkdir C:\DokanMirror
    echo foo > C:\DokanTarget\foo.txt
5. Modify DokanNetMirror\Program.cs to specify DokanOptions.MountManager to Mount() and build. Copy bits to VM.
6. Launch DokanNetMirror.exe -what=C:\DokanTarget -where=C:\DokanMirror
7. Observe that foo.txt is mirrored:
>dir C:\DokanMirror
 Directory of C:\DokanMirror
06/24/2021  01:59 PM                 6 foo.txt

8. Exit DokanNetMirror.
9. Attach the ProjFS PrjFlt filter driver to a volume. Note that this would be done automatically by using ProjFS in a volume, this is just a simpler way to avoid having to build and launch the ProjFS sample app:
  
  fltmc attach PrjFlt C:
 
10. Re-launch DokanNetMirror with the same command line.
11. Observe C:\DokanMirror is empty because SET_REPARSE_POINT request from dokan1.sys failed, as is evidenced in the System event log:

  SendDirectoryFsctl - ZwFsControlFile Code 900AC on "\??\C:\DokanMirror" failed

- Hans

Adrien JUND

unread,
Jun 25, 2021, 3:46:48 AM6/25/21
to do...@googlegroups.com
Hi Hans,

Thanks for sharing the issue. Interesting that it is failing with the ProjFS filter.

You are right, the FSCTL_SET_REPARSE_POINT also fails on my VM after the filter is attached. The status returned is STATUS_FLT_INVALID_NAME_REQUEST that is probably returned by the filter driver.
I reviewed again how we build the REPARSE_DATA_BUFFER in case we missed something but it looks good to me https://github.com/dokan-dev/dokany/blob/31f8381e1efc207e7c02bdea0a47c819e9810c3f/sys/fscontrol.c#L525-L558
There is 0 FileSystem activity between the opening of the directory and calling ZwFsControlFile.

If you have the contacts, it might be the fastest way for us to know if we can improve the situation.

FYI it looks like from your logs that you have changed FSCTL_SET_REPARSE_POINT to FSCTL_SET_SPARSE.

--
You received this message because you are subscribed to the Google Groups "Dokan" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dokan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dokan/83cd5896-4bb0-443e-82b3-c164ea9fa623n%40googlegroups.com.
Message has been deleted
Message has been deleted
Message has been deleted
Message has been deleted

Hans Olav Norheim

unread,
Jun 28, 2021, 1:26:35 PM6/28/21
to Dokan
I have escalated to the maintainers - will keep you posted.

But on the Dokan side - should we make Mount() throw when this occurs? Today the error is swallowed and the user mode library just sits there receiving no activity when the mount in reality failed.

I did not change  FSCTL_SET_REPARSE_POINT - where did you see this?

Adrien JUND

unread,
Jul 4, 2021, 2:26:21 PM7/4/21
to do...@googlegroups.com

Yes, we should definitely make Mount() throw an error when this occurs.
For now the status is just ignored here https://github.com/dokan-dev/dokany/blob/4208150968d650cc4102c07b715b4c9658c42afb/sys/event.c#L904-L906



>I did not change  FSCTL_SET_REPARSE_POINT - where did you see this?

From your log, I was expecting 900a4 for FSCTL_SET_REPARSE_POINT but it is 900AC is for FSCTL_DELETE_REPARSE_POINT my bad.

Thank you again for looking into this!

--
You received this message because you are subscribed to a topic in the Google Groups "Dokan" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dokan/TKVtXow3_w0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dokan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dokan/f486d217-58da-4d34-86c0-55aa0c2b39d9n%40googlegroups.com.

Adrien JUND

unread,
Sep 30, 2021, 1:42:13 PM9/30/21
to do...@googlegroups.com
Hi,

I will hopefully be able to work on this in the next weeks.
Have you been able to get a response from the ProjFs team?

Best regards,
Liryna

Hans Olav Norheim

unread,
Oct 2, 2021, 4:40:16 PM10/2/21
to do...@googlegroups.com

Hi,

 

Yes, I heard back from them. They found the problem and has made a fix to ProjFS. It will ship in a future version of Windows so we may still want to investigate fixes from the Dokan side. This is what the ProjFS dev said:

 

The problem is that Dokan unconditionally sets top-level IRP before sending any IRP down the stack. Setting top-level IRP is a signal to Filter Manager that locks may be held above it, so it is not safe to query the file system for the file’s name. I’m not sure why Dokan does this though since it isn’t holding locks here. It also would interfere with any minifilter that queries names, which is most of them.

For PrjFlt, being unable to query the file path prevents it from being able to tell whether the caller is trying turn a directory into a virtualization root when it has a descendant that is already one, or the caller is trying to create a virtualization root inside an existing one. Either of those things is illegal and would cause runtime problems.

We could narrow the check so that if we’re unable to query the name we fail only if the incoming reparse tag is one of ours. That’d fix this specific issue since the reparse point being set doesn’t belong to ProjFS: it is IO_REPARSE_TAG_MOUNT_POINT to mount the Dokan volume to C:\DokanMirror.

 

- Hans

Adrien JUND

unread,
Oct 4, 2021, 9:39:06 PM10/4/21
to do...@googlegroups.com
Thanks Hans. This is very valuable!
I will look into this when I will do the other change.

Best regards,
Liryna

You received this message because you are subscribed to the Google Groups "Dokan" group.
To unsubscribe from this group and stop receiving emails from it, send an email to dokan+un...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/dokan/MWHPR22MB0861E8633E1248141D9171ABABAC9%40MWHPR22MB0861.namprd22.prod.outlook.com.

Adrien JUND

unread,
Nov 23, 2021, 1:02:04 PM11/23/21
to do...@googlegroups.com
Hi Hans,

I just pushed 2 commit that handle the ProjFs conflict and cleanup the mount resources on failure.
I will try to get a signed release during the week.

Sorry for the delay again

Best regards,
Liryna
Reply all
Reply to author
Forward
0 new messages