Comments (7)
Ok, after playing around with this, I think I see what is happening, though I still have a question towards the bottom and it would be helpful to know if I missed something...
It looks like Utils.TryGetOnDiskFileState() will invoke GetPlaceholderInfo() to test if the file exists in the backing store (if needed), and it then uses that (in combination with what it knows about the local file, if anything) to return false in all situations where an application should treat the file as not existing, which include:
- No local file, no backing store file
- No local file, backing store has file but there is a local tombstone (user deleted "virtual" file locally)
... else it will return true.
Does that sound correct?
Also, assuming that is correct, my remaining question is ... under what circumstance would Utils.TryGetOnDiskFileState() return OnDiskFileState.Tombstone?
Thanks
from projfs-managed-api.
Utils.TryGetOnDiskFileState()
will only return OnDiskFileState.Tombstone
when the provider is not running. That routine is really not meant to be used by a running provider. It is a utility routine meant for use by tools. A provider that needs to know whether a file has been deleted needs to register for NotificationType.FileHandleClosedFileDeleted
and use that to keep track of what's been deleted.
What Utils.TryGetOnDiskFileState()
does is try to open the file at the given path and query the contents of its reparse point, if any. If the file doesn't exist on disk then you'll see GetPlaceholderInfo()
called (this is why the documentation for Utils.TryGetOnDiskFileState()
says that a running provider needs to be careful calling it because "it may cause callbacks to be invoked in the provider").
In the case of a tombstone you have a file on disk with a special "tombstone" reparse point. Utils.TryGetOnDiskFileState()
will open that tombstone file, see that it is a tombstone, and report OnDiskFileState.Tombstone
.
However there is a caveat. The job of a tombstone is to make it look like there's nothing there, but there are certain circumstances where we need to be able to reveal the tombstone's existence. For instance, if you want do rmdir /s
on your virtualization root we can't very well keep hiding the tombstones or you'd never be able to delete them. So when the ProjFS file system filter driver sees an attempt to open a tombstone it checks to see whether the provider that owns the tombstone is running. If so, it makes it look like there's nothing there. Otherwise it allows the tombstone to be opened (and thus deleted). The filter driver can't tell the difference between an open issued by Utils.TryGetOnDiskFileState()
and any other random open, which is why Utils.TryGetOnDiskFileState()
won't report OnDiskFileState.Tombstone
while the provider that owns the tombstone is running.
from projfs-managed-api.
Thanks for the clarification and additional info!
It is unfortunate that there isn't a way to query the VirtualizationInstance for its understanding of the local file state (only - so no callback invocation), since it is the source of truth for that, while I am already the source of truth for the backing store (so I don't need to necessarily know what my own GetPlaceholder callback says, for example).
If I were to go the notification route where I have to handle and persist the notion of all files the user has deleted, I fear it is fragile, as my process can be killed before I get a change to handle and persist all notifications. Further, users can delete things while my process isn't running ... which suggests I'd need to scan the NTFS journal to catch up/find missed notifications or something.
Not insurmountable, just annoying, especially since that local file state I want must be readily available to you just on the other side of that api fence ;)
Thanks again for your prompt and detailed response!
from projfs-managed-api.
I just remembered that there might be a different direction you could approach this. If you use FindFirstFileEx with the FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY
flag (and then of course FindNextFileW) you'll get an enumeration of only what is on disk. That is, it will not return any virtual files and the results will contain any tombstones that might be present.
- The WIN32_FIND_DATAW structures that you get back report the reparse tag, if any, in the
dwReserved0
member if "the dwFileAttributes member includes the FILE_ATTRIBUTE_REPARSE_POINT attribute". - A tombstone will have the reparse point tag value of
IO_REPARSE_TAG_PROJFS_TOMBSTONE
(0xA0000022).
The issue of how to handle modifications to the virtualization root while the provider isn't running still exists, but even if Utils.TryGetOnDiskFileState()
could tell you about tombstones when the provider is running it wouldn't help. A tombstone is only created if your provider is running when the file is deleted. That's because to create a tombstone ProjFS has to know whether or not the file being deleted exists in the provider's backing store. If it does not, then there's no reason for ProjFS to create a tombstone. If the provider is not running when the delete happens, then ProjFS can't ask the provider whether the file exists in the backing store. So the file is simply deleted. When the provider comes back up it is re-projected as if it had never been hydrated in the first place.
from projfs-managed-api.
Ah, that sounds interesting, I'll give that a try.
Also good info/point about deletions that happen when provider isn't running.
Thanks!
from projfs-managed-api.
I finally got around to playing with this today.
I think this will be useful/helpful!
One thing I wasn't expecting, though, is that this does still invoke GetPlaceholderInfo() callbacks on the sub-directories between the virtualization root and the parent directory of the file/directory passed to FindFirstFileEx() ... my ideal would be for it to just return ERROR_PATH_NOT_FOUND or error 369 (provider unavailable) if the subdirectory doesn't exist locally and has no placeholder, but this still will greatly reduce the number of placeholders requested/cached in my use case.
Is that expected?
Actually, given that behavior, I suppose I could query each subdirectory myself, stopping as soon as one is not found, to prevent any placeholders from being created...
Thanks again!
from projfs-managed-api.
This is expected. The FIND_FIRST_EX_ON_DISK_ENTRIES_ONLY
flag only applies to the actual enumeration, not to the NtOpenFile
call that FindFirstFileEx
issues to get a handle to the directory that is going to be enumerated.
That is an interesting suggestion though, and I can see how that behavior would be more consistent. I'll put it on my backlog for future consideration.
from projfs-managed-api.
Related Issues (20)
- PrjGetOnDiskFileState not available? HOT 4
- Is there a way to clean up ProjFS placeholders/markup without deleting everything? HOT 2
- Pure virtual file system (without any kind of caching/hydrating) HOT 4
- Is there a way to retrieve the ProviderId and ContentId from a placeholder? HOT 3
- HResult.Handle result code from WriteFileData() and left a hydrated placeholder in a bad state? HOT 2
- After closing SimpleProviderManager artifacts are left behind in the virtual root HOT 1
- PreConvertToFull handler not notified HOT 1
- Revert full state file keeping it hydrated HOT 2
- Document C++ runtime as prerequisite HOT 3
- Proper way to handle renaming placeholder files HOT 3
- Odd file behavior in virtual branches, perhaps after installing Windows Updates HOT 13
- The build agent needs an upgrade to build against the new ProjFS API
- DirectoryEnumerationResults.Add symlink override is incompatible with EnumerateFileSystemInfos on .NET Framework HOT 1
- Why are NuGet packages for this library no longer updated? HOT 1
- This repo is missing important files
- Compiling with Visual Studio 2022 : Change ProjectedFSLib.Managed.Props HOT 1
- Section on BadImageFormatExceptions also applies to FileNotFoundExceptions
- windows 10 projected file system issues
- Upgrade to .NET 8 from .NET Core 3.1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from projfs-managed-api.