From 336a6a155d33c6946d2bb7ac6ca567570405279b Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 24 May 2019 10:38:13 -0700 Subject: [PATCH] scoutfs-utils: add setattr more command Add a command that wraps the setattr_more ioctl. Signed-off-by: Zach Brown --- utils/src/ioctl.h | 18 ++++++++ utils/src/setattr.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+) create mode 100644 utils/src/setattr.c diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 1b592522..e49116b4 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -253,4 +253,22 @@ struct scoutfs_ioctl_data_waiting { #define SCOUTFS_IOC_DATA_WAITING _IOW(SCOUTFS_IOCTL_MAGIC, 9, \ struct scoutfs_ioctl_data_waiting) +/* + * If i_size is set then data_version must be non-zero. If the offline + * flag is set then i_size must be set and a offline extent will be + * created from offset 0 to i_size. + */ +struct scoutfs_ioctl_setattr_more { + __u64 data_version; + __u64 i_size; + __u64 flags; + struct scoutfs_timespec ctime; +} __packed; + +#define SCOUTFS_IOC_SETATTR_MORE_OFFLINE (1 << 0) +#define SCOUTFS_IOC_SETATTR_MORE_UNKNOWN (U8_MAX << 1) + +#define SCOUTFS_IOC_SETATTR_MORE _IOW(SCOUTFS_IOCTL_MAGIC, 10, \ + struct scoutfs_ioctl_setattr_more) + #endif diff --git a/utils/src/setattr.c b/utils/src/setattr.c new file mode 100644 index 00000000..5c29f1f5 --- /dev/null +++ b/utils/src/setattr.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "util.h" +#include "format.h" +#include "ioctl.h" +#include "parse.h" +#include "cmd.h" + +static struct option long_ops[] = { + { "ctime", 1, NULL, 'c' }, + { "data_version", 1, NULL, 'd' }, + { "file", 1, NULL, 'f' }, + { "offline", 0, NULL, 'o' }, + { "i_size", 1, NULL, 's' }, + { NULL, 0, NULL, 0} +}; + +static int setattr_more_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_setattr_more sm; + char *path = NULL; + int ret; + int fd = -1; + int c; + + memset(&sm, 0, sizeof(sm)); + + while ((c = getopt_long(argc, argv, "c:d:f:os:", long_ops, NULL)) != -1) { + switch (c) { + case 'c': + ret = parse_timespec(optarg, &sm.ctime); + if (ret) + goto out; + break; + case 'd': + ret = parse_u64(optarg, &sm.data_version); + if (ret) + goto out; + break; + case 'f': + path = strdup(optarg); + if (!path) { + fprintf(stderr, "path mem alloc failed\n"); + ret = -ENOMEM; + goto out; + } + break; + case 'o': + sm.flags |= SCOUTFS_IOC_SETATTR_MORE_OFFLINE; + break; + case 's': + ret = parse_u64(optarg, &sm.i_size); + if (ret) + goto out; + break; + case '?': + default: + ret = -EINVAL; + goto out; + } + } + + if (path == NULL) { + fprintf(stderr, "must specify -f path to file\n"); + ret = -EINVAL; + goto out; + } + + fd = open(path, O_WRONLY); + if (fd < 0) { + ret = -errno; + fprintf(stderr, "failed to open '%s': %s (%d)\n", + path, strerror(errno), errno); + goto out; + } + + ret = ioctl(fd, SCOUTFS_IOC_SETATTR_MORE, &sm); + if (ret < 0) { + ret = -errno; + fprintf(stderr, "setattr_more ioctl failed on '%s': " + "%s (%d)\n", path, strerror(errno), errno); + goto out; + } + + ret = 0; +out: + if (fd >= 0) + close(fd); + return ret; +} + +static void __attribute__((constructor)) setattr_more_ctor(void) +{ + cmd_register("setattr", "-c ctime -d data_version -o -s i_size -f ", + "set attributes on file with no data", + setattr_more_cmd); +}