Chapter 11. File LockingSection 7.5, "File locking", we introduced the concept of file locking and the two primary components: the RPC lock daemon and the status monitor. This chapter will delve more deeply into file locking and will examine the administrative aspects.
11.1. What is file locking?File locking is the act of ensuring that when you access a file, usually via a software application, no one can change the file until you are done examining it. If you want to modify the file, then file locking ensures that no one else can examine or modify the file until you are done modifying it.
The earliest versions of Unix had no way to lock files except to create lock files. The idea is that two or more processes would more or less simultaneously try to create a lock file in exclusive mode, via the O_EXCL flag of the open( ) system call. The operating system would return success to the process that won the race, and a "file exists" error to losing processes. One problem with this scheme is that it relies on the winning process to remove the lock file before it exits. If the process is running buggy software, this might not happen. Some applications mitigate this problem by recording the process ID of the winner into the contents of the lock file. A process that finds that it gets a "file exists" error can then read the lock file to see if the owning process is still running.
Still, lock files can be clumsy. In the 1980s, Unix versions were released with file locking support built into the operating system. The System V branch of Unix offered file locking via the fcntl( ) system call, whereas the BSD branch provided the flock( ) system call. In both cases, when the process that creates the lock dies, the lock will be automatically released.
11.1.1. Exclusive and shared locksBoth fcntl and flock give the choice of either an exclusive lock, where only one process could hold the lock, or a shared lock, where multiple holders could simultaneously exist, to the exclusion of holders of the exclusive lock. The exclusive lock is sometimes called a "single writer" lock, because its exclusive nature lends itself to allowing safe writes to a file. The shared lock is sometimes called a "multiple readers" lock because its shared nature lends itself to allowing multiple safe reads of a file.
11.1.2. Record locksThe fcntl system call also has the feature of byte range record locking. This means that the application can partition a file into as many arbitrarily sized segments or records that it wants, and by specifying a file offset and length, lock them. Thus, it is possible to have both an exclusive lock and a shared lock on a file, provided the file offsets and lengths of each record lock do not overlap.
11.1.3. Mandatory versus advisory lockingBoth fcntl and flock offer advisory locking. Advisory locking is locking that requires the cooperation of participating processes. Suppose process A acquires an exclusive lock on the file, with the intent to write it. Suppose process B opens the file with the intent to write it. If process B fails to acquire a lock, there is nothing to prevent it from issuing a write system call and corrupting the process that A is writing. For this reason, advisory locking is sometimes called unenforced locking.
System V (and therefore Solaris) offers mandatory or enforced locking as an option. This option is enabled if mandatory lock permissions are set on a file. Mandatory lock permissions are an overload of the set group ID execution bit (02000 in octal). If the set group ID execution bit is set, and if the group execution bit is not set, then all reads and writes to the file will use enforced locking. So, for example:
This makes file example readable and writable by the file's owner, and readable by everyone else. The appearance of the l in the first field of the output of the ls command tells you that mandatory locking is enabled. Of course, you can use any combination of read or write permissions for the file's owner, group, and world.% chmod 2644 example % ls -l example -rw-r-lr-- 1 mre staff 9 Dec 28 10:52 example
If the mandatory lock permissions are set on a file, then every write( ) or read( ) system call results in an implicit sequence of:
What if the process has already acquired a lock by an explicit fcntl call? If the range locked is equal to or encompasses the range the read or write is done on, then no implicit pair of fcntl calls are done. If the range explicitly locked partly overlaps the range read or write will do, then implicit fcntl calls are done on the unlocked portion of the range.fcntl(...); /* lock the file at the range we are reading or writing */ read(...); /* or */ write(...); fcntl(...); /* unlock the file at the range locked above */
Mandatory locking seems very useful, but it is open to denial of service attacks. Suppose mandatory lock permissions are set on a file. An attacker named Mallet decides to issue an fcntl call to get an exclusive lock on the entire file. Bob now tries to read the file and finds that his application hangs. A proponent of mandatory locking might point out that the mistake was in allowing the file to be accessible by Mallet (if Mallet can't open the file, he can't lock it). The counter argument is that if you are going to rely on permissions to avoid a denial of service (and restricted permissions are a good thing to have for critical applications), then the set of users who can access the file is limited to those with a vested interest in avoiding denial of service. In that case, mandatory locking is no more useful than advisory locking.
11.1.4. Windows/NT locking schemeThe discussion so far has been about Unix locking paradigms. The Windows world has a different paradigm. There are two major differences between Unix and Windows locking:
TIP: Share reservations in the Windows world do not interact at all with Windows byte range or whole file locking.
Copyright © 2002 O'Reilly & Associates. All rights reserved.