summaryrefslogtreecommitdiffstats
path: root/sysfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysfs.c')
-rw-r--r--sysfs.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/sysfs.c b/sysfs.c
index b3c8b10d..7a81cc5b 100644
--- a/sysfs.c
+++ b/sysfs.c
@@ -73,6 +73,47 @@ void sysfs_free(struct mdinfo *sra)
sra = sra2;
}
}
+/**
+ * write_attr() - write value to fd, don't check errno.
+ * @attr: value to write.
+ * @fd: file descriptor write to.
+ *
+ * Size to write is calculated by strlen().
+ */
+mdadm_status_t write_attr(const char *value, const int fd)
+{
+ return sysfs_write_descriptor(fd, value, strlen(value), NULL);
+}
+
+/**
+ * sysfs_write_descriptor()- wrapper for write(), projected to be used with sysfs.
+ * @fd: file descriptor.
+ * @value: value to set.
+ * @len: length of the value.
+ * @errno_p: On write() failure, buffer to copy errno value, might be NULL.
+ *
+ * Errors are differentiated, because (at least theoretically) kernel may not process whole string
+ * and it may or may not be a problem (it depends on implementation in kernel). Decision belongs to
+ * caller then.
+ * Generally, it should be safe to check if @errno_p changed to determine if error occurred.
+ */
+mdadm_status_t sysfs_write_descriptor(const int fd, const char *value, const ssize_t len,
+ int *errno_p)
+{
+ ssize_t ret;
+
+ ret = write(fd, value, len);
+ if (ret == -1) {
+ if (errno_p)
+ *errno_p = errno;
+ return MDADM_STATUS_ERROR;
+ }
+
+ if (ret != len)
+ return MDADM_STATUS_UNDEF;
+
+ return MDADM_STATUS_SUCCESS;
+}
/**
* sysfs_get_container_devnm() - extract container device name.
@@ -486,7 +527,6 @@ int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev,
char *name, char *val)
{
char fname[MAX_SYSFS_PATH_LEN];
- unsigned int n;
int fd;
snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/%s/md/%s/%s",
@@ -494,13 +534,14 @@ int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev,
fd = open(fname, O_WRONLY);
if (fd < 0)
return -1;
- n = write(fd, val, strlen(val));
- close(fd);
- if (n != strlen(val)) {
- dprintf("failed to write '%s' to '%s' (%s)\n",
- val, fname, strerror(errno));
+
+ if (write_attr(val, fd)) {
+ pr_err("failed to write '%s' to '%s' (%s)\n", val, fname, strerror(errno));
+ close(fd);
return -1;
}
+
+ close(fd);
return 0;
}
@@ -523,7 +564,6 @@ int sysfs_set_num_signed(struct mdinfo *sra, struct mdinfo *dev,
int sysfs_uevent(struct mdinfo *sra, char *event)
{
char fname[MAX_SYSFS_PATH_LEN];
- int n;
int fd;
snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/%s/uevent",
@@ -531,13 +571,14 @@ int sysfs_uevent(struct mdinfo *sra, char *event)
fd = open(fname, O_WRONLY);
if (fd < 0)
return -1;
- n = write(fd, event, strlen(event));
- close(fd);
- if (n != (int)strlen(event)) {
- dprintf("failed to write '%s' to '%s' (%s)\n",
- event, fname, strerror(errno));
+
+ if (write_attr(event, fd)) {
+ pr_err("failed to write '%s' to '%s' (%s)\n", event, fname, strerror(errno));
+ close(fd);
return -1;
}
+
+ close(fd);
return 0;
}