device-mapper-multipath/0028-libmultipath-use-atomic-linkat-in-mark_failed_wwid.patch
Benjamin Marzinski 2b0cd7cceb device-mapper-multipath-0.8.4-2
Rebased on top of Martin Wilck's queue of ACKed upstream commits
  * https://github.com/openSUSE/multipath-tools/tree/upstream-queue
  * All previous patches have been reordered, with the exception of
    0011-libdmmp-Add-support-for-upcoming-json-c-0.14.0.patch
    which has been replaced with
    0029-fix-boolean-value-with-json-c-0.14.patch
Modify 0054-RH-add-mpathconf.patch
  * remove default enable_foreign and property blacklist_exceptions
    settings, and deal with the builtin default change from
    0031-libmultipath-set-enable_foreign-to-NONE-by-default.patch.
    Fixes bz #1853668
Add 0048-Makefile.inc-trim-extra-information-from-systemd-ver.patch
Add 0049-kpartx-fix-Wsign-compare-error.patch
  * The above two patches have been submitted upstream
2020-07-08 23:16:57 -05:00

97 lines
2.8 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@suse.com>
Date: Tue, 19 May 2020 12:08:45 -0500
Subject: [PATCH] libmultipath: use atomic linkat() in mark_failed_wwid()
This keeps (almost) the simplicity of the previous patch, while
making sure that the return value of mark_failed_wwid()
(WWID_FAILED_CHANGED vs. WWID_FAILED_UNCHANGED) is correct, even
if several processes access this WWID at the same time.
Signed-off-by: Martin Wilck <mwilck@suse.com>
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
---
libmultipath/wwids.c | 42 +++++++++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 13 deletions(-)
diff --git a/libmultipath/wwids.c b/libmultipath/wwids.c
index aab5da8a..61d9c39e 100644
--- a/libmultipath/wwids.c
+++ b/libmultipath/wwids.c
@@ -374,7 +374,7 @@ int is_failed_wwid(const char *wwid)
if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
condlog(1, "%s: path name overflow", __func__);
- return -1;
+ return WWID_FAILED_ERROR;
}
if (lstat(path, &st) == 0)
@@ -390,27 +390,43 @@ int is_failed_wwid(const char *wwid)
int mark_failed_wwid(const char *wwid)
{
- char path[PATH_MAX];
- int r, fd;
+ char tmpfile[WWID_SIZE + 2 * sizeof(long) + 1];
+ int r = WWID_FAILED_ERROR, fd, dfd;
- if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
- condlog(1, "%s: path name overflow", __func__);
- return -1;
+ dfd = open(shm_dir, O_RDONLY|O_DIRECTORY);
+ if (dfd == -1 && errno == ENOENT) {
+ char path[sizeof(shm_dir) + 2];
+
+ /* arg for ensure_directories_exist() must not end with "/" */
+ safe_sprintf(path, "%s/_", shm_dir);
+ ensure_directories_exist(path, 0700);
+ dfd = open(shm_dir, O_RDONLY|O_DIRECTORY);
}
- if (ensure_directories_exist(path, 0700) < 0) {
- condlog(1, "%s: can't setup directories", __func__);
- return -1;
+ if (dfd == -1) {
+ condlog(1, "%s: can't setup %s: %m", __func__, shm_dir);
+ return WWID_FAILED_ERROR;
}
- fd = open(path, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR);
- if (fd >= 0) {
+ safe_sprintf(tmpfile, "%s.%lx", wwid, (long)getpid());
+ fd = openat(dfd, tmpfile, O_RDONLY | O_CREAT | O_EXCL, S_IRUSR);
+ if (fd >= 0)
close(fd);
+ else
+ goto out_closedir;
+
+ if (linkat(dfd, tmpfile, dfd, wwid, 0) == 0)
r = WWID_FAILED_CHANGED;
- } else if (errno == EEXIST)
+ else if (errno == EEXIST)
r = WWID_FAILED_UNCHANGED;
else
r = WWID_FAILED_ERROR;
+ if (unlinkat(dfd, tmpfile, 0) == -1)
+ condlog(2, "%s: failed to unlink %s/%s: %m",
+ __func__, shm_dir, tmpfile);
+
+out_closedir:
+ close(dfd);
print_failed_wwid_result("mark_failed", wwid, r);
return r;
}
@@ -422,7 +438,7 @@ int unmark_failed_wwid(const char *wwid)
if (safe_sprintf(path, "%s/%s", shm_dir, wwid)) {
condlog(1, "%s: path name overflow", __func__);
- return -1;
+ return WWID_FAILED_ERROR;
}
if (unlink(path) == 0)
--
2.17.2