]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: add parent pointer ioctls
authorDarrick J. Wong <djwong@kernel.org>
Mon, 29 Jul 2024 23:22:49 +0000 (16:22 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 30 Jul 2024 00:01:03 +0000 (17:01 -0700)
Source kernel commit: 233f4e12bbb2c5fb1588b857336a26e8bb6942af

This patch adds a pair of new file ioctls to retrieve the parent pointer
of a given inode.  They both return the same results, but one operates
on the file descriptor passed to ioctl() whereas the other allows the
caller to specify a file handle for which the caller wants results.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/xfs_fs.h
libxfs/xfs_ondisk.h
libxfs/xfs_parent.c
libxfs/xfs_parent.h

index 97384ab95de431433c4af3f0c7d91b2300ba2bd9..ea654df0505f21538f93edb3d8d75e4e3c0a670a 100644 (file)
@@ -816,6 +816,78 @@ struct xfs_exchange_range {
                                         XFS_EXCHANGE_RANGE_DRY_RUN | \
                                         XFS_EXCHANGE_RANGE_FILE1_WRITTEN)
 
+/* Iterating parent pointers of files. */
+
+/* target was the root directory */
+#define XFS_GETPARENTS_OFLAG_ROOT      (1U << 0)
+
+/* Cursor is done iterating pptrs */
+#define XFS_GETPARENTS_OFLAG_DONE      (1U << 1)
+
+#define XFS_GETPARENTS_OFLAGS_ALL      (XFS_GETPARENTS_OFLAG_ROOT | \
+                                        XFS_GETPARENTS_OFLAG_DONE)
+
+#define XFS_GETPARENTS_IFLAGS_ALL      (0)
+
+struct xfs_getparents_rec {
+       struct xfs_handle       gpr_parent; /* Handle to parent */
+       __u32                   gpr_reclen; /* Length of entire record */
+       __u32                   gpr_reserved; /* zero */
+       char                    gpr_name[]; /* Null-terminated filename */
+};
+
+/* Iterate through this file's directory parent pointers */
+struct xfs_getparents {
+       /*
+        * Structure to track progress in iterating the parent pointers.
+        * Must be initialized to zeroes before the first ioctl call, and
+        * not touched by callers after that.
+        */
+       struct xfs_attrlist_cursor      gp_cursor;
+
+       /* Input flags: XFS_GETPARENTS_IFLAG* */
+       __u16                           gp_iflags;
+
+       /* Output flags: XFS_GETPARENTS_OFLAG* */
+       __u16                           gp_oflags;
+
+       /* Size of the gp_buffer in bytes */
+       __u32                           gp_bufsize;
+
+       /* Must be set to zero */
+       __u64                           gp_reserved;
+
+       /* Pointer to a buffer in which to place xfs_getparents_rec */
+       __u64                           gp_buffer;
+};
+
+static inline struct xfs_getparents_rec *
+xfs_getparents_first_rec(struct xfs_getparents *gp)
+{
+       return (struct xfs_getparents_rec *)(uintptr_t)gp->gp_buffer;
+}
+
+static inline struct xfs_getparents_rec *
+xfs_getparents_next_rec(struct xfs_getparents *gp,
+                       struct xfs_getparents_rec *gpr)
+{
+       void *next = ((void *)gpr + gpr->gpr_reclen);
+       void *end = (void *)(uintptr_t)(gp->gp_buffer + gp->gp_bufsize);
+
+       if (next >= end)
+               return NULL;
+
+       return next;
+}
+
+/* Iterate through this file handle's directory parent pointers. */
+struct xfs_getparents_by_handle {
+       /* Handle to file whose parents we want. */
+       struct xfs_handle               gph_handle;
+
+       struct xfs_getparents           gph_request;
+};
+
 /*
  * ioctl commands that are used by Linux filesystems
  */
@@ -851,6 +923,8 @@ struct xfs_exchange_range {
 /*     XFS_IOC_GETFSMAP ------ hoisted 59         */
 #define XFS_IOC_SCRUB_METADATA _IOWR('X', 60, struct xfs_scrub_metadata)
 #define XFS_IOC_AG_GEOMETRY    _IOWR('X', 61, struct xfs_ag_geometry)
+#define XFS_IOC_GETPARENTS     _IOWR('X', 62, struct xfs_getparents)
+#define XFS_IOC_GETPARENTS_BY_HANDLE _IOWR('X', 63, struct xfs_getparents_by_handle)
 
 /*
  * ioctl commands that replace IRIX syssgi()'s
index 25952ef584eeea1171a7f6119f8782da220b3cf2..e8cdd77d03fa83efa34bc04e012aeed38dac09f9 100644 (file)
@@ -156,6 +156,11 @@ xfs_check_ondisk_structs(void)
        XFS_CHECK_OFFSET(struct xfs_efi_log_format_32, efi_extents,     16);
        XFS_CHECK_OFFSET(struct xfs_efi_log_format_64, efi_extents,     16);
 
+       /* parent pointer ioctls */
+       XFS_CHECK_STRUCT_SIZE(struct xfs_getparents_rec,        32);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_getparents,            40);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_getparents_by_handle,  64);
+
        /*
         * The v5 superblock format extended several v4 header structures with
         * additional data. While new fields are only accessible on v5
index a53b7d13d324a8c552e26caf478c025d5ea9cf90..bb046519746a06d0a54360ea46806a508d49eeeb 100644 (file)
@@ -254,3 +254,37 @@ xfs_parent_replacename(
        xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_REPLACE);
        return 0;
 }
+
+/*
+ * Extract parent pointer information from any parent pointer xattr into
+ * @parent_ino/gen.  The last two parameters can be NULL pointers.
+ *
+ * Returns 0 if this is not a parent pointer xattr at all; or -EFSCORRUPTED for
+ * garbage.
+ */
+int
+xfs_parent_from_attr(
+       struct xfs_mount        *mp,
+       unsigned int            attr_flags,
+       const unsigned char     *name,
+       unsigned int            namelen,
+       const void              *value,
+       unsigned int            valuelen,
+       xfs_ino_t               *parent_ino,
+       uint32_t                *parent_gen)
+{
+       const struct xfs_parent_rec     *rec = value;
+
+       ASSERT(attr_flags & XFS_ATTR_PARENT);
+
+       if (!xfs_parent_namecheck(attr_flags, name, namelen))
+               return -EFSCORRUPTED;
+       if (!xfs_parent_valuecheck(mp, value, valuelen))
+               return -EFSCORRUPTED;
+
+       if (parent_ino)
+               *parent_ino = be64_to_cpu(rec->p_ino);
+       if (parent_gen)
+               *parent_gen = be32_to_cpu(rec->p_gen);
+       return 0;
+}
index 768633b313671a32f23fc7a8477e8bed4a1b4c38..d7ab09e738ad42df52517132908978bdd38ca719 100644 (file)
@@ -91,4 +91,9 @@ int xfs_parent_replacename(struct xfs_trans *tp,
                struct xfs_inode *new_dp, const struct xfs_name *new_name,
                struct xfs_inode *child);
 
+int xfs_parent_from_attr(struct xfs_mount *mp, unsigned int attr_flags,
+               const unsigned char *name, unsigned int namelen,
+               const void *value, unsigned int valuelen,
+               xfs_ino_t *parent_ino, uint32_t *parent_gen);
+
 #endif /* __XFS_PARENT_H__ */