From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Add some simple wrappers around the fcntl() discretionary file locking capability. * src/util/util.c, src/util/util.h, src/libvirt_private.syms: Add virFileLock and virFileUnlock APIs --- src/libvirt_private.syms | 2 + src/util/virfile.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 3 ++ 3 files changed, 88 insertions(+), 0 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 830222b..261f3e0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1039,6 +1039,7 @@ virFileFindMountPoint; virFileHasSuffix; virFileIsExecutable; virFileLinkPointsTo; +virFileLock; virFileMakePath; virFileMatchesNameSuffix; virFileOpenAs; @@ -1051,6 +1052,7 @@ virFileReadPidPath; virFileResolveLink; virFileSanitizePath; virFileStripSuffix; +virFileUnlock; virFileWaitForDevices; virFileWriteStr; virFindFileInPath; diff --git a/src/util/virfile.c b/src/util/virfile.c index 8b32518..1346c1a 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -251,3 +251,86 @@ virFileDirectFdFree(virFileDirectFdPtr dfd) virCommandFree(dfd->cmd); VIR_FREE(dfd); } + + +#ifndef WIN32 +/** + * virFileLock: + * @fd: file descriptor to acquire the lock on + * @shared: type of lock to acquire + * @start: byte offset to start lock + * @len: length of lock (0 to acquire entire remaining file from @start) + * + * Attempt to acquire a lock on the file @fd. If @shared + * is true, then the 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. + * + * The lock will be released will @fd is closed. The lock + * will also be released if *any* other open file descriptor + * pointing to the same underlying file is closed. As such + * this function should not be relied on in multi-threaded + * apps where other threads can be opening/closing arbitrary + * files. + * + * Returns: 0 on success, or -errno otherwise + */ +int virFileLock(int fd, bool shared, off_t start, off_t len) +{ + struct flock fl = { + .l_type = shared ? F_RDLCK : F_WRLCK, + .l_whence = SEEK_SET, + .l_start = start, + .l_len = len, + }; + + if (fcntl(fd, F_SETLK, &fl) < 0) + return -errno; + + return 0; +} + + +/** + * virFileUnlock: + * @fd: file descriptor to release the lock on + * @start: byte offset to start unlock + * @len: length of lock (0 to release entire remaining file from @start) + * + * Release a lock previously acquired with virFileUnlock(). + * NB the lock will also be released if any open file descriptor + * pointing to the same file as @fd is closed + * + * Returns 0 on succcess, or -errno on error + */ +int virFileUnlock(int fd, off_t start, off_t len) +{ + struct flock fl = { + .l_type = F_UNLCK, + .l_whence = SEEK_SET, + .l_start = start, + .l_len = len, + }; + + if (fcntl(fd, F_SETLK, &fl) < 0) + return -errno; + + return 0; +} +#else +int virFileLock(int fd ATTRIBUTE_UNUSED, + bool shared ATTRIBUTE_UNUSED, + off_t start ATTRIBUTE_UNUSED, + off_t len ATTRIBUTE_UNUSED) +{ + return -ENOSYS; +} +int virFileUnlock(int fd ATTRIBUTE_UNUSED, + off_t start ATTRIBUTE_UNUSED, + off_t len ATTRIBUTE_UNUSED) +{ + return -ENOSYS; +} +#endif diff --git a/src/util/virfile.h b/src/util/virfile.h index 0906568..e025614 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -65,4 +65,7 @@ int virFileDirectFdClose(virFileDirectFdPtr dfd); void virFileDirectFdFree(virFileDirectFdPtr dfd); +int virFileLock(int fd, bool shared, off_t start, off_t len); +int virFileUnlock(int fd, off_t start, off_t len); + #endif /* __VIR_FILES_H */ -- 1.7.6 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list