file-lock.c revision f1243d7759a3dddc1c3eaf7eda8a153c8ef0112b
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "istream.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "file-lock.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "time-util.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include <time.h>
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include <sys/stat.h>
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#ifdef HAVE_FLOCK
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen# include <sys/file.h>
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#endif
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainenstruct file_lock {
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen int fd;
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen char *path;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen struct timeval locked_time;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int lock_type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum file_lock_method lock_method;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic struct timeval lock_wait_start;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic uint64_t file_lock_wait_usecs = 0;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic long long file_lock_slow_warning_usecs = -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void file_lock_log_warning_if_slow(struct file_lock *lock);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenbool file_lock_method_parse(const char *name, enum file_lock_method *method_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcasecmp(name, "fcntl") == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *method_r = FILE_LOCK_METHOD_FCNTL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else if (strcasecmp(name, "flock") == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *method_r = FILE_LOCK_METHOD_FLOCK;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen else if (strcasecmp(name, "dotlock") == 0)
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen *method_r = FILE_LOCK_METHOD_DOTLOCK;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return TRUE;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenconst char *file_lock_method_to_str(enum file_lock_method method)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen switch (method) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen case FILE_LOCK_METHOD_FCNTL:
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return "fcntl";
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen case FILE_LOCK_METHOD_FLOCK:
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return "flock";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case FILE_LOCK_METHOD_DOTLOCK:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return "dotlock";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_unreached();
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint file_try_lock(int fd, const char *path, int lock_type,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum file_lock_method lock_method,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct file_lock **lock_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return file_wait_lock(fd, path, lock_type, lock_method, 0, lock_r);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint file_try_lock_error(int fd, const char *path, int lock_type,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum file_lock_method lock_method,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct file_lock **lock_r, const char **error_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return file_wait_lock_error(fd, path, lock_type, lock_method, 0,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen lock_r, error_r);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfile_lock_find_fcntl(int lock_fd, int lock_type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct flock fl;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_zero(&fl);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_type = lock_type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_whence = SEEK_SET;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_start = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_len = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (fcntl(lock_fd, F_GETLK, &fl) < 0 ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_type == F_UNLCK || fl.l_pid == -1 || fl.l_pid == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return "";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return t_strdup_printf(" (%s lock held by pid %ld)",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen fl.l_type == F_RDLCK ? "READ" : "WRITE", (long)fl.l_pid);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic const char *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenfile_lock_find_proc_locks(int lock_fd ATTR_UNUSED)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* do anything except Linux support this? don't bother trying it for
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen OSes we don't know about. */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen#ifdef __linux__
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen static bool have_proc_locks = TRUE;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct stat st;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen char node_buf[MAX_INT_STRLEN*3 + 2 + 1];
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct istream *input;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const char *line, *lock_type = "";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen pid_t pid = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int fd;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if (!have_proc_locks)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen return NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (fstat(lock_fd, &st) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return "";
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_snprintf(node_buf, sizeof(node_buf), "%02x:%02x:%llu",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen major(st.st_dev), minor(st.st_dev),
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen (unsigned long long)st.st_ino);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen fd = open("/proc/locks", O_RDONLY);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (fd == -1) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen have_proc_locks = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return "";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen input = i_stream_create_fd_autoclose(&fd, 512);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen while (pid == 0 && (line = i_stream_read_next_line(input)) != NULL) T_BEGIN {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *const *args = t_strsplit_spaces(line, " ");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* number: FLOCK/POSIX ADVISORY READ/WRITE pid
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen major:minor:inode region-start region-end */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (str_array_length(args) < 8) {
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen ; /* don't continue from within a T_BEGIN {...} T_END */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } else if (strcmp(args[5], node_buf) == 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen lock_type = strcmp(args[3], "READ") == 0 ?
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen "READ" : "WRITE";
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (str_to_pid(args[4], &pid) < 0)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen pid = 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } T_END;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_stream_destroy(&input);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (pid == 0) {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* not found */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return "";
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (pid == getpid())
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return " (BUG: lock is held by our own process)";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return t_strdup_printf(" (%s lock held by pid %ld)", lock_type, (long)pid);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#else
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return "";
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen#endif
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenconst char *file_lock_find(int lock_fd, enum file_lock_method lock_method,
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen int lock_type)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *ret;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (lock_method == FILE_LOCK_METHOD_FCNTL) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen ret = file_lock_find_fcntl(lock_fd, lock_type);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (ret[0] != '\0')
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen return ret;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return file_lock_find_proc_locks(lock_fd);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstatic bool err_is_lock_timeout(time_t started, unsigned int timeout_secs)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen{
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen /* if EINTR took at least timeout_secs-1 number of seconds,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen assume it was the alarm. otherwise log EINTR failure.
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen (We most likely don't want to retry EINTR since a signal
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen means somebody wants us to stop blocking). */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return errno == EINTR &&
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen (unsigned long)(time(NULL) - started + 1) >= timeout_secs;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int file_lock_do(int fd, const char *path, int lock_type,
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen enum file_lock_method lock_method,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int timeout_secs, const char **error_r)
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *lock_type_str;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen time_t started = time(NULL);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_assert(fd != -1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (timeout_secs != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen alarm(timeout_secs);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen file_lock_wait_start();
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen lock_type_str = lock_type == F_UNLCK ? "unlock" :
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk (lock_type == F_RDLCK ? "read-lock" : "write-lock");
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk switch (lock_method) {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen case FILE_LOCK_METHOD_FCNTL: {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk#ifndef HAVE_FCNTL
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk *error_r = t_strdup_printf(
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk "Can't lock file %s: fcntl() locks not supported", path);
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen return -1;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen#else
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct flock fl;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen fl.l_type = lock_type;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen fl.l_whence = SEEK_SET;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen fl.l_start = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fl.l_len = 0;
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen ret = fcntl(fd, timeout_secs != 0 ? F_SETLKW : F_SETLK, &fl);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (timeout_secs != 0) {
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen alarm(0);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen file_lock_wait_end(path);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (ret == 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen break;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (timeout_secs == 0 &&
9abf5be0962538e1f6f5c73c838ff677341da0c9Timo Sirainen (errno == EACCES || errno == EAGAIN)) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* locked by another process */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *error_r = t_strdup_printf(
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "fcntl(%s, %s, F_SETLK) locking failed: %m "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "(File is already locked)", path, lock_type_str);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (err_is_lock_timeout(started, timeout_secs)) {
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen errno = EAGAIN;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen *error_r = t_strdup_printf(
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "fcntl(%s, %s, F_SETLKW) locking failed: "
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen "Timed out after %u seconds%s",
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen path, lock_type_str, timeout_secs,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen file_lock_find(fd, lock_method, lock_type));
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen *error_r = t_strdup_printf("fcntl(%s, %s, %s) locking failed: %m",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen path, lock_type_str, timeout_secs == 0 ? "F_SETLK" : "F_SETLKW");
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (errno == EDEADLK)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen i_panic("%s%s", *error_r, file_lock_find(fd, lock_method, lock_type));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen#endif
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen case FILE_LOCK_METHOD_FLOCK: {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen#ifndef HAVE_FLOCK
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *error_r = t_strdup_printf(
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen "Can't lock file %s: flock() not supported", path);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen#else
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen int operation = timeout_secs != 0 ? 0 : LOCK_NB;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen switch (lock_type) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen case F_RDLCK:
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen operation |= LOCK_SH;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen case F_WRLCK:
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen operation |= LOCK_EX;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen break;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen case F_UNLCK:
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen operation |= LOCK_UN;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen break;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen ret = flock(fd, operation);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (timeout_secs != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen alarm(0);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen file_lock_wait_end(path);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen }
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (ret == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (timeout_secs == 0 && errno == EWOULDBLOCK) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* locked by another process */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *error_r = t_strdup_printf(
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen "flock(%s, %s) failed: %m "
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen "(File is already locked)", path, lock_type_str);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (err_is_lock_timeout(started, timeout_secs)) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen errno = EAGAIN;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen *error_r = t_strdup_printf("flock(%s, %s) failed: "
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen "Timed out after %u seconds%s",
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen path, lock_type_str, timeout_secs,
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen file_lock_find(fd, lock_method, lock_type));
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen *error_r = t_strdup_printf("flock(%s, %s) failed: %m",
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen path, lock_type_str);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (errno == EDEADLK)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_panic("%s%s", *error_r, file_lock_find(fd, lock_method, lock_type));
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return -1;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#endif
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen case FILE_LOCK_METHOD_DOTLOCK:
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* we shouldn't get here */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen i_unreached();
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenint file_wait_lock(int fd, const char *path, int lock_type,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen enum file_lock_method lock_method,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen unsigned int timeout_secs,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct file_lock **lock_r)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *error;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen int ret;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen ret = file_wait_lock_error(fd, path, lock_type, lock_method,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen timeout_secs, lock_r, &error);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (ret < 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_error("%s", error);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return ret;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenint file_wait_lock_error(int fd, const char *path, int lock_type,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen enum file_lock_method lock_method,
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen unsigned int timeout_secs,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct file_lock **lock_r, const char **error_r)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct file_lock *lock;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen int ret;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen ret = file_lock_do(fd, path, lock_type, lock_method, timeout_secs, error_r);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (ret <= 0)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return ret;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen lock = i_new(struct file_lock, 1);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen lock->fd = fd;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen lock->path = i_strdup(path);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen lock->lock_type = lock_type;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen lock->lock_method = lock_method;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (gettimeofday(&lock->locked_time, NULL) < 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_fatal("gettimeofday() failed: %m");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen *lock_r = lock;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint file_lock_try_update(struct file_lock *lock, int lock_type)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *error;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen int ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen ret = file_lock_do(lock->fd, lock->path, lock_type,
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen lock->lock_method, 0, &error);
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen if (ret <= 0)
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen return ret;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen file_lock_log_warning_if_slow(lock);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen lock->lock_type = lock_type;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid file_unlock(struct file_lock **_lock)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct file_lock *lock = *_lock;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const char *error;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen *_lock = NULL;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (file_lock_do(lock->fd, lock->path, F_UNLCK,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen lock->lock_method, 0, &error) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* this shouldn't happen */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_error("file_unlock(%s) failed: %m", lock->path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen file_lock_free(&lock);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid file_lock_free(struct file_lock **_lock)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct file_lock *lock = *_lock;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen *_lock = NULL;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen file_lock_log_warning_if_slow(lock);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_free(lock->path);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_free(lock);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenconst char *file_lock_get_path(struct file_lock *lock)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return lock->path;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenvoid file_lock_wait_start(void)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_assert(lock_wait_start.tv_sec == 0);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (gettimeofday(&lock_wait_start, NULL) < 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_fatal("gettimeofday() failed: %m");
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic void file_lock_wait_init_warning(void)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen const char *value;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_assert(file_lock_slow_warning_usecs == -1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen value = getenv("FILE_LOCK_SLOW_WARNING_MSECS");
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (value == NULL)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen file_lock_slow_warning_usecs = LLONG_MAX;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen else if (str_to_llong(value, &file_lock_slow_warning_usecs) == 0 &&
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen file_lock_slow_warning_usecs > 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen file_lock_slow_warning_usecs *= 1000;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_error("FILE_LOCK_SLOW_WARNING_MSECS: "
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen "Invalid value '%s' - ignoring", value);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen file_lock_slow_warning_usecs = LLONG_MAX;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainenstatic void file_lock_log_warning_if_slow(struct file_lock *lock)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (file_lock_slow_warning_usecs < 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen file_lock_wait_init_warning();
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (file_lock_slow_warning_usecs == LLONG_MAX) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* slowness checking is disabled */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen if (lock->lock_type != F_WRLCK) {
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen /* some shared locks can legitimately be kept for a long time.
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen don't warn about them. */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct timeval now;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (gettimeofday(&now, NULL) < 0)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_fatal("gettimeofday() failed: %m");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen int diff = timeval_diff_msecs(&now, &lock->locked_time);
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen if (diff > file_lock_slow_warning_usecs/1000) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_warning("Lock %s kept for %d.%03d secs", lock->path,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen diff / 1000, diff % 1000);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen}
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainenvoid file_lock_wait_end(const char *lock_name)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen{
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen struct timeval now;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen i_assert(lock_wait_start.tv_sec != 0);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (gettimeofday(&now, NULL) < 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_fatal("gettimeofday() failed: %m");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen long long diff = timeval_diff_usecs(&now, &lock_wait_start);
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen if (diff > file_lock_slow_warning_usecs) {
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen if (file_lock_slow_warning_usecs < 0)
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen file_lock_wait_init_warning();
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen if (diff > file_lock_slow_warning_usecs) {
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen int diff_msecs = (diff + 999) / 1000;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen i_warning("Locking %s took %d.%03d secs", lock_name,
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen diff_msecs / 1000, diff_msecs % 1000);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen file_lock_wait_usecs += diff;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen lock_wait_start.tv_sec = 0;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainenuint64_t file_lock_wait_get_total_usecs(void)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return file_lock_wait_usecs;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen