Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:15.3
btrfsprogs
0005-btrfs-progs-add-helper-to-check-or-wait-fo...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0005-btrfs-progs-add-helper-to-check-or-wait-for-exclusiv.patch of Package btrfsprogs
From 741a437cdc6b0b258d262d611fd8fa9d5f08bd48 Mon Sep 17 00:00:00 2001 From: David Sterba <dsterba@suse.com> Date: Thu, 5 Nov 2020 02:52:40 +0100 Subject: [PATCH] btrfs-progs: add helper to check or wait for exclusive operation Add helper that will either check a running operation or wait until it's done, so that commands can be started and enqueued. If there are more enqueued, an attempt to avoid racing is done based on the remaining waiting time of each command. Signed-off-by: David Sterba <dsterba@suse.com> --- utils.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 1 2 files changed, 70 insertions(+) --- a/utils.c +++ b/utils.c @@ -2681,3 +2681,72 @@ return exclop_def[op]; return "UNKNOWN"; } + +/* + * Check if there's another exclusive operation running and either return error + * or wait until there's none in case @enqueue is true. The timeout between + * checks is 1 minute as we get notification on the sysfs file when the + * operation finishes. + * + * Return: + * 0 - caller can continue, nothing running or the status is not available + * 1 - another operation running + * <0 - there was another error + */ +int check_running_fs_exclop(int fd, const char *desc, bool enqueue) +{ + int sysfs_fd; + int exclop; + int ret; + + sysfs_fd = sysfs_open_fsid_file(fd, "exclusive_operation"); + if (sysfs_fd < 0) { + if (errno == ENOENT) + return 0; + return -errno; + } + + exclop = get_fs_exclop(fd); + if (exclop <= 0) { + ret = 0; + goto out; + } + + if (!enqueue) { + error( + "unable to start %s, another exclusive operation '%s' in progress", + desc, get_fs_exclop_name(exclop)); + ret = 1; + goto out; + } + + while (exclop > 0) { + fd_set fds; + struct timeval tv = { .tv_sec = 60, .tv_usec = 0 }; + + FD_ZERO(&fds); + FD_SET(sysfs_fd, &fds); + + ret = select(sysfs_fd + 1, NULL, NULL, &fds, &tv); + if (ret < 0) { + ret = -errno; + break; + } + if (ret > 0) { + /* + * Notified before the timeout, check again before + * returning. In case there are more operations + * waiting, we want to reduce the chances to race so + * reuse the remaining time to randomize the order. + */ + tv.tv_sec /= 2; + ret = select(sysfs_fd + 1, NULL, NULL, &fds, &tv); + exclop = get_fs_exclop(fd); + continue; + } + } +out: + close(sysfs_fd); + + return ret; +} --- a/utils.h +++ b/utils.h @@ -124,6 +124,7 @@ int get_fsid(const char *path, u8 *fsid, int silent); int get_fsid_fd(int fd, u8 *fsid); int get_fs_exclop(int fd); +int check_running_fs_exclop(int fd, const char *desc, bool enqueue); const char *get_fs_exclop_name(int op); int is_seen_fsid(u8 *fsid, struct seen_fsid *seen_fsid_hash[]);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor