fcntl-linux.h: add new definitions and manual updates for open file description locks
authorJeff Layton <jlayton@poochiereds.net>
Wed, 23 Jul 2014 18:21:05 +0000 (14:21 -0400)
committerCarlos O'Donell <carlos@redhat.com>
Wed, 30 Jul 2014 03:27:21 +0000 (23:27 -0400)
Open file description locks have been merged into the Linux kernel for
v3.15.  Add the appropriate command-value definitions and an update to
the manual that describes their usage.

ChangeLog
NEWS
manual/examples/ofdlocks.c [new file with mode: 0644]
manual/llio.texi
sysdeps/unix/sysv/linux/bits/fcntl-linux.h

index e60dfcc..1c263b3 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2014-07-29  Jeff Layton  <jlayton@poochiereds.net>
+
+       [BZ #16839]
+       * manual/llio.texi: Add section about open file description locks.
+       * manual/examples/ofdlocks.c: Example of open file description
+       lock usage.
+       * sysdeps/unix/sysv/linux/bits/fcntl-linux.h: Define F_OFD_GETLK,
+       F_OFD_SETLK, and F_OFD_SETLKW.
+
 2014-07-23  Allan McRae  <allan@archlinux.org>
 
        * po/es.po: Update Spanish translation from translation project.
diff --git a/NEWS b/NEWS
index a88d3e0..d195913 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -9,20 +9,26 @@ Version 2.20
 
 * The following bugs are resolved with this release:
 
-  6804, 9894, 12994, 13347, 13651, 14308, 14770, 15119, 15132, 15347, 15514,
-  15698, 15804, 15894, 15946, 16002, 16064, 16095, 16198, 16284, 16287,
-  16315, 16348, 16349, 16354, 16357, 16362, 16447, 16516, 16532, 16539,
-  16545, 16561, 16562, 16564, 16574, 16599, 16600, 16609, 16610, 16611,
-  16613, 16619, 16623, 16629, 16632, 16634, 16639, 16642, 16648, 16649,
-  16670, 16674, 16677, 16680, 16681, 16683, 16689, 16695, 16701, 16706,
-  16707, 16712, 16713, 16714, 16724, 16731, 16739, 16740, 16743, 16754,
-  16758, 16759, 16760, 16770, 16786, 16789, 16791, 16796, 16799, 16800,
-  16815, 16823, 16824, 16831, 16838, 16849, 16854, 16876, 16877, 16878,
-  16882, 16885, 16888, 16890, 16912, 16915, 16916, 16917, 16918, 16922,
-  16927, 16928, 16932, 16943, 16958, 16965, 16966, 16967, 16977, 16978,
-  16984, 16990, 16996, 17009, 17022, 17031, 17042, 17048, 17050, 17058,
-  17061, 17062, 17069, 17075, 17078, 17079, 17084, 17086, 17088, 17092,
-  17097, 17125, 17135, 17137, 17150, 17153.
+  6804, 9894, 12994, 13347, 13651, 14308, 14770, 15119, 15132, 15347,
+  15514, 15698, 15804, 15894, 15946, 16002, 16064, 16095, 16198, 16284,
+  16287, 16315, 16348, 16349, 16354, 16357, 16362, 16447, 16516, 16532,
+  16539, 16545, 16561, 16562, 16564, 16574, 16599, 16600, 16609, 16610,
+  16611, 16613, 16619, 16623, 16629, 16632, 16634, 16639, 16642, 16648,
+  16649, 16670, 16674, 16677, 16680, 16681, 16683, 16689, 16695, 16701,
+  16706, 16707, 16712, 16713, 16714, 16724, 16731, 16739, 16740, 16743,
+  16754, 16758, 16759, 16760, 16770, 16786, 16789, 16791, 16796, 16799,
+  16800, 16815, 16823, 16824, 16831, 16838, 16839, 16849, 16854, 16876,
+  16877, 16878, 16882, 16885, 16888, 16890, 16912, 16915, 16916, 16917,
+  16918, 16922, 16927, 16928, 16932, 16943, 16958, 16965, 16966, 16967,
+  16977, 16978, 16984, 16990, 16996, 17009, 17022, 17031, 17042, 17048,
+  17050, 17058, 17061, 17062, 17069, 17075, 17078, 17079, 17084, 17086,
+  17088, 17092, 17097, 17125, 17135, 17137, 17150, 17153.
+
+* Support for file description locks is added to systems running the
+  Linux kernel. The standard file locking interfaces are extended to
+  operate on file descriptions, not file descriptors, via the use of
+  F_OFD_GETLK, F_OFD_SETLK, and F_OFD_SETLKW. File description locks
+  are associated with an open file instead of a process.
 
 * Optimized strchr implementation for AArch64.  Contributed by ARM Ltd.
 
diff --git a/manual/examples/ofdlocks.c b/manual/examples/ofdlocks.c
new file mode 100644 (file)
index 0000000..85e193c
--- /dev/null
@@ -0,0 +1,77 @@
+/* Open File Description Locks Usage Example
+   Copyright (C) 1991-2014 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License
+   as published by the Free Software Foundation; either version 2
+   of the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <pthread.h>
+
+#define FILENAME       "/tmp/foo"
+#define NUM_THREADS    3
+#define ITERATIONS     5
+
+void *
+thread_start (void *arg)
+{
+  int i, fd, len;
+  long tid = (long) arg;
+  char buf[256];
+  struct flock lck = {
+    .l_whence = SEEK_SET,
+    .l_start = 0,
+    .l_len = 1,
+  };
+
+  fd = open ("/tmp/foo", O_RDWR | O_CREAT, 0666);
+
+  for (i = 0; i < ITERATIONS; i++)
+    {
+      lck.l_type = F_WRLCK;
+      fcntl (fd, F_OFD_SETLKW, &lck);
+
+      len = sprintf (buf, "%d: tid=%ld fd=%d\n", i, tid, fd);
+
+      lseek (fd, 0, SEEK_END);
+      write (fd, buf, len);
+      fsync (fd);
+
+      lck.l_type = F_UNLCK;
+      fcntl (fd, F_OFD_SETLK, &lck);
+
+      /* sleep to ensure lock is yielded to another thread */
+      usleep (1);
+    }
+  pthread_exit (NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+  long i;
+  pthread_t threads[NUM_THREADS];
+
+  truncate (FILENAME, 0);
+
+  for (i = 0; i < NUM_THREADS; i++)
+    pthread_create (&threads[i], NULL, thread_start, (void *) i);
+
+  pthread_exit (NULL);
+  return 0;
+}
index 6f8adfc..864060d 100644 (file)
@@ -57,6 +57,10 @@ directly.)
                                          flags associated with open files.
 * File Locks::                          Fcntl commands for implementing
                                          file locking.
