Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 9383e745e23602bc45f9c92184feea59 > files > 103

gfs2-utils-0.1.62-28.el5.src.rpm

commit 59cdde95dbad76b573eb93b88fb7e69ca0b7a9ea
Author: Bob Peterson <rpeterso@redhat.com>
Date:   Thu Feb 11 08:24:53 2010 -0600

    fsck.gfs2: Use fsck.ext3's method of dealing with root mounts
    
    This patch scraps the old way of determining if a gfs2 file
    system is mounted and does it the way fsck.ext3 does.
    
    rhbz#557128

diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 9958980..167aef0 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -664,6 +664,7 @@ uint32_t compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
 			    uint32_t bsize1, int diptrs, int inptrs);
 void compute_constants(struct gfs2_sbd *sdp);
 int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount);
+int is_gfs2(struct gfs2_sbd *sdp);
 void check_for_gfs2(struct gfs2_sbd *sdp);
 void mount_gfs2_meta(struct gfs2_sbd *sdp);
 void cleanup_metafs(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index bcccba9..2c475a0 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -27,6 +27,8 @@
 #include <sys/file.h>
 #include <dirent.h>
 #include <linux/kdev_t.h>
+#include <sys/statfs.h>
+#include <mntent.h>
 
 #include "libgfs2.h"
 
@@ -107,57 +109,82 @@ compute_constants(struct gfs2_sbd *sdp)
 
 int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
 {
-	FILE *fp = fopen("/proc/mounts", "r");
-	char buffer[PATH_MAX];
-	char fstype[80];
-	int fsdump, fspass, ret;
-	char fspath[PATH_MAX];
-	char fsoptions[PATH_MAX];
-	char *realname;
+	FILE *fp;
+	struct mntent *mnt;
+	dev_t file_dev=0, file_rdev=0;
+	ino_t file_ino=0;
+	struct stat st_buf;
 
 	*ro_mount = 0;
-	realname = realpath(sdp->path_name, NULL);
-	if (!realname) {
-		perror(sdp->path_name);
+	if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
+		perror("open: /proc/mounts");
 		return 0;
 	}
-	if (fp == NULL) {
-		perror("open: /proc/mounts");
-		exit(EXIT_FAILURE);
+	if (stat(sdp->path_name, &st_buf) == 0) {
+		if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__ /* The GNU hurd is broken with respect to stat devices */
+			file_rdev = st_buf.st_rdev;
+#endif  /* __GNU__ */
+		} else {
+			file_dev = st_buf.st_dev;
+			file_ino = st_buf.st_ino;
+		}
 	}
-	while ((fgets(buffer, PATH_MAX - 1, fp)) != NULL) {
-		buffer[PATH_MAX - 1] = 0;
-
-		if (strstr(buffer, "0") == 0)
-			continue;
-
-		if ((ret = sscanf(buffer, "%s %s %s %s %d %d",
-				  sdp->device_name, fspath, 
-				  fstype, fsoptions, &fsdump, &fspass)) != 6) 
-			continue;
-
-		if (strcmp(fstype, "gfs2") != 0)
-			continue;
-
+	while ((mnt = getmntent (fp)) != NULL) {
 		/* Check if they specified the device instead of mnt point */
-		if (strcmp(sdp->device_name, realname) == 0)
-			strcpy(sdp->path_name, fspath); /* fix it */
-		else if (strcmp(fspath, realname) != 0)
-			continue;
+		if (strcmp(sdp->device_name, mnt->mnt_fsname) == 0) {
+			strcpy(sdp->path_name, mnt->mnt_dir); /* fix it */
+			break;
+		}
+		if (strcmp(sdp->path_name, mnt->mnt_dir) == 0) {
+			strcpy(sdp->device_name, mnt->mnt_fsname); /* fix it */
+			break;
+		}
+		if (stat(mnt->mnt_fsname, &st_buf) == 0) {
+			if (S_ISBLK(st_buf.st_mode)) {
+#ifndef __GNU__
+				if (file_rdev && (file_rdev == st_buf.st_rdev))
+					break;
+#endif  /* __GNU__ */
+			} else {
+				if (file_dev && ((file_dev == st_buf.st_dev) &&
+						 (file_ino == st_buf.st_ino)))
+					break;
+			}
+		}
+	}
+	endmntent (fp);
+	if (mnt == NULL)
+		return 0;
+	if (stat(mnt->mnt_dir, &st_buf) < 0) {
+		if (errno == ENOENT)
+			return 0;
+	}
+	/* Can't trust fstype because / has "rootfs". */
+	if (file_rdev && (st_buf.st_dev != file_rdev))
+		return 0;
+	if (hasmntopt(mnt, MNTOPT_RO))
+               *ro_mount = 1;
+	return 1; /* mounted */
+}
 
-		if (strncmp(fsoptions, "ro,", 3) == 0 ||
-		    strcmp(fsoptions, "ro") == 0)
-			*ro_mount = 1;
-		fclose(fp);
-		if (strncmp(sdp->device_name, "/dev/loop", 9) == 0)
-			die("Cannot perform this operation on a loopback GFS2 mount.\n");
+int is_gfs2(struct gfs2_sbd *sdp)
+{
+	int fd, rc;
+	struct gfs2_sb sb;
 
-		free(realname);
-		return 1; /* mounted */
-	}
-	fclose(fp);
-	free(realname);
-	return 0; /* not mounted */
+	fd = open(sdp->device_name, O_RDWR);
+	if (fd < 0)
+		return 0;
+
+	rc = 0;
+	if (lseek(fd, GFS2_SB_ADDR * GFS2_BASIC_BLOCK, SEEK_SET) >= 0 &&
+	    read(fd, &sb, sizeof(sb)) == sizeof(sb) &&
+	    be32_to_cpu(sb.sb_header.mh_magic) == GFS2_MAGIC &&
+	    be32_to_cpu(sb.sb_header.mh_type) == GFS2_METATYPE_SB)
+		rc = 1;
+	close(fd);
+	return rc;
 }
 
 void
@@ -167,6 +194,8 @@ check_for_gfs2(struct gfs2_sbd *sdp)
 
 	if (!is_pathname_mounted(sdp, &ro))
 		die("gfs2 Filesystem %s is not mounted.\n", sdp->path_name);
+	if (!is_gfs2(sdp))
+		die("Filesystem %s is not GFS2.\n", sdp->path_name);
 }
 
 static void