Compare commits

...
Sign in to create a new pull request.

3 commits

Author SHA1 Message Date
Andrew Price
97e0ba8dfe * Sat Apr 18 2015 Andrew Price <anprice@redhat.com> - 3.1.8-2
- fsck.gfs2: replace recent i_goal fixes with simple logic
2015-04-18 19:22:14 +01:00
Andrew Price
16d8ed6e31 * Tue Apr 07 2015 Andrew Price <anprice@redhat.com> - 3.1.8-1
- New upstream release
- Remove perl dependency
- Update spec per the latest packaging guidelines
2015-04-07 19:55:23 +01:00
Andrew Price
ec1de9c327 * Mon Sep 08 2014 Andrew Price <anprice@redhat.com> - 3.1.7-1
- New upstream release
- Drop all patches
- gfs2-utils tests: Build unit tests with consistent cpp flags
2014-09-08 12:50:15 +01:00
8 changed files with 333 additions and 627 deletions

2
.gitignore vendored
View file

@ -5,3 +5,5 @@
/gfs2-utils-3.1.4.tar.gz
/gfs2-utils-3.1.5.tar.gz
/gfs2-utils-3.1.6.tar.gz
/gfs2-utils-3.1.7.tar.gz
/gfs2-utils-3.1.8.tar.gz

View file

