diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index a471b3b01f..27c4fff679 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -1369,7 +1369,7 @@ int main(int argc, char **argv) { umask(old_umask); /* Try to claim the pidfile, exiting if we can't */ - if ((pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) { + if ((pid_file_fd = virPidFileAcquirePath(pid_file, false, getpid())) < 0) { ret = VIR_DAEMON_ERR_PIDFILE; goto cleanup; } diff --git a/src/locking/lock_daemon.c b/src/locking/lock_daemon.c index e047751d74..7dc4292a92 100644 --- a/src/locking/lock_daemon.c +++ b/src/locking/lock_daemon.c @@ -1020,7 +1020,7 @@ virLockDaemonPostExecRestart(const char *state_file, /* Re-claim PID file now as we will not be daemonizing */ if (pid_file && - (*pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) + (*pid_file_fd = virPidFileAcquirePath(pid_file, false, getpid())) < 0) goto cleanup; if (!(lockDaemon = virLockDaemonNewPostExecRestart(object, privileged))) @@ -1382,7 +1382,7 @@ int main(int argc, char **argv) { } /* If we have a pidfile set, claim it now, exiting if already taken */ - if ((pid_file_fd = virPidFileAcquirePath(pid_file, getpid())) < 0) { + if ((pid_file_fd = virPidFileAcquirePath(pid_file, false, getpid())) < 0) { ret = VIR_LOCK_DAEMON_ERR_PIDFILE; goto cleanup; } diff --git a/src/util/virfile.c b/src/util/virfile.c index 6da564b43e..a4a4827776 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -339,13 +339,14 @@ virFileWrapperFdFree(virFileWrapperFdPtr wfd) * @shared: type of lock to acquire * @start: byte offset to start lock * @len: length of lock (0 to acquire entire remaining file from @start) + * @waitForLock: wait for previously held lock or not * * Attempt to acquire a lock on the file @fd. If @shared * is true, then a shared lock will be acquired, * otherwise an exclusive lock will be acquired. If * the lock cannot be acquired, an error will be - * returned. This will not wait to acquire the lock if - * another process already holds it. + * returned. If @waitForLock is true, this will wait + * for the lock if another process has already acquired it. * * The lock will be released when @fd is closed. The lock * will also be released if *any* other open file descriptor @@ -356,7 +357,7 @@ virFileWrapperFdFree(virFileWrapperFdPtr wfd) * * Returns 0 on success, or -errno otherwise */ -int virFileLock(int fd, bool shared, off_t start, off_t len) +int virFileLock(int fd, bool shared, off_t start, off_t len, bool waitForLock) { struct flock fl = { .l_type = shared ? F_RDLCK : F_WRLCK, @@ -365,7 +366,9 @@ int virFileLock(int fd, bool shared, off_t start, off_t len) .l_len = len, }; - if (fcntl(fd, F_SETLK, &fl) < 0) + int cmd = waitForLock ? F_SETLKW : F_SETLK; + + if (fcntl(fd, cmd, &fl) < 0) return -errno; return 0; @@ -402,7 +405,8 @@ int virFileUnlock(int fd, off_t start, off_t len) int virFileLock(int fd ATTRIBUTE_UNUSED, bool shared ATTRIBUTE_UNUSED, off_t start ATTRIBUTE_UNUSED, - off_t len ATTRIBUTE_UNUSED) + off_t len ATTRIBUTE_UNUSED, + bool waitForLock ATTRIBUTE_UNUSED) { return -ENOSYS; } diff --git a/src/util/virfile.h b/src/util/virfile.h index 20baf6f9d2..302b74ffe7 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -97,7 +97,7 @@ int virFileWrapperFdClose(virFileWrapperFdPtr dfd); void virFileWrapperFdFree(virFileWrapperFdPtr dfd); -int virFileLock(int fd, bool shared, off_t start, off_t len); +int virFileLock(int fd, bool shared, off_t start, off_t len, bool waitForLock); int virFileUnlock(int fd, off_t start, off_t len); typedef int (*virFileRewriteFunc)(int fd, void *opaque); diff --git a/src/util/virlockspace.c b/src/util/virlockspace.c index 90a39bb543..a187e1e3e6 100644 --- a/src/util/virlockspace.c +++ b/src/util/virlockspace.c @@ -82,7 +82,7 @@ static void virLockSpaceResourceFree(virLockSpaceResourcePtr res) if (res->flags & VIR_LOCK_SPACE_ACQUIRE_SHARED) { /* We must upgrade to an exclusive lock to ensure * no one else still has it before trying to delete */ - if (virFileLock(res->fd, false, 0, 1) < 0) { + if (virFileLock(res->fd, false, 0, 1, false) < 0) { VIR_DEBUG("Could not upgrade shared lease to exclusive, not deleting"); } else { if (unlink(res->path) < 0 && @@ -155,7 +155,7 @@ virLockSpaceResourceNew(virLockSpacePtr lockspace, goto error; } - if (virFileLock(res->fd, shared, 0, 1) < 0) { + if (virFileLock(res->fd, shared, 0, 1, false) < 0) { if (errno == EACCES || errno == EAGAIN) { virReportError(VIR_ERR_RESOURCE_BUSY, _("Lockspace resource '%s' is locked"), @@ -202,7 +202,7 @@ virLockSpaceResourceNew(virLockSpacePtr lockspace, goto error; } - if (virFileLock(res->fd, shared, 0, 1) < 0) { + if (virFileLock(res->fd, shared, 0, 1, false) < 0) { if (errno == EACCES || errno == EAGAIN) { virReportError(VIR_ERR_RESOURCE_BUSY, _("Lockspace resource '%s' is locked"), diff --git a/src/util/virpidfile.c b/src/util/virpidfile.c index 298d57c94c..28db24c949 100644 --- a/src/util/virpidfile.c +++ b/src/util/virpidfile.c @@ -372,6 +372,7 @@ cleanup: } int virPidFileAcquirePath(const char *path, + bool waitForLock, pid_t pid) { int fd = -1; @@ -405,7 +406,7 @@ int virPidFileAcquirePath(const char *path, return -1; } - if (virFileLock(fd, false, 0, 1) < 0) { + if (virFileLock(fd, false, 0, 1, waitForLock) < 0) { virReportSystemError(errno, _("Failed to acquire pid file '%s'"), path); @@ -448,6 +449,7 @@ int virPidFileAcquirePath(const char *path, int virPidFileAcquire(const char *dir, const char *name, + bool waitForLock, pid_t pid) { int rc = 0; @@ -463,7 +465,7 @@ int virPidFileAcquire(const char *dir, goto cleanup; } - rc = virPidFileAcquirePath(pidfile, pid); + rc = virPidFileAcquirePath(pidfile, waitForLock, pid); cleanup: VIR_FREE(pidfile); diff --git a/src/util/virpidfile.h b/src/util/virpidfile.h index 3194a897be..2720206ccc 100644 --- a/src/util/virpidfile.h +++ b/src/util/virpidfile.h @@ -56,9 +56,11 @@ int virPidFileDelete(const char *dir, int virPidFileAcquirePath(const char *path, + bool waitForLock, pid_t pid) ATTRIBUTE_RETURN_CHECK; int virPidFileAcquire(const char *dir, const char *name, + bool waitForLock, pid_t pid) ATTRIBUTE_RETURN_CHECK; int virPidFileReleasePath(const char *path,