microsoft / ProjFS-Managed-API

A managed-code API for the Windows Projected File System
Other
142 stars 34 forks source link

ProjFS doesn't allow deletion of virtualization root directory #36

Open grossag opened 5 years ago

grossag commented 5 years ago

Note: I tried finding a ProjFS category in Feedback Hub because https://github.com/Microsoft/VFSForGit/issues/504 mentioned that one was in progress, but I couldn't find it.

Repro steps (I am running on Win10 1903):

  1. Add a virtualization root.
  2. Go into Explorer and try to delete the folder.

Expected results: I had expected ProjFS to support root deletion, specifically sending a PRJ_NOTIFICATION_PRE_DELETE for the root context so I can shut down my virtualization provider and return success or optionally block the deletion using an error code. Actual results: Other than one directory enumeration callback, I don't receive a callback in my provider and Explorer shows an "unexpected error" dialog showing error code 0x80070032

This is important for my project because I am working on using ProjFS to virtualize my company's build output. I want to developers to be able to delete the root virtualization directory to do a completely clean build, but that doesn't work right now. Their workaround would be to run "rm -rf build/*" but that is confusing.

wilbaker commented 5 years ago

Transferring this issue to ProjFS-Managed-API

grossag commented 5 years ago

I was mistaken on part of the initial bug description because I hadn't subscribed for pre-deletion notifications. This may end up being more of an "is it supported" documentation type question instead of an actual defect.

I have found that if I subscribe to pre-deletion notifications, I do receive one for FilePathName "" if I try to delete the root virtualization directory. However, I can't fulfill it immediately in that notification function by calling PrjStopVirtualizing because that causes a deadlock somewhere in the ProjFS code. But I do need stop virtualizing very quickly after the callback or I will risk the deletion failing. That said, I have found that I can do the following to support deletion of the root context:

  1. Return HRESULT_FROM_WIN32(ERROR_IO_PENDING) from the notification callback in response to PRJ_NOTIFICATION_PRE_DELETE.
  2. Handle deletion asynchronously on another thread by calling the following in rapid succession: (1) PrjCompleteCommand with the commandId from the PRE_DELETE notification and (2) PrjStopVirtualizing.

I would think that this is open to race conditions because I need the PrjStopVirtualizing call to go through quickly or else the deletion will fail. But I don't know how serious those race conditions are yet until I write some automated tests.

I am wondering, is this the best way to support deletion of the root virtualization directory? Or is there a better way somehow?

cgallred commented 5 years ago

@grossag, deleting the virtualization root while the provider is running isn't really supported. Currently the supported scenario for deleting the root itself is to stop the provider (PrjStopVirtualizing()) and then rm -rf <root>. I can see the value in your scenario though. It is something we can consider supporting in a future update.

BTW, we do have a Feedback Hub category. You should be able to find it under category "Developer Platform", subcategory "Projected File System (ProjFS)".

grossag commented 5 years ago

Thanks @cgallred . I posted https://aka.ms/AA6066c in case it helps. I do hope that this can be supported; otherwise I have to design some sort of out-of-band way for a developer to signal my component to stop virtualizing the directory.

grossag commented 4 years ago

1 year since I posted that request in Feedback Hub and no response there :(