@ -1,183 +0,0 @@
commit 23bcbc3512a6609216b6884a3bf088684d1e7c72
Author: Andrew Price <anprice@redhat.com>
Date: Thu Aug 8 17:50:47 2013 +0100
gfs2_grow: Don't try to open an empty string
sdp->device_name wasn't getting set in gfs2_grow so is_gfs2() (called
via check_for_gfs2()) fails to open "" and so we get an ENOENT.
This fixes the open("") by setting sdp->device_name before passing it to
is_pathname_mounted(), which has been updated to make it more clear
which args will be modified by it.
is_gfs2() and check_for_gfs2() have also been removed from libgfs2 as
these were the only places they were being called and they aren't
needed: superblock checking is done further along via other functions
calling check_sb().
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index b45ae08..6612fe7 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -1491,7 +1491,7 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
strncpy(sdp->device_name, opts.device,
sizeof(sdp->device_name));
sdp->path_name = sdp->device_name; /* This gets overwritten */
- is_mounted = is_pathname_mounted(sdp, &ro);
+ is_mounted = is_pathname_mounted(sdp->path_name, sdp->device_name, &ro);
/* If the device is busy, but not because it's mounted, fail.
This protects against cases where the file system is LVM
and perhaps mounted on a different node. */
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index fe7129a..e994d3b 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -716,11 +716,9 @@ extern void decrease_verbosity(void);
extern int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs);
extern int compute_constants(struct gfs2_sbd *sdp);
-extern int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount);
-extern int is_gfs2(struct gfs2_sbd *sdp);
+extern int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount);
extern int find_gfs2_meta(struct gfs2_sbd *sdp);
extern int dir_exists(const char *dir);
-extern int check_for_gfs2(struct gfs2_sbd *sdp);
extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
extern void cleanup_metafs(struct gfs2_sbd *sdp);
extern int set_sysfs(const char *fsname, const char *filename, const char *val);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index c05a770..6f2dbdb 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -99,7 +99,7 @@ int compute_constants(struct gfs2_sbd *sdp)
return 0;
}
-int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
+int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount)
{
FILE *fp;
struct mntent *mnt;
@@ -112,7 +112,7 @@ int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
perror("open: /proc/mounts");
return 0;
}
- if (stat(sdp->path_name, &st_buf) == 0) {
+ if (stat(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;
@@ -124,12 +124,12 @@ int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
}
while ((mnt = getmntent (fp)) != NULL) {
/* Check if they specified the device instead of mnt point */
- if (strcmp(sdp->device_name, mnt->mnt_fsname) == 0) {
- strcpy(sdp->path_name, mnt->mnt_dir); /* fix it */
+ if (strcmp(device_name, mnt->mnt_fsname) == 0) {
+ strcpy(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 */
+ if (strcmp(path_name, mnt->mnt_dir) == 0) {
+ strcpy(device_name, mnt->mnt_fsname); /* fix it */
break;
}
if (stat(mnt->mnt_fsname, &st_buf) == 0) {
@@ -160,36 +160,6 @@ int is_pathname_mounted(struct gfs2_sbd *sdp, int *ro_mount)
return 1; /* mounted */
}
-int is_gfs2(struct gfs2_sbd *sdp)
-{
- int fd, rc;
- struct gfs2_sb sb;
-
- 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;
-}
-
-int check_for_gfs2(struct gfs2_sbd *sdp)
-{
- int ro;
-
- if (!is_pathname_mounted(sdp, &ro))
- return -1;
- if (!is_gfs2(sdp))
- return -1;
- return 0;
-}
-
static int lock_for_admin(struct gfs2_sbd *sdp)
{
int error;
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 73c7f84..d324af9 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -323,6 +323,7 @@ main_grow(int argc, char *argv[])
int rgcount, rindex_fd;
char rindex_name[PATH_MAX];
int error = EXIT_SUCCESS;
+ int ro_mnt = 0;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->bsize = GFS2_DEFAULT_BSIZE;
@@ -336,17 +337,20 @@ main_grow(int argc, char *argv[])
int sane;
struct rgrp_tree *last_rgrp;
+ strncpy(sdp->device_name, argv[optind], PATH_MAX - 1);
sdp->path_name = argv[optind++];
- sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
- if (sdp->path_fd < 0){
+
+ if ((!is_pathname_mounted(sdp->path_name, sdp->device_name, &ro_mnt))) {
perror(sdp->path_name);
exit(EXIT_FAILURE);
}
- if (check_for_gfs2(sdp)) {
+ sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
+ if (sdp->path_fd < 0){
perror(sdp->path_name);
exit(EXIT_FAILURE);
}
+
sdp->device_fd = open(sdp->device_name,
(test ? O_RDONLY : O_RDWR) | O_CLOEXEC);
if (sdp->device_fd < 0){
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
index 58fb046..2646829 100644
--- a/gfs2/mkfs/main_jadd.c
+++ b/gfs2/mkfs/main_jadd.c
@@ -491,6 +491,7 @@ void main_jadd(int argc, char *argv[])
{
struct gfs2_sbd sbd, *sdp = &sbd;
unsigned int total;
+ int ro_mnt = 0;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->jsize = GFS2_DEFAULT_JSIZE;
@@ -506,7 +507,7 @@ void main_jadd(int argc, char *argv[])
exit(EXIT_FAILURE);
}
- if (check_for_gfs2(sdp)) {
+ if (!is_pathname_mounted(sdp->path_name, sdp->device_name, &ro_mnt)) {
perror(sdp->path_name);
exit(EXIT_FAILURE);
}

View file

@ -1,141 +0,0 @@
commit 25c6e51bb4d083eb341bbc8541bb2ad278988f10
Author: Andrew Price <anprice@redhat.com>
Date: Sat Nov 16 02:10:52 2013 -0600
libgfs2: Add lgfs2_open_mnt* functions
lgfs2_open_mnt is a replacement for is_pathname_mounted which tries to reduce
races by opening paths speculatively and passing back the open fds once they're
known to be correct. lgfs2_open_mnt_{dev,dir} build on this to provide a
convenient way to open just the device or mount directory relating to a path
which could be either.
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index f864a08..3e5d09c 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -12,6 +12,7 @@
#include <linux/limits.h>
#include <endian.h>
#include <byteswap.h>
+#include <mntent.h>
#include <linux/gfs2_ondisk.h>
#include "osi_list.h"
@@ -715,6 +716,9 @@ extern int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs);
extern int compute_constants(struct gfs2_sbd *sdp);
extern int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount);
+extern int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt);
+extern int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt);
+extern int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt);
extern int find_gfs2_meta(struct gfs2_sbd *sdp);
extern int dir_exists(const char *dir);
extern int mount_gfs2_meta(struct gfs2_sbd *sdp);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index 7f500e6..195b983 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -163,6 +163,100 @@ int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount)
return 1; /* mounted */
}
+/* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
+static int fdcmp(int fd1, int fd2)
+{
+ struct stat st1, st2;
+ if ((fstat(fd1, &st1) != 0) || (fstat(fd2, &st2) != 0))
+ return -1;
+ if (S_ISBLK(st1.st_mode) && S_ISBLK(st2.st_mode)) {
+ if (st1.st_rdev == st2.st_rdev) {
+ return 0;
+ }
+ } else if ((st1.st_dev == st2.st_dev) && (st1.st_ino == st2.st_ino)) {
+ return 0;
+ }
+ return 1;
+}
+
+int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt)
+{
+ FILE *fp = setmntent("/proc/mounts", "r");
+ if (fp == NULL) {
+ perror("open: /proc/mounts");
+ return 1;
+ }
+ /* Assume path is mount point until we know better. */
+ *dirfd = open(path, dirflags);
+ if (*dirfd < 0)
+ return 1;
+
+ while ((*mnt = getmntent(fp)) != NULL) {
+ int fd;
+ if (strcmp((*mnt)->mnt_type, "gfs2") != 0)
+ continue;
+ *devfd = open((*mnt)->mnt_fsname, devflags);
+ /* Defer checking *devfd until later: whether it's ok to ignore
+ * the error depends on whether we find the mount point. */
+
+ if (strcmp(path, (*mnt)->mnt_dir) == 0)
+ break;
+ if (strcmp(path, (*mnt)->mnt_fsname) == 0 || fdcmp(*dirfd, *devfd) == 0) {
+ /* We have a match but our above assumption was
+ incorrect and *dirfd is actually the device. */
+ close(*dirfd);
+ *dirfd = open((*mnt)->mnt_dir, dirflags);
+ break;
+ }
+
+ fd = open((*mnt)->mnt_dir, dirflags);
+ if (fd >= 0) {
+ int diff = fdcmp(*dirfd, fd);
+ close(fd);
+ if (diff == 0)
+ break;
+ }
+ if (*devfd >= 0)
+ close(*devfd);
+ }
+ endmntent(fp);
+ if (*mnt == NULL) {
+ close(*dirfd);
+ return 0; /* Success. Answer is no. Both fds closed. */
+ }
+ if (*dirfd < 0) {
+ close(*devfd);
+ return 1;
+ }
+ if (*devfd < 0) {
+ close(*dirfd);
+ return 1;
+ }
+ return 0; /* Success. Answer is yes. Both fds open. */
+}
+
+int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt)
+{
+ int dirfd = -1;
+ int devfd = -1;
+ if (lgfs2_open_mnt(path, O_RDONLY, &dirfd, flags, &devfd, mnt) != 0)
+ return -1;
+ if (*mnt != NULL)
+ close(dirfd);
+ return devfd;
+}
+
+int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt)
+{
+ int dirfd = -1;
+ int devfd = -1;
+ if (lgfs2_open_mnt(path, flags, &dirfd, O_RDONLY, &devfd, mnt) != 0)
+ return -1;
+ if (*mnt != NULL)
+ close(devfd);
+ return dirfd;
+}
+
static int lock_for_admin(struct gfs2_sbd *sdp)
{
int error;

View file

@ -1,168 +0,0 @@
commit ad11e277ebd8d01a1b0a29ee9f697ba90c8577a4
Author: Andrew Price <anprice@redhat.com>
Date: Sat Nov 16 02:19:07 2013 -0600
Switch is_pathname_mounted callers to lgfs2_open_mnt*
Use the new lgfs2_open_mnt* functions in fsck.gfs2, gfs2_grow, and gfs2_jadd.
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 6612fe7..5758607 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -1475,8 +1475,7 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
sdp->device_fd = open(opts.device, open_flag);
if (sdp->device_fd < 0) {
- int is_mounted, ro;
-
+ struct mntent *mnt;
if (open_flag == O_RDONLY || errno != EBUSY) {
log_crit( _("Unable to open device: %s\n"),
opts.device);
@@ -1485,30 +1484,23 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
/* We can't open it EXCL. It may be already open rw (in which
case we want to deny them access) or it may be mounted as
the root file system at boot time (in which case we need to
- allow it.) We use is_pathname_mounted here even though
- we're specifying a device name, not a path name. The
- function checks for device as well. */
- strncpy(sdp->device_name, opts.device,
- sizeof(sdp->device_name));
- sdp->path_name = sdp->device_name; /* This gets overwritten */
- is_mounted = is_pathname_mounted(sdp->path_name, sdp->device_name, &ro);
- /* If the device is busy, but not because it's mounted, fail.
+ allow it.)
+ If the device is busy, but not because it's mounted, fail.
This protects against cases where the file system is LVM
- and perhaps mounted on a different node. */
- if (!is_mounted)
+ and perhaps mounted on a different node.
+ Try opening without O_EXCL. */
+ sdp->device_fd = lgfs2_open_mnt_dev(opts.device, O_RDWR, &mnt);
+ if (sdp->device_fd < 0)
goto mount_fail;
/* If the device is mounted, but not mounted RO, fail. This
protects them against cases where the file system is
mounted RW, but still allows us to check our own root
file system. */
- if (!ro)
- goto mount_fail;
+ if (!hasmntopt(mnt, MNTOPT_RO))
+ goto close_fail;
/* The device is mounted RO, so it's likely our own root
file system. We can only do so much to protect the users
- from themselves. Try opening without O_EXCL. */
- if ((sdp->device_fd = open(opts.device, O_RDWR)) < 0)
- goto mount_fail;
-
+ from themselves. */
was_mounted_ro = 1;
}
@@ -1591,6 +1583,8 @@ int initialize(struct gfs2_sbd *sdp, int force_check, int preen,
return FSCK_OK;
+close_fail:
+ close(sdp->device_fd);
mount_fail:
log_crit( _("Device %s is busy.\n"), opts.device);
return FSCK_USAGE;
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 5db91d9..541b0f2 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -323,7 +323,7 @@ main_grow(int argc, char *argv[])
int rgcount, rindex_fd;
char rindex_name[PATH_MAX];
int error = EXIT_SUCCESS;
- int ro_mnt = 0;
+ int devflags = (test ? O_RDONLY : O_RDWR) | O_CLOEXEC;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->bsize = GFS2_DEFAULT_BSIZE;
@@ -333,30 +333,23 @@ main_grow(int argc, char *argv[])
sdp->md.journals = 1;
decode_arguments(argc, argv, sdp);
- while ((argc - optind) > 0) {
+ for(; (argc - optind) > 0; optind++) {
int sane;
+ struct mntent *mnt;
struct rgrp_tree *last_rgrp;
- strncpy(sdp->device_name, argv[optind], PATH_MAX - 1);
- sdp->path_name = argv[optind++];
-
- if ((!is_pathname_mounted(sdp->path_name, sdp->device_name, &ro_mnt))) {
- perror(sdp->path_name);
- exit(EXIT_FAILURE);
- }
-
- sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
- if (sdp->path_fd < 0){
- perror(sdp->path_name);
+ error = lgfs2_open_mnt(argv[optind], O_RDONLY|O_CLOEXEC, &sdp->path_fd,
+ devflags, &sdp->device_fd, &mnt);
+ if (error != 0) {
+ fprintf(stderr, _("Error looking up mount '%s': %s\n"), argv[optind], strerror(errno));
exit(EXIT_FAILURE);
}
-
- sdp->device_fd = open(sdp->device_name,
- (test ? O_RDONLY : O_RDWR) | O_CLOEXEC);
- if (sdp->device_fd < 0){
- perror(sdp->device_name);
- exit(EXIT_FAILURE);
+ if (mnt == NULL) {
+ fprintf(stderr, _("%s: not a mounted gfs2 file system\n"), argv[optind]);
+ continue;
}
+ sdp->path_name = mnt->mnt_dir;
+ strncpy(sdp->device_name, mnt->mnt_fsname, PATH_MAX - 1);
if (lgfs2_get_dev_info(sdp->device_fd, &sdp->dinfo) < 0) {
perror(sdp->device_name);
diff --git a/gfs2/mkfs/main_jadd.c b/gfs2/mkfs/main_jadd.c
index b6cd8e4..815dd52 100644
--- a/gfs2/mkfs/main_jadd.c
+++ b/gfs2/mkfs/main_jadd.c
@@ -490,8 +490,8 @@ add_j(struct gfs2_sbd *sdp)
void main_jadd(int argc, char *argv[])
{
struct gfs2_sbd sbd, *sdp = &sbd;
+ struct mntent *mnt;
unsigned int total;
- int ro_mnt = 0;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->jsize = GFS2_DEFAULT_JSIZE;
@@ -500,17 +500,18 @@ void main_jadd(int argc, char *argv[])
decode_arguments(argc, argv, sdp);
verify_arguments(sdp);
-
- sdp->path_fd = open(sdp->path_name, O_RDONLY | O_CLOEXEC);
- if (sdp->path_fd < 0){
- perror(sdp->path_name);
+
+ sbd.path_fd = lgfs2_open_mnt_dir(sbd.path_name, O_RDONLY|O_CLOEXEC, &mnt);
+ if (sbd.path_fd < 0) {
+ fprintf(stderr, _("Error looking up mount '%s': %s\n"), sbd.path_name, strerror(errno));
exit(EXIT_FAILURE);
}
-
- if (!is_pathname_mounted(sdp->path_name, sdp->device_name, &ro_mnt)) {
- perror(sdp->path_name);
+ if (mnt == NULL) {
+ fprintf(stderr, _("%s: not a mounted gfs2 file system\n"), sbd.path_name);
exit(EXIT_FAILURE);
}
+ sbd.path_name = mnt->mnt_dir;
+ strncpy(sbd.device_name, mnt->mnt_fsname, PATH_MAX - 1);
gather_info(sdp);

View file

@ -1,94 +0,0 @@
commit 63db4e964739673d36c430cc5c78b02d93419f8a
Author: Andrew Price <anprice@redhat.com>
Date: Sat Nov 16 02:21:36 2013 -0600
libgfs2: Remove is_pathname_mounted
All callers are now using lgfs2_open_mnt* instead.
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 3e5d09c..e785017 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -715,7 +715,6 @@ extern int metafs_interrupted;
extern int compute_heightsize(struct gfs2_sbd *sdp, uint64_t *heightsize,
uint32_t *maxheight, uint32_t bsize1, int diptrs, int inptrs);
extern int compute_constants(struct gfs2_sbd *sdp);
-extern int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount);
extern int lgfs2_open_mnt(const char *path, int dirflags, int *dirfd, int devflags, int *devfd, struct mntent **mnt);
extern int lgfs2_open_mnt_dev(const char *path, int flags, struct mntent **mnt);
extern int lgfs2_open_mnt_dir(const char *path, int flags, struct mntent **mnt);
diff --git a/gfs2/libgfs2/misc.c b/gfs2/libgfs2/misc.c
index 195b983..c4ed722 100644
--- a/gfs2/libgfs2/misc.c
+++ b/gfs2/libgfs2/misc.c
@@ -102,67 +102,6 @@ int compute_constants(struct gfs2_sbd *sdp)
return 0;
}
-int is_pathname_mounted(char *path_name, char *device_name, int *ro_mount)
-{
- 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;
- if ((fp = setmntent("/proc/mounts", "r")) == NULL) {
- perror("open: /proc/mounts");
- return 0;
- }
- if (stat(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 ((mnt = getmntent (fp)) != NULL) {
- /* Check if they specified the device instead of mnt point */
- if (strcmp(device_name, mnt->mnt_fsname) == 0) {
- strcpy(path_name, mnt->mnt_dir); /* fix it */
- break;
- }
- if (strcmp(path_name, mnt->mnt_dir) == 0) {
- strcpy(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 */
-}
-
/* Returns 0 if fd1 and fd2 refer to the same device/file, 1 otherwise, or -1 on error */
static int fdcmp(int fd1, int fd2)
{

View file

@ -0,0 +1,304 @@
commit f1028ec054f2d7f85a449b2bf0894e0435c01d6a
Author: Abhi Das <adas@redhat.com>
Date: Tue Apr 14 19:51:55 2015 -0500
fsck.gfs2: replace recent i_goal fixes with simple logic
This patch reverses the recent set of i_goal fixes for fsck.gfs2.
This is because of two problems.
1. It is not possible to determine if a valid block within the fs
is the correct goal block for a given inode.
2. Conversely, given an inode, it is also not possible to accurately
determine what its goal block should be.
The previous patches assumed that the last block of a file is its
goal block, but that is not true if the file is a directory or if
its blocks are not allocated sequentially. fsck.gfs2 would flag
these inodes incorrectly as having bad i_goal values.
This patch takes a simple approach. It checks if the i_goal of a
given inode is out of bounds of the fs. If so, we can be certain
that it is wrong and we set it to the inode metadata block. This
is a safe starting point for gfs2 to determine where to allocate
from next.
Resolves: rhbz#1186515
Signed-off-by: Abhi Das <adas@redhat.com>
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index f05fb51..4d5a660 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -1428,8 +1428,7 @@ static int build_and_check_metalist(struct gfs2_inode *ip, osi_list_t *mlp,
*/
static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass,
struct gfs2_buffer_head *bh, int head_size,
- uint64_t *last_block, uint64_t *blks_checked,
- uint64_t *error_blk)
+ uint64_t *blks_checked, uint64_t *error_blk)
{
int error = 0, rc = 0;
uint64_t block, *ptr;
@@ -1444,7 +1443,7 @@ static int check_data(struct gfs2_inode *ip, struct metawalk_fxns *pass,
if (skip_this_pass || fsck_abort)
return error;
- *last_block = block = be64_to_cpu(*ptr);
+ block = be64_to_cpu(*ptr);
/* It's important that we don't call valid_block() and
bypass calling check_data on invalid blocks because that
would defeat the rangecheck_block related functions in
@@ -1548,15 +1547,12 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
struct gfs2_buffer_head *bh;
uint32_t height = ip->i_di.di_height;
int i, head_size;
- uint64_t blks_checked = 0, last_block = 0;
+ uint64_t blks_checked = 0;
int error, rc;
int metadata_clean = 0;
uint64_t error_blk = 0;
int hit_error_blk = 0;
- if (!height && pass->check_i_goal)
- pass->check_i_goal(ip, ip->i_di.di_num.no_addr,
- pass->private);
if (!height && !is_dir(&ip->i_di, ip->i_sbd->gfs1))
return 0;
@@ -1575,9 +1571,6 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
* comprise the directory hash table, so we perform the directory
* checks and exit. */
if (is_dir(&ip->i_di, ip->i_sbd->gfs1)) {
- last_block = ip->i_di.di_num.no_addr;
- if (pass->check_i_goal)
- pass->check_i_goal(ip, last_block, pass->private);
if (!(ip->i_di.di_flags & GFS2_DIF_EXHASH))
goto out;
/* check validity of leaf blocks and leaf chains */
@@ -1604,7 +1597,7 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
if (pass->check_data)
error = check_data(ip, pass, bh, head_size,
- &last_block, &blks_checked, &error_blk);
+ &blks_checked, &error_blk);
if (pass->big_file_msg && ip->i_di.di_blocks > COMFORTABLE_BLKS)
pass->big_file_msg(ip, blks_checked);
}
@@ -1616,8 +1609,6 @@ int check_metatree(struct gfs2_inode *ip, struct metawalk_fxns *pass)
(unsigned long long)ip->i_di.di_num.no_addr);
fflush(stdout);
}
- if (!error && pass->check_i_goal)
- pass->check_i_goal(ip, last_block, pass->private);
undo_metalist:
if (!error)
goto out;
@@ -1958,80 +1949,6 @@ static int alloc_leaf(struct gfs2_inode *ip, uint64_t block, void *private)
return 0;
}
-/**
- * rgrp_contains_block - Check if the rgrp provided contains the
- * given block. Taken directly from the gfs2 kernel code
- * @rgd: The rgrp to search within
- * @block: The block to search for
- *
- * Returns: 1 if present, 0 if not.
- */
-static inline int rgrp_contains_block(struct rgrp_tree *rgd, uint64_t block)
-{
- uint64_t first = rgd->ri.ri_data0;
- uint64_t last = first + rgd->ri.ri_data;
- return first <= block && block < last;
-}
-
-/**
- * check_i_goal
- * @ip
- * @goal_blk: What the goal block should be for this inode
- *
- * The goal block for a regular file is typically the last
- * data block of the file. If we can't get the right value,
- * the inode metadata block is the next best thing.
- *
- * Returns: 0 if corrected, 1 if not corrected
- */
-int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk,
- void *private)
-{
- struct gfs2_sbd *sdp = ip->i_sbd;
- uint64_t i_block = ip->i_di.di_num.no_addr;
-
- /* Don't fix gfs1 inodes, system inodes or inodes whose goal blocks are
- * set to the inode blocks themselves. */
- if (sdp->gfs1 || ip->i_di.di_flags & GFS2_DIF_SYSTEM ||
- ip->i_di.di_goal_meta == i_block)
- return 0;
- /* Don't fix directory goal blocks unless we know they're wrong.
- * i.e. out of bounds of the fs. Directories can easily have blocks
- * outside of the dinode's rgrp and thus we have no way of knowing
- * if the goal block is bogus or not. */
- if (is_dir(&ip->i_di, ip->i_sbd->gfs1) &&
- (ip->i_di.di_goal_meta > sdp->sb_addr &&
- ip->i_di.di_goal_meta <= sdp->fssize))
- return 0;
- /* We default to the inode block */
- if (!goal_blk)
- goal_blk = i_block;
-
- if (ip->i_di.di_goal_meta != goal_blk) {
- /* If the existing goal block is in the same rgrp as the inode,
- * we give the benefit of doubt and assume the value is correct */
- if (ip->i_rgd &&
- rgrp_contains_block(ip->i_rgd, ip->i_di.di_goal_meta))
- goto skip;
- log_err( _("Error: inode %llu (0x%llx) has invalid "
- "allocation goal block %llu (0x%llx). Should"
- " be %llu (0x%llx)\n"),
- (unsigned long long)i_block, (unsigned long long)i_block,
- (unsigned long long)ip->i_di.di_goal_meta,
- (unsigned long long)ip->i_di.di_goal_meta,
- (unsigned long long)goal_blk, (unsigned long long)goal_blk);
- if (query( _("Fix the invalid goal block? (y/n) "))) {
- ip->i_di.di_goal_meta = ip->i_di.di_goal_data = goal_blk;
- bmodified(ip->i_bh);
- } else {
- log_err(_("Invalid goal block not fixed.\n"));
- return 1;
- }
- }
-skip:
- return 0;
-}
-
struct metawalk_fxns alloc_fxns = {
.private = NULL,
.check_leaf = alloc_leaf,
@@ -2042,7 +1959,6 @@ struct metawalk_fxns alloc_fxns = {
.check_dentry = NULL,
.check_eattr_entry = NULL,
.check_eattr_extentry = NULL,
- .check_i_goal = check_i_goal,
.finish_eattr_indir = NULL,
};
diff --git a/gfs2/fsck/metawalk.h b/gfs2/fsck/metawalk.h
index 779360e..fa4c850 100644
--- a/gfs2/fsck/metawalk.h
+++ b/gfs2/fsck/metawalk.h
@@ -50,8 +50,6 @@ extern int _fsck_blockmap_set(struct gfs2_inode *ip, uint64_t bblock,
const char *caller, int line);
extern int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
int error_on_dinode, int new_blockmap_state);
-extern int check_i_goal(struct gfs2_inode *ip, uint64_t goal_blk,
- void *private);
extern void reprocess_inode(struct gfs2_inode *ip, const char *desc);
extern struct duptree *dupfind(uint64_t block);
extern struct gfs2_inode *fsck_system_inode(struct gfs2_sbd *sdp,
@@ -91,7 +89,6 @@ enum meta_check_rc {
* check_dentry:
* check_eattr_entry:
* check_eattr_extentry:
- * check_i_goal:
*/
struct metawalk_fxns {
void *private;
@@ -143,8 +140,6 @@ struct metawalk_fxns {
struct gfs2_ea_header *ea_hdr,
struct gfs2_ea_header *ea_hdr_prev,
void *private);
- int (*check_i_goal) (struct gfs2_inode *ip, uint64_t goal_blk,
- void *private);
int (*finish_eattr_indir) (struct gfs2_inode *ip, int leaf_pointers,
int leaf_pointer_errors, void *private);
void (*big_file_msg) (struct gfs2_inode *ip, uint64_t blks_checked);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 69c88f4..0909873 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -100,7 +100,6 @@ struct metawalk_fxns pass1_fxns = {
.check_dentry = NULL,
.check_eattr_entry = check_eattr_entries,
.check_eattr_extentry = check_extended_leaf_eattr,
- .check_i_goal = check_i_goal,
.finish_eattr_indir = finish_eattr_indir,
.big_file_msg = big_file_comfort,
.repair_leaf = pass1_repair_leaf,
@@ -1205,12 +1204,37 @@ bad_dinode:
return -1;
}
+static void check_i_goal(struct gfs2_sbd *sdp, struct gfs2_inode *ip)
+{
+ if (sdp->gfs1 || ip->i_di.di_flags & GFS2_DIF_SYSTEM)
+ return;
+
+ if (ip->i_di.di_goal_meta <= sdp->sb_addr ||
+ ip->i_di.di_goal_meta > sdp->fssize) {
+ log_err(_("Inode #%llu (0x%llx): Bad allocation goal block "
+ "found: %llu (0x%llx)\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_goal_meta,
+ (unsigned long long)ip->i_di.di_goal_meta);
+ if (query( _("Fix goal block in inode #%llu (0x%llx)? (y/n) "),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr)) {
+ ip->i_di.di_goal_meta = ip->i_di.di_num.no_addr;
+ bmodified(ip->i_bh);
+ } else
+ log_err(_("Allocation goal block in inode #%lld "
+ "(0x%llx) not fixed\n"),
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ }
+}
+
/*
* handle_di - This is now a wrapper function that takes a gfs2_buffer_head
* and calls handle_ip, which takes an in-code dinode structure.
*/
-static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
- struct rgrp_tree *rgd)
+static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh)
{
int error = 0;
uint64_t block = bh->b_blocknr;
@@ -1252,7 +1276,7 @@ static int handle_di(struct gfs2_sbd *sdp, struct gfs2_buffer_head *bh,
(unsigned long long)block,
(unsigned long long)block);
}
- ip->i_rgd = rgd;
+ check_i_goal(sdp, ip);
error = handle_ip(sdp, ip);
fsck_inode_put(&ip);
return error;
@@ -1378,6 +1402,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
"directory entries.\n"), filename);
}
}
+ check_i_goal(sdp, *sysinode);
error = handle_ip(sdp, *sysinode);
return error ? error : err;
}
@@ -1602,7 +1627,7 @@ static int pass1_process_bitmap(struct gfs2_sbd *sdp, struct rgrp_tree *rgd, uin
(unsigned long long)block,
(unsigned long long)block);
check_n_fix_bitmap(sdp, block, 0, GFS2_BLKST_FREE);
- } else if (handle_di(sdp, bh, rgd) < 0) {
+ } else if (handle_di(sdp, bh) < 0) {
stack;
brelse(bh);
gfs2_special_free(&gfs1_rindex_blks);
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index f1f81d3..ccae721 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -233,7 +233,6 @@ struct gfs2_inode {
struct gfs2_dinode i_di;
struct gfs2_buffer_head *i_bh;
struct gfs2_sbd *i_sbd;
- struct rgrp_tree *i_rgd; /* The rgrp this inode is in */
};
struct master_dir

View file

@ -1,7 +1,7 @@
###############################################################################
###############################################################################
##
## Copyright (C) 2004-2013 Red Hat, Inc. All rights reserved.
## Copyright (C) 2004-2014 Red Hat, Inc. All rights reserved.
##
## This copyrighted material is made available to anyone wishing to use,
## modify, copy, or redistribute it subject to the terms and conditions
@ -11,19 +11,17 @@
###############################################################################
Name: gfs2-utils
Version: 3.1.6
Release: 9%{?dist}
Version: 3.1.8
Release: 2%{?dist}
License: GPLv2+ and LGPLv2+
Group: System Environment/Kernel
Summary: Utilities for managing the global file system (GFS2)
%ifnarch %{arm}
%{?fedora:Requires: kmod(gfs2.ko) kmod(dlm.ko)}
%endif
Obsoletes: gfs2-cluster < %{version}
BuildRequires: ncurses-devel
BuildRequires: kernel-headers
BuildRequires: automake
BuildRequires: perl
BuildRequires: libtool
BuildRequires: zlib-devel
BuildRequires: gettext-devel
@ -31,61 +29,36 @@ BuildRequires: bison
BuildRequires: flex
BuildRequires: libblkid-devel
BuildRequires: check-devel
Source: https://fedorahosted.org/released/gfs2-utils/gfs2-utils-%{version}.tar.gz
URL: https://fedorahosted.org/cluster/wiki/HomePage
# The source for this package was pulled from the upstream git tree.
# Use the following commands to generate the tarball:
# git clone git://git.fedorahosted.org/gfs2-utils.git
# cd gfs2-utils
# ./make-tarball.sh
#
Source0: https://fedorahosted.org/released/gfs2-utils/gfs2-utils-%{version}.tar.gz
Patch0: bz1079286-0-gfs2_grow_Don_t_try_to_open_an_empty_string.patch
Patch1: bz1079286-1-libgfs2_Add_lgfs2_open_mnt_functions.patch
Patch2: bz1079286-2-Switch_is_pathname_mounted_callers_to_lgfs2_open_mnt.patch
Patch3: bz1079286-3-libgfs2_Remove_is_pathname_mounted.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
Patch0: fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic.patch
%prep
%setup -q -n gfs2-utils
%patch0 -p1 -b .bz1079286-0-gfs2_grow_Don_t_try_to_open_an_empty_string
%patch1 -p1 -b .bz1079286-1-libgfs2_Add_lgfs2_open_mnt_functions
%patch2 -p1 -b .bz1079286-2-Switch_is_pathname_mounted_callers_to_lgfs2_open_mnt
%patch3 -p1 -b .bz1079286-3-libgfs2_Remove_is_pathname_mounted
%setup -q -n gfs2-utils-%{version}
%patch0 -p 1 -b .fsck_gfs2_replace_recent_i_goal_fixes_with_simple_logic
%build
./autogen.sh
%configure
make %{_smp_mflags}
make %{_smp_mflags} V=1
%check
make check
make check || { cat tests/testsuite.log; exit 1; }
%install
rm -rf %{buildroot}
make -C gfs2 install DESTDIR=%{buildroot}
# Don't ship gfs2_{trace,lockcapture} in this package
rm -f %{buildroot}/sbin/gfs2_trace
rm -f %{buildroot}/sbin/gfs2_lockcapture
rm -f %{buildroot}/usr/sbin/gfs2_trace
rm -f %{buildroot}/usr/sbin/gfs2_lockcapture
rm -f %{buildroot}%{_mandir}/man8/gfs2_trace.8
rm -f %{buildroot}%{_mandir}/man8/gfs2_lockcapture.8
# Install into /usr/sbin per UsrMove
mv %{buildroot}/sbin/fsck.gfs2 %{buildroot}/usr/sbin/
mv %{buildroot}/sbin/mkfs.gfs2 %{buildroot}/usr/sbin/
mv %{buildroot}/sbin/gfs2_grow %{buildroot}/usr/sbin/
mv %{buildroot}/sbin/gfs2_jadd %{buildroot}/usr/sbin/
%clean
rm -rf %{buildroot}
%description -n gfs2-utils
%description
The gfs2-utils package contains a number of utilities for creating,
checking, modifying, and correcting any inconsistencies in GFS2
file systems.
%files -n gfs2-utils
%defattr(-,root,root,-)
%files
%doc doc/COPYING.* doc/COPYRIGHT doc/*.txt
%doc doc/README.contributing doc/README.licence
%{_sbindir}/fsck.gfs2
@ -99,6 +72,19 @@ file systems.
%{_mandir}/man5/*
%changelog
* Sat Apr 18 2015 Andrew Price <anprice@redhat.com> - 3.1.8-2
- fsck.gfs2: replace recent i_goal fixes with simple logic
* Tue Apr 07 2015 Andrew Price <anprice@redhat.com> - 3.1.8-1
- New upstream release
- Remove perl dependency
- Update spec per the latest packaging guidelines
* Mon Sep 08 2014 Andrew Price <anprice@redhat.com> - 3.1.7-1
- New upstream release
- Drop all patches
- gfs2-utils tests: Build unit tests with consistent cpp flags
* Sat Aug 16 2014 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 3.1.6-9
- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild

View file

@ -1 +1 @@
9d47c272298c62868dd49c7b1f4bcefc gfs2-utils-3.1.6.tar.gz
f43b26f006b0a58d86a08eed579871f1 gfs2-utils-3.1.8.tar.gz