Our current pidfile acquire APis (virPidFileAcquire) simply return -1 upon
failure to acquire a lock. This patch adds a parameter 'bool waitForLock'
which instructs the APIs if we want to make it block and wait for the lock
or not.
---
Based on Daniel's comments on:
https://www.redhat.com/archives/libvir-list/2014-March/msg00841.html
daemon/libvirtd.c | 2 +-
src/locking/lock_daemon.c | 4 ++--
src/util/virfile.c | 14 +++++++++-----
src/util/virfile.h | 2 +-
src/util/virlockspace.c | 6 +++---
src/util/virpidfile.c | 6 ++++--
src/util/virpidfile.h | 2 ++
7 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index a471b3b..27c4fff 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 e047751..7dc4292 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 6da564b..a4a4827 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 20baf6f..302b74f 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 90a39bb..a187e1e 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 298d57c..28db24c 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 3194a89..2720206 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,
--
1.7.1