A process can check to see if a file has a lock on any data in the file by using F_GETLK with fcntl(). The l_pid field of the flock structure may be used under certain conditions with F_GETLK to return the process ID of the process holding the lock. Existing applications commonly use the l_pid returned to kill the process holding the lock, thereby releasing the lock.
In a network environment, processes may be running on different nodes. Consider what would happen if the l_pid returned refers to a process on another node. An application might kill an innocent process on its own node. This situation arises because F_GETLK with fcntl() is being used in an environment for which it was not designed. This is a semantic issue because the semantics of traditional Unix and IEEE 1003.1-1990 must be modified to avoid this situation.
There are several ways to modify the semantics of fcntl() to deal with this problem. One way would be to have a process ID space which would span several systems on a network, i.e., a given pid would uniquely identify both the process and the system on which the process runs. Then, a pid applied to a kill() could correctly signal the intended process. Another approach would be to have a unique process ID value which could refer to a process ``not known to the system.'' When this unique value for pid is used as an argument to kill() (or any other function which takes pid as an argument), the function would return an error.
Demonstrations were developed using an NFS implementation to illustrate for
different client/server configurations what happens when a file is locked
and F_GETLK with fcntl() is used to show the value of
l_pid returned. Figure 2.1 illustrates how the
demonstration proceeds.
Commands are displayed in italics and the output
of those commands is displayed in bold.
The program setlock locks an entire file, waits for a newline,
and then unlocks the
file. The program getlock uses F_GETLK to show the value
of l_pid returned for different client/server configurations.
Source code for the demonstration programs (setlock.c and
getlock.c) is located in
Appendix
. For the following demonstrations, Process A is
the program setlock, Process B is the program getlock, and
testfile is the file which is locked.
In addition to Process A and Process B, another process
on the system running Process A uses the ``ps'' command to confirm that
the value for l_pid returned
by Process B is indeed the process ID of Process A.
Note that in these demonstrations, the Status Monitor and the Lock
Manager must be running on both the client and the server.
Table 2.1 illustrates the use of Processes A and B in four different client/server configurations as follows:
Figure: l_pid returned by fcntl() demonstration procedure.
Process A and Process B are on the same client and testfile is remote to both processes. Process A locks testfile and Process B gets the process ID of the process holding the lock on testfile. In this case, the l_pid returned is indeed the process ID of Process A, the process holding the lock on testfile. Notice that for the NFS implementation, the correct l_pid is returned even though the file is remote.
The file testfile is remote to Process A and local to Process B. Process A on the client locks testfile. Process B on the server gets the process ID of the process holding the lock on testfile. The l_pid returned to Process B on the server is the correct process ID of Process A on the client. Even though the correct l_pid is returned on the server, the process ID does not refer to a process on the server node. Traditional Unix semantics do not enable a process to be aware that the l_pid returned in this case is on another network node.
The file testfile is local to Process A and remote to Process B. Process A on the server locks testfile and Process B on the client obtains the l_pid of the remote process holding the lock on testfile. The correct l_pid for Process A is returned but as in the previous case, Process B may not be aware that Process A is a process on another system.
The file testfile is remote to both Process A and Process B. Process A on Client A locks testfile. Process B on Client B gets the l_pid of the remote process holding the lock on testfile. The correct l_pid is returned. As in the previous two cases, the l_pid identifies Process A but does not identify the system on which Process A is running.
The NFS implementation makes F_GETLK and l_pid work correctly in all cases. This is accomplished by two additional protocols, the Lock Manager protocol and the Status Monitor protocol, used in conjunction with NFS. The Status Monitor protocol permits both clients and servers to be aware of what systems are up and running. The Status Monitor informs interested applications when a system failure occurs on a system which it is monitoring. The Lock Manager protocol implements record locking on NFS mounted file systems. A process on a remote system locking a file is identified by the Lock Manager and that value is returned by fcntl(). However, fcntl() does not identify the system on which the process holding the lock is running.