]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
libfrog: add a function to grab the path from an open fd and a file handle
authorDarrick J. Wong <djwong@kernel.org>
Sun, 22 Feb 2026 22:41:12 +0000 (14:41 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Thu, 9 Apr 2026 22:30:16 +0000 (15:30 -0700)
handle_walk_paths operates on a file handle, but requires that the fs
has been registered with libhandle via path_to_fshandle.  For a normal
libhandle client this is the desirable behavior because the application
*should* maintain an open fd to the filesystem mount.

However for xfs_healer this isn't going to work well because the healer
mustn't pin the mount while it's running.  It's smart enough to know how
to find and reconnect to the mountpoint, but libhandle doesn't have any
such concept.

Therefore, alter the libfrog getparents code so that xfs_healer can pass
in the mountpoint and reconnected fd without needing libhandle.  All
we're really doing here is trying to obtain a user-visible path for a
file that encountered problems for logging purposes; if it fails, we'll
fall back to logging the inode number.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libfrog/getparents.c
libfrog/getparents.h

index 9118b0ff32db0d9a0a6af006eb3075aa9a3e28c3..e8f545392634e49bcffa7c70c2ec57c35200beab 100644 (file)
@@ -112,9 +112,13 @@ out_buf:
        return ret;
 }
 
-/* Walk all parent pointers of this handle.  Returns 0 or positive errno. */
-int
-handle_walk_parents(
+/*
+ * Walk all parent pointers of this handle using the given fd to query the
+ * filesystem.  Returns 0 or positive errno.
+ */
+static int
+handle_walk_parents_fd(
+       int                     fd,
        const void              *hanp,
        size_t                  hlen,
        size_t                  bufsize,
@@ -123,21 +127,11 @@ handle_walk_parents(
 {
        struct xfs_getparents_by_handle gph = { };
        void                    *buf;
-       char                    *mntpt;
-       int                     fd;
        int                     ret;
 
        if (hlen != sizeof(struct xfs_handle))
                return EINVAL;
 
-       /*
-        * This function doesn't modify the handle, but we don't want to have
-        * to bump the libhandle major version just to change that.
-        */
-       fd = handle_to_fsfd((void *)hanp, &mntpt);
-       if (fd < 0)
-               return errno;
-
        buf = alloc_records(&gph.gph_request, bufsize);
        if (!buf)
                return errno;
@@ -158,6 +152,29 @@ out_buf:
        return ret;
 }
 
+/* Walk all parent pointers of this handle.  Returns 0 or positive errno. */
+int
+handle_walk_parents(
+       const void              *hanp,
+       size_t                  hlen,
+       size_t                  bufsize,
+       walk_parent_fn          fn,
+       void                    *arg)
+{
+       char                    *mntpt;
+       int                     fd;
+
+       /*
+        * This function doesn't modify the handle, but we don't want to have
+        * to bump the libhandle major version just to change that.
+        */
+       fd = handle_to_fsfd((void *)hanp, &mntpt);
+       if (fd < 0)
+               return errno;
+
+       return handle_walk_parents_fd(fd, hanp, hlen, bufsize, fn, arg);
+}
+
 struct walk_ppaths_info {
        /* Callback */
        walk_path_fn            fn;
@@ -169,7 +186,11 @@ struct walk_ppaths_info {
        /* Path that we're constructing. */
        struct path_list        *path;
 
+       /* Use this much memory per call. */
        size_t                  ioctl_bufsize;
+
+       /* Use this fd for calling the getparents ioctl. */
+       int                     mntfd;
 };
 
 /*
@@ -200,8 +221,14 @@ find_parent_component(
                return errno;
        path_list_add_parent_component(wpi->path, pc);
 
-       ret = handle_walk_parents(&rec->p_handle, sizeof(rec->p_handle),
-                       wpi->ioctl_bufsize, find_parent_component, wpi);
+       if (wpi->mntfd >= 0)
+               ret = handle_walk_parents_fd(wpi->mntfd, &rec->p_handle,
+                               sizeof(rec->p_handle), wpi->ioctl_bufsize,
+                               find_parent_component, wpi);
+       else
+               ret = handle_walk_parents(&rec->p_handle,
+                               sizeof(rec->p_handle), wpi->ioctl_bufsize,
+                               find_parent_component, wpi);
 
        path_list_del_component(wpi->path, pc);
        path_component_free(pc);
@@ -222,6 +249,7 @@ handle_walk_paths(
 {
        struct walk_ppaths_info wpi = {
                .ioctl_bufsize  = ioctl_bufsize,
+               .mntfd          = -1,
        };
        int                     ret;
 
@@ -246,6 +274,41 @@ handle_walk_paths(
        return ret;
 }
 
+/*
+ * Call the given function on all known paths from the vfs root to the inode
+ * described in the handle using an already open mountpoint and fd.  Returns 0
+ * for success or positive errno.
+ */
+int
+handle_walk_paths_fd(
+       const char              *mntpt,
+       int                     mntfd,
+       const void              *hanp,
+       size_t                  hlen,
+       size_t                  ioctl_bufsize,
+       walk_path_fn            fn,
+       void                    *arg)
+{
+       struct walk_ppaths_info wpi = {
+               .ioctl_bufsize  = ioctl_bufsize,
+               .mntfd          = mntfd,
+               .mntpt          = (char *)mntpt,
+       };
+       int                     ret;
+
+       wpi.path = path_list_init();
+       if (!wpi.path)
+               return errno;
+       wpi.fn = fn;
+       wpi.arg = arg;
+
+       ret = handle_walk_parents_fd(mntfd, hanp, hlen, ioctl_bufsize,
+                       find_parent_component, &wpi);
+
+       path_list_free(wpi.path);
+       return ret;
+}
+
 /*
  * Call the given function on all known paths from the vfs root to the inode
  * referred to by the file description.  Returns 0 or positive errno.
index 8098d594219b4c2dc9d4ef611e5d4c716f6e6889..e1df30889c76067e92f8205fc7d7dc902cb722f5 100644 (file)
@@ -39,4 +39,8 @@ int fd_to_path(int fd, size_t ioctl_bufsize, char *path, size_t pathlen);
 int handle_to_path(const void *hanp, size_t hlen, size_t ioctl_bufsize,
                char *path, size_t pathlen);
 
+int handle_walk_paths_fd(const char *mntpt, int mntfd, const void *hanp,
+               size_t hanlen, size_t ioctl_bufsize, walk_path_fn fn,
+               void *arg);
+
 #endif /* __LIBFROG_GETPARENTS_H_ */