0% found this document useful (0 votes)
45 views12 pages

BSCS cs-511: Function Name Purpose and Operation

This document provides an overview of file and record locking in UNIX operating systems. It discusses advisory and mandatory locking, which allow processes to synchronize access to shared file data. Advisory locking relies on cooperation between processes, while mandatory locking is enforced by the operating system kernel. The document also describes read (shared) locks and write (exclusive) locks, which are used to control access to records within files. It provides examples of opening files and setting locks using various system calls and library functions.

Uploaded by

Aliza Saher
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
45 views12 pages

BSCS cs-511: Function Name Purpose and Operation

This document provides an overview of file and record locking in UNIX operating systems. It discusses advisory and mandatory locking, which allow processes to synchronize access to shared file data. Advisory locking relies on cooperation between processes, while mandatory locking is enforced by the operating system kernel. The document also describes read (shared) locks and write (exclusive) locks, which are used to control access to records within files. It provides examples of opening files and setting locks using various system calls and library functions.

Uploaded by

Aliza Saher
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 12

BSCS cs-511

Overview of File and Record Locking


Simultaneous access to file data is characteristic of many multiprocess, multithreaded, or real-time applications.The
purpose of the file and record locking facility is to provide a way for programs to synchronize their use of common file
data.
Advisory file and record locking can be used to coordinate independent, unrelated processes. In mandatory locking,
on the other hand, the standard I/O subroutines and I/O system calls enforce the locking protocol. Mandatory locking
keeps unrelated programs from accessing data out of sequence, at some cost of access speed.
The system functions used in file and record locking are summarized in Table 7-1.

Table 7-1. Functions for File and Record Locking


Function Name Purpose and Operation
fcntl(2), fcntl(5) General function for modifying an open file descriptor; can be used to
set file and record locks.
lockf(3C), lockf(3F) Library function to set and remove file and record locks on open files
(SVR4 compatible).
flock(3B) Library function to set and remove file and record locks on open files
(BSD compatible).
chmod(1), chmod(2) Command and system function that can enable mandatory file locking on
a specified file.

Record

A record is any contiguous sequence of bytes in a file. The UNIX operating system does not impose any record
structure on files. The boundaries of records are defined by the programs that use the files. Within a single file, a
record as defined by one process can overlap partially or completely on a record as defined by some other process.

Read (Shared) Lock

A read lock keeps a record from changing while one or more processes read the data. If a process holds a read lock,
it may assume that no other process can alter that record at the same time. A read lock is also a shared lock because
more than one process can place a read lock on the same record or on a record that overlaps a read-locked record.
No process, however, can have a write lock that overlaps a read lock.

Write (Exclusive) Lock

A write lock is used to gain complete control over a record. A write lock is an exclusive lock because, when a write
lock is in place on a record, no other process may read- or write-lock that record or any data that overlaps it. If a
process holds a write lock it can assume that no other process will read or write that record at the same time.
Advisory Locking

An advisory lock is visible only when a program explicitly tries to place a conflicting lock. An advisory lock is not
visible to the file I/O system functions such as read() and write(). A process that does not test for an advisory
lock can violate the terms of the lock, for example, by writing into a locked record.
Advisory locks are useful when all processes make an appropriate record lock request before performing any I/O
operation. When all processes use advisory locking, access to the locked data is controlled by the advisory lock
requests. The success of advisory locking depends on the cooperation of all processes in enforcing the locking
protocol; it is not enforced by the file I/O subsystem.

Mandatory Locking

Mandatory record locking is enforced by the file I/O system functions, and so is effective on unrelated processes that
are not part of a cooperating group. Respect for locked records is enforced by the creat(),open(), read(),
and write() system calls. When a record is locked, access to that record by any other process is restricted
according to the type of lock on the record. Cooperating processes should still request an appropriate record lock
before an I/O operation, but an additional check is made by IRIX before each I/O operation to ensure the record
locking protocol is being honored. Mandatory locking offers security against unplanned file use by unrelated
programs, but it imposes additional system overhead on access to the controlled files.

