New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rclone mount: race condition with multiple RWFileHandle's #2034
Comments
I have to say I've been kind of ignoring the multiple file opens on the same file problem and hoping it will never happen :-)
OK, so assume we put a mutex in File for the use of Handles. We should probably use it in Open and close() If close() decided it didn't need to transfer the file then it should exit as it currently does. However if it did need to transfer the file and there were other writers then it should set a pending transfer flag in the File object and exit for the next close() to check. How does something like that sound? |
You never heard of Murphy's law, don't you? 😆
I'm not sure whether open needs to be protected by the same mutex. Only file.addWriter and file.delWriter should need to be synchronized. This is a list of functions i think need to be synchronized:
And now the part how this works in my head 😄 openPending needs to be synchronized to other openPending of the same file, so only one copy gets downloaded. A open with O_TRUNC could cancel a running copy and clear the cache file. RWFileHandle.close is mostly run with file.muClose held. file.delWriter is called to determine whether this handle was the last writer and when this is true do a operations.CopyFile to upload the cache file. Now file.muClose is released and cache.close is called, which removes the cache file when no reader is present. It's pretty late here, so i can not guarantee this locking scheme is complete. I will look at it again tomorrow. |
I think openPending should probably be synchronized to close also, so
Do you see there being a separate download phase which is running without the (Aside: one thing I'd like to do at some point is run the download in the background in
Though note not all the close() operations do transfer the file.
I think it is an excellent start :-) I think for the next evolution we should try to keep the changes as minimal as possible even if it is less than perfectly efficient - that has been my strategy in the VFS layer, correctness over efficiency. Not always achieved though! |
A download is only done once per cache file (this is how it should work) and close is doing an openPending. This way only one can happen at the same time. I want to make sure open and close use separate locks to allow the cache file to be opened while being uploaded.
This was just an idea which could speed up the open process in case the file get's opened with O_TRUNC, while another handle is downloading it.
Right, only when the last writer is closing and the cache file has be modified. The modified flag count be passed via the delWriter call like this:
You are right, the vfs layer is pretty complicated. As it is mostly working great we should be careful to not break any existing use case. I will start working today on the changes we outlined until now. |
OK
Oh I see... You'd have to block if it wasn't opened with truncate though. I guess if opened read only you are OK, but if not then I guess you have to block until the upload has finished otherwise? Getting complicated :-)
Looks perfect.
There are some exhaustive tests for the RW handles, however there aren't any tests for concurrent opens, so it might be worth writing some of those first, see them break then fix them!
Excellent :-) |
Following the forum thread Extracting to ACD mount possible? I'm now creating this issue.
I found a race condition involving multiple open
*vfs.RWFileHandle
's for one file.This is a log containing a failed upload: rclone_extract_ptr_empty.log. The state after this log is the following:
I assume the problem is
*vfs.RWFileHandle.close()
not being synchronized between multiple files.The log file above shows two
close()
executing in parallel.The first
RWFileHandle
belongs to a new empty file. The second one the handle being written to. During theclose()
of the first handle, the empty cache file getsMove
'ed to the backend. After the move is completed the cache file get's deleted.When the second
close()
tries to move the cache file, which is already gone.This could also be related to #1181.
I think,
close()
should check whether there is anotherRWFileHandle
opened for it's file. Hopefully this fixes the race condition.rclone v1.39-096-gcf6d522d
Linux 4.14.13-1-ARCH #1 SMP PREEMPT Wed Jan 10 11:14:50 UTC 2018 x86_64 GNU/Linux
Google Drive
rclone mount -vv --dir-cache-time 24h --vfs-cache-mode writes TestDrive:Test/JD /mnt/JD/extracted
The text was updated successfully, but these errors were encountered: