Gitweb:
http://git.fedorahosted.org/git/cluster.git?p=cluster.git;a=commitdiff;h=...
Commit: 59cdde95dbad76b573eb93b88fb7e69ca0b7a9ea
Parent: 5c6b9d216ad358e83ae6f5307f1622427c878afc
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Thu Feb 11 08:24:53 2010 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Thu Feb 11 09:20:07 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
---
gfs2/libgfs2/libgfs2.h | 1 +
gfs2/libgfs2/misc.c | 115 ++++++++++++++++++++++++++++++------------------
2 files changed, 73 insertions(+), 43 deletions(-)
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