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