From 02993a2dd7fd7dda39ceac5ee52c447851bcadcd Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Fri, 3 Feb 2017 13:34:38 -0800 Subject: [PATCH] Update ino_path for the large cursor Previously we could iterate over backref items with a small u64. Now we need a larger opaque buffer. Signed-off-by: Zach Brown --- utils/src/ino_path.c | 15 +++++++++++-- utils/src/ioctl.h | 51 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/utils/src/ino_path.c b/utils/src/ino_path.c index 69240a4f..69c50892 100644 --- a/utils/src/ino_path.c +++ b/utils/src/ino_path.c @@ -18,7 +18,8 @@ static int ino_path_cmd(int argc, char **argv) { struct scoutfs_ioctl_ino_path args; char *endptr = NULL; - char *path; + char *path = NULL; + char *curs = NULL; u64 ino; int ret; int fd; @@ -51,9 +52,18 @@ static int ino_path_cmd(int argc, char **argv) goto out; } + curs = calloc(1, SCOUTFS_IOC_INO_PATH_CURSOR_BYTES); + if (!curs) { + fprintf(stderr, "couldn't allocate %ld byte cursor\n", + SCOUTFS_IOC_INO_PATH_CURSOR_BYTES); + ret = -ENOMEM; + goto out; + } + args.ino = ino; - args.ctr = 0; + args.cursor_ptr = (intptr_t)curs; args.path_ptr = (intptr_t)path; + args.cursor_bytes = SCOUTFS_IOC_INO_PATH_CURSOR_BYTES; args.path_bytes = PATH_MAX; do { ret = ioctl(fd, SCOUTFS_IOC_INO_PATH, &args); @@ -68,6 +78,7 @@ static int ino_path_cmd(int argc, char **argv) } out: free(path); + free(curs); close(fd); return ret; }; diff --git a/utils/src/ioctl.h b/utils/src/ioctl.h index 94963273..5a047328 100644 --- a/utils/src/ioctl.h +++ b/utils/src/ioctl.h @@ -1,6 +1,8 @@ #ifndef _SCOUTFS_IOCTL_H_ #define _SCOUTFS_IOCTL_H_ +#include "format.h" + /* XXX I have no idea how these are chosen. */ #define SCOUTFS_IOCTL_MAGIC 's' @@ -24,18 +26,61 @@ struct scoutfs_ioctl_inodes_since { #define SCOUTFS_IOC_INODES_SINCE _IOW(SCOUTFS_IOCTL_MAGIC, 1, \ struct scoutfs_ioctl_inodes_since) -/* returns bytes of path buffer set starting at _off, including null */ +/* + * Fill the path buffer with the next path to the target inode. An + * iteration cursor is stored in the cursor buffer which advances + * through the paths to the inode at each call. + * + * @ino: The target ino that we're finding paths to. Constant across + * all the calls that make up an iteration over all the inode's paths. + * + * @cursor_ptr: A pointer to the buffer that will hold the iteration + * cursor. It must be initialized to 0 before iterating. Each call + * modifies it to skip past the result of that call. + * + * @cusur_bytes: The length of the cursor buffer. Must be + * SCOUTFS_IOC_INO_PATH_CURSOR_BYTES. + * + * @path_ptr: The buffer to store each found path. + * + * @path_bytes: The size of the buffer that will the found path + * including null termination. (PATH_MAX is a solid choice.) + * + * This only walks back through full hard links. None of the returned + * paths will reflect symlinks to components in the path. + * + * This doesn't ensure that the caller has permissions to traverse the + * returned paths to the inode. It requires CAP_DAC_READ_SEARCH which + * bypasses permissions checking. + * + * ENAMETOOLONG is returned when the next path found from the cursor + * doesn't fit in the path buffer. + * + * This call is not serialized with any modification (create, rename, + * unlink) of the path components. It will return all the paths that + * were stable both before and after the call. It may or may not return + * paths which are created or unlinked during the call. + * + * The number of bytes in the path, including the null terminator, are + * returned when a path is found. 0 is returned when there are no more + * paths to the link to the inode from the cursor. + */ struct scoutfs_ioctl_ino_path { __u64 ino; - __u64 ctr; /* init to 0, set to next */ + __u64 cursor_ptr; __u64 path_ptr; - __u16 path_bytes; /* total buffer space, including null term */ + __u16 cursor_bytes; + __u16 path_bytes; } __packed; +#define SCOUTFS_IOC_INO_PATH_CURSOR_BYTES \ + (sizeof(u64) + SCOUTFS_NAME_LEN + 1) + /* 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 { __u64 first_ino;