252 lines
8.3 KiB
Diff
252 lines
8.3 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Martin Wilck <mwilck@suse.com>
|
||
|
Date: Tue, 5 Jul 2022 17:51:41 +0200
|
||
|
Subject: [PATCH] libmultipath: sysfs_attr_set_value(): don't return 0 on
|
||
|
partial write
|
||
|
|
||
|
sysfs_attr_set_value() returned 0 if not all requested bytes were written.
|
||
|
Change this to return the number of bytes written. Error checking is now
|
||
|
somewhat more involved; provide a helper macro for it.
|
||
|
|
||
|
Signed-off-by: Martin Wilck <mwilck@suse.com>
|
||
|
Reviewed-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||
|
Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>
|
||
|
---
|
||
|
libmultipath/configure.c | 10 ++++--
|
||
|
libmultipath/discovery.c | 74 +++++++++++++++++++++++++---------------
|
||
|
libmultipath/sysfs.c | 6 ++--
|
||
|
libmultipath/sysfs.h | 10 ++++++
|
||
|
4 files changed, 66 insertions(+), 34 deletions(-)
|
||
|
|
||
|
diff --git a/libmultipath/configure.c b/libmultipath/configure.c
|
||
|
index 467bbaa6..0607dbac 100644
|
||
|
--- a/libmultipath/configure.c
|
||
|
+++ b/libmultipath/configure.c
|
||
|
@@ -568,6 +568,7 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload)
|
||
|
struct pathgroup * pgp;
|
||
|
struct path *pp;
|
||
|
char buff[11];
|
||
|
+ ssize_t len;
|
||
|
int i, j, ret, err = 0;
|
||
|
struct udev_device *udd;
|
||
|
int max_sectors_kb;
|
||
|
@@ -600,14 +601,17 @@ sysfs_set_max_sectors_kb(struct multipath *mpp, int is_reload)
|
||
|
}
|
||
|
}
|
||
|
snprintf(buff, 11, "%d", max_sectors_kb);
|
||
|
+ len = strlen(buff);
|
||
|
|
||
|
vector_foreach_slot (mpp->pg, pgp, i) {
|
||
|
vector_foreach_slot(pgp->paths, pp, j) {
|
||
|
ret = sysfs_attr_set_value(pp->udev,
|
||
|
"queue/max_sectors_kb",
|
||
|
- buff, strlen(buff));
|
||
|
- if (ret < 0) {
|
||
|
- condlog(1, "failed setting max_sectors_kb on %s : %s", pp->dev, strerror(-ret));
|
||
|
+ buff, len);
|
||
|
+ if (ret != len) {
|
||
|
+ log_sysfs_attr_set_value(1, ret,
|
||
|
+ "failed setting max_sectors_kb on %s",
|
||
|
+ pp->dev);
|
||
|
err = 1;
|
||
|
}
|
||
|
}
|
||
|
diff --git a/libmultipath/discovery.c b/libmultipath/discovery.c
|
||
|
index 54b1caf0..ee290093 100644
|
||
|
--- a/libmultipath/discovery.c
|
||
|
+++ b/libmultipath/discovery.c
|
||
|
@@ -598,13 +598,15 @@ sysfs_set_eh_deadline(struct path *pp)
|
||
|
len = sprintf(value, "%d", pp->eh_deadline);
|
||
|
|
||
|
ret = sysfs_attr_set_value(hostdev, "eh_deadline",
|
||
|
- value, len + 1);
|
||
|
+ value, len);
|
||
|
/*
|
||
|
* not all scsi drivers support setting eh_deadline, so failing
|
||
|
* is totally reasonable
|
||
|
*/
|
||
|
- if (ret <= 0)
|
||
|
- condlog(3, "%s: failed to set eh_deadline to %s, error %d", udev_device_get_sysname(hostdev), value, -ret);
|
||
|
+ if (ret != len)
|
||
|
+ log_sysfs_attr_set_value(3, ret,
|
||
|
+ "%s: failed to set eh_deadline to %s",
|
||
|
+ udev_device_get_sysname(hostdev), value);
|
||
|
|
||
|
udev_device_unref(hostdev);
|
||
|
return (ret <= 0);
|
||
|
@@ -667,19 +669,22 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||
|
pp->fast_io_fail != MP_FAST_IO_FAIL_OFF) {
|
||
|
/* Check if we need to temporarily increase dev_loss_tmo */
|
||
|
if ((unsigned int)pp->fast_io_fail >= tmo) {
|
||
|
+ ssize_t len;
|
||
|
+
|
||
|
/* Increase dev_loss_tmo temporarily */
|
||
|
snprintf(value, sizeof(value), "%u",
|
||
|
(unsigned int)pp->fast_io_fail + 1);
|
||
|
+ len = strlen(value);
|
||
|
ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
|
||
|
- value, strlen(value));
|
||
|
- if (ret <= 0) {
|
||
|
+ value, len);
|
||
|
+ if (ret != len) {
|
||
|
if (ret == -EBUSY)
|
||
|
condlog(3, "%s: rport blocked",
|
||
|
rport_id);
|
||
|
else
|
||
|
- condlog(0, "%s: failed to set "
|
||
|
- "dev_loss_tmo to %s, error %d",
|
||
|
- rport_id, value, -ret);
|
||
|
+ log_sysfs_attr_set_value(0, ret,
|
||
|
+ "%s: failed to set dev_loss_tmo to %s",
|
||
|
+ rport_id, value);
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
@@ -691,32 +696,39 @@ sysfs_set_rport_tmo(struct multipath *mpp, struct path *pp)
|
||
|
pp->dev_loss = DEFAULT_DEV_LOSS_TMO;
|
||
|
}
|
||
|
if (pp->fast_io_fail != MP_FAST_IO_FAIL_UNSET) {
|
||
|
+ ssize_t len;
|
||
|
+
|
||
|
if (pp->fast_io_fail == MP_FAST_IO_FAIL_OFF)
|
||
|
sprintf(value, "off");
|
||
|
else if (pp->fast_io_fail == MP_FAST_IO_FAIL_ZERO)
|
||
|
sprintf(value, "0");
|
||
|
else
|
||
|
snprintf(value, 16, "%u", pp->fast_io_fail);
|
||
|
+ len = strlen(value);
|
||
|
ret = sysfs_attr_set_value(rport_dev, "fast_io_fail_tmo",
|
||
|
- value, strlen(value));
|
||
|
- if (ret <= 0) {
|
||
|
+ value, len);
|
||
|
+ if (ret != len) {
|
||
|
if (ret == -EBUSY)
|
||
|
condlog(3, "%s: rport blocked", rport_id);
|
||
|
else
|
||
|
- condlog(0, "%s: failed to set fast_io_fail_tmo to %s, error %d",
|
||
|
- rport_id, value, -ret);
|
||
|
+ log_sysfs_attr_set_value(0, ret,
|
||
|
+ "%s: failed to set fast_io_fail_tmo to %s",
|
||
|
+ rport_id, value);
|
||
|
}
|
||
|
}
|
||
|
if (pp->dev_loss != DEV_LOSS_TMO_UNSET) {
|
||
|
+ ssize_t len;
|
||
|
+
|
||
|
snprintf(value, 16, "%u", pp->dev_loss);
|
||
|
- ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo",
|
||
|
- value, strlen(value));
|
||
|
- if (ret <= 0) {
|
||
|
+ len = strlen(value);
|
||
|
+ ret = sysfs_attr_set_value(rport_dev, "dev_loss_tmo", value, len);
|
||
|
+ if (ret != len) {
|
||
|
if (ret == -EBUSY)
|
||
|
condlog(3, "%s: rport blocked", rport_id);
|
||
|
else
|
||
|
- condlog(0, "%s: failed to set dev_loss_tmo to %s, error %d",
|
||
|
- rport_id, value, -ret);
|
||
|
+ log_sysfs_attr_set_value(0, ret,
|
||
|
+ "%s: failed to set dev_loss_tmo to %s",
|
||
|
+ rport_id, value);
|
||
|
}
|
||
|
}
|
||
|
out:
|
||
|
@@ -754,12 +766,16 @@ sysfs_set_session_tmo(struct path *pp)
|
||
|
condlog(3, "%s: can't set fast_io_fail_tmo to '0'"
|
||
|
"on iSCSI", pp->dev);
|
||
|
} else {
|
||
|
+ ssize_t len, ret;
|
||
|
+
|
||
|
snprintf(value, 11, "%u", pp->fast_io_fail);
|
||
|
- if (sysfs_attr_set_value(session_dev, "recovery_tmo",
|
||
|
- value, strlen(value)) <= 0) {
|
||
|
- condlog(3, "%s: Failed to set recovery_tmo, "
|
||
|
- " error %d", pp->dev, errno);
|
||
|
- }
|
||
|
+ len = strlen(value);
|
||
|
+ ret = sysfs_attr_set_value(session_dev, "recovery_tmo",
|
||
|
+ value, len);
|
||
|
+ if (ret != len)
|
||
|
+ log_sysfs_attr_set_value(3, ret,
|
||
|
+ "%s: Failed to set recovery_tmo to %s",
|
||
|
+ pp->dev, value);
|
||
|
}
|
||
|
}
|
||
|
udev_device_unref(session_dev);
|
||
|
@@ -802,12 +818,16 @@ sysfs_set_nexus_loss_tmo(struct path *pp)
|
||
|
pp->sg_id.channel, pp->sg_id.scsi_id, end_dev_id);
|
||
|
|
||
|
if (pp->dev_loss != DEV_LOSS_TMO_UNSET) {
|
||
|
+ ssize_t len, ret;
|
||
|
+
|
||
|
snprintf(value, 11, "%u", pp->dev_loss);
|
||
|
- if (sysfs_attr_set_value(sas_dev, "I_T_nexus_loss_timeout",
|
||
|
- value, strlen(value)) <= 0)
|
||
|
- condlog(3, "%s: failed to update "
|
||
|
- "I_T Nexus loss timeout, error %d",
|
||
|
- pp->dev, errno);
|
||
|
+ len = strlen(value);
|
||
|
+ ret = sysfs_attr_set_value(sas_dev, "I_T_nexus_loss_timeout",
|
||
|
+ value, len);
|
||
|
+ if (ret != len)
|
||
|
+ log_sysfs_attr_set_value(3, ret,
|
||
|
+ "%s: failed to update I_T Nexus loss timeout",
|
||
|
+ pp->dev);
|
||
|
}
|
||
|
udev_device_unref(sas_dev);
|
||
|
return;
|
||
|
diff --git a/libmultipath/sysfs.c b/libmultipath/sysfs.c
|
||
|
index 125f1c2b..9c84af70 100644
|
||
|
--- a/libmultipath/sysfs.c
|
||
|
+++ b/libmultipath/sysfs.c
|
||
|
@@ -134,7 +134,7 @@ ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
|
||
|
/* write attribute value */
|
||
|
fd = open(devpath, O_WRONLY);
|
||
|
if (fd < 0) {
|
||
|
- condlog(2, "%s: attribute '%s' can not be opened: %s",
|
||
|
+ condlog(3, "%s: attribute '%s' can not be opened: %s",
|
||
|
__func__, devpath, strerror(errno));
|
||
|
return -errno;
|
||
|
}
|
||
|
@@ -144,11 +144,9 @@ ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
|
||
|
size = -errno;
|
||
|
condlog(3, "%s: write to %s failed: %s", __func__,
|
||
|
devpath, strerror(errno));
|
||
|
- } else if (size < (ssize_t)value_len) {
|
||
|
+ } else if (size < (ssize_t)value_len)
|
||
|
condlog(3, "%s: underflow writing %zu bytes to %s. Wrote %zd bytes",
|
||
|
__func__, value_len, devpath, size);
|
||
|
- size = 0;
|
||
|
- }
|
||
|
|
||
|
close(fd);
|
||
|
return size;
|
||
|
diff --git a/libmultipath/sysfs.h b/libmultipath/sysfs.h
|
||
|
index cdc84e40..799f68e9 100644
|
||
|
--- a/libmultipath/sysfs.h
|
||
|
+++ b/libmultipath/sysfs.h
|
||
|
@@ -5,6 +5,7 @@
|
||
|
#ifndef _LIBMULTIPATH_SYSFS_H
|
||
|
#define _LIBMULTIPATH_SYSFS_H
|
||
|
#include <stdbool.h>
|
||
|
+#include "strbuf.h"
|
||
|
|
||
|
ssize_t sysfs_attr_set_value(struct udev_device *dev, const char *attr_name,
|
||
|
const char * value, size_t value_len);
|
||
|
@@ -25,6 +26,15 @@ ssize_t sysfs_bin_attr_get_value(struct udev_device *dev, const char *attr_name,
|
||
|
sysfs_attr_value_ok(__rc, __l); \
|
||
|
})
|
||
|
|
||
|
+#define log_sysfs_attr_set_value(prio, rc, fmt, __args...) \
|
||
|
+do { \
|
||
|
+ STRBUF_ON_STACK(__buf); \
|
||
|
+ if (print_strbuf(&__buf, fmt, ##__args) >= 0 && \
|
||
|
+ print_strbuf(&__buf, ": %s", rc < 0 ? strerror(-rc) : \
|
||
|
+ "write underflow") >= 0) \
|
||
|
+ condlog(prio, "%s", get_strbuf_str(&__buf)); \
|
||
|
+} while(0)
|
||
|
+
|
||
|
int sysfs_get_size (struct path *pp, unsigned long long * size);
|
||
|
int sysfs_check_holders(char * check_devt, char * new_devt);
|
||
|
bool sysfs_is_multipathed(struct path *pp, bool set_wwid);
|