static void virLockSpaceResourceFree(virLockSpaceResourcePtr res) { if (!res) return; if (res->lockHeld && (res->flags & VIR_LOCK_SPACE_ACQUIRE_AUTOCREATE)) { 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) { VIR_DEBUG("Could not upgrade shared lease to exclusive, not deleting"); } else { if (unlink(res->path) < 0 && errno != ENOENT) { char ebuf[1024]; VIR_WARN("Failed to unlink resource %s: %s", res->path, virStrerror(errno, ebuf, sizeof(ebuf))); } } } else { if (unlink(res->path) < 0 && errno != ENOENT) { char ebuf[1024]; VIR_WARN("Failed to unlink resource %s: %s", res->path, virStrerror(errno, ebuf, sizeof(ebuf))); } } } VIR_FORCE_CLOSE(res->fd); VIR_FREE(res->path); VIR_FREE(res->name); VIR_FREE(res); }
static virLockSpaceResourcePtr virLockSpaceResourceNew(virLockSpacePtr lockspace, const char *resname, unsigned int flags, pid_t owner) { virLockSpaceResourcePtr res; bool shared = !!(flags & VIR_LOCK_SPACE_ACQUIRE_SHARED); if (VIR_ALLOC(res) < 0) return NULL; res->fd = -1; res->flags = flags; if (VIR_STRDUP(res->name, resname) < 0) goto error; if (!(res->path = virLockSpaceGetResourcePath(lockspace, resname))) goto error; if (flags & VIR_LOCK_SPACE_ACQUIRE_AUTOCREATE) { while (1) { struct stat a, b; if ((res->fd = open(res->path, O_RDWR|O_CREAT, 0600)) < 0) { virReportSystemError(errno, _("Unable to open/create resource %s"), res->path); goto error; } if (virSetCloseExec(res->fd) < 0) { virReportSystemError(errno, _("Failed to set close-on-exec flag '%s'"), res->path); goto error; } if (fstat(res->fd, &b) < 0) { virReportSystemError(errno, _("Unable to check status of pid file '%s'"), res->path); goto error; } if (virFileLock(res->fd, shared, 0, 1, false) < 0) { if (errno == EACCES || errno == EAGAIN) { virReportError(VIR_ERR_RESOURCE_BUSY, _("Lockspace resource '%s' is locked"), resname); } else { virReportSystemError(errno, _("Unable to acquire lock on '%s'"), res->path); } goto error; } /* Now make sure the pidfile we locked is the same * one that now exists on the filesystem */ if (stat(res->path, &a) < 0) { char ebuf[1024] ATTRIBUTE_UNUSED; VIR_DEBUG("Resource '%s' disappeared: %s", res->path, virStrerror(errno, ebuf, sizeof(ebuf))); VIR_FORCE_CLOSE(res->fd); /* Someone else must be racing with us, so try again */ continue; } if (a.st_ino == b.st_ino) break; VIR_DEBUG("Resource '%s' was recreated", res->path); VIR_FORCE_CLOSE(res->fd); /* Someone else must be racing with us, so try again */ } } else {
int virPidFileAcquirePath(const char *path, pid_t pid) { int fd = -1; char pidstr[INT_BUFSIZE_BOUND(pid)]; if (path[0] == '\0') return 0; while (1) { struct stat a, b; if ((fd = open(path, O_WRONLY|O_CREAT, 0644)) < 0) { virReportSystemError(errno, _("Failed to open pid file '%s'"), path); return -1; } if (virSetCloseExec(fd) < 0) { virReportSystemError(errno, _("Failed to set close-on-exec flag '%s'"), path); VIR_FORCE_CLOSE(fd); return -1; } if (fstat(fd, &b) < 0) { virReportSystemError(errno, _("Unable to check status of pid file '%s'"), path); VIR_FORCE_CLOSE(fd); return -1; } if (virFileLock(fd, false, 0, 1) < 0) { virReportSystemError(errno, _("Failed to acquire pid file '%s'"), path); VIR_FORCE_CLOSE(fd); return -1; } /* Now make sure the pidfile we locked is the same * one that now exists on the filesystem */ if (stat(path, &a) < 0) { char ebuf[1024] ATTRIBUTE_UNUSED; VIR_DEBUG("Pid file '%s' disappeared: %s", path, virStrerror(errno, ebuf, sizeof(ebuf))); VIR_FORCE_CLOSE(fd); /* Someone else must be racing with us, so try agin */ continue; } if (a.st_ino == b.st_ino) break; VIR_DEBUG("Pid file '%s' was recreated", path); VIR_FORCE_CLOSE(fd); /* Someone else must be racing with us, so try agin */ }