#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)
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);