Lock Promotion and Demotion

A read lock can be promoted to write-lock status if no other process is holding a read lock in the same record. If
processes with pending write locks are waiting for the same record, the lock promotion succeeds and the other
(sleeping) processes wait. Demoting a write lock to a read lock can be done at any time.
Because the lockf() function does not support read locks, lock promotion is not applicable to locks set with that
call. >

Controlling File Access With File Permissions


The access permissions for each UNIX file control which users can read, write, or execute the file. These access
permissions may be set only by the owner of the file or by the super user. The permissions of the directory in which
the file resides can also affect the access permissions for a file. Note that if the permissions for a directory allow
anyone to write in the directory, and the “sticky bit” is not included in the permissions, files within that directory can be
removed even by a user who does not have read, write, or execute permission for those files.
If your application warrants the use of record locking, make sure that the permissions on your files and directories are
also set properly. A record lock, even a mandatory record lock, protects only the records that are locked, while they
are locked. Unlocked parts of the files can be corrupted if proper precautions are not taken.
Only a known set of programs or users should be able to read or write a database. This can be enforced through file
permissions as follows:
1. Using the chown facility (see the chown(1) and chown(2) reference pages), set the ownership of the
critical directories and files to reflect the authorized group ID.
2. Using the chmod facility (see also the chmod(1) and chmod(2) reference pages), set the file
permissions of the critical directories and files so that only members of the authorized group have write access
(“775” permissions).
3. Using the chown facility, set the accessing program executable files to be owned by the authorized group.
4. Using the chmod facility, set the set-GID bit for each accessing program executable file and to permit
execution by anyone (“2755” permissions).
Users who are not members of the authorized group cannot modify the critical directories and files. However, when
an ordinary user executes one of the accessing programs, the program automatically adopts the group ID of its
owner. The accessing program can create and modify files in the critical directory, but other programs started by an
ordinary user cannot.

Using Record Locking


This section covers the following topics:
 “Opening a File for Record Locking”
 “Setting a File Lock”
 “Setting and Removing Record Locks”
 “Getting Lock Information”
 “Deadlock Handling”

Opening a File for Record Locking


The first requirement for locking a file or segment of a file is having a valid open file descriptor. If read locks are to be
used, then the file must be opened with at least read access; likewise for write locks and write access.
Example 7-1 opens a file for both read and write access.
Example 7-1. Opening a File for Locked Use

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
int fd; /* file descriptor */
char *filename;
main(argc, argv)
int argc;
char *argv[];
{
extern void exit(), perror();
/* get database file name from command line and open the
* file for read and write access. 
*/
if (argc < 2) {
(void) fprintf(stderr, "usage: %s filename\n", argv[0]);
exit(2);
}
filename = argv[1];
fd = open(filename, O_RDWR);
if (fd < 0) {
perror(filename);
exit(2);
}
}

The file is now open to perform both locking and I/O functions. The next step is to set a lock.

Setting a File Lock


Several ways exist to set a lock on a file. These methods depend upon how the lock interacts with the rest of the
program. Issues of portability and performance need to be considered. Three methods for setting a lock are given
here: using the fcntl() system call; using the /usr/group standards-compatible lockf() library function; and
using the BSD compatible flock() library function.
Locking an entire file is just a special case of record locking—one record is locked, which has the size of the entire
file. The file is locked starting at a byte offset of zero and size of the maximum file size. This size is beyond any real
end-of-file so that no other lock can be placed on the file.
You have a choice of three functions for this operation: the basic fcntl(), the library function lockf(), and the
BSD compatible library function flock(). All three functions can interoperate. That is, a lock placed by one is
respected by the other two.

Whole-File Lock With fcntl()

The fcntl() function treats a lock length of 0 as meaning “size of file.” The


