krb5 commit: Use OFD locks where available

Greg Hudson ghudson at mit.edu
Mon Dec 15 15:27:25 EST 2014


https://github.com/krb5/krb5/commit/0008014a748310e38b3e4d69e3227af935e86cf7
commit 0008014a748310e38b3e4d69e3227af935e86cf7
Author: Greg Hudson <ghudson at mit.edu>
Date:   Tue Oct 7 12:12:11 2014 -0400

    Use OFD locks where available
    
    Linux 3.15 has added OFD locks, which contend with POSIX file locks
    but are owned by the open file description instead of the process.
    Use these in krb5_lock_file where available, for safer concurrency
    behavior.
    
    ticket: 8023 (new)

 src/lib/krb5/os/lock_file.c |   26 +++++++++++++++++++++++++-
 1 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/src/lib/krb5/os/lock_file.c b/src/lib/krb5/os/lock_file.c
index 224e58f..a2f247c 100644
--- a/src/lib/krb5/os/lock_file.c
+++ b/src/lib/krb5/os/lock_file.c
@@ -57,6 +57,30 @@
 #endif
 #endif
 
+#ifdef POSIX_FILE_LOCKS
+/*
+ * Try to use OFD locks where available (e.g. Linux 3.15 and later).  OFD locks
+ * contend with regular POSIX file locks, but are owned by the open file
+ * description instead of the process, which is much better for thread safety.
+ * Fall back to regular POSIX locks on EINVAL in case we are running with an
+ * older kernel than we were built with.
+ */
+static int
+ofdlock(int fd, int cmd, struct flock *lock_arg)
+{
+#ifdef F_OFD_SETLKW
+    int st, ofdcmd;
+
+    assert(cmd == F_SETLKW || cmd == F_SETLK);
+    ofdcmd = (cmd == F_SETLKW) ? F_OFD_SETLKW : F_OFD_SETLK;
+    st = fcntl(fd, ofdcmd, lock_arg);
+    if (st == 0 || errno != EINVAL)
+        return st;
+#endif
+    return fcntl(fd, cmd, lock_arg);
+}
+#endif /* POSIX_FILE_LOCKS */
+
 /*ARGSUSED*/
 krb5_error_code
 krb5_lock_file(krb5_context context, int fd, int mode)
@@ -105,7 +129,7 @@ krb5_lock_file(krb5_context context, int fd, int mode)
     lock_arg.l_whence = 0;
     lock_arg.l_start = 0;
     lock_arg.l_len = 0;
-    if (fcntl(fd, lock_cmd, &lock_arg) == -1) {
+    if (ofdlock(fd, lock_cmd, &lock_arg) == -1) {
         if (errno == EACCES || errno == EAGAIN) /* see POSIX/IEEE 1003.1-1988,
                                                    6.5.2.4 */
             return(EAGAIN);


More information about the cvs-krb5 mailing list