+* Open File Description Locks::         Fcntl commands for implementing
+                                         open file description locking.
+* Open File Description Locks Example:: An example of open file description lock
+                                         usage
 * Interrupt Input::                     Getting an asynchronous signal when
                                          input arrives.
 * IOCTLs::                              Generic I/O Control operations.
@@ -2890,7 +2894,7 @@ Get flags associated with the open file.  @xref{File Status Flags}.
 Set flags associated with the open file.  @xref{File Status Flags}.
 
 @item F_GETLK
-Get a file lock.  @xref{File Locks}.
+Test a file lock.  @xref{File Locks}.
 
 @item F_SETLK
 Set or clear a file lock.  @xref{File Locks}.
@@ -2898,6 +2902,18 @@ Set or clear a file lock.  @xref{File Locks}.
 @item F_SETLKW
 Like @code{F_SETLK}, but wait for completion.  @xref{File Locks}.
 
+@item F_OFD_GETLK
+Test an open file description lock.  @xref{Open File Description Locks}.
+Specific to Linux.
+
+@item F_OFD_SETLK
+Set or clear an open file description lock.  @xref{Open File Description Locks}.
+Specific to Linux.
+
+@item F_OFD_SETLKW
+Like @code{F_OFD_SETLK}, but block until lock is acquired.
+@xref{Open File Description Locks}.  Specific to Linux.
+
 @item F_GETOWN
 Get process or process group ID to receive @code{SIGIO} signals.
 @xref{Interrupt Input}.
@@ -3576,6 +3592,10 @@ set_nonblock_flag (int desc, int value)
 
 @cindex file locks
 @cindex record locking
+This section describes record locks that are associated with the process.
+There is also a different type of record lock that is associated with the
+open file description instead of the process.  @xref{Open File Description Locks}.
+
 The remaining @code{fcntl} commands are used to support @dfn{record
 locking}, which permits multiple cooperating programs to prevent each
 other from simultaneously accessing parts of a file in error-prone
@@ -3641,7 +3661,10 @@ the file.
 @item pid_t l_pid
 This field is the process ID (@pxref{Process Creation Concepts}) of the
 process holding the lock.  It is filled in by calling @code{fcntl} with
-the @code{F_GETLK} command, but is ignored when making a lock.
+the @code{F_GETLK} command, but is ignored when making a lock.  If the
+conflicting lock is an open file description lock
+(@pxref{Open File Description Locks}), then this field will be set to
+@math{-1}.
 @end table
 @end deftp
 
@@ -3813,10 +3836,222 @@ that part of the file for writing.
 
 @c ??? This section could use an example program.
 