function lockWholeFile() in Example 7-2 attempts a specified number of times to obtain a whole-file lock
using fcntl(). When the lock is placed, it returns 0; otherwise it returns the error code for the failure.
Example 7-2. Setting a Whole-File Lock With fcntl()

#include <fcntl.h>
#include <errno.h>
#define MAX_TRY 10

int
lockWholeFile(int fd, int tries)
{
int limit = (tries)?tries:MAX_TRY;
int try;
struct flock lck;
lck.l_type = F_WRLCK;  /* write (exclusive) lock */
lck.l_whence = 0;  /* 0 offset for l_start */
lck.l_start = 0L;  /* lock starts at BOF */
lck.l_len = 0L;  /* extent is entire file */
for (try = 0; try < limit; ++try)
{
if ( 0 == fcntl(fd, F_SETLK, &lck) )
break; /* mission accomplished */
if ((errno != EAGAIN) && (errno != EACCES))
break; /* mission impossible */
sginap(1); /* let lock holder run */
}
return errno;
}

The following points should be noted in Example 7-2:


 Because fcntl() supports both read and write locks, the type of the lock (F_WRLCK) is specified in
the l_type.
 The operation code F_SETLK is used to request that the function return if it cannot place the lock. The code
F_SETLKW would request that the function suspend until the lock can be placed.
 The starting location of the record is the sum of two fields, l_whence and l_start. Both must be set to 0 in
order to get the starting point to the beginning of the file.

Whole-File Lock With lockf()

Example 7-3 shows a version of the lockWholeFile() function that uses lockf().


Like fcntl(), lockf() treats a record length of 0 as meaning “to end of file.”
Example 7-3. Setting a Whole-File Lock With lockf()

#include <unistd.h> /* for F_TLOCK */
#include <fcntl.h> /* for O_RDWR */
#include <errno.h> /* for EAGAIN */
#define MAX_TRY 10

int
lockWholeFile(int fd, int tries)
{
int limit = (tries)?tries:MAX_TRY;
int try;
lseek(fd,0L,SEEK_SET); /* set start of lock range */
for (try = 0; try < limit; ++try)
{
if (0 == lockf(fd, F_TLOCK, 0L) )
break; /* mission accomplished */
if (errno != EAGAIN)
break; /* mission impossible */
sginap(1); /* let lock holder run */
}
return errno;
}

The following points should be noted about Example 7-3:


 The type of lock is not specified, because lockf() only supports exclusive locks.
 The operation code F_TLOCK specifies that the function should return if the lock cannot be placed. The
F_LOCK operation would request that the function suspend until the lock could be placed.
 The start of the record is set implicitly by the current file position. That is why lseek() is called, to ensure
the correct file position before lockf() is called.

Whole-File Lock With flock()

Example 7-4 displays a third example of the lockWholeFile subroutine, this one using flock().


Example 7-4. Setting a Whole-File Lock With flock()

#define _BSD_COMPAT
#include <sys/file.h> /* includes fcntl.h */
#include <errno.h> /* for EAGAIN */
#define MAX_TRY 10
int
lockWholeFile(int fd, int tries)
{
int limit = (tries)?tries:MAX_TRY;
int try;
for (try = 0; try < limit; ++try)
{
if ( 0 == flock(fd, LOCK_EX+LOCK_NB) )
break; /* mission accomplished */
if (errno != EWOULDBLOCK)
break; /* mission impossible */
sginap(1); /* let lock holder run */
}
return errno;
}

The following points should be noted about Example 7-4:


 The compiler variable _BSD_COMPAT is defined in order to get BSD-compatible definitions from standard
header files.
 The only use of flock() is to lock an entire file, so there is no attempt to specify the start or length of a
record.
 The LOCK_NB flag requests the function to return if the lock cannot be placed. Without this flag the function
suspends until the lock can be placed.

Setting and Removing Record Locks


