]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
xfs: check if an open file is on the health monitored fs
authorDarrick J. Wong <djwong@kernel.org>
Wed, 21 Jan 2026 02:06:51 +0000 (18:06 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 21 Jan 2026 02:06:51 +0000 (18:06 -0800)
Create a new ioctl for the healthmon file that checks that a given fd
points to the same filesystem that the healthmon file is monitoring.
This allows xfs_healer to check that when it reopens a mountpoint to
perform repairs, the file that it gets matches the filesystem that
generated the corruption report.

(Note that xfs_healer doesn't maintain an open fd to a filesystem that
it's monitoring so that it doesn't pin the mount.)

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

index 4ec1b2aede976f6ddd72a2f23c8f2ba2d73a17ab..a01303c5de6ce614baa24f04ae181044383019c3 100644 (file)
@@ -1151,6 +1151,15 @@ struct xfs_health_monitor {
 /* Initial return format version */
 #define XFS_HEALTH_MONITOR_FMT_V0      (0)
 
+/*
+ * Check that a given fd points to the same filesystem that the health monitor
+ * is monitoring.
+ */
+struct xfs_health_file_on_monitored_fs {
+       __s32           fd;
+       __u32           flags;  /* zero for now */
+};
+
 /*
  * ioctl commands that are used by Linux filesystems
  */
@@ -1191,7 +1200,8 @@ struct xfs_health_monitor {
 #define XFS_IOC_SCRUBV_METADATA        _IOWR('X', 64, struct xfs_scrub_vec_head)
 #define XFS_IOC_RTGROUP_GEOMETRY _IOWR('X', 65, struct xfs_rtgroup_geometry)
 #define XFS_IOC_HEALTH_MONITOR _IOW ('X', 68, struct xfs_health_monitor)
-
+#define XFS_IOC_HEALTH_FD_ON_MONITORED_FS \
+                               _IOW ('X', 69, struct xfs_health_file_on_monitored_fs)
 /*
  * ioctl commands that replace IRIX syssgi()'s
  */
index 4a8cbd87932201a753d03ffe16991c255a738306..3030fa93c1e5753adb9761cc50a07c54f815dee3 100644 (file)
@@ -1090,6 +1090,38 @@ xfs_healthmon_reconfigure(
        return 0;
 }
 
+/* Does the fd point to the same filesystem as the one we're monitoring? */
+STATIC long
+xfs_healthmon_file_on_monitored_fs(
+       struct file                     *file,
+       unsigned int                    cmd,
+       void __user                     *arg)
+{
+       struct xfs_health_file_on_monitored_fs hms;
+       struct xfs_healthmon            *hm = file->private_data;
+       struct inode                    *hms_inode;
+
+       if (copy_from_user(&hms, arg, sizeof(hms)))
+               return -EFAULT;
+
+       if (hms.flags)
+               return -EINVAL;
+
+       CLASS(fd, hms_fd)(hms.fd);
+       if (fd_empty(hms_fd))
+               return -EBADF;
+
+       hms_inode = file_inode(fd_file(hms_fd));
+       mutex_lock(&hm->lock);
+       if (hm->mount_cookie != (uintptr_t)hms_inode->i_sb) {
+               mutex_unlock(&hm->lock);
+               return -ESTALE;
+       }
+
+       mutex_unlock(&hm->lock);
+       return 0;
+}
+
 /* Handle ioctls for the health monitoring thread. */
 STATIC long
 xfs_healthmon_ioctl(
@@ -1102,6 +1134,8 @@ xfs_healthmon_ioctl(
        switch (cmd) {
        case XFS_IOC_HEALTH_MONITOR:
                return xfs_healthmon_reconfigure(file, cmd, arg);
+       case XFS_IOC_HEALTH_FD_ON_MONITORED_FS:
+               return xfs_healthmon_file_on_monitored_fs(file, cmd, arg);
        default:
                break;
        }