-Remember that file locks are only a @emph{voluntary} protocol for
+Remember that file locks are only an @emph{advisory} protocol for
 controlling access to a file.  There is still potential for access to
 the file by programs that don't use the lock protocol.
 
+@node Open File Description Locks
+@section Open File Description Locks
+
+In contrast to process-associated record locks (@pxref{File Locks}),
+open file description record locks are associated with an open file
+description rather than a process.
+
+Using @code{fcntl} to apply an open file description lock on a region that
+already has an existing open file description lock that was created via the
+same file descriptor will never cause a lock conflict.
+
+Open file description locks are also inherited by child processes across
+@code{fork}, or @code{clone} with @code{CLONE_FILES} set
+(@pxref{Creating a Process}), along with the file descriptor.
+
+It is important to distinguish between the open file @emph{description} (an
+instance of an open file, usually created by a call to @code{open}) and
+an open file @emph{descriptor}, which is a numeric value that refers to the
+open file description.  The locks described here are associated with the
+open file @emph{description} and not the open file @emph{descriptor}.
+
+Using @code{dup} (@pxref{Duplicating Descriptors}) to copy a file
+descriptor does not give you a new open file description, but rather copies a
+reference to an existing open file description and assigns it to a new
+file descriptor.  Thus, open file description locks set on a file
+descriptor cloned by @code{dup} will never conflict with open file
+description locks set on the original descriptor since they refer to the
+same open file description.  Depending on the range and type of lock
+involved, the original lock may be modified by a @code{F_OFD_SETLK} or
+@code{F_OFD_SETLKW} command in this situation however.
+
+Open file description locks always conflict with process-associated locks,
+even if acquired by the same process or on the same open file
+descriptor.
+
+Open file description locks use the same @code{struct flock} as
+process-associated locks as an argument (@pxref{File Locks}) and the
+macros for the @code{command} values are also declared in the header file
+@file{fcntl.h}. To use them, the macro @code{_GNU_SOURCE} must be
+defined prior to including any header file.
+
+In contrast to process-associated locks, any @code{struct flock} used as
+an argument to open file description lock commands must have the @code{l_pid}
+value set to @math{0}.  Also, when returning information about an
+open file description lock in a @code{F_GETLK} or @code{F_OFD_GETLK} request,
+the @code{l_pid} field in @code{struct flock} will be set to @math{-1}
+to indicate that the lock is not associated with a process.
+
+When the same @code{struct flock} is reused as an argument to a
+@code{F_OFD_SETLK} or @code{F_OFD_SETLKW} request after being used for an
+@code{F_OFD_GETLK} request, it is necessary to inspect and reset the
+@code{l_pid} field to @math{0}.
+
+@pindex fcntl.h.
+
+@deftypevr Macro int F_OFD_GETLK
+This macro is used as the @var{command} argument to @code{fcntl}, to
+specify that it should get information about a lock.  This command
+requires a third argument of type @w{@code{struct flock *}} to be passed
+to @code{fcntl}, so that the form of the call is:
+
+@smallexample
+fcntl (@var{filedes}, F_OFD_GETLK, @var{lockp})
+@end smallexample
+
+If there is a lock already in place that would block the lock described
+by the @var{lockp} argument, information about that lock is written to
+@code{*@var{lockp}}.  Existing locks are not reported if they are
+compatible with making a new lock as specified.  Thus, you should
+specify a lock type of @code{F_WRLCK} if you want to find out about both
+read and write locks, or @code{F_RDLCK} if you want to find out about
+write locks only.
+
+There might be more than one lock affecting the region specified by the
+@var{lockp} argument, but @code{fcntl} only returns information about
+one of them. Which lock is returned in this situation is undefined.
+
+The @code{l_whence} member of the @var{lockp} structure are set to
+@code{SEEK_SET} and the @code{l_start} and @code{l_len} fields are set
+to identify the locked region.
+
+If no conflicting lock exists, the only change to the @var{lockp} structure
+is to update the @code{l_type} field to the value @code{F_UNLCK}.
+
+The normal return value from @code{fcntl} with this command is either @math{0}
+on success or @math{-1}, which indicates an error. The following @code{errno}
+error conditions are defined for this command:
+
+@table @code
+@item EBADF
+The @var{filedes} argument is invalid.
+
+@item EINVAL
+Either the @var{lockp} argument doesn't specify valid lock information,
+the operating system kernel doesn't support open file description locks, or the file
+associated with @var{filedes} doesn't support locks.
+@end table
+@end deftypevr
+
+@comment fcntl.h
+@comment POSIX.1
+@deftypevr Macro int F_OFD_SETLK
+This macro is used as the @var{command} argument to @code{fcntl}, to
+specify that it should set or clear a lock.  This command requires a
+third argument of type @w{@code{struct flock *}} to be passed to
+@code{fcntl}, so that the form of the call is:
+
+@smallexample
+fcntl (@var{filedes}, F_OFD_SETLK, @var{lockp})
+@end smallexample
+
+If the open file already has a lock on any part of the
+region, the old lock on that part is replaced with the new lock.  You
+can remove a lock by specifying a lock type of @code{F_UNLCK}.
+
+If the lock cannot be set, @code{fcntl} returns immediately with a value
+of @math{-1}.  This command does not wait for other tasks
+to release locks.  If @code{fcntl} succeeds, it returns @math{0}.
+
+The following @code{errno} error conditions are defined for this
+command:
+
+@table @code
+@item EAGAIN
+The lock cannot be set because it is blocked by an existing lock on the
+file.
+
+@item EBADF
+Either: the @var{filedes} argument is invalid; you requested a read lock
+but the @var{filedes} is not open for read access; or, you requested a
+write lock but the @var{filedes} is not open for write access.
+
+@item EINVAL
+Either the @var{lockp} argument doesn't specify valid lock information,
+the operating system kernel doesn't support open file description locks, or the
+file associated with @var{filedes} doesn't support locks.
+
+@item ENOLCK
+The system has run out of file lock resources; there are already too
+many file locks in place.
+
+Well-designed file systems never report this error, because they have no
+limitation on the number of locks.  However, you must still take account
+of the possibility of this error, as it could result from network access
+to a file system on another machine.
+@end table
+@end deftypevr
+
+@comment fcntl.h
+@comment POSIX.1
+@deftypevr Macro int F_OFD_SETLKW
+This macro is used as the @var{command} argument to @code{fcntl}, to
+specify that it should set or clear a lock.  It is just like the
+@code{F_OFD_SETLK} command, but causes the process to wait until the request
+can be completed.
+
+This command requires a third argument of type @code{struct flock *}, as
+for the @code{F_OFD_SETLK} command.
+
+The @code{fcntl} return values and errors are the same as for the
+@code{F_OFD_SETLK} command, but these additional @code{errno} error conditions
+are defined for this command:
+
+@table @code
+@item EINTR
+The function was interrupted by a signal while it was waiting.
+@xref{Interrupted Primitives}.
+
+@end table
+@end deftypevr
+
+Open file description locks are useful in the same sorts of situations as
+process-associated locks. They can also be used to synchronize file
+access between threads within the same process by having each thread perform
+its own @code{open} of the file, to obtain its own open file description.
+
+Because open file description locks are automatically freed only upon
+closing the last file descriptor that refers to the open file
+description, this locking mechanism avoids the possibility that locks
+are inadvertently released due to a library routine opening and closing
+a file without the application being aware.
+
+As with process-associated locks, open file description locks are advisory.
+
+@node Open File Description Locks Example
+@section Open File Description Locks Example
+
+Here is an example of using open file description locks in a threaded
+program. If this program used process-associated locks, then it would be
+subject to data corruption because process-associated locks are shared
+by the threads inside a process, and thus cannot be used by one thread
+to lock out another thread in the same process.
+
+Proper error handling has been omitted in the following program for
+brevity.
+
+@smallexample
+@include ofdlocks.c.texi
+@end smallexample
+
+This example creates three threads each of which loops five times,
+appending to the file.  Access to the file is serialized via open file
+description locks. If we compile and run the above program, we'll end up
+with /tmp/foo that has 15 lines in it.
+
+If we, however, were to replace the @code{F_OFD_SETLK} and
+@code{F_OFD_SETLKW} commands with their process-associated lock
+equivalents, the locking essentially becomes a noop since it is all done
+within the context of the same process. That leads to data corruption
+(typically manifested as missing lines) as some threads race in and
+overwrite the data written by others.
+
 @node Interrupt Input
 @section Interrupt-Driven Input
 
index 527eb5c..e224dab 100644 (file)
 # define F_SETLKW64    14      /* Set record locking info (blocking).  */
 #endif
 
+/* open file description locks.
+
+   Usually record locks held by a process are released on *any* close and are
+   not inherited across a fork.
+
+   These cmd values will set locks that conflict with process-associated record
+   locks, but are "owned" by the opened file description, not the process.
+   This means that they are inherited across fork or clone with CLONE_FILES
+   like BSD (flock) locks, and they are only released automatically when the
+   last reference to the the file description against which they were acquired
+   is put. */
+#ifdef __USE_GNU
+# define F_OFD_GETLK   36
+# define F_OFD_SETLK   37
+# define F_OFD_SETLKW  38
+#endif
+
 #ifdef __USE_LARGEFILE64
 # define O_LARGEFILE __O_LARGEFILE
 #endif