libxl: functions to lock / unlock libxl userdata store

This lock is used to protect all userdata files related to a particular
domain, which include but are not limited to domain configuration.  A
new "domain-userdata-lock" entry is introduced in libxl registry.

This lock works among different processes and different threads within
the same process.

Locking protocol inspired by Ian Jackson's chiark-utils with-lock-ex. A
file lock is taken with flock(2). If that succeeds that thread fstat the
fd and stat the lock file path. If the device and inode match then the
lock has been successfully acquired. This lock remains acquired until
the lock file gets deleted or released by flock(2). If device and inode
don't match then another thread acquired the lock and deleted the file
in the meantime; lock procedure should restart.

Portability note: this lock utilises flock(2) so a proper implementation
of flock(2) is required -- that is, it should not be implemented with
fcntl(2).

Signed-off-by: Wei Liu <wei.liu2@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
Wei Liu authored and Ian Campbell committed 2014-09-09 12:45:10 +01:00
1 parent 34714e3222
commit d2cd9d4f56
3 files changed
+77

No files matched your search

+3
View File
@@ -1220,6 +1220,9 @@ void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
* "xl" domain config file in xl format, Unix line endings
* "libvirt-xml" domain config file in libvirt XML format. See
* http://libvirt.org/formatdomain.html
* "domain-userdata-lock" lock file to protect domain userdata in libxl.
* It's a per-domain lock. Applications should
* not touch this file.
*
* libxl does not enforce the registration of userdata userids or the
* semantics of the data. For specifications of the data formats
+69
View File
@@ -381,6 +381,75 @@ out:
return rc;
}
/* Portability note: this lock utilises flock(2) so a proper implementation of
* flock(2) is required.
*/
libxl__carefd *libxl__lock_domain_userdata(libxl__gc *gc, uint32_t domid)
{
libxl__carefd *carefd = NULL;
const char *lockfile;
int fd;
struct stat stab, fstab;
lockfile = libxl__userdata_path(gc, domid, "domain-userdata-lock", "l");
if (!lockfile) goto out;
while (true) {
libxl__carefd_begin();
fd = open(lockfile, O_RDWR|O_CREAT, 0666);
if (fd < 0)
LOGE(ERROR, "cannot open lockfile %s, errno=%d", lockfile, errno);
carefd = libxl__carefd_opened(CTX, fd);
if (fd < 0) goto out;
/* Lock the file in exclusive mode, wait indefinitely to
* acquire the lock
*/
while (flock(fd, LOCK_EX)) {
switch (errno) {
case EINTR:
/* Signal received, retry */
continue;
default:
/* All other errno: EBADF, EINVAL, ENOLCK, EWOULDBLOCK */
LOGE(ERROR,
"unexpected error while trying to lock %s, fd=%d, errno=%d",
lockfile, fd, errno);
goto out;
}
}
if (fstat(fd, &fstab)) {
LOGE(ERROR, "cannot fstat %s, fd=%d, errno=%d",
lockfile, fd, errno);
goto out;
}
if (stat(lockfile, &stab)) {
if (errno != ENOENT) {
LOGE(ERROR, "cannot stat %s, errno=%d", lockfile, errno);
goto out;
}
} else {
if (stab.st_dev == fstab.st_dev && stab.st_ino == fstab.st_ino)
break;
}
libxl__carefd_close(carefd);
}
return carefd;
out:
if (carefd) libxl__carefd_close(carefd);
return NULL;
}
void libxl__unlock_domain_userdata(libxl__carefd *lock_carefd)
{
/* Simply closing the file descriptor releases the lock */
libxl__carefd_close(lock_carefd);
}
/*
* Local variables:
* mode: C
+5
View File
@@ -43,6 +43,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <xenstore.h>
#include <xenctrl.h>
@@ -3223,6 +3224,10 @@ static inline int libxl__key_value_list_is_empty(libxl_key_value_list *pkvl)
int libxl__cpuid_policy_is_empty(libxl_cpuid_policy_list *pl);
/* Portability note: a proper flock(2) implementation is required */
libxl__carefd *libxl__lock_domain_userdata(libxl__gc *gc, uint32_t domid);
void libxl__unlock_domain_userdata(libxl__carefd *lock_carefd);
#endif
/*
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.