I have become suspicious of Section 0 of /usr/src/linux/Documentation/filesystems/mandatory-locking.txt.<br><br>I am going to tell this as it unfolded, so that if I went wrong somewhere you can point it out to me.<br><br>For some time I have been lecturing in computer science at the local public university. Last term, I had<br>
75 students for "Systems Programming", and we reach a point about 2 weeks from the end where the<br>topics become more or less optional, because the students have already been told the things necessary<br>for all of the programming assignments. This time I had decided to go a bit beyond my own familiarity<br>
and lecture on file locking, down to mandatory locks.<br><br>Naturally, wanting to get the details right, I did some browsing of documentation. It seems the Stevens &<br>Rago text that I'm using has a pretty good section on file locking in the Advanced I/O chapter, and it agreed<br>
with what I had expected well enough. But I found a reference to this file mentioned above, and was<br>shocked to find it began with a warning to avoid this feature. It seemed it was like the BUGS section of<br>the linux man page for the gets() function: do not use gets. I gave up on this topic, but told my students<br>
about it.<br><br>Here is the section of concern:<br><br>> 15 April 1996 <br>
> (Updated September 2007) <br>> <br>
> 0. Why you should avoid mandatory locking <br>> ----------------------------------------- <br>
> <br>> The Linux implementation is prey to a number of difficult-to-fix race <br>
> conditions which in practice make it not dependable: <br>> <br>
> - The write system call checks for a mandatory lock only once <br>> at its start. It is therefore possible for a lock request to <br>
> be granted after this check but before the data is modified. <br>> A process may then see file data change even while a mandatory <br>
> lock was held. <br>> - Similarly, an exclusive lock may be granted on a file after <br>
> the kernel has decided to proceed with a read, but before the <br>> read has actually completed, and the reading process may see <br>
> the file data in a state which should not have been visible <br>> to it. <br>
> - Similar races make the claimed mutual exclusion between lock <br>> and mmap similarly unreliable. <br>
<br>But it nagged at me. For one thing, it seems pretty horrible to provide a fix for a synchronization feature that<br>introduces race conditions. UGH. Moreover, it doesn't seem hard to fix: I can think of two approaches<br>
that both seem workable:<br> 1) Make mandatory locks mandatory: that is, disallow any file operation on a section of the file that is<br>not locked by the invoking process.<br> 2) Actually lock any such section of the file on behalf of the process, and release the lock when done.<br>
<br>Both have some details to be worked out, but it doesn't strike me as anything like impossible.<br><br>But I'm not the only guy on the planet who has done stuff like this before, but here's this warning that's<br>
been there in one form or another for at least 15 years, and the feature has not been fixed. What's<br>wrong with this picture? Does nobody in his right mind use mandatory locking? Is the entire universe<br>of competent programmers too busy with something else? I had to think things through, which had to<br>
wait for the end of the term.<br><br>First, my impression of the relevant history is that advisory locks were upgraded to mandatory to deal with<br>the possibility of a race with a program that was not properly locking a file before access. The race<br>
conditions in mandatory locking arise only in the same circumstances -- a program is issuing file operations<br>without owning a lock. Is this a legitimate concern?<br><br>The fcntl() locks were introduced to support database operations. In most databases I've seen deployed,<br>
system administrators arrange to protect the database files from access other than through the database.<br>So while there is certainly a lot of bad code out there, I would expect the database engine itself to do<br>proper locking on all operations, or else that the database will be heaped with scorn and promptly thrown<br>
away. Likewise system admins who don't protect their crucial files should be treated similarly.<br><br>It is true that there's a lot of bad code out there, but any project that is using locks at all is showing some<br>
effort to "get it right", and it should be easy to make the locking easily verifiable. Even advisory locks<br>should be sufficient if all operations are performed under such a lock.<br><br>So here's the question: This short bit of documentation prevented my class from hearing about an<br>
important feature of Unix OSen. I think something should be done, but I'm not sure just what. The<br>likely candidates are:<br> 1) Fix that section 0 so it tells the whole truth, and change its heading to something like "Cautions<br>
and concerns to observe when using advisory or mandatory locks."<br> 2) Fix the race conditions and ditch section 0, using some method -- maybe one of my suggestions<br> above.<br> 3) Somebody points out that I've misunderstood the situation, proves it, and tells me to go away.<br>
As things now stand, I'm upset that section 0 exists in the current form. I only hope I'm the only<br>fool who got misled by it.<br><br>I eagerly await reactions and advice.<br><br>-- <br>Kevin O'Gorman, PhD<br>
<br>