From: Darrick J. Wong Date: Sun, 22 Feb 2026 22:41:16 +0000 (-0800) Subject: xfs_healer: use getmntent to find moved filesystems X-Git-Tag: v7.0.0~39 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=54c0ba68b007b3fa992835dbe8822ee3056759f2;p=xfsprogs-dev.git xfs_healer: use getmntent to find moved filesystems It's possible that a mounted filesystem can move mountpoints between the time of the initial mount (at which point xfs_healer starts) and when it actually wants to start a repair. When this happens, weakhandle::mountpoint becomes obsolete and opening it will either fail with ENOENT or the handle revalidation will return ESTALE. However, we do still have a means to find the mounted filesystem -- the fsname parameter (aka the path to the data device at mount time). This is record in /proc/mounts, which means that we can iterate getmntent to see if we can find the mount elsewhere. As documented a few patches ago, this would be easier if we had revocable fds that didn't pin mounts, but that's a very huge ask. This getmntent code enables xfs_healer to find a filesystem that has been bind mounted in a new place and the original mountpoint detached: # mount /dev/sda /mnt # xfs_healer /mnt & # mount /mnt /opt --bind # umount /mnt The key here is that each bind mount gets a separate struct mount object. Signed-off-by: "Darrick J. Wong" Reviewed-by: Christoph Hellwig --- diff --git a/healer/weakhandle.c b/healer/weakhandle.c index 849aa288..5df52075 100644 --- a/healer/weakhandle.c +++ b/healer/weakhandle.c @@ -65,10 +65,14 @@ out_wh: return -1; } -/* Reopen a file handle obtained via weak reference. */ -int -weakhandle_reopen( +/* + * Reopen a file handle obtained via weak reference, using the given path to a + * mount point. + */ +static int +weakhandle_reopen_from( struct weakhandle *wh, + const char *path, int *fd) { void *hanp; @@ -78,7 +82,7 @@ weakhandle_reopen( *fd = -1; - mnt_fd = open(wh->mntpoint, O_RDONLY); + mnt_fd = open(path, O_RDONLY); if (mnt_fd < 0) return -1; @@ -102,6 +106,49 @@ out_mntfd: return -1; } +/* Reopen a file handle obtained via weak reference. */ +int +weakhandle_reopen( + struct weakhandle *wh, + int *fd) +{ + FILE *mtab; + struct mntent *mnt; + int ret; + + /* First try reopening using the original mountpoint */ + ret = weakhandle_reopen_from(wh, wh->mntpoint, fd); + if (!ret) + return 0; + + /* + * That didn't work, so now walk /proc/mounts to find a mount with the + * same fsname (aka xfs data device path) as when we started. + */ + mtab = setmntent(_PATH_PROC_MOUNTS, "r"); + if (!mtab) + return -1; + + while ((mnt = getmntent(mtab)) != NULL) { + if (strcmp(mnt->mnt_type, "xfs")) + continue; + if (strcmp(mnt->mnt_fsname, wh->fsname)) + continue; + + ret = weakhandle_reopen_from(wh, mnt->mnt_dir, fd); + if (!ret) + break; + } + + if (*fd < 0) { + errno = ESTALE; + ret = -1; + } + + endmntent(mtab); + return ret; +} + /* Tear down a weak handle */ void weakhandle_free(