Locking a record is done the same way as locking a file, except that the record does not encompass the entire file
contents. This section examines an example problem of dealing with two records (which may be either in the same
file or in different files) that must be updated simultaneously so that other processes get a consistent view of the
information they contain. This type of problem occurs, for example, when updating the inter-record pointers in a
doubly linked list.
To deal with multiple locks, consider the following questions:
 What do you want to lock?
 For multiple locks, in what order do you want to lock and unlock the records?
 What do you do if you succeed in getting all the required locks?
 What do you do if you fail to get one or more locks?
In managing record locks, you must plan a failure strategy for the case in which you cannot obtain all the required
locks. It is because of contention for these records that you have decided to use record locking in the first place.
Different programs might
 wait a certain amount of time, and try again
 end the procedure and warn the user
 let the process sleep until signaled that the lock has been freed
 a combination of the above
Look now at the example of inserting an entry into a doubly linked list. All the following examples assume that a
record is declared as follows:

struct record {
.../* data portion of record */...
long prev; /* index to previous record in the list */
long next; /* index to next record in the list */
};

For the example, assume that the record after which the new record is to be inserted has a read lock on it already.
The lock on this record must be promoted to a write lock so that the record may be edited.Example 7-5 shows a
function that can be used for this.
Example 7-5. Record Locking With Promotion Using fcntl()

/*
|| This function is called with a file descriptor and the
|| offsets to three records in it: this, here, and next.
|| The caller is assumed to hold read locks on both here and next.
|| This function promotes these locks to write locks.
|| If write locks on "here" and "next" are obtained
|| Set a write lock on "this".
|| Return index to "this" record.
|| If any write lock is not obtained:
|| Restore read locks on "here" and "next".
|| Remove all other locks.
|| Return -1.
*/
long set3Locks(int fd, long this, long here, long next)
{
struct flock lck;
lck.l_type = F_WRLCK; /* setting a write lock */
lck.l_whence = 0; /* offsets are absolute */
lck.l_len = sizeof(struct record);
/* Promote the lock on "here" to write lock */
lck.l_start = here;
if (fcntl(fd, F_SETLKW, &lck) < 0) {
return (-1);
}
/* Lock "this" with write lock */
lck.l_start = this;
if (fcntl(fd, F_SETLKW, &lck) < 0) {
/* Failed to lock "this"; return "here" to read lock. */
lck.l_type = F_RDLCK;
lck.l_start = here;
(void) fcntl(fd, F_SETLKW, &lck);
return (-1);
}
/* Promote lock on "next" to write lock */
lck.l_start = next;
if (fcntl(fd, F_SETLKW, &lck) < 0) {
/* Failed to promote "next"; return "here" to read lock... */
lck.l_type = F_RDLCK;
lck.l_start = here;
(void) fcntl(fd, F_SETLK, &lck);
/* ...and remove lock on "this". */
lck.l_type = F_UNLCK;
lck.l_start = this;
(void) fcntl(fd, F_SETLK, &lck);
return (-1)
}
return (this);
}

Example 7-5 uses the F_SETLKW command to fcntl(), with the result that the calling process will sleep if there
are conflicting locks at any of the three points. If the F_SETLK command was used instead, the fcntl() system
calls would fail if blocked. The program would then have to be changed to handle the blocked condition in each of the
error return sections (as in Example 7-2).
It is possible to unlock or change the type of lock on a subsection of a previously set lock; this may cause an
additional lock (two locks for one system call) to be used by the operating system. This occurs if the subsection is
from the middle of the previously set lock.
Example 7-6 shows a similar example using the lockf() function. Since it does not support read locks, all (write)
locks are referenced generically as locks.
Example 7-6. Record Locking Using lockf()

