Compare commits

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

2 commits

Author SHA1 Message Date
Andrew Price
e0c1c0a278 * 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:21:12 +01:00
Andrew Price
a05f0e530c * 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:41:10 +01:00
5 changed files with 325 additions and 89 deletions

1
.gitignore vendored
View file

@ -6,3 +6,4 @@
/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

@ -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

@ -11,19 +11,17 @@
###############################################################################
Name: gfs2-utils
Version: 3.1.7
Release: 1%{?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,55 +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: gfs2_utils_tests_Build_unit_tests_with_consistent_cpp_flags.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-%{version}
%patch0 -p1 -b .gfs2_utils_tests_Build_unit_tests_with_consistent_cpp_flags
%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
@ -93,6 +72,14 @@ 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

View file

@ -1,56 +0,0 @@
commit 54c5ee8ee1b5bf008400d1c86af3a44f15eb4970
Author: Andrew Price <anprice@redhat.com>
Date: Mon Sep 8 12:03:40 2014 +0200
gfs2-utils tests: Build unit tests with consistent cpp flags
The check_rgrp unit test was failing on ARM and s390 due to struct
gfs2_sbd having a different alignment from libgfs2. This was due to the
unit tests being built with different options to libgfs2. Fix up the
unit test CPPFLAGS to make sure the alignment is consistent.
Also bump the test timeout for check_rgrp to make sure it completes on
slower build machines.
Signed-off-by: Andrew Price <anprice@redhat.com>
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 70e77ef..b912dfa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,16 +15,22 @@ UNIT_CFLAGS = \
UNIT_LDADD = \
$(top_builddir)/gfs2/libgfs2/libgfs2.la \
@check_LIBS@
+UNIT_CPPFLAGS = \
+ -D_FILE_OFFSET_BITS=64 \
+ -D_LARGEFILE64_SOURCE \
+ -D_GNU_SOURCE
check_PROGRAMS = $(UNIT_TESTS)
check_meta_SOURCES = $(UNIT_SOURCES) check_meta.c
check_meta_CFLAGS = $(UNIT_CFLAGS)
check_meta_LDADD = $(UNIT_LDADD)
+check_meta_CPPFLAGS = $(UNIT_CPPFLAGS)
check_rgrp_SOURCES = $(UNIT_SOURCES) check_rgrp.c
check_rgrp_CFLAGS = $(UNIT_CFLAGS)
check_rgrp_LDADD = $(UNIT_LDADD)
+check_rgrp_CPPFLAGS = $(UNIT_CPPFLAGS)
endif
# The `:;' works around a Bash 3.2 bug when the output is not writable.
diff --git a/tests/check_rgrp.c b/tests/check_rgrp.c
index d113846..e5fca8d 100644
--- a/tests/check_rgrp.c
+++ b/tests/check_rgrp.c
@@ -125,7 +125,7 @@ static Suite * libgfs2_suite(void)
tcase_add_test(tc_rgrp, test_rbm_find_good);
tcase_add_test(tc_rgrp, test_rbm_find_bad);
tcase_add_test(tc_rgrp, test_rbm_find_lastblock);
- tcase_set_timeout(tc_rgrp, 60);
+ tcase_set_timeout(tc_rgrp, 120);
suite_add_tcase(s, tc_rgrp);
return s;

View file

@ -1 +1 @@
b020102a326aecafef458fd1c9ccc5f3 gfs2-utils-3.1.7.tar.gz
f43b26f006b0a58d86a08eed579871f1 gfs2-utils-3.1.8.tar.gz