diff options
author | Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com> | 2024-09-24 15:53:18 +0200 |
---|---|---|
committer | Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com> | 2024-09-27 11:08:49 +0200 |
commit | d95edceb362a6b647ec454c2a83add11c4ed4e64 (patch) | |
tree | 0252bfed2ab558eeb9d4a33458a123c9c9cb2afd | |
parent | Incremental: Rename IncrementalRemove (diff) | |
download | mdadm-d95edceb362a6b647ec454c2a83add11c4ed4e64.tar.xz mdadm-d95edceb362a6b647ec454c2a83add11c4ed4e64.zip |
sysfs: add function for writing to sysfs fd
Proposed function sysfs_wrte_descriptor() unifies error handling for
write() done to sysfs files. Main purpose is to use it with MD sysfs
file but it can be used elsewhere.
No functional changes.
Signed-off-by: Mariusz Tkaczyk <mariusz.tkaczyk@linux.intel.com>
-rw-r--r-- | Manage.c | 45 | ||||
-rw-r--r-- | managemon.c | 13 | ||||
-rw-r--r-- | mdadm.h | 3 | ||||
-rw-r--r-- | monitor.c | 12 | ||||
-rw-r--r-- | sysfs.c | 65 | ||||
-rw-r--r-- | util.c | 19 |
6 files changed, 101 insertions, 56 deletions
@@ -1439,7 +1439,7 @@ int Manage_subdevs(char *devname, int fd, for (dv = devlist; dv; dv = dv->next) { dev_t rdev = 0; /* device to add/remove etc */ - int rv; + int rv, err = 0; int mj,mn; raid_slot = -1; @@ -1670,9 +1670,8 @@ int Manage_subdevs(char *devname, int fd, rv = Manage_remove(tst, fd, dv, sysfd, rdev, verbose, force, devname); - if (sysfd >= 0) - close_fd(&sysfd); - sysfd = -1; + close_fd(&sysfd); + if (rv < 0) goto abort; if (rv > 0) @@ -1686,23 +1685,31 @@ int Manage_subdevs(char *devname, int fd, close_fd(&sysfd); goto abort; } - case 'I': /* incremental fail */ - if ((sysfd >= 0 && write(sysfd, "faulty", 6) != 6) || - (sysfd < 0 && ioctl(fd, SET_DISK_FAULTY, - rdev))) { - if (errno == EBUSY) - busy = 1; - pr_err("set device faulty failed for %s: %s\n", - dv->devname, strerror(errno)); - close_fd(&sysfd); - goto abort; + case 'I': + if (is_fd_valid(sysfd)) { + static const char val[] = "faulty"; + + rv = sysfs_write_descriptor(sysfd, val, strlen(val), &err); + } else { + rv = ioctl(fd, SET_DISK_FAULTY, rdev); + if (rv) + err = errno; } + close_fd(&sysfd); - count++; - if (verbose >= 0) - pr_err("set %s faulty in %s\n", - dv->devname, devname); - break; + + if (rv == MDADM_STATUS_SUCCESS) { + count++; + + pr_vrb("set %s faulty in %s\n", dv->devname, devname); + break; + } + + if (err == EBUSY) + busy = 1; + + pr_err("set device faulty failed for %s: %s\n", dv->devname, strerror(err)); + goto abort; case 'R': /* Mark as replaceable */ if (subarray) { pr_err("Cannot replace disks in a \'member\' array, perform this operation on the parent container\n"); diff --git a/managemon.c b/managemon.c index add6a79e..877e8605 100644 --- a/managemon.c +++ b/managemon.c @@ -512,16 +512,9 @@ static void manage_member(struct mdstat_ent *mdstat, if (a->container == NULL) return; - if (sigterm && a->info.safe_mode_delay != 1 && - a->safe_mode_delay_fd >= 0) { - long int new_delay = 1; - char delay[10]; - ssize_t len; - - len = snprintf(delay, sizeof(delay), "0.%03ld\n", new_delay); - if (write(a->safe_mode_delay_fd, delay, len) == len) - a->info.safe_mode_delay = new_delay; - } + if (sigterm && a->info.safe_mode_delay != 1 && a->safe_mode_delay_fd >= 0) + if (write_attr("0.001", a->safe_mode_delay_fd) == MDADM_STATUS_SUCCESS) + a->info.safe_mode_delay = 1; /* We don't check the array while any update is pending, as it * might container a change (such as a spare assignment) which @@ -803,6 +803,9 @@ enum sysfs_read_flags { #define SYSFS_MAX_BUF_SIZE 64 +extern mdadm_status_t sysfs_write_descriptor(const int fd, const char *value, + const ssize_t len, int *errno_p); +extern mdadm_status_t write_attr(const char *value, const int fd); extern void sysfs_get_container_devnm(struct mdinfo *mdi, char *buf); /* If fd >= 0, get the array it is open on, @@ -35,11 +35,6 @@ enum bb_action { COMPARE_BB, }; -static int write_attr(char *attr, int fd) -{ - return write(fd, attr, strlen(attr)); -} - static void add_fd(fd_set *fds, int *maxfd, int fd) { struct stat st; @@ -173,7 +168,7 @@ int process_ubb(struct active_array *a, struct mdinfo *mdi, const unsigned long * via sysfs file */ if ((ss->record_bad_block(a, mdi->disk.raid_disk, sector, length)) && - (write(mdi->bb_fd, buf, buf_len) == buf_len)) + (sysfs_write_descriptor(mdi->bb_fd, buf, buf_len, NULL) == MDADM_STATUS_SUCCESS)) return 1; /* @@ -622,14 +617,11 @@ static int read_and_act(struct active_array *a, fd_set *fds) } if ((mdi->next_state & DS_REMOVE) && mdi->state_fd >= 0) { - int remove_result; - /* The kernel may not be able to immediately remove the * disk. In that case we wait a little while and * try again. */ - remove_result = write_attr("remove", mdi->state_fd); - if (remove_result > 0) { + if (write_attr("remove", mdi->state_fd) == MDADM_STATUS_SUCCESS) { dprintf_cont(" %d:removed", mdi->disk.raid_disk); close(mdi->state_fd); close(mdi->recovery_fd); @@ -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; } @@ -1854,13 +1854,22 @@ int hot_remove_disk(int mdfd, unsigned long dev, int force) int sys_hot_remove_disk(int statefd, int force) { int cnt = force ? 500 : 5; - int ret; + static const char val[] = "faulty"; + + while (cnt--) { + int err = 0; + int ret = sysfs_write_descriptor(statefd, val, strlen(val), &err); + + if (ret == MDADM_STATUS_SUCCESS) + return 0; + + if (err != EBUSY) + break; - while ((ret = write(statefd, "remove", 6)) == -1 && - errno == EBUSY && - cnt-- > 0) sleep_for(0, MSEC_TO_NSEC(10), true); - return ret == 6 ? 0 : -1; + } + + return -1; } int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info) |