diff --git a/utils/src/format.h b/utils/src/format.h index 685f1d53..d88ed4d4 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -255,13 +255,10 @@ struct scoutfs_dirent { #define SCOUTFS_NAME_LEN 255 /* - * This is arbitrarily limiting the max size of the single buffer - * that's needed in the inode_paths ioctl to return all the paths - * that link to an inode. The structures could easily support much - * more than this but then we'd need to grow a more thorough interface - * for iterating over referring paths. That sounds horrible. + * Just to keep sloppy (int) apps from being confused. 2^31 is good + * enough for everybody. */ -#define SCOUTFS_LINK_MAX 255 +#define SCOUTFS_LINK_MAX (1 << 31) /* * We only use 31 bits for readdir positions so that we don't confuse diff --git a/utils/src/ino_path.c b/utils/src/ino_path.c new file mode 100644 index 00000000..69240a4f --- /dev/null +++ b/utils/src/ino_path.c @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sparse.h" +#include "util.h" +#include "ioctl.h" +#include "cmd.h" + +static int ino_path_cmd(int argc, char **argv) +{ + struct scoutfs_ioctl_ino_path args; + char *endptr = NULL; + char *path; + u64 ino; + int ret; + int fd; + + if (argc != 2) { + fprintf(stderr, "must specify ino and path\n"); + return -EINVAL; + } + + ino = strtoull(argv[0], &endptr, 0); + if (*endptr != '\0' || + ((ino == LLONG_MIN || ino == LLONG_MAX) && errno == ERANGE)) { + fprintf(stderr, "error parsing inode number '%s'\n", + argv[0]); + 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; + } + + path = malloc(PATH_MAX); + if (!path) { + fprintf(stderr, "couldn't allocate %d byte buffer\n", PATH_MAX); + ret = -ENOMEM; + goto out; + } + + args.ino = ino; + args.ctr = 0; + args.path_ptr = (intptr_t)path; + args.path_bytes = PATH_MAX; + do { + ret = ioctl(fd, SCOUTFS_IOC_INO_PATH, &args); + if (ret > 0) + printf("%s\n", path); + } while (ret > 0); + + if (ret < 0) { + ret = -errno; + fprintf(stderr, "inodes_since ioctl failed: %s (%d)\n", + strerror(errno), errno); + } +out: + free(path); + close(fd); + return ret; +}; + +static void __attribute__((constructor)) ino_path_ctor(void) +{ + cmd_register("ino-path", " ", + "print paths that refer to inode #", ino_path_cmd); +} diff --git a/utils/src/ino_paths.c b/utils/src/ino_paths.c deleted file mode 100644 index 17a087e5..00000000 --- a/utils/src/ino_paths.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sparse.h" -#include "util.h" -#include "ioctl.h" -#include "cmd.h" - -static int inode_paths_cmd(int argc, char **argv) -{ - struct scoutfs_ioctl_inode_paths args; - char *endptr; - void *ptr = NULL; - char *path; - u64 ino; - int len; - int ret; - int fd; - - if (argc != 2) { - fprintf(stderr, "must specify ino and path\n"); - return -EINVAL; - } - - ino = strtoull(argv[0], &endptr, 0); - if (*endptr != '\0' || - ((ino == LLONG_MIN || ino == LLONG_MAX) && errno == ERANGE)) { - fprintf(stderr, "error parsing inode number '%s'\n", - argv[0]); - 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; - } - - len = 16 * PATH_MAX; - do { - free(ptr); - ptr = malloc(len); - if (!ptr) { - fprintf(stderr, "couldn't allocate %d byte buffer\n", - len); - ret = -EINVAL; - goto out; - } - - args.ino = ino; - args.buf_ptr = (intptr_t)ptr; - args.buf_len = len; - - ret = ioctl(fd, SCOUTFS_IOC_INODE_PATHS, &args); - if (ret < 0 && errno != EOVERFLOW) { - ret = -errno; - fprintf(stderr, "inodes_since ioctl failed: %s (%d)\n", - strerror(errno), errno); - goto out; - } - - len *= 2; - - } while (ret < 0 && errno == EOVERFLOW); - - path = ptr; - while (*path) { - printf("%s\n", path); - path += strlen(path) + 1; - } - -out: - free(ptr); - close(fd); - return ret; -}; - -static void __attribute__((constructor)) since_ctor(void) -{ - cmd_register("inode-paths", " ", - "print paths that refer to inode #", inode_paths_cmd); -} diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index a4991b69..e5598103 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -24,18 +24,17 @@ struct scoutfs_ioctl_inodes_since { #define SCOUTFS_IOC_INODES_SINCE _IOW(SCOUTFS_IOCTL_MAGIC, 1, \ struct scoutfs_ioctl_inodes_since) -struct scoutfs_ioctl_inode_paths { +/* returns bytes of path buffer set starting at _off, including null */ +struct scoutfs_ioctl_ino_path { __u64 ino; - __u64 buf_ptr; - __u32 buf_len; + __u64 ctr; /* init to 0, set to next */ + __u64 path_ptr; + __u16 path_bytes; /* total buffer space, including null term */ } __packed; -/* - * Fills the callers buffer with all the paths from the root to the - * target inode. - */ -#define SCOUTFS_IOC_INODE_PATHS _IOW(SCOUTFS_IOCTL_MAGIC, 2, \ - struct scoutfs_ioctl_inode_paths) +/* Get a single path from the root to the given inode number */ +#define SCOUTFS_IOC_INO_PATH _IOW(SCOUTFS_IOCTL_MAGIC, 2, \ + struct scoutfs_ioctl_ino_path) /* XXX might as well include a seq? 0 for current behaviour? */ struct scoutfs_ioctl_find_xattr { @@ -52,4 +51,6 @@ struct scoutfs_ioctl_find_xattr { #define SCOUTFS_IOC_FIND_XATTR_VAL _IOW(SCOUTFS_IOCTL_MAGIC, 4, \ struct scoutfs_ioctl_find_xattr) +#define SCOUTFS_IOC_INODE_DATA_SINCE _IOW(SCOUTFS_IOCTL_MAGIC, 5, \ + struct scoutfs_ioctl_inodes_since) #endif