/*
|| This function is called with a file descriptor and the
|| offsets to three records in it: this, here, and next.
|| The caller is assumed to hold no locks on any of the records.
|| This function tries to lock "here" and "next" using lockf().
|| If locks on "here" and "next" are obtained
|| Set a lock on "this".
|| Return index to "this" record.
|| If any lock is not obtained:
|| Remove all other locks.
|| Return -1.
*/
long set3Locks(int fd, long this, long here, long next)
{
/* Set a lock on "here" */
(void) lseek(fd, here, 0);
if (lockf(fd, F_LOCK, sizeof(struct record)) < 0) {
return (-1);
}
/* Lock "this" */
(void) lseek(fd, this, 0);
if (lockf(fd, F_LOCK, sizeof(struct record)) < 0) {
/* Failed to lock "this"; clear "here" lock. */
(void) lseek(fd, here, 0);
(void) lockf(fd, F_ULOCK, sizeof(struct record));
return (-1);
}
/* Lock "next" */
(void) lseek(fd, next, 0);
if (lockf(fd, F_LOCK, sizeof(struct record)) < 0) {
/* Failed to lock "next"; release "here"... */
(void) lseek(fd, here, 0);
(void) lockf(fd, F_ULOCK, sizeof(struct record));
/* ...and remove lock on "this". */
(void) lseek(fd, this, 0);
(void) lockf(fd, F_ULOCK, sizeof(struct record));
return (-1)
}
return (this);
}

Locks are removed in the same manner as they are set; only the lock type is different (F_UNLCK or F_ULOCK). An
unlock cannot be blocked by another process. An unlock can affect only locks that were placed by the unlocking
process.

Getting Lock Information


You can determine which processes, if any, are blocking a lock from being set. This can be used as a simple test or
as a means to find locks on a file. To find this information, set up a lock as in the previous examples and use the
F_GETLK command in the fcntl() call. If the lock passed to fcntl() would be blocked, the first blocking lock is
returned to the process through the structure passed to fcntl(). That is, the lock data passed to fcntl() is
overwritten by blocking lock information.
The returned information includes two pieces of data, l_pidf and l_sysid, that are used only with F_GETLK. These
fields uniquely identify the process holding the lock. (For systems that do not support a distributed architecture, the
value in l_sysid can be ignored.)
If a lock passed to fcntl() using the F_GETLK command is not blocked by another lock, the l_type field is
changed to F_UNLCK and the remaining fields in the structure are unaffected.
Example 7-7 shows how to use this capability to print all the records locked by other processes. Note that if several
read locks occur over the same record, only one of these is found.
Example 7-7. Detecting Contending Locks Using fcntl()

/*
|| This function takes a file descriptor and prints a report showing
|| all locks currently set on that file. The loop variable is the
|| l_start field of the flock structure. The function asks fcntl()
|| for the first lock that would block a lock from l_start to the end
|| of the file (l_len==0). When no lock would block such a lock,
|| the returned l_type contains F_UNLCK and the loop ends.
|| Otherwise the contending lock is displayed, l_start is set to
|| the end-point of that lock, and the loop repeats.
*/
void printAllLocksOn(int fd)
{
struct flock lck;
/* Find and print "write lock" blocked segments of file. */
(void) printf("sysid pid type start length\n");
lck.l_whence = 0;
lck.l_start = 0L;
lck.l_len = 0L;
for( lck.l_type = 0; lck.l_type != F_UNLCK; )
{
lck.l_type = F_WRLCK;
(void) fcntl(fd, F_GETLK, &lck);
if (lck.l_type != F_UNLCK)
{
(void) printf("%5d %5d %c %8d %8d\n",
lck.l_sysid,
lck.l_pid,
(lck.l_type == F_WRLCK) ? 'W' : 'R',
lck.l_start,
lck.l_len);
if (lck.l_len == 0)
break; /* this lock goes to end of file, stop */
lck.l_start += lck.l_len;
}
}
}

fcntl() with the F_GETLK command always returns correctly (that is, it will not sleep or fail) if the values passed
to it as arguments are valid.
The lockf() function with the F_TEST command can also be used to test if there is a process blocking a lock. This
function does not, however, return the information about where the lock actually is and which process owns the
lock. Example 7-8 shows a code fragment that uses lockf() to test for a lock on a file.
Example 7-8. Testing for Contending Lock Using lockf()

/* find a blocked record. */
/* seek to beginning of file */
(void) lseek(fd, 0, 0L);
/* set the size of the test region to zero
* to test until the end of the file address space.
*/
if (lockf(fd, F_TEST, 0L) < 0) {
switch (errno) {
case EACCES:
case EAGAIN:
(void) printf("file is locked by another process\n");
break;
case EBADF:
/* bad argument passed to lockf */
perror("lockf");
break;
default:
(void) printf("lockf: unknown error <%d>\n", errno);
break;
}
}

When a process forks, the child receives a copy of the file descriptors that the parent has opened. The parent and
child also share a common file pointer for each file. If the parent seeks to a point in the file, the child's file pointer is
also set to that location. Similarly, when a share group of processes is created using sproc(), and
the sproc() flag PR_SFDS is used to keep the open-file table synchronized for all processes (see
the sproc(2) reference page), then there is a single file pointer for each file and it is shared by every process in
the share group.
This feature has important implications when using record locking. The current value of the file pointer is used as the
reference for the offset of the beginning of the lock, in lockf() at all times and in fcntl()when using
an l_whence value of 1. Since there is no way to perform the sequence lseek(); fcntl(); as an atomic operation, there
is an obvious potential for race conditions—a lock might be set using a file pointer that was just changed by another
process.
The solution is to have the child process close and reopen the file. This creates a distinct file descriptor for the use of
that process. Another solution is to always use the fcntl() function for locking with anl_whence value of 0 or 2.
This makes the locking function independent of the file pointer (processes might still contend for the use of the file
pointer for other purposes such as direct-access input).

Deadlock Handling
A certain level of deadlock detection and avoidance is built into the record locking facility. This deadlock handling
provides the same level of protection granted by the /usr/group standard lockf() call. This deadlock detection is
valid only for processes that are locking files or records on a single system.
Deadlocks can potentially occur only when the system is about to put a record locking system call to sleep. A search
is made for constraint loops of processes that would cause the system call to sleep indefinitely. If such a situation is
found, the locking system call fails and sets errno to the deadlock error number.
If a process wishes to avoid using the system's deadlock detection, it should set its locks using F_GETLK instead of
F_GETLKW.

Enforcing Mandatory Locking


File locking is usually an in-memory service of the IRIX kernel. The kernel keeps a table of locks that have been
placed. Processes anywhere in the system update the table by calling fcntl() or lockf() to request locks.
When all processes that use a file do this, and respect the results, file integrity can be maintained.
It is possible to extend file locking by making it mandatory on all processes, whether or not they were designed to be
part of the cooperating group. Mandatory locking is enforced by the file I/O function calls. As a result, an independent
process that calls write() to update a locked record is blocked or receives an error code.
The write() and other system functions test for a contending lock on a file that has mandatory locking applied.
The test is made for every operation on that file. When the caller is a process that is cooperating in the lock, and has
already set an appropriate lock, the mandatory test is unnecessary overhead.
Mandatory locking is enforced on a file-by-file basis, triggered by a bit in the file inode that is set by chmod (see
the chmod(1) and chmod(2) reference pages). In order to enforce mandatory locking on a particular file, turn on
the set-group-ID bit along with a nonexecutable group permission, as in these examples, which are equivalent:

$ chmod 2644 target.file


$ chmod +l target.file

The bit must be set before the file is opened; a change has no effect on a file that is already open.
Example 7-9 shows a fragment of code that sets mandatory lock mode on a given filename.
Example 7-9. Setting Mandatory Locking Permission Bits

#include <sys/types.h>
#include <sys/stat.h>
int setMandatoryLocking(char *filename)
{
int mode;
struct stat buf;
if (stat(filename, &buf) < 0)
{
perror("stat(2)");
return error;
}
mode = buf.st_mode;
/* ensure group execute permission 0010 bit is off */
mode &= ~(S_IEXEC>>3);
/* turn on 'set group id bit' in mode */
mode |= S_ISGID;
if (chmod(filename, mode) < 0)
{
perror("chmod(2)");
return error;
}
return 0;
}

When IRIX opens a file, it checks to see whether both of two conditions are true:
 Set-group-ID bit is 1.
 Group execute permission is 0.
When both are true, the file is marked for mandatory locking, and each use of creat(), open(), read(),
and write() tests for contending locks.
Some points to remember about mandatory locking:
 Mandatory locking does not protect against file truncation with the truncate() function (see
the truncate(2) reference page), which does not look for locks on the truncated portion of the file.
 Mandatory locking protects only those portions of a file that are locked. Other portions of the file that are not
locked may be accessed according to normal UNIX system file permissions.
 Advisory locking is more efficient because a record lock check does not have to be performed for every I/O
request.

Record Locking Across Multiple Systems


Record locking is always effective within a single copy of the IRIX kernel. Locking is effective within a multiprocessor
because processes running in different CPUs of the multiprocessor share a single copy of the IRIX kernel.
Record locking can be effective on processes that execute in different systems that access a filesystem mounted
through NFS. However, there are these drawbacks:
 Deadlock detection is not possible between processes in different systems.
 You must make sure that the NFS locking daemon is running in both the NFS client (application) and server
systems.
 Using record locking on NFS files has a strong impact on performance.

NFS File Locking


When a process running in an NFS client system requests a file or record lock, a complex sequence of events
begins. (For details, consult the lockd(1M) reference page.)
First the kernel in the client system receives the lock request and determines that the file resides on a filesystem
mounted using NFS. The kernel sends the lock request to a daemon called rpc.lockd. This daemon is
responsible for communicating lock requests to other systems.
The rpc.lockd process sends the lock request to the rpc.lockd daemon running on the NFS server where the
target file is physically mounted. On the server, that rpc.lockd issues the lock request locally. The
server rpc.lockd sends the result, success or failure, back to the client rpc.lockd. The result is passed back
to the calling process.
When the lock succeeds on the server side, rpc.lockd on the client system requests another
daemon, rpc.statd, to monitor the NFS server that implements the lock. If the server fails and then
recovers,rpc.statd will be informed. It then tries to reestablish all active locks. If the NFS server fails and
recovers, and rpc.lockd is unable to reestablish a lock, it sends a signal (SIGUSR1) to the process that
requested the lock.
When a process writes to a write-locked record, the data is sent directly to the NFS server, bypassing the local NFS
buffer cache. This can have a significant impact on file performance.

Configuring NFS Locking


When rpc.lockd is not running in the NFS client system, or in the NFS server system, a cross-system lock cannot
be established. In this case, locks are effective within the local system, but are not effective against contending file
access from other systems.
To discover whether rpc.lockd is running, use the chkconfig command:

% /etc/chkconfig | grep lockd

If the returned value is off, rpc.lockd is not running and locks have local scope only.
To use rpc.lockd, the administrator must configure it on as follows:

% /etc/chkconfig lockd on

Then the system must be rebooted. This must be done on both the NFS file server and on all NFS clients where locks
are requested.

Performance Impact
Normally, the NFS software uses a data cache to speed access to files. Data read or written to NFS mounted files is
held in a memory cache for some time, and access requests to cached data is satisfied from memory instead of being
read from the server. Data caching has a major effect on the speed of NFS file access.
As soon as any process places a file or record lock on an NFS mounted file, the file is marked as uncachable. All I/O
requests for that file bypass the local memory cache and are sent to the NFS server. This ensures consistent results
and data integrity. However, it means that every read or write to the file, at any offset, and from any process, incurs a
network delay.
The file remains uncachable even when the lock is released. The file cannot use the cache again until it has been
closed by all processes that have it open.

You might also like