From 74f85ff93da6848a30f097a306d87500a45a89bf Mon Sep 17 00:00:00 2001 From: Benjamin LaHaise Date: Wed, 20 May 2020 16:19:45 -0400 Subject: [PATCH] scoutfs: add data_wait_err for reporting errors Add support for reporting errors to data waiters via a new SCOUTFS_IOC_DATA_WAIT_ERR ioctl. This allows waiters to return an error to readers when staging fails. Signed-off-by: Benjamin LaHaise [zab: renamed to data_wait_err, took ino arg] Signed-off-by: Zach Brown --- utils/src/ioctl.h | 17 +++++++++ utils/src/sparse.h | 1 + utils/src/waiting.c | 90 ++++++++++++++++++++++++++++++++++++--------- 3 files changed, 90 insertions(+), 18 deletions(-) diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index df0c1b54..4b635f88 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -346,5 +346,22 @@ struct scoutfs_ioctl_statfs_more { #define SCOUTFS_IOC_STATFS_MORE _IOR(SCOUTFS_IOCTL_MAGIC, 10, \ struct scoutfs_ioctl_statfs_more) +/* + * Cause matching waiters to return an error. + * + * Find current waiters that match the inode, op, and block range to wake + * up and return an error. + */ +struct scoutfs_ioctl_data_wait_err { + __u64 ino; + __u64 data_version; + __u64 offset; + __u64 count; + __u64 op; + __s64 err; +}; + +#define SCOUTFS_IOC_DATA_WAIT_ERR _IOR(SCOUTFS_IOCTL_MAGIC, 11, \ + struct scoutfs_ioctl_data_wait_err) #endif diff --git a/utils/src/sparse.h b/utils/src/sparse.h index 16fddc54..6cd08345 100644 --- a/utils/src/sparse.h +++ b/utils/src/sparse.h @@ -33,6 +33,7 @@ typedef u16 __u16; typedef u32 __u32; typedef s32 __s32; typedef u64 __u64; +typedef s64 __s64; typedef u16 __sp_biwise __le16; typedef u16 __sp_biwise __be16; diff --git a/utils/src/waiting.c b/utils/src/waiting.c index 72f32b17..414a3c4c 100644 --- a/utils/src/waiting.c +++ b/utils/src/waiting.c @@ -14,25 +14,11 @@ #include "format.h" #include "ioctl.h" #include "cmd.h" +#include "parse.h" -static int parse_u64(char *str, u64 *val_ret) -{ - unsigned long long ull; - char *endptr = NULL; - - ull = strtoull(str, &endptr, 0); - if (*endptr != '\0' || - ((ull == LLONG_MIN || ull == LLONG_MAX) && - errno == ERANGE)) { - fprintf(stderr, "invalid 64bit value: '%s'\n", str); - *val_ret = 0; - return -EINVAL; - } - - *val_ret = ull; - - return 0; -} +#ifndef MAX_ERRNO +#define MAX_ERRNO 4095 +#endif #define OP_FMT "%s%s" @@ -110,3 +96,71 @@ static void __attribute__((constructor)) waiting_ctor(void) cmd_register("data-waiting", " ", "print ops waiting for data blocks", waiting_cmd); } + +static int data_wait_err_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_data_wait_err args; + int fd = -1; + int ret; + + memset(&args, 0, sizeof(args)); + + if (argc != 8) { + fprintf(stderr, "must specify path, ino, version, offset, count,op, and err\n"); + return -EINVAL; + } + + ret = parse_u64(argv[2], &args.ino) ?: + parse_u64(argv[3], &args.data_version) ?: + parse_u64(argv[4], &args.offset) ?: + parse_u64(argv[5], &args.count) ?: + parse_s64(argv[7], &args.err); + if (ret) + return ret; + + if ((args.err >= 0) || (args.err < -MAX_ERRNO)) { + fprintf(stderr, "err %lld invalid\n", args.err); + ret = -EINVAL; + goto out; + } + + if (!strcmp(argv[6], "read")) { + args.op = SCOUTFS_IOC_DWO_READ; + } else if (!strcmp(argv[6], "write")) { + args.op = SCOUTFS_IOC_DWO_WRITE; + } else if (!strcmp(argv[6], "change_size")) { + args.op = SCOUTFS_IOC_DWO_CHANGE_SIZE; + } else { + fprintf(stderr, "invalid data wait op: '%s'\n", argv[6]); + return -EINVAL; + } + + fd = open(argv[1], O_RDONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + argv[1], strerror(errno), errno); + return ret; + } + + ret = ioctl(fd, SCOUTFS_IOC_DATA_WAIT_ERR, &args); + if (ret < 0) { + fprintf(stderr, "data_wait_err returned %d: error %s (%d)\n", + ret, strerror(errno), errno); + ret = -EIO; + goto out; + } + printf("data_wait_err found %d waiters.\n", ret); + +out: + if (fd > -1) + close(fd); + return ret; +}; + +static void __attribute__((constructor)) data_wait_err_ctor(void) +{ + cmd_register("data-wait-err", " ", + "return error from matching waiters", + data_wait_err_cmd); +}