Blame SOURCES/xfsprogs-3.2.0-init-mounts-symlinks.patch

564d46
[PATCH] xfsprogs: handle symlinks etc in fs_table_initialise_mounts()
564d46
564d46
Commit:
564d46
564d46
6a23747d xfs_quota: support relative path as `path' arguments
564d46
564d46
used realpath() on the supplied pathname to handle things like
564d46
relative pathnames and pathnames ending in "/" which otherwise
564d46
caused the getmntent scanning to fail.
564d46
564d46
However, this regressed cases where a path in mtab was a symlink;
564d46
realpath() resolves this to the target, and so no match is found.
564d46
564d46
This causes i.e.:
564d46
564d46
# xfs_quota -x -c report /dev/mapper/testvg-testlv
564d46
564d46
to fail with:
564d46
564d46
xfs_quota: cannot setup path for mount /dev/mapper/testvg-testlv: No such device or address
564d46
564d46
because the scanning looks for /dev/dm-3, but the long symlink
564d46
name is what exists in mtab, and no match is found.
564d46
564d46
Fix this, but keep the intended enhancements, by testing *both* the
564d46
user-specified path (which might be relative, or contain a trailing
564d46
slash on a mountpoint) and the realpath-resolved path (which turns
564d46
a relative mountpoint into a full path, and removes trailing slashes),
564d46
to determine whether the user-specified path is an xfs mountpoint or
564d46
device.
564d46
564d46
While we're at it, add a few comments, and go back to the testing
564d46
of "path" not "rpath"; whether or not path is passed to the function
564d46
is what determines control flow.  If path is specified, and realpath
564d46
succeeds, we're guaranteed to have rpath as well, so there is no need
564d46
to retest that.  rpath is initialized to NULL, so an unconditional
564d46
free(rpath) is safe as well.
564d46
564d46
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
564d46
---
564d46
564d46
564d46
diff --git a/libxcmd/paths.c b/libxcmd/paths.c
564d46
index bd84cde..7b0e434 100644
564d46
--- a/libxcmd/paths.c
564d46
+++ b/libxcmd/paths.c
564d46
@@ -266,6 +266,10 @@ out_nomem:
564d46
 	return ENOMEM;
564d46
 }
564d46
 
564d46
+/*
564d46
+ * If *path is NULL, initialize the fs table with all xfs mount points in mtab
564d46
+ * If *path is specified, search for that path in mtab
564d46
+ */
564d46
 static int
564d46
 fs_table_initialise_mounts(
564d46
 	char		*path)
564d46
@@ -288,6 +292,7 @@ fs_table_initialise_mounts(
564d46
 	if ((mtp = setmntent(mtab_file, "r")) == NULL)
564d46
 		return ENOENT;
564d46
 
564d46
+	/* Use realpath to resolve symlinks, relative paths, etc */
564d46
 	if (path)
564d46
 		if ((rpath = realpath(path, NULL)) == NULL)
564d46
 			return ENOENT;
564d46
@@ -295,31 +300,37 @@ fs_table_initialise_mounts(
564d46
 	while ((mnt = getmntent(mtp)) != NULL) {
564d46
 		if (strcmp(mnt->mnt_type, "xfs") != 0)
564d46
 			continue;
564d46
-		if (rpath &&
564d46
-		    ((strcmp(rpath, mnt->mnt_dir) != 0) &&
564d46
+		if (path &&
564d46
+		    ((strcmp(path, mnt->mnt_dir) != 0) &&
564d46
+		     (strcmp(path, mnt->mnt_fsname) != 0) &&
564d46
+		     (strcmp(rpath, mnt->mnt_dir) != 0) &&
564d46
 		     (strcmp(rpath, mnt->mnt_fsname) != 0)))
564d46
 			continue;
564d46
 		if (fs_extract_mount_options(mnt, &fslog, &fsrt))
564d46
 			continue;
564d46
 		(void) fs_table_insert(mnt->mnt_dir, 0, FS_MOUNT_POINT,
564d46
 					mnt->mnt_fsname, fslog, fsrt);
564d46
-		if (rpath) {
564d46
+		if (path) {
564d46
 			found = 1;
564d46
 			break;
564d46
 		}
564d46
 	}
564d46
 	endmntent(mtp);
564d46
-	if (rpath) {
564d46
-		free(rpath);
564d46
-		if (!found)
564d46
-			error = ENXIO;
564d46
-	}
564d46
+	free(rpath);
564d46
+
564d46
+	if (path && !found)
564d46
+		error = ENXIO;
564d46
+
564d46
 	return error;
564d46
 }
564d46
 
564d46
 #elif defined(HAVE_GETMNTINFO)
564d46
 #include <sys/mount.h>
564d46
 
564d46
+/*
564d46
+ * If *path is NULL, initialize the fs table with all xfs mount points in mtab
564d46
+ * If *path is specified, search for that path in mtab
564d46
+ */
564d46
 static int
564d46
 fs_table_initialise_mounts(
564d46
 	char		*path)
564d46
@@ -335,6 +346,7 @@ fs_table_initialise_mounts(
564d46
 		return 0;
564d46
 	}
564d46
 
564d46
+	/* Use realpath to resolve symlinks, relative paths, etc */
564d46
 	if (path)
564d46
 		if ((rpath = realpath(path, NULL)) == NULL)
564d46
 			return ENOENT;
564d46
@@ -342,24 +354,24 @@ fs_table_initialise_mounts(
564d46
 	for (i = 0; i < count; i++) {
564d46
 		if (strcmp(stats[i].f_fstypename, "xfs") != 0)
564d46
 			continue;
564d46
-		if (rpath &&
564d46
-		    ((strcmp(rpath, stats[i].f_mntonname) != 0) &&
564d46
+		if (path &&
564d46
+		    ((strcmp(path, stats[i].f_mntonname) != 0) &&
564d46
+		     (strcmp(path, stats[i].f_mntfromname) != 0) &&
564d46
+		     (strcmp(rpath, stats[i].f_mntonname) != 0) &&
564d46
 		     (strcmp(rpath, stats[i].f_mntfromname) != 0)))
564d46
 			continue;
564d46
 		/* TODO: external log and realtime device? */
564d46
 		(void) fs_table_insert(stats[i].f_mntonname, 0,
564d46
 					FS_MOUNT_POINT, stats[i].f_mntfromname,
564d46
 					NULL, NULL);
564d46
-		if (rpath) {
564d46
+		if (path) {
564d46
 			found = 1;
564d46
 			break;
564d46
 		}
564d46
 	}
564d46
-	if (rpath) {
564d46
-		free(rpath);
564d46
-		if (!found)
564d46
-			error = ENXIO;
564d46
-	}
564d46
+	free(rpath);
564d46
+	if (path && !found)
564d46
+		error = ENXIO;
564d46
 
564d46
 	return error;
564d46
 }
564d46
564d46
564d46
564d46
_______________________________________________
564d46
xfs mailing list
564d46
xfs@oss.sgi.com
564d46
http://oss.sgi.com/mailman/listinfo/xfs
564d46
564d46