Skip to content
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

Internal file locking (MainResource, PagingIoResource) should be refined #7

Open
billziss-gh opened this issue Apr 26, 2016 · 3 comments

Comments

@billziss-gh
Copy link
Collaborator

Originally reported by: Bill Zissimopoulos (Bitbucket: billziss, GitHub: billziss-gh)


Internal file locking (MainResource, PagingIoResource) is currently rather crude. In particular the PagingIoResource should only be acquired exclusively when the file size is changed (truncated). In all other cases the PagingIoResource should be acquired shared or not at all.

An important message regarding this subject from Maxim S. Shatskih at the end of this thread: http://www.osronline.com/showthread.cfm?link=275592


@fsgeek
Copy link

fsgeek commented Feb 19, 2017

Honestly, I've become less and less convinced over the years that its worth serializing the truncation in this fashion because you have to deal with paging I/O beyond EOF anyway.

There are race conditions between paging I/O and file size changes and the way NTFS (and FAT) deal with this is to return STATUS_SUCCESS with a write length of zero. So what's the benefit of serialization down this path then?

@billziss-gh
Copy link
Collaborator Author

@fsgeek thank you for your comments. Your expertise in these matters is invaluable.

When I was first designing the WinFsp locking model, I struggled to understand the roles of MainResource and PagingIoResource by studying the FastFat source code. I eventually developed a mental model of how FastFast does things, but by that time I had already implemented most of WinFsp using a different locking model where the PagingIoResource is taken whenever the WinFsp FSD reaches out to the user mode file system.

However in the current WinFsp state, I believe that every time the PagingIoResource is acquired, the MainResource has already been acquired. This makes acquiring the PagingIoResource on top of the MainResource useless.

I logged this issue for two reasons:

  1. To see if it was possible to emulate in WinFsp how FastFat handles locking.

  2. To eliminate use of the PagingIoResource if I was not successful at (1).

Your comments suggest that even if (1) is possible, it may not be worthwhile. I have come to similar conclusions.

@fsgeek
Copy link

fsgeek commented Feb 20, 2017

FastFat's locking was never intended to support highly parallel activity and the locking interface, such as it is, reflects the increasingly nuanced handling of locking. For example, the callbacks for Mm actually provide you with a high water mark, so you don't have to guarantee no truncation, just no truncation below a certain threshold.

The real issue for the paging I/O resource is the risk of performing allocation in the paging write path, since allocation could involve performing potentially complex operations. So they split it into two separate steps: allocation and then writing. If you can handle doing allocation in the paging write path, you're fine.

Hence how NTFS (and FAT) end up dealing with this situation: if you are doing paging I/O then you don't extend the file because it means that it's been truncated since it was extended. The one exception there might be for the lazy writer thread, though even there it probably doesn't matter.

In some of the work I've done in the past (in an isolation filter) we didn't hold locks across calls to the underlying file system and what we found is that "just deal with it" is a viable approach to an area in which there are already inherent race conditions.

Note, by "locking interface" I mean the mish-mash of calls inherent in the fast I/O interface, the Cc callbacks, and the default rules around grabbing ERESOURCE locks inside the common header (which is not good engineering practice!)

NTFS (for example) actually registers filter callbacks (!) because it provides more nuanced control and the ability to reject file mapping requests. NTFS is not, however, a filter. Then again, we see all sorts of OS components calling Filter Manager to resolve names as well. The encapsulation module for the functionality was insufficiently broad, but since it's available, people call it anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants