1
.TH LOCKFILE_CREATE 3 "29 March 2001" "Linux Manpage" "Linux Programmer's Manual"
3
lockfile_create, lockfile_remove, lockfile_touch, lockfile_check \- manage lockfiles
5
.B #include <lockfile.h>
7
.BI "cc [ "flag " ... ] "file " ... -llockfile [ "library " ] "
9
.BI "int lockfile_create( const char *" lockfile ", int " retrycnt ", int " flags " );"
11
.BI "int lockfile_remove( const char *" lockfile " );"
13
.BI "int lockfile_touch( const char *" lockfile " );"
15
.BI "int lockfile_check( const char *" lockfile ", int " flags " );"
19
function creates a lockfile in an NFS safe way.
23
then lockfile_create will not only check for an existing lockfile, but
24
it will read the contents as well to see if it contains a process id
25
in ASCII. If so, the lockfile is only valid if that process still exists.
27
If the lockfile is on a shared filesystem, it might have been created by
28
a process on a remote host. Thus the process-id checking is useless and
29
the L_PID flag should not be set. In this case,
30
there is no good way to see if a lockfile is stale. Therefore if the lockfile
31
is older then 5 minutes, it will be removed. That is why the
33
function is provided: while holding the lock, it needs to be refreshed
34
regulary (every minute or so) by calling
35
.B lockfile_touch "() ".
40
function checks if a valid lockfile is already present without trying to
41
create a new lockfile.
45
function removes the lockfile.
49
returns one of the following status codes:
52
#define L_SUCCESS 0 /* Lockfile created */
53
#define L_NAMELEN 1 /* Recipient name too long (> 13 chars) */
54
#define L_TMPLOCK 2 /* Error creating tmp lockfile */
55
#define L_TMPWRITE 3 /* Can't write pid int tmp lockfile */
56
#define L_MAXTRYS 4 /* Failed after max. number of attempts */
57
#define L_ERROR 5 /* Unknown error; check errno */
61
returns 0 if a valid lockfile is present. If no lockfile or no valid
62
lockfile is present, -1 is returned.
67
return 0 on success. On failure -1 is returned and
72
The algorithm that is used to create a lockfile in an atomic way,
73
even over NFS, is as follows:
75
A unique file is created. In printf format, the name of the file
76
is .lk%05d%x%s. The first argument (%05d) is the current process id. The
77
second argument (%x) consists of the 4 minor bits of the value returned by
78
\fItime\fP(2). The last argument is the system hostname.
81
Then the lockfile is created using \fIlink\fP(2). The return value of
82
\fIlink\fP is ignored.
85
Now the lockfile is \fIstat\fP()ed. If the stat fails, we go to step \fI6\fP.
88
The \fIstat\fP value of the lockfile is compared with that of the temporary
89
file. If they are the same, we have the lock. The temporary file
90
is deleted and a value of 0 (success) is returned to the caller.
93
A check is made to see if the existing lockfile is a valid one. If it isn't
94
valid, the stale lockfile is deleted.
97
Before retrying, we sleep for \fIn\fP seconds. \fIn\fP is initially 5
98
seconds, but after every retry 5 extra seconds is added up to a maximum
99
of 60 seconds (an incremental backoff). Then we go to
100
step \fI2\fP up to \fIretries\fP times.
103
.SH REMOTE FILE SYSTEMS AND THE KERNEL ATTRIBUTE CACHE
105
These functions do not lock a file - they \fIgenerate\fP a \fIlockfile\fP.
106
However in a lot of cases, such as Unix mailboxes, all concerned programs
107
accessing the mailboxes agree on the fact that the presence of
108
<filename>.lock means that <filename> is locked.
112
to create a lock on a file that resides on a remote server, and you
113
already have that file open, you need to flush the NFS attribute cache
114
after locking. This is needed to prevent the following scenario:
119
open /var/mail/USERNAME
122
attributes, such as size, inode, etc are now cached in the kernel!
125
meanwhile, another remote system appends data to /var/mail/USERNAME
128
grab lock using lockfile_create()
137
Now the end of the file really isn't the end of the file - the kernel
138
cached the attributes on open, and st_size is not the end of the file
139
anymore. So after locking the file, you need to tell the kernel to
140
flush the NFS file attribute cache.
147
file locking primitives - locking a file using
149
has the fortunate side-effect of invalidating the NFS file attribute
153
cannot do this for you for two reasons. One, it just creates a lockfile-
154
it doesn't know which file you are actually trying to lock! Two, even
155
if it could deduce the file you're locking from the filename, by just
156
opening and closing it, it would invalidate any existing POSIX locks the
157
program might already have on that file (yes, POSIX locking semantics
160
So basically what you need to do is something like this:
163
fd = open("/var/mail/USER.lock");
166
lockfile_create("/var/mail/USER.lock", x, y);
168
/* Invalidate NFS attribute cache using POSIX locks */
169
if (lockf(fd, F_TLOCK, 0) == 0) lockf(fd, F_ULOCK, 0);
172
You have to be careful with this if you're putting this in an existing
173
program that might already be using fcntl(), flock() or lockf() locking-
174
you might invalidate existing locks.
178
There is also a non-portable way. A lot of NFS operations return the
179
updated attributes - and the Linux kernel actually uses these to
180
update the attribute cache. One of these operations is
183
So stat()ing a file and then chmod()ing it to st.st_mode will not
184
actually change the file, nor will it interfere with any locks on
185
the file, but it will invalidate the attribute cache. The equivalent
186
to use from a shell script would be
189
chmod u=u /var/mail/USER
194
If you are on a system that has a mail spool directory that is only
195
writable by a special group (usually "mail") you cannot create a lockfile
196
directly in the mailspool directory without special permissions.
198
Lockfile_create and lockfile_remove check if the lockfile ends in
199
$USERNAME.lock, and if the directory the lockfile is writable
200
by group "mail". If so, an external set group-id mail executable
201
(\fIdotlockfile\fP(1) ) is spawned to do the actual locking / unlocking.
204
/usr/lib/liblockfile.so.1
207
Miquel van Smoorenburg <miquels@cistron.nl>
210
.BR dotlockfile "(1), " maillock "(3), " touchlock " (3), " mailunlock (3)