~ubuntu-branches/ubuntu/quantal/liblockfile/quantal-proposed

« back to all changes in this revision

Viewing changes to lockfile_create.3

  • Committer: Bazaar Package Importer
  • Author(s): Miquel van Smoorenburg
  • Date: 2001-04-06 09:53:32 UTC
  • Revision ID: james.westby@ubuntu.com-20010406095332-xtysb4vtpotoa4fx
Tags: 1.03
* Some more manpage updates
* Set priority for liblockfile1 to "important" (closes: #92551)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
.TH LOCKFILE_CREATE 3  "29 March 2001" "Linux Manpage" "Linux Programmer's Manual"
 
2
.SH NAME
 
3
lockfile_create, lockfile_remove, lockfile_touch, lockfile_check \- manage lockfiles
 
4
.SH SYNOPSIS
 
5
.B #include <lockfile.h>
 
6
.sp
 
7
.BI "cc [ "flag " ... ] "file " ... -llockfile [ "library " ] "
 
8
.sp
 
9
.BI "int lockfile_create( const char *" lockfile ", int " retrycnt ", int " flags " );"
 
10
.br
 
11
.BI "int lockfile_remove( const char *" lockfile " );"
 
12
.br
 
13
.BI "int lockfile_touch( const char *" lockfile " );"
 
14
.br
 
15
.BI "int lockfile_check( const char *" lockfile ", int " flags "  );"
 
16
.SH DESCRIPTION
 
17
The
 
18
.B lockfile_create
 
19
function creates a lockfile in an NFS safe way.
 
20
.PP
 
21
If flags is set to
 
22
.B L_PID
 
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.
 
26
.PP
 
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
 
32
.B lockfile_touch
 
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 "() ".
 
36
.PP
 
37
The
 
38
.B
 
39
lockfile_check
 
40
function checks if a valid lockfile is already present without trying to
 
41
create a new lockfile.
 
42
.PP
 
43
Finally the
 
44
.B lockfile_remove
 
45
function removes the lockfile.
 
46
 
 
47
.SH RETURN VALUES
 
48
.B lockfile_create
 
49
returns one of the following status codes:
 
50
.nf
 
51
 
 
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           */
 
58
.fi
 
59
.PP
 
60
.B lockfile_check
 
61
returns 0 if a valid lockfile is present. If no lockfile or no valid
 
62
lockfile is present, -1 is returned.
 
63
.PP
 
64
.B lockfile_touch
 
65
and
 
66
.B lockfile_remove
 
67
return 0 on success. On failure -1 is returned and
 
68
.I errno
 
69
is set appropriately.
 
70
 
 
71
.SH ALGORITHM
 
72
The algorithm that is used to create a lockfile in an atomic way,
 
73
even over NFS, is as follows:
 
74
.IP 1
 
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.
 
79
 
 
80
.IP 2
 
81
Then the lockfile is created using \fIlink\fP(2). The return value of
 
82
\fIlink\fP is ignored.
 
83
 
 
84
.IP 3
 
85
Now the lockfile is \fIstat\fP()ed. If the stat fails, we go to step \fI6\fP.
 
86
 
 
87
.IP 4
 
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.
 
91
 
 
92
.IP 5
 
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.
 
95
 
 
96
.IP 6
 
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.
 
101
 
 
102
.PP
 
103
.SH REMOTE FILE SYSTEMS AND THE KERNEL ATTRIBUTE CACHE
 
104
.PP
 
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.
 
109
.PP
 
110
If you are using 
 
111
.B lockfile_create
 
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:
 
115
.PP
 
116
.PD 0
 
117
.TP 3
 
118
o
 
119
open /var/mail/USERNAME
 
120
.TP 3
 
121
o
 
122
attributes, such as size, inode, etc are now cached in the kernel! 
 
123
.TP 3
 
124
o
 
125
meanwhile, another remote system appends data to /var/mail/USERNAME
 
126
.TP 3
 
127
o
 
128
grab lock using lockfile_create()
 
129
.TP 3
 
130
o
 
131
seek to end of file
 
132
.TP 3
 
133
o
 
134
write data
 
135
.PD 1
 
136
.PP
 
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.
 
141
.PP
 
142
The only
 
143
.I portable
 
144
way to do this is
 
145
the POSIX
 
146
.I fcntl()
 
147
file locking primitives - locking a file using
 
148
.I fcntl()
 
149
has the fortunate side-effect of invalidating the NFS file attribute
 
150
cache of the kernel.
 
151
.PP
 
152
.B lockfile_create()
 
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
 
158
are insane!).
 
159
.PP
 
160
So basically what you need to do is something like this:
 
161
.nf
 
162
 
 
163
  fd = open("/var/mail/USER.lock");
 
164
  .. program code ..
 
165
 
 
166
  lockfile_create("/var/mail/USER.lock", x, y);
 
167
 
 
168
  /* Invalidate NFS attribute cache using POSIX locks */
 
169
  if (lockf(fd, F_TLOCK, 0) == 0) lockf(fd, F_ULOCK, 0);
 
170
.fi
 
171
 
 
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.
 
175
 
 
176
.PP
 
177
 
 
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
 
181
.B chmod(2).
 
182
.PP
 
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
 
187
.nf
 
188
 
 
189
  chmod u=u /var/mail/USER
 
190
.fi
 
191
 
 
192
.SH PERMISSIONS
 
193
 
 
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.
 
197
.PP
 
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.
 
202
 
 
203
.SH FILES
 
204
/usr/lib/liblockfile.so.1
 
205
 
 
206
.SH AUTHOR
 
207
Miquel van Smoorenburg <miquels@cistron.nl>
 
208
 
 
209
.SH "SEE ALSO"
 
210
.BR dotlockfile "(1), " maillock "(3), " touchlock " (3), " mailunlock (3)