github / libprojfs

Linux projected filesystem library
GNU Lesser General Public License v2.1
92 stars 14 forks source link

Set initial projection state on backing store at first mount #71

Closed chrisd8088 closed 5 years ago

chrisd8088 commented 5 years ago

To utilize libprojfs with VFSForGit, we need client-managed mechanism by which to set the initial projection state on the top-level mount point directory. Currently, we do this in libprojfs by testing, at mount time, whether the mount point directory is empty.

However, when used with VFSForGit, we want to set the flag once sometime after the user runs gvfs clone, at which point the directory will already have .git and .gitattributes in it, so our default check_dir_empty() test will not work.

A simple fix is to have the VFSForGit C# code "manually" set the user.projection.empty flag to y on the directory after gvfs clone runs. But this breaks our API abstraction, which assumes this flag is managed by libprojfs.

From the libprojfs perspective, an option which aligns well with libfuse is to accept an args array of option arguments, which are parsed at the time the FUSE filesystem handle is created. Similarly, our projfs_new() function could accept a list of arguments to parse, including (potentially) supported FUSE arguments like -o debug which could be passed down to fuse_new() instead of our current fixed compile-time argument array to FUSE.

If we implement such an option (e.g., -o init or --initial-mount or something like that) following, for instance, the example of the libfuse mount utility, then we will want to pass an additional bool "initial mount" flag argument to StartVirtualizationInstance() which can be converted into the appropriate argument array and passed down to projfs_new().

To determine the value of this flag will be an interesting effort, since we do not want to set it on every gvfs mount operation, only the first one. Two options present themselves:

  1. Perform a call to StartVirtualizationInstance() at the end of gvfs clone, perhaps in the TryPrepareFolderForCallbacks() method which is run at the very end of the CloneVerb process.
  2. At the start of the gvfs mount process, check whether the .gvfs/lower directory contains only .git and .gitattributes, and if so, set the "initial mount" flag to the StartVirtualizationInstance() call.

I am personally inclined toward the second option, as it effectively lifts the "is this directory empty" logic up to the client program's level, where it can determine if the directory is empty according to its own rules (in this case, if it only has the expected post-clone contents), and because it should avoid the need for a full mount/unmount cycle at the end of the cloning step, which feels like a more fragile solution overall.

See also github/VFSForGit#20.

kivikakk commented 5 years ago

I am personally inclined toward the second option, as it effectively lifts the "is this directory empty" logic up to the client program's level, where it can determine if the directory is empty according to its own rules (in this case, if it only has the expected post-clone contents), and because it should avoid the need for a full mount/unmount cycle at the end of the cloning step, which feels like a more fragile solution overall.

This sounds most correct to me 👍