mirror of
https://github.com/versity/scoutfs.git
synced 2026-09-05 23:56:58 +00:00
Implement argp support for data-waiting and data-wait-err
These both have a lot of required options. Signed-off-by: Andy Grover <agrover@versity.com>
This commit is contained in:
+216
-58
@@ -8,6 +8,8 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <argp.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "sparse.h"
|
||||
#include "util.h"
|
||||
@@ -31,7 +33,16 @@
|
||||
(((ops) & (bit)) ? (str) : ""), \
|
||||
(((ops) & (bit)) && ((ops) & ~(((bit) << 1) - 1)) ? "," : "")
|
||||
|
||||
static int waiting_cmd(int argc, char **argv)
|
||||
|
||||
struct waiting_args {
|
||||
char *path;
|
||||
bool inode_set;
|
||||
u64 inode;
|
||||
bool blkno_set;
|
||||
u64 blkno;
|
||||
};
|
||||
|
||||
static int do_waiting(struct waiting_args *args)
|
||||
{
|
||||
struct scoutfs_ioctl_data_waiting_entry dwe[16];
|
||||
struct scoutfs_ioctl_data_waiting idw;
|
||||
@@ -39,25 +50,13 @@ static int waiting_cmd(int argc, char **argv)
|
||||
int fd;
|
||||
int i;
|
||||
|
||||
if (argc != 4) {
|
||||
fprintf(stderr, "must specify ino, iblock, and path\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = parse_u64(argv[1], &idw.after_ino) ?:
|
||||
parse_u64(argv[2], &idw.after_iblock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
fd = open(argv[3], O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ret = -errno;
|
||||
fprintf(stderr, "failed to open '%s': %s (%d)\n",
|
||||
argv[3], strerror(errno), errno);
|
||||
return ret;
|
||||
}
|
||||
fd = get_path(args->path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
idw.flags = 0;
|
||||
idw.after_ino = args->inode;
|
||||
idw.after_iblock = args->blkno;
|
||||
idw.ents_ptr = (unsigned long)dwe;
|
||||
idw.ents_nr = array_size(dwe);
|
||||
|
||||
@@ -91,59 +90,114 @@ static int waiting_cmd(int argc, char **argv)
|
||||
return ret;
|
||||
};
|
||||
|
||||
static void __attribute__((constructor)) waiting_ctor(void)
|
||||
static int waiting_parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
cmd_register("data-waiting", "<ino> <iblock> <path>",
|
||||
"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;
|
||||
struct waiting_args *args = state->input;
|
||||
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;
|
||||
switch (key) {
|
||||
case 'p':
|
||||
args->path = strdup_or_error(state, arg);
|
||||
break;
|
||||
case 'I': /* inode */
|
||||
ret = parse_u64(arg, &args->inode);
|
||||
if (ret)
|
||||
argp_error(state, "inode parse error");
|
||||
args->inode_set = true;
|
||||
break;
|
||||
case 'B': /* blkno */
|
||||
ret = parse_u64(arg, &args->blkno);
|
||||
if (ret)
|
||||
argp_error(state, "blkno parse error");
|
||||
args->blkno_set = true;
|
||||
break;
|
||||
case ARGP_KEY_FINI:
|
||||
if (!args->inode_set)
|
||||
argp_error(state, "no inode given");
|
||||
if (!args->blkno_set)
|
||||
argp_error(state, "no blkno given");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option waiting_options[] = {
|
||||
{ "path", 'p', "PATH", 0, "Path to ScoutFS filesystem"},
|
||||
{ "inode", 'I', "INODE-NUM", 0, "Inode number [Required]"},
|
||||
{ "block", 'B', "BLKNO-NUM", 0, "Block number [Required]"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static int waiting_cmd(int argc, char **argv)
|
||||
{
|
||||
struct argp argp = {
|
||||
waiting_options,
|
||||
waiting_parse_opt,
|
||||
"--inode INODE-NUM --block BLOCK-NUM",
|
||||
"Print operations waiting for data blocks"
|
||||
};
|
||||
struct waiting_args waiting_args = {NULL};
|
||||
int ret;
|
||||
|
||||
ret = argp_parse(&argp, argc, argv, 0, NULL, &waiting_args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if ((args.err >= 0) || (args.err < -MAX_ERRNO)) {
|
||||
fprintf(stderr, "err %lld invalid\n", args.err);
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
return do_waiting(&waiting_args);
|
||||
}
|
||||
|
||||
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;
|
||||
static void __attribute__((constructor)) waiting_ctor(void)
|
||||
{
|
||||
cmd_register("data-waiting", "--inode <inode> --blockno <blockno>",
|
||||
"print ops waiting for data blocks", waiting_cmd);
|
||||
}
|
||||
|
||||
struct wait_err_args {
|
||||
char *path;
|
||||
bool inode_set;
|
||||
u64 inode;
|
||||
bool version_set;
|
||||
u64 version;
|
||||
bool offset_set;
|
||||
u64 offset;
|
||||
bool count_set;
|
||||
u64 count;
|
||||
char *op;
|
||||
bool err_set;
|
||||
s64 err;
|
||||
};
|
||||
|
||||
static int do_wait_err(struct wait_err_args *args)
|
||||
{
|
||||
struct scoutfs_ioctl_data_wait_err dwe = {0};
|
||||
int fd = -1;
|
||||
int ret;
|
||||
|
||||
|
||||
dwe.ino = args->inode;
|
||||
dwe.data_version = args->version;
|
||||
dwe.offset = args->offset;
|
||||
dwe.count = args->count;
|
||||
if (!strcmp(args->op, "read")) {
|
||||
dwe.op = SCOUTFS_IOC_DWO_READ;
|
||||
} else if (!strcmp(args->op, "write")) {
|
||||
dwe.op = SCOUTFS_IOC_DWO_WRITE;
|
||||
} else if (!strcmp(args->op, "change_size")) {
|
||||
dwe.op = SCOUTFS_IOC_DWO_CHANGE_SIZE;
|
||||
} else {
|
||||
fprintf(stderr, "invalid data wait op: '%s'\n", argv[6]);
|
||||
fprintf(stderr, "invalid data wait op: '%s'\n", args->op);
|
||||
return -EINVAL;
|
||||
}
|
||||
dwe.err = args->err;
|
||||
|
||||
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;
|
||||
}
|
||||
fd = get_path(args->path, O_RDONLY);
|
||||
if (fd < 0)
|
||||
return fd;
|
||||
|
||||
ret = ioctl(fd, SCOUTFS_IOC_DATA_WAIT_ERR, &args);
|
||||
ret = ioctl(fd, SCOUTFS_IOC_DATA_WAIT_ERR, &dwe);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "data_wait_err returned %d: error %s (%d)\n",
|
||||
ret, strerror(errno), errno);
|
||||
@@ -158,9 +212,113 @@ out:
|
||||
return ret;
|
||||
};
|
||||
|
||||
static int wait_err_parse_opt(int key, char *arg, struct argp_state *state)
|
||||
{
|
||||
struct wait_err_args *args = state->input;
|
||||
int ret;
|
||||
|
||||
switch (key) {
|
||||
case 'p':
|
||||
args->path = strdup_or_error(state, arg);
|
||||
break;
|
||||
case 'I': /* inode */
|
||||
ret = parse_u64(arg, &args->inode);
|
||||
if (ret)
|
||||
argp_error(state, "inode parse error");
|
||||
args->inode_set = true;
|
||||
break;
|
||||
case 'V': /* version */
|
||||
ret = parse_u64(arg, &args->version);
|
||||
if (ret)
|
||||
argp_error(state, "version parse error");
|
||||
args->version_set = true;
|
||||
break;
|
||||
case 'F': /* offset */
|
||||
ret = parse_human(arg, &args->offset);
|
||||
if (ret)
|
||||
argp_error(state, "version parse error");
|
||||
args->offset_set = true;
|
||||
break;
|
||||
case 'C': /* count */
|
||||
ret = parse_u64(arg, &args->count);
|
||||
if (ret)
|
||||
argp_error(state, "count parse error");
|
||||
args->count_set = true;
|
||||
break;
|
||||
case 'O': /* op */
|
||||
args->op = strdup_or_error(state, arg);
|
||||
break;
|
||||
case 'E': /* err */
|
||||
ret = parse_s64(arg, &args->err);
|
||||
if (ret)
|
||||
argp_error(state, "error parse error");
|
||||
if ((args->err >= 0) || (args->err < -MAX_ERRNO))
|
||||
argp_error(state, "errno out of range");
|
||||
args->err_set = true;
|
||||
break;
|
||||
case ARGP_KEY_FINI:
|
||||
if (!args->inode_set)
|
||||
argp_error(state, "no inode given");
|
||||
if (!args->version_set)
|
||||
argp_error(state, "no version given");
|
||||
if (!args->offset_set)
|
||||
argp_error(state, "no offset given");
|
||||
if (!args->count_set)
|
||||
argp_error(state, "no count given");
|
||||
if (!args->op)
|
||||
argp_error(state, "no operation given");
|
||||
if (!args->err_set)
|
||||
argp_error(state, "no error given");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct argp_option wait_err_options[] = {
|
||||
{ "path", 'p', "PATH", 0, "Path to ScoutFS filesystem"},
|
||||
{ "inode", 'I', "INODE-NUM", 0, "Inode number [Required]"},
|
||||
{ "version", 'V', "VER-NUM", 0, "Version [Required]"},
|
||||
{ "offset", 'F', "OFF-NUM", 0, "Offset (bytes or KMGTP units) [Required]"},
|
||||
{ "count", 'C', "COUNT", 0, "Count [Required]"},
|
||||
{ "op", 'O', "OP", 0, "Operation: \"read\", \"write\", \"change_size\" [Required]"},
|
||||
{ "err", 'E', "ERR", 0, "Error [Required]"},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct argp wait_err_argp = {
|
||||
wait_err_options,
|
||||
wait_err_parse_opt,
|
||||
"--inode INODE-NUM --version VER-NUM "
|
||||
"--offset OFF-NUM --count COUNT --op OP --err ERR",
|
||||
"Return error from matching waiters"
|
||||
};
|
||||
|
||||
static int wait_err_cmd(int argc, char **argv)
|
||||
{
|
||||
struct argp argp = {
|
||||
wait_err_options,
|
||||
wait_err_parse_opt,
|
||||
"--inode INODE-NUM --block BLOCK-NUM --version VER-NUM "
|
||||
"--offset OFF-NUM --count COUNT --op OP --err ERR",
|
||||
"Return error from matching waiters"
|
||||
};
|
||||
struct wait_err_args wait_err_args = {NULL};
|
||||
int ret;
|
||||
|
||||
ret = argp_parse(&argp, argc, argv, 0, NULL, &wait_err_args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return do_wait_err(&wait_err_args);
|
||||
}
|
||||
|
||||
|
||||
static void __attribute__((constructor)) data_wait_err_ctor(void)
|
||||
{
|
||||
cmd_register("data-wait-err", "<path> <ino> <vers> <offset> <count> <op> <err>",
|
||||
"return error from matching waiters",
|
||||
data_wait_err_cmd);
|
||||
wait_err_cmd);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user