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;
*fd = -1;
- mnt_fd = open(wh->mntpoint, O_RDONLY);
+ mnt_fd = open(path, O_RDONLY);
if (mnt_fd < 0)
return -1;
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(