Commit 8b85dc40 authored by Darrick J. Wong's avatar Darrick J. Wong
Browse files

xfs: check if an open file is on the health monitored fs



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: default avatar"Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
parent c0e719cb
Loading
Loading
Loading
Loading
+11 −1
Original line number Diff line number Diff line
@@ -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
 */
+34 −0
Original line number Diff line number Diff line
@@ -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;
	}