From: Anand A. <ana...@gm...> - 2012-09-26 17:49:50
|
On Fri, Sep 21, 2012 at 8:14 AM, Miklos Szeredi <mi...@sz...> wrote: > Kelly Smith <kel...@sb...> writes: > > > Hi, > > > > I am trying to build a POSIX-compliant filesystem using FUSE, however, I > > am running into a problem because release() is called asynchronous to > > the user’s close() operation. I am using fuse 2.7.4, which I know isn’t > > recent, but a search of the mailing list and a ‘net search seems to show > > that this issue has not been resolved yet. > > > > I found this thread regarding asynchronous release: > > > > > http://sourceforge.net/mailarchive/forum.php?thread_name=87wslu4dq9.fsf%40frosties.localdomain&forum_name=fuse-devel > > > > Unfortunately, with an asynchronous release(), rsync on my filesystem > > does not work without the --inplace option, because by default rsync > > creates the destination file in a temporary location via > > open-write...-close, then does a rename of the file to the proper > > destination. Because my filesystem does write buffering, the close() > > must also do a final flush. But that may not happen before the rename > > occurs, in which case I am left with an incomplete file. > > > > I do not know how to fix this problem in my filesystem. I'd be glad to > > hear any suggestions for how I can fix this, otherwise it seems that the > > only solution is to make release() synchronous. > > Use the ->flush method, which is called synchronously from close(2). > > ->flush does not solve all problems. It only indicates one file "descriptor" was closed. In the simplest of the examples: if I do a "dd if=/dev/zero of=/mnt/fuse/file", the first step performed by dd is "dup (3, 1); close (3)" -- which causes ->flush() invoked on the fuse_file. After doing its job dd performs "close (1)" which causes another ->flush() to be invoked on the fuse_file. After the second ->flush(), sure enough, ->release() is called as well. >From a filesystem point of view, how do I differentiate the first flush and the second flush? Because of this we are forced to perform cleanup in ->release(). Now ->flush() is sufficient to handle the standard fcntl() and flock() semantics of doing cleanup (with proper lkowner setting). But for the filesystem's internal leases and oplocks (not leases requested by the app), there is a gap between the second ->flush() and the ->release() where we are exposed to a race where the application performs a close() on the file, but the internal lease is not yet released before another app "rightfully" tries to access the file. I am not sure about the side effects of making ->release() synchronous, but that is one way of solving this problem. Avati |