cluster: RHEL510 - gfs2_convert: mask out proper bits when identifying symlinks
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=6e4fb7809d4...
Commit: 6e4fb7809d4146929c22b8683cb436d38fccdf1d
Parent: 400a5cc46d6295d1d93394186fba5f505f6cb606
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Dec 19 07:47:15 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:14 2013 -0700
gfs2_convert: mask out proper bits when identifying symlinks
This patch masks out the proper file type bit in order to
distinguish files from symlinks. Include stat.h defines:
So the check for "di_mode & S_IFLNK" will match regular files,
not just symlinks. The problem was that gfs2_convert was matching
regular files and treating them as symlinks, which destroyed
the di_blocks field in the dinode. The patch also has some minor
cleanups.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 13 ++++++-------
1 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index f22b2d3..1b3f44b 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -828,7 +828,6 @@ static int has_cdpn(const char *str)
static int fix_cdpn_symlink(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct gfs2_inode *ip)
{
- int ret = 0;
char *linkptr = NULL;
if (ip->i_di.di_height != 0)
@@ -849,7 +848,7 @@ static int fix_cdpn_symlink(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, s
(osi_list_t *)&cdpns_to_fix);
}
- return ret;
+ return 0;
}
/*
@@ -864,7 +863,7 @@ static int fix_cdpn_symlink(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, s
*/
static int fix_xattr(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct gfs2_inode *ip)
{
- int ret = 0, len, old_hdr_sz, new_hdr_sz;
+ int len, old_hdr_sz, new_hdr_sz;
struct gfs2_buffer_head *eabh;
char *buf;
@@ -887,7 +886,7 @@ static int fix_xattr(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh, struct g
}
brelse(eabh);
- return ret;
+ return 0;
}
/* ------------------------------------------------------------------------- */
@@ -906,8 +905,8 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
inode_was_gfs1 = (inode->i_di.di_num.no_formal_ino ==
inode->i_di.di_num.no_addr);
/* Fix the inode number: */
- inode->i_di.di_num.no_formal_ino = sbp->md.next_inum; ;
-
+ inode->i_di.di_num.no_formal_ino = sbp->md.next_inum;
+
/* Fix the inode type: gfs1 uses di_type, gfs2 uses di_mode. */
inode->i_di.di_mode &= ~S_IFMT;
switch (inode->i_di.__pad1) { /* formerly di_type */
@@ -973,7 +972,7 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
if (adjust_indirect_blocks(sbp, inode))
return -1;
/* Check for cdpns */
- if (inode->i_di.di_mode & S_IFLNK) {
+ if (S_ISLNK(inode->i_di.di_mode)) {
ret = fix_cdpn_symlink(sbp, bh, inode);
if (ret)
return -1;
11 years, 2 months
cluster: RHEL510 - gfs2_convert: clear out old di_mode before setting it
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=400a5cc46d6...
Commit: 400a5cc46d6295d1d93394186fba5f505f6cb606
Parent: 078afe992b4ad9b96e8fb2079a6cedbd1cdda843
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Tue Dec 18 14:14:08 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:07 2013 -0700
gfs2_convert: clear out old di_mode before setting it
This patch clears the dinode 'di_mode' inode type field before
setting it based on the GFS1 value. In rare circumstances
(e.g. fsck.gfs2 ran on a GFS1 file system and created lost+found
with both GFS1 and GFS2 data) di_mode might have an old value.
In these cases, simply doing a logical 'or' with the correct
value produces an invalid value. Zeroing it out beforehand ensures
it is set correctly based on the GFS1 type.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 659127a..f22b2d3 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -909,6 +909,7 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
inode->i_di.di_num.no_formal_ino = sbp->md.next_inum; ;
/* Fix the inode type: gfs1 uses di_type, gfs2 uses di_mode. */
+ inode->i_di.di_mode &= ~S_IFMT;
switch (inode->i_di.__pad1) { /* formerly di_type */
case GFS_FILE_DIR: /* directory */
inode->i_di.di_mode |= S_IFDIR;
11 years, 2 months
cluster: RHEL510 - gfs2_convert: calculate height 1 for small files that were once big
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=078afe992b4...
Commit: 078afe992b4ad9b96e8fb2079a6cedbd1cdda843
Parent: 11795482c88f4866654c583466e336fd5fffdece
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Dec 17 15:11:34 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:06 2013 -0700
gfs2_convert: calculate height 1 for small files that were once big
This patch changes function calc_gfs2_tree_height so that it gives
a height of 1 to small files that once were big. The problems here
is with files that were once big (needed two levels of indirection
(height 2)) and then are truncated to a tiny non-zero size
(ordinarily, they would be stuffed, but due to the growth followed
by truncate, they're still at height 2). The required GFS2 height is
zero, whereas the GFS1 height is 2. After the conversion the file
will not really be stuffed, because function fix_metatree will
unstuff the dinode as part of its conversion. So at least it will
be at height 1. The problem is that if we don't fix the 0 height to
its proper value of 1, fix_ind_reg_or_dir gets called with gfs2_hgt=0,
which then calls mp_gfs1_to_gfs2, which then tries to set:
gfs2factor[gfs2_h - 1] = 1ull. This results in a negative index of the
array.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index b3e9538..659127a 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -268,6 +268,12 @@ static unsigned int calc_gfs2_tree_height(struct gfs2_inode *ip, uint64_t size)
for (height = 0; height < max; height++)
if (arr[height] >= size)
break;
+ /* If calc_gfs2_tree_height was called, the dinode is not stuffed or
+ we would have returned before this point. After the call, a call is
+ made to fix_metatree, which unstuffs the dinode. Therefore, the
+ smallest height that can result after this call is 1. */
+ if (!height)
+ height = 1;
return height;
}
11 years, 2 months
cluster: RHEL510 - gfs2_convert: Use proper header size when reordering meta pointers
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=11795482c88...
Commit: 11795482c88f4866654c583466e336fd5fffdece
Parent: 183e3d6a5ea335db7f2c176a2fca009ab18e9f07
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Dec 17 15:01:02 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:05 2013 -0700
gfs2_convert: Use proper header size when reordering meta pointers
This patch changes function fix_metatree to use a proper metadata
header size. Before, it was using sizeof(struct gfs2_meta_header).
That's correct in almost all cases. But if you make a big file,
such that it goes into height==2 (two levels of indirection), then
truncate the file back to where it only would normally only need
height==1, then run gfs2_convert, it gets into trouble. That's
because you have a small file size, which calculates a much smaller
number of GFS2 pointers needed, due to the truncation. Function
fix_metatree will ensure at least one level of indirection by
unstuffing the converted dinode, but we need to start pushing out
the pointers onto the dinode's buffer, and for that, we need to
calculate the right header size.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 597eb8c..b3e9538 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -352,7 +352,8 @@ static void fix_metatree(struct gfs2_sbd *sbp, struct gfs2_inode *ip,
gfs2_meta_header_out(&mh, bh);
}
- hdrsize = sizeof(struct gfs2_meta_header);
+ hdrsize = blk->height ? sizeof(struct gfs2_meta_header) :
+ sizeof(struct gfs2_dinode);
if (amount > sbp->bsize - hdrsize - ptramt)
amount = sbp->bsize - hdrsize - ptramt;
11 years, 2 months
cluster: RHEL510 - gfs2_convert: remember number of blocks when converting quotas
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=183e3d6a5ea...
Commit: 183e3d6a5ea335db7f2c176a2fca009ab18e9f07
Parent: 144f8bed07e000b4394d3846c16a6855c7fb2448
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Dec 17 14:56:16 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:04 2013 -0700
gfs2_convert: remember number of blocks when converting quotas
This patch changes function copy_quotas so that it properly copies
the di_blocks field from the GFS1 quotas file to its new GFS2 file.
If the quota file had a non-trivial size, gfs2_convert was copying
all the data and pointers, but not properly setting the di_blocks.
This ordinarily isn't tragic because the file is never deleted, but
it did flag fsck.gfs2 errors.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 613e508..597eb8c 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -2032,6 +2032,7 @@ static void copy_quotas(struct gfs2_sbd *sdp)
nq_ip->i_di.di_height = oq_ip->i_di.di_height;
nq_ip->i_di.di_size = oq_ip->i_di.di_size;
+ nq_ip->i_di.di_blocks = oq_ip->i_di.di_blocks;
memcpy(nq_ip->i_bh->b_data + sizeof(struct gfs2_dinode),
oq_ip->i_bh->b_data + sizeof(struct gfs2_dinode),
sdp->bsize - sizeof(struct gfs2_dinode));
11 years, 2 months
cluster: RHEL510 - gfs2_convert: mark buffer dirty when switching dirs from meta to data
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=144f8bed07e...
Commit: 144f8bed07e000b4394d3846c16a6855c7fb2448
Parent: 5e79e9672f21f0745ebbb3347406f1fc4c7919e7
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Dec 17 14:47:50 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:02 2013 -0700
gfs2_convert: mark buffer dirty when switching dirs from meta to data
This patch changes function inode_renumber so that it properly marks
the rgrp bitmap dirty after switching bits from "meta" to "data".
This happens when directory leaf, hash table, eattr, etc. blocks come
in from GFS1 as "meta" and need to be switched to GFS2 as "data".
In GFS2, only dinodes get the "meta" designation. This conversion was
taking place, but the code broke out of the loop before properly
marking the buffer as modified. So if no other modifications were
done to that bitmap, the bitmap change would be forgotten.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 9af468a..613e508 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -1063,10 +1063,10 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr, osi_li
~(0x03 << (GFS2_BIT_SIZE * byte_bit));
rgd->bh[blk]->b_data[buf_offset + bitmap_byte] |=
(0x01 << (GFS2_BIT_SIZE * byte_bit));
+ bmodified(rgd->bh[blk]);
break;
}
bitmap_byte -= (sbp->bsize - buf_offset);
- bmodified(rgd->bh[blk]);
}
}
brelse(bh);
11 years, 2 months
cluster: RHEL510 - gfs2_convert: mark rgrp bitmaps dirty when converting
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=5e79e9672f2...
Commit: 5e79e9672f21f0745ebbb3347406f1fc4c7919e7
Parent: a472edcae35302d0abc4bf9ca0e5183b27ca715d
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Mon Dec 17 14:43:04 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 07:02:00 2013 -0700
gfs2_convert: mark rgrp bitmaps dirty when converting
This patch changes gfs2_convert function convert_bitmaps so that
it marks the affected rgrp buffers as modified when bitmap bits
are switched from unlinked metadata to free blocks.
rhbz#887374
---
gfs2/convert/gfs2_convert.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index 2300e63..9af468a 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -194,8 +194,10 @@ static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_tree *rg)
for (y = 0; y < GFS2_NBBY; y++) {
state = (rg->bh[blk]->b_data[x] >>
(GFS2_BIT_SIZE * y)) & 0x03;
- if (state == 0x02) /* unallocated metadata state invalid */
+ if (state == 0x02) {/* unallocated metadata state invalid */
rg->bh[blk]->b_data[x] &= ~(0x02 << (GFS2_BIT_SIZE * y));
+ bmodified(rg->bh[blk]);
+ }
}
}
}/* convert_bitmaps */
11 years, 2 months
cluster: RHEL510 - libgfs2: Make in-core rgrps use rbtree
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=a472edcae35...
Commit: a472edcae35302d0abc4bf9ca0e5183b27ca715d
Parent: 737668db7dec805e3bcddd32c1e03b7ddf2eecb2
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Fri Jan 6 16:02:26 2012 -0600
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
libgfs2: Make in-core rgrps use rbtree
This patch changes the in-core structure used for resource groups
from a linked list to an rbtree.
rhbz#877150
---
gfs2/convert/gfs2_convert.c | 61 +++++++------
gfs2/edit/extended.c | 2 +-
gfs2/edit/hexedit.c | 56 ++++++------
gfs2/edit/hexedit.h | 4 +-
gfs2/edit/savemeta.c | 27 ++++---
gfs2/fsck/fs_recovery.c | 1 +
gfs2/fsck/initialize.c | 32 ++++----
gfs2/fsck/main.c | 9 +-
gfs2/fsck/metawalk.c | 2 +-
gfs2/fsck/pass1.c | 14 ++--
gfs2/fsck/pass5.c | 11 ++-
gfs2/fsck/rgrepair.c | 205 +++++++++++++++++++++++++------------------
gfs2/fsck/util.c | 1 -
gfs2/libgfs2/fs_bits.c | 4 +-
gfs2/libgfs2/fs_geometry.c | 52 ++++++-----
gfs2/libgfs2/fs_ops.c | 16 ++--
gfs2/libgfs2/gfs1.c | 31 +++----
gfs2/libgfs2/libgfs2.h | 45 +++++----
gfs2/libgfs2/rgrp.c | 78 ++++++++++------
gfs2/libgfs2/structures.c | 22 +++---
gfs2/libgfs2/super.c | 29 +++----
gfs2/mkfs/main_grow.c | 55 ++++++------
gfs2/mkfs/main_mkfs.c | 6 +-
gfs2/tool/df.c | 2 +-
24 files changed, 417 insertions(+), 348 deletions(-)
diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c
index d887838..2300e63 100644
--- a/gfs2/convert/gfs2_convert.c
+++ b/gfs2/convert/gfs2_convert.c
@@ -178,7 +178,7 @@ void print_it(const char *label, const char *fmt, const char *fmt2, ...)
/* Fixes all unallocated metadata bitmap states (which are */
/* valid in gfs1 but invalid in gfs2). */
/* ------------------------------------------------------------------------- */
-static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rg)
+static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_tree *rg)
{
uint32_t blk;
int x, y;
@@ -206,16 +206,18 @@ static void convert_bitmaps(struct gfs2_sbd *sdp, struct rgrp_list *rg)
/* ------------------------------------------------------------------------- */
static int convert_rgs(struct gfs2_sbd *sbp)
{
- struct rgrp_list *rgd;
- osi_list_t *tmp;
+ struct rgrp_tree *rgd;
+ struct osi_node *n, *next = NULL;
struct gfs1_rgrp *rgd1;
int rgs = 0;
/* --------------------------------- */
/* Now convert its rgs into gfs2 rgs */
/* --------------------------------- */
- osi_list_foreach(tmp, &sbp->rglist) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sbp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
+
rgd1 = (struct gfs1_rgrp *)&rgd->rg; /* recast as gfs1 structure */
/* rg_freemeta is a gfs1 structure, so libgfs2 doesn't know to */
/* convert from be to cpu. We must do it now. */
@@ -990,8 +992,8 @@ static int adjust_inode(struct gfs2_sbd *sbp, struct gfs2_buffer_head *bh)
/* ------------------------------------------------------------------------- */
static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr, osi_list_t *cdpn_to_fix)
{
- struct rgrp_list *rgd;
- osi_list_t *tmp;
+ struct rgrp_tree *rgd;
+ struct osi_node *n, *next = NULL;
uint64_t block;
struct gfs2_buffer_head *bh;
int first;
@@ -1006,9 +1008,10 @@ static int inode_renumber(struct gfs2_sbd *sbp, uint64_t root_inode_addr, osi_li
/* ---------------------------------------------------------------- */
/* Traverse the resource groups to figure out where the inodes are. */
/* ---------------------------------------------------------------- */
- osi_list_foreach(tmp, &sbp->rglist) {
+ for (n = osi_first(&sbp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
rgs_processed++;
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
first = 1;
while (1) { /* for all inodes in the resource group */
gettimeofday(&tv, NULL);
@@ -1510,7 +1513,7 @@ static int init(struct gfs2_sbd *sbp)
sbp->dinodes_alloced = 0; /* dinodes allocated - total them up later */
sbp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
sbp->bsize = sbp->sd_sb.sb_bsize;
- osi_list_init(&sbp->rglist);
+ sbp->rgtree.osi_node = NULL;
compute_constants(sbp);
bh = bread(sbp, GFS2_SB_ADDR >> sbp->sd_fsb2bb_shift);
@@ -1726,9 +1729,10 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
int error = 0;
int j, x;
struct gfs1_jindex *jndx;
- struct rgrp_list *rgd, *rgdhigh;
- osi_list_t *tmp;
+ struct rgrp_tree *rgd, *rgdhigh;
+ struct osi_node *n, *next = NULL;
struct gfs2_meta_header mh;
+ uint64_t ri_addr;
mh.mh_magic = GFS2_MAGIC;
mh.mh_type = GFS2_METATYPE_RB;
@@ -1746,8 +1750,9 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
by jadd. gfs_grow adds rgs out of order, so we can't count
on them being in ascending order. */
rgdhigh = NULL;
- osi_list_foreach(tmp, &sdp->rglist) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
if (rgd->ri.ri_addr < jndx->ji_addr &&
((rgdhigh == NULL) ||
(rgd->ri.ri_addr > rgdhigh->ri.ri_addr)))
@@ -1759,15 +1764,12 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
log_crit("Error: No suitable rg found for journal.\n");
return -1;
}
+ ri_addr = jndx->ji_addr;
/* Allocate a new rgd entry which includes rg and ri. */
+ rgd = rgrp_insert(&sdp->rgtree, ri_addr);
/* convert the gfs1 rgrp into a new gfs2 rgrp */
- rgd = malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Error: unable to allocate memory for rg conversion.\n");
- return -1;
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- size = jndx->ji_nsegment * be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size);
+ size = jndx->ji_nsegment *
+ be32_to_cpu(raw_gfs1_ondisk_sb.sb_seg_size);
rgd->rg.rg_header.mh_magic = GFS2_MAGIC;
rgd->rg.rg_header.mh_type = GFS2_METATYPE_RG;
rgd->rg.rg_header.mh_format = GFS2_FORMAT_RG;
@@ -1810,9 +1812,6 @@ static int journ_space_to_rg(struct gfs2_sbd *sdp)
else
gfs2_rgrp_out(&rgd->rg, rgd->bh[x]);
}
- /* Add the new gfs2 rg to our list: We'll output the rg index later. */
- osi_list_add_prev((osi_list_t *)&rgd->list,
- (osi_list_t *)&sdp->rglist);
} /* for each journal */
return error;
}/* journ_space_to_rg */
@@ -1988,16 +1987,17 @@ static int check_fit(struct gfs2_sbd *sdp)
/* build_rindex() */
{
- osi_list_t *tmp, *head;
+ struct osi_node *n, *next = NULL;
unsigned int rg_count = 0;
blks_need++; /* creationg of 'rindex' disk inode */
/* find the total # of rindex entries, gives size of rindex inode */
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next)
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
rg_count++;
- blks_need +=
- total_file_blocks(sdp, rg_count * sizeof(struct gfs2_rindex), 1);
+ }
+ blks_need += total_file_blocks(sdp, rg_count *
+ sizeof(struct gfs2_rindex), 1);
}
/* build_quota() */
blks_need++; /* quota inode block and uid=gid=0 quota - total 1 block */
@@ -2132,6 +2132,7 @@ int main(int argc, char **argv)
/* ---------------------------------------------- */
if (!error) {
int jreduce = 0;
+
/* Now we've got to treat it as a gfs2 file system */
compute_constants(&sb2);
@@ -2187,7 +2188,7 @@ int main(int argc, char **argv)
fsync(sb2.device_fd); /* write the buffers to disk */
/* Now free all the in memory */
- gfs2_rgrp_free(&sb2.rglist);
+ gfs2_rgrp_free(&sb2.rgtree);
log_notice("Committing changes to disk.\n");
fflush(stdout);
/* Set filesystem type in superblock to gfs2. We do this at the */
diff --git a/gfs2/edit/extended.c b/gfs2/edit/extended.c
index 3c45060..b615b19 100644
--- a/gfs2/edit/extended.c
+++ b/gfs2/edit/extended.c
@@ -662,7 +662,7 @@ int display_extended(void)
return -1;
else if (display_indirect(indirect, indirect_blocks, 0, 0) == 0)
return -1;
- else if (block_is_rglist()) {
+ else if (block_is_rgtree()) {
if (gfs1)
tmp_bh = bread(&sbd, sbd1->sb_rindex_di.no_addr);
else
diff --git a/gfs2/edit/hexedit.c b/gfs2/edit/hexedit.c
index 3cc05f4..d3b1f24 100644
--- a/gfs2/edit/hexedit.c
+++ b/gfs2/edit/hexedit.c
@@ -1166,7 +1166,7 @@ int display_block_type(int from_restore)
return ret_type;
if (termlines && dmode == HEX_MODE) {
int type;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
rgd = gfs2_blk2rgrpd(&sbd, block);
if (rgd) {
@@ -1484,7 +1484,7 @@ static void rgcount(void)
printf("%lld RGs in this file system.\n",
(unsigned long long)sbd.md.riinode->i_di.di_size / risize());
inode_put(&sbd.md.riinode);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_SUCCESS);
}
@@ -1757,7 +1757,7 @@ static int block_has_extended_info(void)
{
if (has_indirect_blocks() ||
block_is_rindex() ||
- block_is_rglist() ||
+ block_is_rgtree() ||
block_is_jindex() ||
block_is_inum_file() ||
block_is_statfs_file() ||
@@ -1784,7 +1784,7 @@ static void read_superblock(int fd)
sbd.utsize = GFS2_DEFAULT_UTSIZE;
sbd.qcsize = GFS2_DEFAULT_QCSIZE;
sbd.time = time(NULL);
- osi_list_init(&sbd.rglist);
+ sbd.rgtree.osi_node = NULL;
gfs2_sb_in(&sbd.sd_sb, bh); /* parse it out into the sb structure */
/* Check to see if this is really gfs1 */
if (sbd1->sb_fs_format == GFS_FORMAT_FS &&
@@ -2102,7 +2102,7 @@ static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int p
else
printf("%llu\n", (unsigned long long)blk);
}
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
if (print)
exit(0);
return blk;
@@ -2117,16 +2117,17 @@ static uint64_t find_metablockoftype_slow(uint64_t startblk, int metatype, int p
/* ------------------------------------------------------------------------ */
static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int print)
{
+ struct osi_node *n, *next = NULL;
uint64_t blk;
int first = 1, found = 0;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
- osi_list_t *tmp;
blk = 0;
/* Skip the rgs prior to the block we've been given */
- for(tmp = sbd.rglist.next; tmp != &sbd.rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sbd.rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
ri = &rgd->ri;
if (first && startblk <= ri->ri_data0) {
startblk = ri->ri_data0;
@@ -2141,12 +2142,13 @@ static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int pri
if (!rgd) {
if (print)
printf("0\n");
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
if (print)
exit(-1);
}
- for(; !found && tmp != &sbd.rglist; tmp = tmp->next){
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (; !found && n; n = next){
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
first = 1;
do {
if (gfs2_next_rg_metatype(&sbd, rgd, &blk, metatype,
@@ -2167,7 +2169,7 @@ static uint64_t find_metablockoftype_rg(uint64_t startblk, int metatype, int pri
else
printf("%llu\n", (unsigned long long)blk);
}
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
if (print)
exit(0);
return blk;
@@ -2201,7 +2203,7 @@ static uint64_t find_metablockoftype(const char *strtype, int print)
"specified: must be one of:\n");
fprintf(stderr, "sb rg rb di in lf jd lh ld"
" ea ed lb 13 qc\n");
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(-1);
}
return blk;
@@ -2502,7 +2504,7 @@ static void find_print_block_type(void)
type = get_block_type(lbh);
print_block_type(tblock, type, "");
brelse(lbh);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(0);
}
@@ -2513,7 +2515,7 @@ static void find_print_block_rg(int bitmap)
{
uint64_t rblock, rgblock;
int i;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
rblock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
if (rblock == sbd.sb_addr)
@@ -2545,7 +2547,7 @@ static void find_print_block_rg(int bitmap)
printf("-1 (block invalid or part of an rgrp).\n");
}
}
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(0);
}
@@ -2556,7 +2558,7 @@ static void find_change_block_alloc(int *newval)
{
uint64_t ablock;
int type;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
if (newval &&
(*newval < GFS2_BLKST_FREE || *newval > GFS2_BLKST_DINODE)) {
@@ -2566,7 +2568,7 @@ static void find_change_block_alloc(int *newval)
*newval);
for (i = GFS2_BLKST_FREE; i <= GFS2_BLKST_DINODE; i++)
printf("%d - %s\n", i, allocdesc[gfs1][i]);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(-1);
}
ablock = blockstack[blockhist % BLOCK_STACK_SIZE].block;
@@ -2592,12 +2594,12 @@ static void find_change_block_alloc(int *newval)
}
gfs2_rgrp_relse(rgd);
} else {
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
printf("-1 (block invalid or part of an rgrp).\n");
exit(-1);
}
}
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
if (newval)
fsync(sbd.device_fd);
exit(0);
@@ -3525,7 +3527,7 @@ static void process_parameters(int argc, char *argv[], int pass)
printf("Error: field not specified.\n");
printf("Format is: %s -p <block> field "
"<field> [newvalue]\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_FAILURE);
}
process_field(argv[i], argv[i + 1]);
@@ -3558,7 +3560,7 @@ static void process_parameters(int argc, char *argv[], int pass)
printf("Error: rg # not specified.\n");
printf("Format is: %s rgflags rgnum"
"[newvalue]\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_FAILURE);
}
if (argv[i][0]=='0' && argv[i][1]=='x')
@@ -3575,7 +3577,7 @@ static void process_parameters(int argc, char *argv[], int pass)
new_flags = atoi(argv[i]);
}
set_rgrp_flags(rg, new_flags, set, FALSE);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_SUCCESS);
} else if (!strcmp(argv[i], "rg")) {
int rg;
@@ -3584,7 +3586,7 @@ static void process_parameters(int argc, char *argv[], int pass)
if (i >= argc - 1) {
printf("Error: rg # not specified.\n");
printf("Format is: %s rg rgnum\n", argv[0]);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_FAILURE);
}
rg = atoi(argv[i]);
@@ -3593,7 +3595,7 @@ static void process_parameters(int argc, char *argv[], int pass)
push_block(temp_blk);
} else {
set_rgrp_flags(rg, 0, FALSE, TRUE);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_SUCCESS);
}
}
@@ -3705,6 +3707,6 @@ int main(int argc, char *argv[])
close(fd);
if (indirect)
free(indirect);
- gfs2_rgrp_free(&sbd.rglist);
+ gfs2_rgrp_free(&sbd.rgtree);
exit(EXIT_SUCCESS);
}
diff --git a/gfs2/edit/hexedit.h b/gfs2/edit/hexedit.h
index 8732c27..d90b4c5 100644
--- a/gfs2/edit/hexedit.h
+++ b/gfs2/edit/hexedit.h
@@ -262,11 +262,11 @@ static inline int risize(void)
}
/* ------------------------------------------------------------------------ */
-/* block_is_rglist - there's no such block as the rglist. This is a */
+/* block_is_rgtree - there's no such block as the rglist. This is a */
/* special case meant to parse the rindex and follow the */
/* blocks to the real rgs. */
/* ------------------------------------------------------------------------ */
-static inline int block_is_rglist(void)
+static inline int block_is_rgtree(void)
{
if (block == RGLIST_DUMMY_BLOCK)
return TRUE;
diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c
index fd0e1e4..337d98a 100644
--- a/gfs2/edit/savemeta.c
+++ b/gfs2/edit/savemeta.c
@@ -600,7 +600,7 @@ static void get_journal_inode_blocks(void)
}
}
-static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
+static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
uint64_t *nrfblock, int first)
{
struct gfs2_bitmap *bits = NULL;
@@ -642,11 +642,10 @@ static int next_rg_freemeta(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
void savemeta(char *out_fn, int saveoption, int gziplevel)
{
int slow;
- osi_list_t *tmp;
int rgcount;
uint64_t jindex_block;
struct gfs2_buffer_head *lbh;
- struct rgrp_list *last_rgd;
+ struct rgrp_tree *last_rgd, *prev_rgd;
struct metafd mfd;
slow = (saveoption == 1);
@@ -665,7 +664,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
if (!slow) {
device_geometry(&sbd);
fix_device_geometry(&sbd);
- osi_list_init(&sbd.rglist);
+ sbd.rgtree.osi_node = NULL;
if (!gfs1)
sbd.sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
compute_constants(&sbd);
@@ -716,6 +715,7 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
if (!slow) {
int sane;
uint64_t fssize;
+ struct osi_node *n;
printf("Reading resource groups...");
fflush(stdout);
@@ -723,9 +723,12 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
slow = gfs1_ri_update(&sbd, 0, &rgcount, 0);
else
slow = ri_update(&sbd, 0, &rgcount, &sane);
- last_rgd = osi_list_entry(sbd.rglist.prev,
- struct rgrp_list, list);
- fssize = last_rgd->ri.ri_addr + rgrp_size(last_rgd);
+ n = osi_last(&sbd.rgtree);
+ last_rgd = (struct rgrp_tree *)n;
+ n = osi_prev(n);
+ prev_rgd = (struct rgrp_tree *)n;
+ fssize = last_rgd->ri.ri_addr +
+ (last_rgd->ri.ri_addr - prev_rgd->ri.ri_addr);
last_fs_block = fssize;
fssize *= sbd.bsize;
printf("Done. File system size: %s\n\n",
@@ -734,6 +737,8 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
}
get_journal_inode_blocks();
if (!slow) {
+ struct osi_node *n, *next = NULL;
+
/* Save off the superblock */
save_block(sbd.device_fd, &mfd, 0x10 * (4096 / sbd.bsize));
/* If this is gfs1, save off the rindex because it's not
@@ -755,12 +760,12 @@ void savemeta(char *out_fn, int saveoption, int gziplevel)
}
}
/* Walk through the resource groups saving everything within */
- for (tmp = sbd.rglist.next; tmp != &sbd.rglist;
- tmp = tmp->next){
- struct rgrp_list *rgd;
+ for (n = osi_first(&sbd.rgtree); n; n = next) {
int first;
+ struct rgrp_tree *rgd;
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
slow = gfs2_rgrp_read(&sbd, rgd);
if (slow)
continue;
diff --git a/gfs2/fsck/fs_recovery.c b/gfs2/fsck/fs_recovery.c
index 214aa18..da80f5c 100644
--- a/gfs2/fsck/fs_recovery.c
+++ b/gfs2/fsck/fs_recovery.c
@@ -14,6 +14,7 @@
#include <errno.h>
#include <inttypes.h>
#include <linux_endian.h>
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
diff --git a/gfs2/fsck/initialize.c b/gfs2/fsck/initialize.c
index 75f81f5..7855db4 100644
--- a/gfs2/fsck/initialize.c
+++ b/gfs2/fsck/initialize.c
@@ -121,7 +121,7 @@ static void gfs2_inodetree_free(void)
static void empty_super_block(struct gfs2_sbd *sdp)
{
log_info( _("Freeing buffers.\n"));
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
if (bl)
gfs2_bmap_destroy(sdp, bl);
@@ -142,10 +142,9 @@ static void empty_super_block(struct gfs2_sbd *sdp)
*/
static int set_block_ranges(struct gfs2_sbd *sdp)
{
-
- struct rgrp_list *rgd;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
- osi_list_t *tmp;
char buf[sdp->sd_sb.sb_bsize];
uint64_t rmax = 0;
uint64_t rmin = 0;
@@ -153,9 +152,9 @@ static int set_block_ranges(struct gfs2_sbd *sdp)
log_info( _("Setting block ranges...\n"));
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next)
- {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
ri = &rgd->ri;
if (ri->ri_data0 + ri->ri_data - 1 > rmax)
rmax = ri->ri_data0 + ri->ri_data - 1;
@@ -200,7 +199,7 @@ static int set_block_ranges(struct gfs2_sbd *sdp)
/**
* check_rgrp_integrity - verify a rgrp free block count against the bitmap
*/
-static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
+static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
int *fixit, int *this_rg_fixed,
int *this_rg_bad)
{
@@ -305,17 +304,18 @@ static void check_rgrp_integrity(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
*/
static int check_rgrps_integrity(struct gfs2_sbd *sdp)
{
+ struct osi_node *n, *next = NULL;
int rgs_good = 0, rgs_bad = 0, rgs_fixed = 0;
int was_bad = 0, was_fixed = 0, error = 0;
- osi_list_t *tmp;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
int reclaim_unlinked = 0;
log_info( _("Checking the integrity of all resource groups.\n"));
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
if (fsck_abort)
return 0;
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
check_rgrp_integrity(sdp, rgd, &reclaim_unlinked,
&was_fixed, &was_bad);
if (was_fixed)
@@ -542,7 +542,7 @@ static int fetch_rgrps(struct gfs2_sbd *sdp)
*******************************************************************/
log_warn( _("Validating Resource Group index.\n"));
for (trust_lvl = blind_faith; trust_lvl <= distrust; trust_lvl++) {
- int ret;
+ int ret = 0;
log_warn( _("Level %d rgrp check: %s.\n"), trust_lvl + 1,
level_desc[trust_lvl]);
@@ -749,7 +749,7 @@ static int get_lockproto_table(struct gfs2_sbd *sdp)
{
FILE *fp;
char line[PATH_MAX];
- char *cluname, *end;
+ char *cluname = NULL, *end = NULL;
const char *fsname, *cfgfile = "/etc/cluster/cluster.conf";
memset(sdp->lockproto, 0, sizeof(sdp->lockproto));
@@ -1218,7 +1218,7 @@ static int fill_super_block(struct gfs2_sbd *sdp)
***************** First, initialize all lists **********************
********************************************************************/
log_info( _("Initializing lists...\n"));
- osi_list_init(&sdp->rglist);
+ sdp->rgtree.osi_node = NULL;
/********************************************************************
************ next, read in on-disk SB and set constants **********
@@ -1298,7 +1298,7 @@ static int init_jindex(struct gfs2_sbd *sdp)
err = build_jindex(sdp);
/* Free rgrps read in earlier (re-read them later) */
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
if (err) {
log_crit(_("Error %d rebuilding jindex\n"), err);
return err;
diff --git a/gfs2/fsck/main.c b/gfs2/fsck/main.c
index 4e556f1..40aaaab 100644
--- a/gfs2/fsck/main.c
+++ b/gfs2/fsck/main.c
@@ -159,8 +159,8 @@ static void interrupt(int sig)
static void check_statfs(struct gfs2_sbd *sdp)
{
- osi_list_t *tmp;
- struct rgrp_list *rgd;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
struct gfs2_statfs_change sc;
char buf[sizeof(struct gfs2_statfs_change)];
@@ -177,8 +177,9 @@ static void check_statfs(struct gfs2_sbd *sdp)
sdp->blks_alloced = 0;
sdp->dinodes_alloced = 0;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
ri = &rgd->ri;
sdp->blks_total += ri->ri_data;
sdp->blks_alloced += (ri->ri_data - rgd->rg.rg_free);
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index a61971c..035fb34 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -43,7 +43,7 @@ int check_n_fix_bitmap(struct gfs2_sbd *sdp, uint64_t blk,
enum gfs2_mark_block new_blockmap_state)
{
int old_bitmap_state, new_bitmap_state;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
rgd = gfs2_blk2rgrpd(sdp, blk);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 6075ac5..c0369c5 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1505,10 +1505,10 @@ static int check_system_inodes(struct gfs2_sbd *sdp)
*/
int pass1(struct gfs2_sbd *sdp)
{
+ struct osi_node *n, *next = NULL;
struct gfs2_buffer_head *bh;
- osi_list_t *tmp;
uint64_t block;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
int first;
uint64_t i;
uint64_t blk_count;
@@ -1533,11 +1533,11 @@ int pass1(struct gfs2_sbd *sdp)
* uses the rg bitmaps, so maybe that's the best way to start
* things - we can change the method later if necessary.
*/
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist;
- tmp = tmp->next, rg_count++) {
- log_debug( _("Checking metadata in Resource Group #%" PRIu64 "\n"),
- rg_count);
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next, rg_count++) {
+ next = osi_next(n);
+ log_debug( _("Checking metadata in Resource Group #%llu\n"),
+ (unsigned long long)rg_count);
+ rgd = (struct rgrp_tree *)n;
for (i = 0; i < rgd->ri.ri_length; i++) {
log_debug( _("rgrp block %lld (0x%llx) "
"is now marked as 'rgrp data'\n"),
diff --git a/gfs2/fsck/pass5.c b/gfs2/fsck/pass5.c
index f2d23cd..a811cdb 100644
--- a/gfs2/fsck/pass5.c
+++ b/gfs2/fsck/pass5.c
@@ -157,7 +157,7 @@ static int check_block_status(struct gfs2_sbd *sdp, char *buffer,
return 0;
}
-static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
+static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_tree *rgp,
uint32_t *count)
{
uint32_t i;
@@ -221,18 +221,19 @@ static void update_rgrp(struct gfs2_sbd *sdp, struct rgrp_list *rgp,
*/
int pass5(struct gfs2_sbd *sdp)
{
- osi_list_t *tmp;
- struct rgrp_list *rgp = NULL;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rgp = NULL;
uint32_t count[3];
uint64_t rg_count = 0;
/* Reconcile RG bitmaps with fsck bitmap */
- for(tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next){
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
if (skip_this_pass || fsck_abort) /* if asked to skip the rest */
return FSCK_OK;
log_info( _("Verifying Resource Group #%" PRIu64 "\n"), rg_count);
memset(count, 0, sizeof(count));
- rgp = osi_list_entry(tmp, struct rgrp_list, list);
+ rgp = (struct rgrp_tree *)n;
rg_count++;
/* Compare the bitmaps and report the differences */
diff --git a/gfs2/fsck/rgrepair.c b/gfs2/fsck/rgrepair.c
index 2afa4ce..fb4d092 100644
--- a/gfs2/fsck/rgrepair.c
+++ b/gfs2/fsck/rgrepair.c
@@ -110,24 +110,22 @@ static int is_false_rg(uint64_t block)
* same RG size determined by the original mkfs, so recovery is easier.
*
*/
-static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
+static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, int *num_rgs)
{
+ struct osi_node *n, *next = NULL;
struct gfs2_buffer_head *bh;
uint64_t shortest_dist_btwn_rgs;
uint64_t blk, block_of_last_rg;
uint64_t fwd_block, block_bump;
uint64_t first_rg_dist, initial_first_rg_dist;
- struct rgrp_list *calc_rgd, *prev_rgd;
+ struct rgrp_tree *calc_rgd, *prev_rgd;
int number_of_rgs, rgi;
struct gfs2_rindex buf, tmpndx;
int rg_was_fnd = FALSE, corrupt_rgs = 0, bitmap_was_fnd;
- osi_list_t *tmp;
/* Figure out if there are any RG-looking blocks in the journal we
need to ignore. */
find_journaled_rgs(sdp);
- osi_list_init(ret_list);
number_of_rgs = 0;
initial_first_rg_dist = first_rg_dist = sdp->sb_addr + 1;
block_of_last_rg = sdp->sb_addr + 1;
@@ -210,6 +208,7 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
log_debug( _("Adjusted first RG distance: 0x%" PRIx64 "\n"),
first_rg_dist);
} /* if first RG distance is within tolerance */
+
/* -------------------------------------------------------------- */
/* Now go through the RGs and verify their integrity, fixing as */
/* needed when corruption is encountered. */
@@ -223,15 +222,12 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
rg_was_fnd = (!gfs2_check_meta(bh, GFS2_METATYPE_RG));
brelse(bh);
/* Allocate a new RG and index. */
- calc_rgd = malloc(sizeof(struct rgrp_list));
+ calc_rgd = rgrp_insert(&sdp->rgcalc, blk);
if (!calc_rgd) {
log_crit( _("Can't allocate memory for rg repair.\n"));
return -1;
}
- memset(calc_rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&calc_rgd->list, ret_list);
calc_rgd->ri.ri_length = 1;
- calc_rgd->ri.ri_addr = blk;
if (!rg_was_fnd) { /* if not an RG */
/* ------------------------------------------------- */
/* This SHOULD be an RG but isn't. */
@@ -316,10 +312,10 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
/* ---------------------------------------------- */
/* Now dump out the information (if verbose mode) */
/* ---------------------------------------------- */
- log_debug( _("RG index rebuilt as follows:\n"));
- for (tmp = ret_list, rgi = 0; tmp != ret_list;
- tmp = tmp->next, rgi++) {
- calc_rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ log_debug( _("rindex rebuilt as follows:\n"));
+ for (n = osi_first(&sdp->rgcalc), rgi = 0; n; n = next, rgi++) {
+ next = osi_next(n);
+ calc_rgd = (struct rgrp_tree *)n;
log_debug("%d: 0x%llx / %x / 0x%llx"
" / 0x%x / 0x%x\n", rgi + 1,
(unsigned long long)calc_rgd->ri.ri_addr,
@@ -344,15 +340,13 @@ static int gfs2_rindex_rebuild(struct gfs2_sbd *sdp, osi_list_t *ret_list,
* Sets: sdp->rglist to a linked list of fsck_rgrp structs representing
* what we think the rindex should really look like.
*/
-static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
+static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, int *num_rgs)
{
- osi_list_init(ret_list);
sdp->rgsize = GFS2_DEFAULT_RGSIZE; /* compute_rgrp_layout adjusts */
device_geometry(sdp);
fix_device_geometry(sdp);
/* Compute the default resource group layout as mkfs would have done */
- compute_rgrp_layout(sdp, FALSE);
+ compute_rgrp_layout(sdp, &sdp->rgcalc, FALSE);
build_rgrps(sdp, FALSE); /* FALSE = calc but don't write to disk. */
*num_rgs = 0;
log_debug( _("fs_total_size = 0x%" PRIX64 " blocks.\n"),
@@ -365,12 +359,8 @@ static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list,
/* the index. */
/* ----------------------------------------------------------------- */
*num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex);
- log_warn( _("L2: number of rgs in the index = %d.\n"), *num_rgs);
- /* Move the rg list to the return list */
- ret_list->next = sdp->rglist.next;
- ret_list->prev = sdp->rglist.prev;
- ret_list->next->prev = ret_list;
- ret_list->prev->next = ret_list;
+
+ sdp->rgcalc.osi_node = NULL;
return 0;
}
@@ -378,8 +368,8 @@ static int gfs2_rindex_calculate(struct gfs2_sbd *sdp, osi_list_t *ret_list,
* rewrite_rg_block - rewrite ("fix") a buffer with rg or bitmap data
* returns: 0 if the rg was repaired, otherwise 1
*/
-static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
- uint64_t errblock)
+static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_tree *rg,
+ uint64_t errblock)
{
int x = errblock - rg->ri.ri_addr;
@@ -418,18 +408,16 @@ static int rewrite_rg_block(struct gfs2_sbd *sdp, struct rgrp_list *rg,
* values as our expected values and assume the
* damage is only to the rgrps themselves.
*/
-static int expect_rindex_sanity(struct gfs2_sbd *sdp, osi_list_t *ret_list,
- int *num_rgs)
+static int expect_rindex_sanity(struct gfs2_sbd *sdp, int *num_rgs)
{
- osi_list_t *tmp;
- struct rgrp_list *exp, *rgd; /* expected, actual */
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rgd, *exp;
*num_rgs = sdp->md.riinode->i_di.di_size / sizeof(struct gfs2_rindex) ;
- osi_list_init(ret_list);
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
-
- exp = calloc(1, sizeof(struct rgrp_list));
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
+ exp = rgrp_insert(&sdp->rgcalc, rgd->ri.ri_addr);
if (exp == NULL) {
fprintf(stderr, "Out of memory in %s\n", __FUNCTION__);
exit(-1);
@@ -440,7 +428,6 @@ static int expect_rindex_sanity(struct gfs2_sbd *sdp, osi_list_t *ret_list,
memcpy(&exp->rg, &rgd->rg, sizeof(exp->rg));
exp->bits = NULL;
gfs2_compute_bitstructs(sdp, exp);
- osi_list_add_prev(&exp->list, ret_list);
}
sdp->rgrps = *num_rgs;
return 0;
@@ -456,10 +443,9 @@ static int expect_rindex_sanity(struct gfs2_sbd *sdp, osi_list_t *ret_list,
*/
int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
{
+ struct osi_node *n, *next = NULL, *e, *enext;
int error, discrepancies;
- osi_list_t expected_rglist;
int calc_rg_count = 0, rgcount_from_index, rg;
- osi_list_t *exp, *act; /* expected, actual */
struct gfs2_rindex buf;
if (trust_lvl == blind_faith)
@@ -470,45 +456,53 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
"expectations.\n"));
return -1;
}
- error = expect_rindex_sanity(sdp, &expected_rglist,
- &calc_rg_count);
- if (error)
+ error = expect_rindex_sanity(sdp, &calc_rg_count);
+ if (error) {
+ gfs2_rgrp_free(&sdp->rgcalc);
return error;
+ }
} else if (trust_lvl == open_minded) { /* If we can't trust RG index */
+ /* Free previous incarnations in memory, if any. */
+ gfs2_rgrp_free(&sdp->rgtree);
+
/* Calculate our own RG index for comparison */
- error = gfs2_rindex_calculate(sdp, &expected_rglist,
- &calc_rg_count);
+ error = gfs2_rindex_calculate(sdp, &calc_rg_count);
if (error) { /* If calculated RGs don't match the fs */
- gfs2_rgrp_free(&expected_rglist);
+ gfs2_rgrp_free(&sdp->rgcalc);
return -1;
}
}
else if (trust_lvl == distrust) { /* If we can't trust RG index */
- error = gfs2_rindex_rebuild(sdp, &expected_rglist,
- &calc_rg_count);
+ /* Free previous incarnations in memory, if any. */
+ gfs2_rgrp_free(&sdp->rgtree);
+
+ error = gfs2_rindex_rebuild(sdp, &calc_rg_count);
if (error) {
- log_crit( _("Error rebuilding rg list.\n"));
- gfs2_rgrp_free(&expected_rglist);
+ log_crit( _("Error rebuilding rgrp list.\n"));
+ gfs2_rgrp_free(&sdp->rgcalc);
return -1;
}
sdp->rgrps = calc_rg_count;
}
+
/* Read in the rindex */
- osi_list_init(&sdp->rglist); /* Just to be safe */
+ sdp->rgtree.osi_node = NULL; /* Just to be safe */
rindex_read(sdp, 0, &rgcount_from_index, sane);
if (sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex)) {
log_warn( _("WARNING: rindex file is corrupt.\n"));
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgcalc);
+ gfs2_rgrp_free(&sdp->rgtree);
return -1;
}
log_warn( _("L%d: number of rgs expected = %lld.\n"), trust_lvl + 1,
(unsigned long long)sdp->rgrps);
if (calc_rg_count != sdp->rgrps) {
- log_warn( _("L%d: They don't match; either (1) the fs was extended, (2) an odd\n"), trust_lvl + 1);
- log_warn( _("L%d: rg size was used, or (3) we have a corrupt rg index.\n"), trust_lvl + 1);
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
+ log_warn( _("L%d: They don't match; either (1) the fs was "
+ "extended, (2) an odd\n"), trust_lvl + 1);
+ log_warn( _("L%d: rgrp size was used, or (3) we have a corrupt "
+ "rg index.\n"), trust_lvl + 1);
+ gfs2_rgrp_free(&sdp->rgcalc);
+ gfs2_rgrp_free(&sdp->rgtree);
return -1;
}
/* ------------------------------------------------------------- */
@@ -519,28 +513,46 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
/* abandon this method of recovery and try a better one. */
/* ------------------------------------------------------------- */
discrepancies = 0;
- for (rg = 0, act = sdp->rglist.next, exp = expected_rglist.next;
- act != &sdp->rglist && exp != &expected_rglist;
- act = act->next, exp = exp->next, rg++) {
- struct rgrp_list *expected, *actual;
-
- expected = osi_list_entry(exp, struct rgrp_list, list);
- actual = osi_list_entry(act, struct rgrp_list, list);
- if (!ri_equal(actual->ri, expected->ri, ri_addr) ||
- !ri_equal(actual->ri, expected->ri, ri_length) ||
+ for (rg = 0, n = osi_first(&sdp->rgtree), e = osi_first(&sdp->rgcalc);
+ n && e && !fsck_abort; rg++) {
+ struct rgrp_tree *expected, *actual;
+
+ next = osi_next(n);
+ enext = osi_next(e);
+
+ expected = (struct rgrp_tree *)e;
+ actual = (struct rgrp_tree *)n;
+ if (actual->ri.ri_addr < expected->ri.ri_addr) {
+ n = next;
+ discrepancies++;
+ log_info(_("%d addr: 0x%llx < 0x%llx * mismatch\n"),
+ rg + 1, actual->ri.ri_addr,
+ expected->ri.ri_addr);
+ continue;
+ } else if (expected->ri.ri_addr < actual->ri.ri_addr) {
+ e = enext;
+ discrepancies++;
+ log_info(_("%d addr: 0x%llx > 0x%llx * mismatch\n"),
+ rg + 1, actual->ri.ri_addr,
+ expected->ri.ri_addr);
+ continue;
+ }
+ if (!ri_equal(actual->ri, expected->ri, ri_length) ||
!ri_equal(actual->ri, expected->ri, ri_data0) ||
!ri_equal(actual->ri, expected->ri, ri_data) ||
!ri_equal(actual->ri, expected->ri, ri_bitbytes)) {
discrepancies++;
}
+ n = next;
+ e = enext;
}
if (trust_lvl < distrust && discrepancies > (trust_lvl * 8)) {
log_warn( _("Level %d didn't work. Too many descepencies.\n"),
trust_lvl + 1);
log_warn( _("%d out of %d RGs did not match what was expected.\n"),
discrepancies, rg);
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgcalc);
+ gfs2_rgrp_free(&sdp->rgtree);
return -1;
}
/* ------------------------------------------------------------- */
@@ -548,19 +560,40 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
/* Our rindex should be pretty predictable unless we've grown */
/* so look for index problems first before looking at the rgs. */
/* ------------------------------------------------------------- */
- for (rg = 0, act = sdp->rglist.next, exp = expected_rglist.next;
- act != &sdp->rglist && exp != &expected_rglist;
- act = act->next, exp = exp->next, rg++) {
- struct rgrp_list *expected, *actual;
-
- expected = osi_list_entry(exp, struct rgrp_list, list);
- actual = osi_list_entry(act, struct rgrp_list, list);
- ri_compare(rg, actual->ri, expected->ri, ri_addr, PRIx64);
- ri_compare(rg, actual->ri, expected->ri, ri_length, PRIx32);
- ri_compare(rg, actual->ri, expected->ri, ri_data0, PRIx64);
- ri_compare(rg, actual->ri, expected->ri, ri_data, PRIx32);
- ri_compare(rg, actual->ri, expected->ri, ri_bitbytes,
- PRIx32);
+ for (rg = 0, n = osi_first(&sdp->rgtree), e = osi_first(&sdp->rgcalc);
+ e && !fsck_abort; rg++) {
+ struct rgrp_tree *expected, *actual;
+
+ if (n)
+ next = osi_next(n);
+ enext = osi_next(e);
+ expected = (struct rgrp_tree *)e;
+
+ /* If we ran out of actual rindex entries due to rindex
+ damage, fill in a new one with the expected values. */
+ if (!n) { /* end of actual rindex */
+ log_err( _("Entry missing from rindex: 0x%llx\n"),
+ (unsigned long long)expected->ri.ri_addr);
+ actual = rgrp_insert(&sdp->rgtree,
+ expected->ri.ri_addr);
+ if (!actual) {
+ log_err(_("Out of memory!\n"));
+ break;
+ }
+ rindex_modified = 1;
+ } else {
+ actual = (struct rgrp_tree *)n;
+ ri_compare(rg, actual->ri, expected->ri, ri_addr,
+ "llx");
+ ri_compare(rg, actual->ri, expected->ri, ri_length,
+ PRIx32);
+ ri_compare(rg, actual->ri, expected->ri, ri_data0,
+ "llx");
+ ri_compare(rg, actual->ri, expected->ri, ri_data,
+ PRIx32);
+ ri_compare(rg, actual->ri, expected->ri, ri_bitbytes,
+ PRIx32);
+ }
/* If we modified the index, write it back to disk. */
if (rindex_modified) {
if (query( _("Fix the index? (y/n)"))) {
@@ -586,23 +619,27 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
gfs2_compute_bitstructs(sdp, actual);
rindex_modified = FALSE;
}
+ e = enext;
+ if (n)
+ n = next;
}
/* ------------------------------------------------------------- */
/* Read the real RGs and check their integrity. */
/* Now we can somewhat trust the rindex and the RG addresses, */
/* so let's read them in, check them and optionally fix them. */
/* ------------------------------------------------------------- */
- for (rg = 0, act = sdp->rglist.next; act != &sdp->rglist;
- act = act->next, rg++) {
- struct rgrp_list *rgd;
+ for (rg = 0, n = osi_first(&sdp->rgtree); n && !fsck_abort;
+ n = next, rg++) {
+ struct rgrp_tree *rgd;
uint64_t prev_err = 0, errblock;
int i;
+ next = osi_next(n);
/* Now we try repeatedly to read in the rg. For every block */
/* we encounter that has errors, repair it and try again. */
i = 0;
do {
- rgd = osi_list_entry(act, struct rgrp_list, list);
+ rgd = (struct rgrp_tree *)n;
errblock = gfs2_rgrp_read(sdp, rgd);
if (errblock) {
if (errblock == prev_err)
@@ -617,7 +654,7 @@ int rg_repair(struct gfs2_sbd *sdp, int trust_lvl, int *rg_count, int *sane)
} while (i < rgd->ri.ri_length);
}
*rg_count = rg;
- gfs2_rgrp_free(&expected_rglist);
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgcalc);
+ gfs2_rgrp_free(&sdp->rgtree);
return 0;
}
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index 79d76cf..d95461b 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -492,7 +492,6 @@ void *gfs2_bmap_destroy(struct gfs2_sbd *sdp, struct gfs2_bmap *il)
int set_ip_blockmap(struct gfs2_inode *ip, int instree)
{
uint64_t block = ip->i_bh->b_blocknr;
- struct gfs2_sbd *sdp = ip->i_sbd;
uint32_t mode;
mode = ip->i_di.di_mode & S_IFMT;
diff --git a/gfs2/libgfs2/fs_bits.c b/gfs2/libgfs2/fs_bits.c
index 11b6fb2..4834a2a 100644
--- a/gfs2/libgfs2/fs_bits.c
+++ b/gfs2/libgfs2/fs_bits.c
@@ -188,7 +188,7 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
int buf;
uint32_t rgrp_block;
struct gfs2_bitmap *bits = NULL;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
unsigned char *byte, cur_state;
unsigned int bit;
@@ -236,7 +236,7 @@ int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state)
* Returns: state on success, -1 on error
*/
int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_list *rgd)
+ struct rgrp_tree *rgd)
{
int i, val;
uint32_t rgrp_block;
diff --git a/gfs2/libgfs2/fs_geometry.c b/gfs2/libgfs2/fs_geometry.c
index 9969577..58c1c89 100644
--- a/gfs2/libgfs2/fs_geometry.c
+++ b/gfs2/libgfs2/fs_geometry.c
@@ -62,12 +62,14 @@ static uint64_t how_many_rgrps(struct gfs2_sbd *sdp, struct device *dev, int rgs
* Returns: a list of rgrp_list_t structures
*/
-void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified)
+void compute_rgrp_layout(struct gfs2_sbd *sdp, struct osi_root *rgtree,
+ int rgsize_specified)
{
struct device *dev;
- struct rgrp_list *rl, *rlast = NULL, *rlast2 = NULL;
- osi_list_t *tmp, *head = &sdp->rglist;
+ struct rgrp_tree *rl, *rlast = NULL, *rlast2 = NULL;
+ struct osi_node *n, *next = NULL;
unsigned int rgrp = 0, nrgrp, rglength;
+ uint64_t rgaddr;
sdp->new_rgrps = 0;
dev = &sdp->device;
@@ -78,7 +80,7 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified)
/* If this is a new file system, compute the length and number */
/* of rgs based on the size of the device. */
/* If we have existing RGs (i.e. gfs2_grow) find the last one. */
- if (osi_list_empty(&sdp->rglist)) {
+ if (!rgtree->osi_node) {
dev->length -= sdp->sb_addr + 1;
nrgrp = how_many_rgrps(sdp, dev, rgsize_specified);
rglength = dev->length / nrgrp;
@@ -87,10 +89,10 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified)
uint64_t old_length, new_chunk;
log_info("Existing resource groups:\n");
- rgsize_specified = TRUE; /* consistently use existing size */
- for (rgrp = 0, tmp = head->next; tmp != head;
- tmp = tmp->next, rgrp++) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ for (rgrp = 0, n = osi_first(rgtree); n; n = next, rgrp++) {
+ next = osi_next(n);
+ rl = (struct rgrp_tree *)n;
+
log_info("%d: start: %" PRIu64 " (0x%"
PRIx64 "), length = %"PRIu64" (0x%"
PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
@@ -109,32 +111,31 @@ void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified)
log_info("\nNew resource groups:\n");
for (; rgrp < nrgrp; rgrp++) {
- zalloc(rl, sizeof(struct rgrp_list));
-
if (rgrp) {
- rl->start = rlast->start + rlast->length;
+ rgaddr = rlast->start + rlast->length;
+ rl = rgrp_insert(rgtree, rgaddr);
rl->length = rglength;
} else {
- rl->start = dev->start;
+ rgaddr = dev->start;
+ rl = rgrp_insert(rgtree, rgaddr);
rl->length = dev->length -
(nrgrp - 1) * (dev->length / nrgrp);
}
-
+ rl->start = rgaddr;
log_info("%d: start: %" PRIu64 " (0x%"
PRIx64 "), length = %"PRIu64" (0x%"
PRIx64 ")\n", rgrp + 1, rl->start, rl->start,
rl->length, rl->length);
- osi_list_add_prev(&rl->list, head);
rlast = rl;
}
sdp->rgrps = nrgrp;
-
if (sdp->debug) {
log_info("\n");
- for (tmp = head->next; tmp != head; tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(rgtree); n; n = next) {
+ next = osi_next(n);
+ rl = (struct rgrp_tree *)n;
log_info("rg_o = %llu, rg_l = %llu\n",
rl->start, rl->length);
}
@@ -185,8 +186,8 @@ rgblocks2bitblocks(unsigned int bsize, uint32_t *rgblocks, uint32_t *bitblocks)
*/
void build_rgrps(struct gfs2_sbd *sdp, int do_write)
{
- osi_list_t *tmp, *head;
- struct rgrp_list *rl;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rl;
uint32_t rgblocks, bitblocks;
struct gfs2_rindex *ri;
struct gfs2_meta_header mh;
@@ -195,11 +196,14 @@ void build_rgrps(struct gfs2_sbd *sdp, int do_write)
mh.mh_magic = GFS2_MAGIC;
mh.mh_type = GFS2_METATYPE_RB;
mh.mh_format = GFS2_FORMAT_RB;
-
- for (head = &sdp->rglist, tmp = head->next;
- tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ if (do_write)
+ n = osi_first(&sdp->rgtree);
+ else
+ n = osi_first(&sdp->rgcalc);
+
+ for (; n; n = next) {
+ next = osi_next(n);
+ rl = (struct rgrp_tree *)n;
ri = &rl->ri;
rgblocks = rl->length;
diff --git a/gfs2/libgfs2/fs_ops.c b/gfs2/libgfs2/fs_ops.c
index 1c20e61..78b3a8d 100644
--- a/gfs2/libgfs2/fs_ops.c
+++ b/gfs2/libgfs2/fs_ops.c
@@ -117,8 +117,8 @@ void inode_put(struct gfs2_inode **ip_in)
static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
{
- osi_list_t *tmp, *head;
- struct rgrp_list *rl = NULL;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rl = NULL;
struct gfs2_rindex *ri;
struct gfs2_rgrp *rg;
unsigned int block, bn = 0, x = 0, y = 0;
@@ -126,14 +126,14 @@ static uint64_t blk_alloc_i(struct gfs2_sbd *sdp, unsigned int type)
struct gfs2_buffer_head *bh;
memset(&rg, 0, sizeof(rg));
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rl = (struct rgrp_tree *)n;
if (rl->rg.rg_free)
break;
}
- if (tmp == head)
+ if (n == NULL)
die("out of space\n");
ri = &rl->ri;
@@ -1676,7 +1676,7 @@ int gfs2_lookupi(struct gfs2_inode *dip, const char *filename, int len,
*/
void gfs2_free_block(struct gfs2_sbd *sdp, uint64_t block)
{
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
/* Adjust the free space count for the freed block */
rgd = gfs2_blk2rgrpd(sdp, block); /* find the rg for indir block */
@@ -1698,7 +1698,7 @@ int gfs2_freedi(struct gfs2_sbd *sdp, uint64_t diblock)
struct gfs2_buffer_head *bh, *nbh;
int h, head_size;
uint64_t *ptr, block;
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
uint32_t height;
osi_list_t metalist[GFS2_MAX_META_HEIGHT];
osi_list_t *cur_list, *next_list, *tmp;
diff --git a/gfs2/libgfs2/gfs1.c b/gfs2/libgfs2/gfs1.c
index 5018334..41edf16 100644
--- a/gfs2/libgfs2/gfs1.c
+++ b/gfs2/libgfs2/gfs1.c
@@ -234,8 +234,8 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
{
unsigned int rg;
int error;
- struct gfs2_rindex buf;
- struct rgrp_list *rgd, *prev_rgd;
+ struct gfs2_rindex buf, ri;
+ struct rgrp_tree *rgd = NULL, *prev_rgd = NULL;
uint64_t prev_length = 0;
*count1 = 0;
@@ -252,20 +252,14 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
if (error != sizeof(struct gfs2_rindex))
return -1;
- rgd = (struct rgrp_list *)malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Cannot allocate memory for rindex.\n");
- exit(-1);
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&rgd->list, &sdp->rglist);
-
- gfs2_rindex_in(&rgd->ri, (char *)&buf);
+ gfs2_rindex_in(&ri, (char *)&buf);
+ rgd = rgrp_insert(&sdp->rgtree, ri.ri_addr);
+ memcpy(&rgd->ri, &ri, sizeof(struct gfs2_rindex));
rgd->start = rgd->ri.ri_addr;
if (prev_rgd) {
prev_length = rgd->start - prev_rgd->start;
- prev_rgd->length = prev_length;
+ prev_rgd->length = rgrp_size(prev_rgd);
}
if(gfs2_compute_bitstructs(sdp, rgd))
@@ -275,7 +269,7 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
prev_rgd = rgd;
}
if (prev_rgd)
- prev_rgd->length = prev_length;
+ prev_rgd->length = rgrp_size(prev_rgd);
return 0;
}
@@ -291,17 +285,18 @@ int gfs1_rindex_read(struct gfs2_sbd *sdp, int fd, int *count1)
*/
int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet)
{
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
- osi_list_t *tmp;
int count1 = 0, count2 = 0;
uint64_t errblock = 0;
uint64_t rmax = 0;
+ struct osi_node *n, *next = NULL;
if (gfs1_rindex_read(sdp, fd, &count1))
goto fail;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
errblock = gfs2_rgrp_read(sdp, rgd);
if (errblock)
return errblock;
@@ -323,7 +318,7 @@ int gfs1_ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int quiet)
return 0;
fail:
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
return -1;
}
diff --git a/gfs2/libgfs2/libgfs2.h b/gfs2/libgfs2/libgfs2.h
index 87c65c6..95a4ddb 100644
--- a/gfs2/libgfs2/libgfs2.h
+++ b/gfs2/libgfs2/libgfs2.h
@@ -23,6 +23,7 @@
#include <linux/gfs2_ondisk.h>
#include "osi_list.h"
#include "copyright.cf"
+#include "osi_tree.h"
#ifndef TRUE
#define TRUE (1)
@@ -94,8 +95,8 @@ struct gfs2_bitmap
};
typedef struct gfs2_bitmap gfs2_bitmap_t;
-struct rgrp_list {
- osi_list_t list;
+struct rgrp_tree {
+ struct osi_node node;
uint64_t start; /* The offset of the beginning of this resource group */
uint64_t length; /* The length of this resource group */
@@ -221,7 +222,8 @@ struct gfs2_sbd {
uint64_t orig_rgrps;
uint64_t rgrps;
uint64_t new_rgrps;
- osi_list_t rglist;
+ struct osi_root rgtree;
+ struct osi_root rgcalc;
unsigned int orig_journals;
@@ -307,22 +309,23 @@ unsigned long gfs2_bitfit(const unsigned char *buf, const unsigned int len,
unsigned long goal, unsigned char state);
/* functions with blk #'s that are rgrp relative */
-uint32_t gfs2_blkalloc_internal(struct rgrp_list *rgd, uint32_t goal,
- unsigned char old_state,
- unsigned char new_state, int do_it);
-int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno);
+extern uint32_t gfs2_blkalloc_internal(struct rgrp_tree *rgd, uint32_t goal,
+ unsigned char old_state,
+ unsigned char new_state, int do_it);
+extern int gfs2_check_range(struct gfs2_sbd *sdp, uint64_t blkno);
/* functions with blk #'s that are file system relative */
extern int valid_block(struct gfs2_sbd *sdp, uint64_t blkno);
extern int gfs2_get_bitmap(struct gfs2_sbd *sdp, uint64_t blkno,
- struct rgrp_list *rgd);
+ struct rgrp_tree *rgd);
extern int gfs2_set_bitmap(struct gfs2_sbd *sdp, uint64_t blkno, int state);
/* fs_geometry.c */
-void rgblocks2bitblocks(unsigned int bsize, uint32_t *rgblocks,
- uint32_t *bitblocks);
-void compute_rgrp_layout(struct gfs2_sbd *sdp, int rgsize_specified);
-void build_rgrps(struct gfs2_sbd *sdp, int write);
+extern void rgblocks2bitblocks(unsigned int bsize, uint32_t *rgblocks,
+ uint32_t *bitblocks);
+extern void compute_rgrp_layout(struct gfs2_sbd *sdp, struct osi_root *rgtree,
+ int rgsize_specified);
+extern void build_rgrps(struct gfs2_sbd *sdp, int write);
/* fs_ops.c */
#define IS_LEAF (1)
@@ -583,13 +586,15 @@ int gfs2_find_jhead(struct gfs2_inode *ip, struct gfs2_log_header *head);
int clean_journal(struct gfs2_inode *ip, struct gfs2_log_header *head);
/* rgrp.c */
-extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
-extern struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk);
-extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd);
-extern void gfs2_rgrp_relse(struct rgrp_list *rgd);
-extern void gfs2_rgrp_free(osi_list_t *rglist);
+extern int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_tree *rgd);
+extern struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk);
+extern uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_tree *rgd);
+extern void gfs2_rgrp_relse(struct rgrp_tree *rgd);
+extern struct rgrp_tree *rgrp_insert(struct osi_root *rgtree,
+ uint64_t rgblock);
+extern void gfs2_rgrp_free(struct osi_root *rgrp_tree);
/* figure out the size of the given resource group, in blocks */
-static inline unsigned int rgrp_size(struct rgrp_list *rgrp)
+static inline unsigned int rgrp_size(struct rgrp_tree *rgrp)
{
return rgrp->ri.ri_data + rgrp->ri.ri_length;
}
@@ -609,9 +614,9 @@ extern int build_root(struct gfs2_sbd *sdp);
extern int do_init_inum(struct gfs2_sbd *sdp);
extern int do_init_statfs(struct gfs2_sbd *sdp);
extern int gfs2_check_meta(struct gfs2_buffer_head *bh, int type);
-extern int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block,
+extern int gfs2_next_rg_meta(struct rgrp_tree *rgd, uint64_t *block,
int first);
-extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
+extern int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
uint64_t *block, uint32_t type, int first);
/* super.c */
extern int check_sb(struct gfs2_sb *sb);
diff --git a/gfs2/libgfs2/rgrp.c b/gfs2/libgfs2/rgrp.c
index 438d320..e9addeb 100644
--- a/gfs2/libgfs2/rgrp.c
+++ b/gfs2/libgfs2/rgrp.c
@@ -24,7 +24,7 @@
*
* Returns: 0 on success, -1 on error
*/
-int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
+int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_tree *rgd)
{
struct gfs2_bitmap *bits;
uint32_t length = rgd->ri.ri_length;
@@ -104,33 +104,21 @@ int gfs2_compute_bitstructs(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
*
* Returns: Ths resource group, or NULL if not found
*/
-struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
+struct rgrp_tree *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
{
- osi_list_t *tmp;
- struct rgrp_list *rgd;
- static struct rgrp_list *prev_rgd = NULL;
+ struct osi_node *node = sdp->rgtree.osi_node;
struct gfs2_rindex *ri;
- if (prev_rgd) {
- ri = &prev_rgd->ri;
- if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data)
- return prev_rgd;
- if (blk >= ri->ri_addr && blk < ri->ri_addr + ri->ri_length)
- return prev_rgd;
- }
-
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ while (node) {
+ struct rgrp_tree *rgd = (struct rgrp_tree *)node;
ri = &rgd->ri;
- if (blk >= ri->ri_addr && blk < ri->ri_addr + ri->ri_length) {
- prev_rgd = rgd;
+ if (blk < ri->ri_addr)
+ node = node->osi_left;
+ else if (blk > ri->ri_data0 + ri->ri_data)
+ node = node->osi_right;
+ else
return rgd;
- }
- if (ri->ri_data0 <= blk && blk < ri->ri_data0 + ri->ri_data) {
- prev_rgd = rgd;
- return rgd;
- }
}
return NULL;
}
@@ -140,7 +128,7 @@ struct rgrp_list *gfs2_blk2rgrpd(struct gfs2_sbd *sdp, uint64_t blk)
* @rgd - resource group structure
* returns: 0 if no error, otherwise the block number that failed
*/
-uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
+uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_tree *rgd)
{
int x, length = rgd->ri.ri_length;
@@ -164,7 +152,7 @@ uint64_t gfs2_rgrp_read(struct gfs2_sbd *sdp, struct rgrp_list *rgd)
return 0;
}
-void gfs2_rgrp_relse(struct rgrp_list *rgd)
+void gfs2_rgrp_relse(struct rgrp_tree *rgd)
{
int x, length = rgd->ri.ri_length;
@@ -177,12 +165,44 @@ void gfs2_rgrp_relse(struct rgrp_list *rgd)
}
}
-void gfs2_rgrp_free(osi_list_t *rglist)
+struct rgrp_tree *rgrp_insert(struct osi_root *rgtree, uint64_t rgblock)
+{
+ struct osi_node **newn = &rgtree->osi_node, *parent = NULL;
+ struct rgrp_tree *data;
+
+ /* Figure out where to put new node */
+ while (*newn) {
+ struct rgrp_tree *cur = (struct rgrp_tree *)*newn;
+
+ parent = *newn;
+ if (rgblock < cur->ri.ri_addr)
+ newn = &((*newn)->osi_left);
+ else if (rgblock > cur->ri.ri_addr)
+ newn = &((*newn)->osi_right);
+ else
+ return cur;
+ }
+
+ data = malloc(sizeof(struct rgrp_tree));
+ if (!data)
+ return NULL;
+ if (!memset(data, 0, sizeof(struct rgrp_tree)))
+ return NULL;
+ /* Add new node and rebalance tree. */
+ data->ri.ri_addr = rgblock;
+ osi_link_node(&data->node, parent, newn);
+ osi_insert_color(&data->node, rgtree);
+
+ return data;
+}
+
+void gfs2_rgrp_free(struct osi_root *rgrp_tree)
{
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
+ struct osi_node *n;
- while(!osi_list_empty(rglist->next)){
- rgd = osi_list_entry(rglist->next, struct rgrp_list, list);
+ while ((n = osi_first(rgrp_tree))) {
+ rgd = (struct rgrp_tree *)n;
if (rgd->bh && rgd->bh[0]) /* if a buffer exists */
gfs2_rgrp_relse(rgd); /* free them all. */
if(rgd->bits)
@@ -191,7 +211,7 @@ void gfs2_rgrp_free(osi_list_t *rglist)
free(rgd->bh);
rgd->bh = NULL;
}
- osi_list_del(&rgd->list);
+ osi_erase(&rgd->node, rgrp_tree);
free(rgd);
}
}
diff --git a/gfs2/libgfs2/structures.c b/gfs2/libgfs2/structures.c
index b7851e8..8a19afe 100644
--- a/gfs2/libgfs2/structures.c
+++ b/gfs2/libgfs2/structures.c
@@ -320,8 +320,8 @@ int build_statfs(struct gfs2_sbd *sdp)
int build_rindex(struct gfs2_sbd *sdp)
{
struct gfs2_inode *ip;
- osi_list_t *tmp, *head;
- struct rgrp_list *rl;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rl;
char buf[sizeof(struct gfs2_rindex)];
int count;
@@ -330,9 +330,9 @@ int build_rindex(struct gfs2_sbd *sdp)
ip->i_di.di_payload_format = GFS2_FORMAT_RI;
bmodified(ip->i_bh);
- for (head = &sdp->rglist, tmp = head->next; tmp != head;
- tmp = tmp->next) {
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rl = (struct rgrp_tree *)n;
gfs2_rindex_out(&rl->ri, buf);
@@ -498,24 +498,24 @@ int gfs2_set_meta(struct gfs2_buffer_head *bh, int type, int format)
*
* Returns: 0 on success, -1 when finished
*/
-int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
+int gfs2_next_rg_meta(struct rgrp_tree *rgd, uint64_t *block, int first)
{
struct gfs2_bitmap *bits = NULL;
uint32_t length = rgd->ri.ri_length;
uint32_t blk = (first)? 0: (uint32_t)((*block+1)-rgd->ri.ri_data0);
int i;
- if(!first && (*block < rgd->ri.ri_data0)) {
+ if (!first && (*block < rgd->ri.ri_data0)) {
log_err("next_rg_meta: Start block is outside rgrp bounds.\n");
exit(1);
}
- for(i=0; i < length; i++){
+ for (i = 0; i < length; i++){
bits = &rgd->bits[i];
if(blk < bits->bi_len*GFS2_NBBY)
break;
blk -= bits->bi_len*GFS2_NBBY;
}
- for(; i < length; i++){
+ for (; i < length; i++){
bits = &rgd->bits[i];
blk = gfs2_bitfit((unsigned char *)rgd->bh[i]->b_data +
bits->bi_offset, bits->bi_len, blk,
@@ -526,7 +526,7 @@ int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
}
blk=0;
}
- if(i == length)
+ if (i == length)
return -1;
return 0;
}
@@ -540,7 +540,7 @@ int gfs2_next_rg_meta(struct rgrp_list *rgd, uint64_t *block, int first)
*
* Returns: 0 on success, -1 on error or finished
*/
-int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_list *rgd,
+int gfs2_next_rg_metatype(struct gfs2_sbd *sdp, struct rgrp_tree *rgd,
uint64_t *block, uint32_t type, int first)
{
struct gfs2_buffer_head *bh = NULL;
diff --git a/gfs2/libgfs2/super.c b/gfs2/libgfs2/super.c
index 51a8047..3a51eb4 100644
--- a/gfs2/libgfs2/super.c
+++ b/gfs2/libgfs2/super.c
@@ -144,12 +144,12 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
unsigned int rg;
int error;
struct gfs2_rindex buf;
- struct rgrp_list *rgd, *prev_rgd;
+ struct gfs2_rindex ri;
+ struct rgrp_tree *rgd = NULL, *prev_rgd = NULL;
uint64_t prev_length = 0;
*sane = 1;
*count1 = 0;
- prev_rgd = NULL;
if (!fd && sdp->md.riinode->i_di.di_size % sizeof(struct gfs2_rindex))
*sane = 0; /* rindex file size must be a multiple of 96 */
for (rg = 0; ; rg++) {
@@ -164,15 +164,9 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
if (error != sizeof(struct gfs2_rindex))
return -1;
- rgd = (struct rgrp_list *)malloc(sizeof(struct rgrp_list));
- if (!rgd) {
- log_crit("Cannot allocate memory for rindex.\n");
- exit(-1);
- }
- memset(rgd, 0, sizeof(struct rgrp_list));
- osi_list_add_prev(&rgd->list, &sdp->rglist);
-
- gfs2_rindex_in(&rgd->ri, (char *)&buf);
+ gfs2_rindex_in(&ri, (char *)&buf);
+ rgd = rgrp_insert(&sdp->rgtree, ri.ri_addr);
+ memcpy(&rgd->ri, &ri, sizeof(struct gfs2_rindex));
rgd->start = rgd->ri.ri_addr;
if (prev_rgd) {
@@ -219,17 +213,18 @@ int rindex_read(struct gfs2_sbd *sdp, int fd, int *count1, int *sane)
*/
int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane)
{
- struct rgrp_list *rgd;
+ struct rgrp_tree *rgd;
struct gfs2_rindex *ri;
- osi_list_t *tmp;
int count1 = 0, count2 = 0;
uint64_t errblock = 0;
uint64_t rmax = 0;
+ struct osi_node *n, *next = NULL;
if (rindex_read(sdp, fd, &count1, sane))
- goto fail;
- for (tmp = sdp->rglist.next; tmp != &sdp->rglist; tmp = tmp->next) {
- rgd = osi_list_entry(tmp, struct rgrp_list, list);
+ goto fail;
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgd = (struct rgrp_tree *)n;
errblock = gfs2_rgrp_read(sdp, rgd);
if (errblock)
return errblock;
@@ -247,7 +242,7 @@ int ri_update(struct gfs2_sbd *sdp, int fd, int *rgcount, int *sane)
return 0;
fail:
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
return -1;
}
diff --git a/gfs2/mkfs/main_grow.c b/gfs2/mkfs/main_grow.c
index 252bcb2..9aba5da 100644
--- a/gfs2/mkfs/main_grow.c
+++ b/gfs2/mkfs/main_grow.c
@@ -129,16 +129,13 @@ static void decode_arguments(int argc, char *argv[], struct gfs2_sbd *sdp)
static uint64_t filesystem_size(struct gfs2_sbd *sdp)
{
- osi_list_t *tmp;
- struct rgrp_list *rgl;
+ struct osi_node *n, *next = NULL;
+ struct rgrp_tree *rgl;
uint64_t size = 0, extent;
- tmp = &sdp->rglist;
- for (;;) {
- tmp = tmp->next;
- if (tmp == &sdp->rglist)
- break;
- rgl = osi_list_entry(tmp, struct rgrp_list, list);
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
+ rgl = (struct rgrp_tree *)n;
extent = rgl->ri.ri_addr + rgl->ri.ri_length + rgl->ri.ri_data;
if (extent > size)
size = extent;
@@ -151,15 +148,19 @@ static uint64_t filesystem_size(struct gfs2_sbd *sdp)
*/
static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count)
{
+ struct osi_node *n, *next = NULL;
uint64_t rgrp = 0;
- osi_list_t *head = &sdp->rglist;
+ struct rgrp_tree *rl;
*old_rg_count = 0;
/* Delete the old RGs from the rglist */
- for (rgrp = 0; !osi_list_empty(head) &&
- rgrp < (sdp->rgrps - sdp->new_rgrps); rgrp++) {
+ for (rgrp = 0, n = osi_first(&sdp->rgtree);
+ n && rgrp < (sdp->rgrps - sdp->new_rgrps); n = next, rgrp++) {
+ next = osi_next(n);
(*old_rg_count)++;
- osi_list_del(head->next);
+ rl = (struct rgrp_tree *)n;
+ osi_erase(&rl->node, &sdp->rgtree);
+ free(rl);
}
/* Build the remaining resource groups */
build_rgrps(sdp, !test);
@@ -176,17 +177,19 @@ static void initialize_new_portion(struct gfs2_sbd *sdp, int *old_rg_count)
*/
static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
{
+ struct osi_node *n, *next = NULL;
int count, rg;
- struct rgrp_list *rl;
+ struct rgrp_tree *rl;
char *buf, *bufptr;
- osi_list_t *tmp;
ssize_t writelen;
struct stat statbuf;
/* Count the number of new RGs. */
rg = 0;
- osi_list_foreach(tmp, &sdp->rglist)
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
rg++;
+ }
log_info( _("%d new rindex entries.\n"), rg);
writelen = rg * sizeof(struct gfs2_rindex);
zalloc(buf, writelen);
@@ -196,13 +199,14 @@ static void fix_rindex(struct gfs2_sbd *sdp, int rindex_fd, int old_rg_count)
/* need to use the gfs2 kernel code rather than the libgfs2 */
/* code so we have a live update while mounted. */
bufptr = buf;
- osi_list_foreach(tmp, &sdp->rglist) {
+ for (n = osi_first(&sdp->rgtree); n; n = next) {
+ next = osi_next(n);
rg++;
- rl = osi_list_entry(tmp, struct rgrp_list, list);
+ rl = (struct rgrp_tree *)n;
gfs2_rindex_out(&rl->ri, bufptr);
bufptr += sizeof(struct gfs2_rindex);
}
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
fsync(sdp->device_fd);
if (!test) {
if (fstat(rindex_fd, &statbuf) != 0) {
@@ -284,7 +288,6 @@ main_grow(int argc, char *argv[])
struct gfs2_sbd sbd, *sdp = &sbd;
int rgcount, rindex_fd;
char rindex_name[PATH_MAX];
- osi_list_t *head = &sdp->rglist;
memset(sdp, 0, sizeof(struct gfs2_sbd));
sdp->bsize = GFS2_DEFAULT_BSIZE;
@@ -296,7 +299,7 @@ main_grow(int argc, char *argv[])
while ((argc - optind) > 0) {
int sane;
- struct rgrp_list *last_rgrp;
+ struct rgrp_tree *last_rgrp;
sdp->path_name = argv[optind++];
sdp->path_fd = open(sdp->path_name, O_RDONLY);
@@ -312,7 +315,8 @@ main_grow(int argc, char *argv[])
sdp->device_name, strerror(errno));
device_geometry(sdp);
log_info( _("Initializing lists...\n"));
- osi_list_init(&sdp->rglist);
+ sdp->rgtree.osi_node = NULL;
+ sdp->rgcalc.osi_node = NULL;
sdp->sd_sb.sb_bsize = GFS2_DEFAULT_BSIZE;
sdp->bsize = sdp->sd_sb.sb_bsize;
@@ -340,11 +344,11 @@ main_grow(int argc, char *argv[])
/* the existing RGs, and only write to the index at EOF. */
ri_update(sdp, rindex_fd, &rgcount, &sane);
fssize = filesystem_size(sdp);
- if (osi_list_empty(head)) {
+ if (!sdp->rgtree.osi_node) {
log_err(_("Error: No resource groups found.\n"));
goto out;
}
- last_rgrp = osi_list_entry(head->prev, struct rgrp_list, list);
+ last_rgrp = (struct rgrp_tree *)osi_last(&sdp->rgtree);
sdp->rgsize = GFS2_DEFAULT_RGSIZE;
rgsize = rgrp_size(last_rgrp);
fsgrowth = ((sdp->device.length - fssize) * sdp->bsize);
@@ -359,15 +363,14 @@ main_grow(int argc, char *argv[])
else {
int old_rg_count;
- compute_rgrp_layout(sdp, TRUE);
+ compute_rgrp_layout(sdp, &sdp->rgtree, TRUE);
print_info(sdp);
initialize_new_portion(sdp, &old_rg_count);
fix_rindex(sdp, rindex_fd, old_rg_count);
}
out:
/* Delete the remaining RGs from the rglist */
- while (!osi_list_empty(head))
- osi_list_del(head->next);
+ gfs2_rgrp_free(&sdp->rgtree);
close(rindex_fd);
cleanup_metafs(sdp);
close(sdp->device_fd);
diff --git a/gfs2/mkfs/main_mkfs.c b/gfs2/mkfs/main_mkfs.c
index bfe6c45..a2ed1be 100644
--- a/gfs2/mkfs/main_mkfs.c
+++ b/gfs2/mkfs/main_mkfs.c
@@ -361,7 +361,7 @@ main_mkfs(int argc, char *argv[])
sdp->qcsize = GFS2_DEFAULT_QCSIZE;
strcpy(sdp->lockproto, GFS2_DEFAULT_LOCKPROTO);
sdp->time = time(NULL);
- osi_list_init(&sdp->rglist);
+ sdp->rgtree.osi_node = NULL;
decode_arguments(argc, argv, sdp);
if (sdp->rgsize == -1) /* if rg size not specified */
@@ -408,7 +408,7 @@ main_mkfs(int argc, char *argv[])
/* Compute the resource group layouts */
- compute_rgrp_layout(sdp, rgsize_specified);
+ compute_rgrp_layout(sdp, &sdp->rgtree, rgsize_specified);
/* Generate a random uuid */
get_random_bytes(uuid, sizeof(uuid));
@@ -438,7 +438,7 @@ main_mkfs(int argc, char *argv[])
inode_put(&sdp->md.inum);
inode_put(&sdp->md.statfs);
- gfs2_rgrp_free(&sdp->rglist);
+ gfs2_rgrp_free(&sdp->rgtree);
error = fsync(sdp->device_fd);
if (error)
die( _("can't fsync device (%d): %s\n"),
diff --git a/gfs2/tool/df.c b/gfs2/tool/df.c
index 26299ff..c4a6d93 100644
--- a/gfs2/tool/df.c
+++ b/gfs2/tool/df.c
@@ -112,7 +112,7 @@ do_df_one(char *path)
sbd.rgsize = GFS2_DEFAULT_RGSIZE;
sbd.utsize = GFS2_DEFAULT_UTSIZE;
sbd.qcsize = GFS2_DEFAULT_QCSIZE;
- osi_list_init(&sbd.rglist);
+ sbd.rgtree.osi_node = NULL;
do_lseek(sbd.device_fd, 0x10 * sbd.bsize);
do_read(sbd.device_fd, buf, sbd.bsize); /* read in the superblock */
11 years, 2 months
cluster: RHEL510 - fsck.gfs2: Check for formal inode number mismatch
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=737668db7de...
Commit: 737668db7dec805e3bcddd32c1e03b7ddf2eecb2
Parent: 8687b393476d7b250da14e72121fd4f7f6b3737c
Author: Bob Peterson <rpeterso(a)redhat.com>
AuthorDate: Wed Sep 26 12:21:21 2012 -0500
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Check for formal inode number mismatch
This patch checks for directory entries that disagree with the
dinode regarding the formal inode number. Directory entries found
in this state are removed.
rhbz#877150
---
gfs2/fsck/fsck.h | 8 +-
gfs2/fsck/inode_hash.c | 13 ++--
gfs2/fsck/inode_hash.h | 2 +-
gfs2/fsck/link.c | 19 +++--
gfs2/fsck/link.h | 2 +-
gfs2/fsck/lost_n_found.c | 32 +++----
gfs2/fsck/metawalk.c | 2 +-
gfs2/fsck/pass1.c | 4 +-
gfs2/fsck/pass1b.c | 10 +-
gfs2/fsck/pass2.c | 218 ++++++++++++++++++++++++++++++----------------
gfs2/fsck/pass3.c | 79 +++++++++--------
gfs2/fsck/pass4.c | 50 ++++++-----
gfs2/fsck/util.c | 15 ++--
13 files changed, 268 insertions(+), 186 deletions(-)
diff --git a/gfs2/fsck/fsck.h b/gfs2/fsck/fsck.h
index 2e301c9..b571d4a 100644
--- a/gfs2/fsck/fsck.h
+++ b/gfs2/fsck/fsck.h
@@ -40,7 +40,7 @@
struct inode_info
{
struct osi_node node;
- uint64_t inode;
+ struct gfs2_inum di_num;
uint32_t di_nlink; /* the number of links the inode
* thinks it has */
uint32_t counted_links; /* the number of links we've found */
@@ -49,9 +49,9 @@ struct inode_info
struct dir_info
{
struct osi_node node;
- uint64_t dinode;
+ struct gfs2_inum dinode;
uint64_t treewalk_parent;
- uint64_t dotdot_parent;
+ struct gfs2_inum dotdot_parent;
uint8_t checked:1;
};
@@ -130,7 +130,7 @@ extern void dirtree_delete(struct dir_info *b);
/* FIXME: Hack to get this going for pass2 - this should be pulled out
* of pass1 and put somewhere else... */
-struct dir_info *dirtree_insert(uint64_t dblock);
+struct dir_info *dirtree_insert(struct gfs2_inum inum);
extern struct gfs2_options opts;
extern struct gfs2_inode *lf_dip; /* Lost and found directory inode */
diff --git a/gfs2/fsck/inode_hash.c b/gfs2/fsck/inode_hash.c
index 8086abb..5532faf 100644
--- a/gfs2/fsck/inode_hash.c
+++ b/gfs2/fsck/inode_hash.c
@@ -30,9 +30,9 @@ struct inode_info *inodetree_find(uint64_t block)
while (node) {
struct inode_info *data = (struct inode_info *)node;
- if (block < data->inode)
+ if (block < data->di_num.no_addr)
node = node->osi_left;
- else if (block > data->inode)
+ else if (block > data->di_num.no_addr)
node = node->osi_right;
else
return data;
@@ -40,7 +40,7 @@ struct inode_info *inodetree_find(uint64_t block)
return NULL;
}
-struct inode_info *inodetree_insert(uint64_t dblock)
+struct inode_info *inodetree_insert(struct gfs2_inum di_num)
{
struct osi_node **newn = &inodetree.osi_node, *parent = NULL;
struct inode_info *data;
@@ -50,9 +50,9 @@ struct inode_info *inodetree_insert(uint64_t dblock)
struct inode_info *cur = (struct inode_info *)*newn;
parent = *newn;
- if (dblock < cur->inode)
+ if (di_num.no_addr < cur->di_num.no_addr)
newn = &((*newn)->osi_left);
- else if (dblock > cur->inode)
+ else if (di_num.no_addr > cur->di_num.no_addr)
newn = &((*newn)->osi_right);
else
return cur;
@@ -68,7 +68,8 @@ struct inode_info *inodetree_insert(uint64_t dblock)
return NULL;
}
/* Add new node and rebalance tree. */
- data->inode = dblock;
+ data->di_num.no_addr = di_num.no_addr;
+ data->di_num.no_formal_ino = di_num.no_formal_ino;
osi_link_node(&data->node, parent, newn);
osi_insert_color(&data->node, &inodetree);
diff --git a/gfs2/fsck/inode_hash.h b/gfs2/fsck/inode_hash.h
index 3495ddc..6275d6d 100644
--- a/gfs2/fsck/inode_hash.h
+++ b/gfs2/fsck/inode_hash.h
@@ -17,7 +17,7 @@
struct inode_info;
extern struct inode_info *inodetree_find(uint64_t block);
-extern struct inode_info *inodetree_insert(uint64_t dblock);
+extern struct inode_info *inodetree_insert(struct gfs2_inum di_num);
extern void inodetree_delete(struct inode_info *b);
#endif /* _INODE_HASH_H */
diff --git a/gfs2/fsck/link.c b/gfs2/fsck/link.c
index 047ef05..9482b34 100644
--- a/gfs2/fsck/link.c
+++ b/gfs2/fsck/link.c
@@ -27,14 +27,13 @@
int set_di_nlink(struct gfs2_inode *ip)
{
struct inode_info *ii;
- uint64_t inode_no = ip->i_di.di_num.no_addr;
/*log_debug( _("Setting link count to %u for %" PRIu64
" (0x%" PRIx64 ")\n"), count, inode_no, inode_no);*/
/* If the list has entries, look for one that matches inode_no */
- ii = inodetree_find(inode_no);
+ ii = inodetree_find(ip->i_di.di_num.no_addr);
if (!ii)
- ii = inodetree_insert(inode_no);
+ ii = inodetree_insert(ip->i_di.di_num);
if (ii)
ii->di_nlink = ip->i_di.di_nlink;
else
@@ -42,29 +41,33 @@ int set_di_nlink(struct gfs2_inode *ip)
return 0;
}
-int incr_link_count(uint64_t inode_no, uint64_t referenced_from,
+int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip,
const char *why)
{
struct inode_info *ii = NULL;
+ uint64_t referenced_from = ip ? ip->i_di.di_num.no_addr : 0;
- ii = inodetree_find(inode_no);
+ ii = inodetree_find(no.no_addr);
/* If the list has entries, look for one that matches inode_no */
if (ii) {
+ if (ii->di_num.no_formal_ino != no.no_formal_ino)
+ return 1;
+
ii->counted_links++;
log_debug( _("Dir (0x%llx) incremented counted "
"links to %u for (0x%llx) via %s\n"),
(unsigned long long)referenced_from,
- ii->counted_links, (unsigned long long)inode_no,
+ ii->counted_links, (unsigned long long)no.no_addr,
why);
return 0;
}
log_debug( _("Ref: (0x%llx) No match found when incrementing "
"link for (0x%llx)!\n"),
(unsigned long long)referenced_from,
- (unsigned long long)inode_no);
+ (unsigned long long)no.no_addr);
/* If no match was found, add a new entry and set its
* counted links to 1 */
- ii = inodetree_insert(inode_no);
+ ii = inodetree_insert(no);
if (ii)
ii->counted_links = 1;
else
diff --git a/gfs2/fsck/link.h b/gfs2/fsck/link.h
index 01ddc24..befb534 100644
--- a/gfs2/fsck/link.h
+++ b/gfs2/fsck/link.h
@@ -16,7 +16,7 @@
#define _LINK_H
int set_di_nlink(struct gfs2_inode *ip);
-int incr_link_count(uint64_t inode_no, uint64_t referenced_from,
+int incr_link_count(struct gfs2_inum no, struct gfs2_inode *ip,
const char *why);
int decr_link_count(uint64_t inode_no, uint64_t referenced_from,
const char *why);
diff --git a/gfs2/fsck/lost_n_found.c b/gfs2/fsck/lost_n_found.c
index b2ad2d3..f90c155 100644
--- a/gfs2/fsck/lost_n_found.c
+++ b/gfs2/fsck/lost_n_found.c
@@ -43,18 +43,19 @@ static void add_dotdot(struct gfs2_inode *ip)
/* If there's a pre-existing .. directory entry, we have to
back out the links. */
di = dirtree_find(ip->i_di.di_num.no_addr);
- if (di && !valid_block(sdp, di->dotdot_parent) == 0) {
+ if (di && valid_block(sdp, di->dotdot_parent.no_addr)) {
struct gfs2_inode *dip;
log_debug(_("Directory %lld (0x%llx) already had a "
"\"..\" link to %lld (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)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent);
- decr_link_count(di->dotdot_parent, ip->i_di.di_num.no_addr,
+ (unsigned long long)di->dotdot_parent.no_addr,
+ (unsigned long long)di->dotdot_parent.no_addr);
+ decr_link_count(di->dotdot_parent.no_addr,
+ ip->i_di.di_num.no_addr,
_(".. unlinked, moving to lost+found"));
- dip = fsck_load_inode(sdp, di->dotdot_parent);
+ dip = fsck_load_inode(sdp, di->dotdot_parent.no_addr);
if (dip->i_di.di_nlink > 0) {
dip->i_di.di_nlink--;
set_di_nlink(dip); /* keep inode tree in sync */
@@ -79,7 +80,7 @@ static void add_dotdot(struct gfs2_inode *ip)
"'..' = 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)di->dotdot_parent);
+ (unsigned long long)di->dotdot_parent.no_addr);
else
log_debug(_("Couldn't find directory %lld (0x%llx) "
"in directory tree.\n"),
@@ -148,15 +149,14 @@ int add_inode_to_lf(struct gfs2_inode *ip){
_("lost+found dinode"),
gfs2_inode_dir);
/* root inode links to lost+found */
- incr_link_count(sdp->md.rooti->i_di.di_num.no_addr,
- lf_dip->i_di.di_num.no_addr, _("root"));
+ incr_link_count(sdp->md.rooti->i_di.di_num,
+ lf_dip, _("root"));
/* lost+found link for '.' from itself */
- incr_link_count(lf_dip->i_di.di_num.no_addr,
- lf_dip->i_di.di_num.no_addr, "\".\"");
+ incr_link_count(lf_dip->i_di.di_num,
+ lf_dip, "\".\"");
/* lost+found link for '..' back to root */
- incr_link_count(lf_dip->i_di.di_num.no_addr,
- sdp->md.rooti->i_di.di_num.no_addr,
- "\"..\"");
+ incr_link_count(lf_dip->i_di.di_num, sdp->md.rooti,
+ "\"..\"");
}
log_info( _("lost+found directory is dinode %lld (0x%llx)\n"),
(unsigned long long)lf_dip->i_di.di_num.no_addr,
@@ -226,12 +226,10 @@ int add_inode_to_lf(struct gfs2_inode *ip){
reprocess_inode(lf_dip, "lost+found");
/* This inode is linked from lost+found */
- incr_link_count(ip->i_di.di_num.no_addr, lf_dip->i_di.di_num.no_addr,
- _("from lost+found"));
+ incr_link_count(ip->i_di.di_num, lf_dip, _("from lost+found"));
/* If it's a directory, lost+found is back-linked to it via .. */
if (mode == S_IFDIR)
- incr_link_count(lf_dip->i_di.di_num.no_addr,
- ip->i_di.di_num.no_addr, _("to lost+found"));
+ incr_link_count(lf_dip->i_di.di_num, ip, _("to lost+found"));
log_notice( _("Added inode #%llu (0x%llx) to lost+found\n"),
(unsigned long long)ip->i_di.di_num.no_addr,
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 15e1b9f..a61971c 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -957,7 +957,7 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
struct gfs2_sbd *sdp = ip->i_sbd;
int first_ea_is_bad = 0;
uint64_t di_eattr_save = ip->i_di.di_eattr;
- uint64_t offset = ip->i_sbd->gfs1 ? sizeof(struct gfs_indirect) : sizeof(struct gfs2_meta_header);
+ uint64_t offset = sizeof(struct gfs2_meta_header);
log_debug( _("Checking EA indirect block #%"PRIu64" (0x%" PRIx64 ").\n"),
indirect, indirect);
diff --git a/gfs2/fsck/pass1.c b/gfs2/fsck/pass1.c
index 8bda4b8..6075ac5 100644
--- a/gfs2/fsck/pass1.c
+++ b/gfs2/fsck/pass1.c
@@ -1347,7 +1347,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert((*sysinode)->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num);
}
} else
log_info( _("System inode for '%s' is corrupt or missing.\n"),
@@ -1374,7 +1374,7 @@ static int check_system_inode(struct gfs2_sbd *sdp,
filename, mark);
ds.q = mark;
if (mark == gfs2_inode_dir)
- dirtree_insert((*sysinode)->i_di.di_num.no_addr);
+ dirtree_insert((*sysinode)->i_di.di_num);
} else {
log_err( _("Cannot continue without valid %s inode\n"),
filename);
diff --git a/gfs2/fsck/pass1b.c b/gfs2/fsck/pass1b.c
index f2922b6..19b9f6a 100644
--- a/gfs2/fsck/pass1b.c
+++ b/gfs2/fsck/pass1b.c
@@ -541,12 +541,12 @@ static int resolve_dup_references(struct gfs2_sbd *sdp, struct duptree *b,
check_inode_eattr(ip, &clear_dup_fxns);
/* If the dup was in data or metadata, clear the dinode */
if (id->reftypecount[ref_as_data] ||
- id->reftypecount[ref_as_meta])
+ id->reftypecount[ref_as_meta]) {
check_metatree(ip, &clear_dup_fxns);
-
- fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
- _("duplicate referencing bad"),
- gfs2_inode_invalid);
+ fsck_blockmap_set(ip, ip->i_di.di_num.no_addr,
+ _("duplicate referencing bad"),
+ gfs2_inode_invalid);
+ }
fsck_inode_put(&ip); /* out, brelse, free */
(dh->ref_inode_count)--;
/* FIXME: other option should be to duplicate the
diff --git a/gfs2/fsck/pass2.c b/gfs2/fsck/pass2.c
index e89640b..1c0d721 100644
--- a/gfs2/fsck/pass2.c
+++ b/gfs2/fsck/pass2.c
@@ -27,43 +27,46 @@
#include "eattr.h"
#include "metawalk.h"
#include "link.h"
+#include "inode_hash.h"
#define MAX_FILENAME 256
/* Set children's parent inode in dir_info structure - ext2 does not set
* dotdot inode here, but instead in pass3 - should we? */
-static int set_parent_dir(struct gfs2_sbd *sdp, uint64_t childblock,
- uint64_t parentblock)
+static int set_parent_dir(struct gfs2_sbd *sdp, struct gfs2_inum child,
+ struct gfs2_inum parent)
{
struct dir_info *di;
- di = dirtree_find(childblock);
+ di = dirtree_find(child.no_addr);
if (!di) {
log_err( _("Unable to find block %llu (0x%llx"
") in dir_info list\n"),
- (unsigned long long)childblock,
- (unsigned long long)childblock);
+ (unsigned long long)child.no_addr,
+ (unsigned long long)child.no_addr);
return -1;
}
- if (di->dinode == childblock) {
+ if (di->dinode.no_addr == child.no_addr &&
+ di->dinode.no_formal_ino == child.no_formal_ino) {
if (di->treewalk_parent) {
- log_err( _("Another directory at block %" PRIu64
- " (0x%" PRIx64 ") already contains this "
- "child %lld (%llx) - checking parent %"
- PRIu64 " (0x%" PRIx64 ")\n"),
- di->treewalk_parent, di->treewalk_parent,
- (unsigned long long)childblock,
- (unsigned long long)childblock,
- parentblock, parentblock);
+ log_err( _("Another directory at block %llx (0x%llx) "
+ "already contains this child %lld (%llx) - "
+ "checking parent %llx (0x%llx)\n"),
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)di->treewalk_parent,
+ (unsigned long long)child.no_addr,
+ (unsigned long long)child.no_addr,
+ (unsigned long long)parent.no_addr,
+ (unsigned long long)parent.no_addr);
return 1;
}
log_debug( _("Child %lld (0x%llx) has parent %lld (0x%llx)\n"),
- (unsigned long long)childblock,
- (unsigned long long)childblock,
- (unsigned long long)parentblock,
- (unsigned long long)parentblock);
- di->treewalk_parent = parentblock;
+ (unsigned long long)child.no_addr,
+ (unsigned long long)child.no_addr,
+ (unsigned long long)parent.no_addr,
+ (unsigned long long)parent.no_addr);
+ di->treewalk_parent = parent.no_addr;
}
return 0;
@@ -71,7 +74,7 @@ static int set_parent_dir(struct gfs2_sbd *sdp, uint64_t childblock,
/* Set's the child's '..' directory inode number in dir_info structure */
static int set_dotdot_dir(struct gfs2_sbd *sdp, uint64_t childblock,
- uint64_t parentblock)
+ struct gfs2_inum parent)
{
struct dir_info *di;
@@ -81,29 +84,30 @@ static int set_dotdot_dir(struct gfs2_sbd *sdp, uint64_t childblock,
") in dir_info tree\n"), childblock, childblock);
return -1;
}
- if (di->dinode != childblock) {
+ if (di->dinode.no_addr != childblock) {
log_debug("'..' doesn't point to what we found: childblock "
"(0x%llx) != dinode (0x%llx)\n",
(unsigned long long)childblock,
- (unsigned long long)di->dinode);
+ (unsigned long long)di->dinode.no_addr);
return -1;
}
/* Special case for root inode because we set it earlier */
- if (di->dotdot_parent &&
- sdp->md.rooti->i_di.di_num.no_addr != di->dinode) {
+ if (di->dotdot_parent.no_addr &&
+ sdp->md.rooti->i_di.di_num.no_addr != di->dinode.no_addr) {
/* This should never happen */
log_crit( _("Dotdot parent already set for block %llu (0x%llx)"
"-> %llu (0x%llx)\n"),
(unsigned long long)childblock,
(unsigned long long)childblock,
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent);
+ (unsigned long long)di->dotdot_parent.no_addr,
+ (unsigned long long)di->dotdot_parent.no_addr);
return -1;
}
log_debug("Setting '..' for directory block (0x%llx) to parent "
"(0x%llx)\n", (unsigned long long)childblock,
- (unsigned long long)parentblock);
- di->dotdot_parent = parentblock;
+ (unsigned long long)parent.no_addr);
+ di->dotdot_parent.no_addr = parent.no_addr;
+ di->dotdot_parent.no_formal_ino = parent.no_formal_ino;
return 0;
}
@@ -232,6 +236,69 @@ struct metawalk_fxns pass2_fxns_delete = {
.check_eattr_extentry = delete_eattr_extentry,
};
+/* bad_formal_ino - handle mismatches in formal inode number
+ * Returns: 0 if the dirent was repaired
+ * 1 if the caller should delete the dirent
+ */
+static int bad_formal_ino(struct gfs2_inode *ip, struct gfs2_dirent *dent,
+ struct gfs2_inum entry, const char *tmp_name,
+ uint8_t q, struct gfs2_dirent *de,
+ struct gfs2_buffer_head *bh)
+{
+ struct inode_info *ii;
+ struct gfs2_inode *child_ip;
+ struct gfs2_inum childs_dotdot;
+ struct gfs2_sbd *sdp = ip->i_sbd;
+ int error;
+
+ ii = inodetree_find(entry.no_addr);
+ log_err( _("Directory entry '%s' pointing to block %llu (0x%llx) in "
+ "directory %llu (0x%llx) has the wrong 'formal' inode "
+ "number.\n"), tmp_name, (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr,
+ (unsigned long long)ip->i_di.di_num.no_addr);
+ log_err( _("The directory entry has %llu (0x%llx) but the inode has "
+ "%llu (0x%llx)\n"), (unsigned long long)entry.no_formal_ino,
+ (unsigned long long)entry.no_formal_ino,
+ (unsigned long long)ii->di_num.no_formal_ino,
+ (unsigned long long)ii->di_num.no_formal_ino);
+ if (q != gfs2_inode_dir) {
+ if (query( _("Remove the corrupt directory entry? (y/n) ")))
+ return 1;
+ log_err( _("Corrupt directory entry not removed.\n"));
+ return 0;
+ }
+ /* We have a directory pointing to another directory, but the
+ formal inode number still doesn't match. If that directory
+ has a '..' pointing back, just fix up the no_formal_ino. */
+ child_ip = inode_read(sdp, entry.no_addr);
+ error = dir_search(child_ip, "..", 2, NULL, &childs_dotdot);
+ if (!error && childs_dotdot.no_addr == ip->i_di.di_num.no_addr) {
+ log_err( _("The entry points to another directory with intact "
+ "linkage.\n"));
+ if (query( _("Fix the bad directory entry? (y/n) "))) {
+ log_err( _("Fixing the corrupt directory entry.\n"));
+ entry.no_formal_ino = ii->di_num.no_formal_ino;
+ de->de_inum.no_formal_ino = entry.no_formal_ino;
+ gfs2_dirent_out(de, (char *)dent);
+ bmodified(bh);
+ incr_link_count(entry, ip, _("fixed reference"));
+ set_parent_dir(sdp, entry, ip->i_di.di_num);
+ } else {
+ log_err( _("Directory entry not fixed.\n"));
+ }
+ } else {
+ if (query( _("Remove the corrupt directory entry? (y/n) "))) {
+ inode_put(&child_ip);
+ return 1;
+ }
+ log_err( _("Corrupt directory entry not removed.\n"));
+ }
+ inode_put(&child_ip);
+ return 0;
+}
+
/* FIXME: should maybe refactor this a bit - but need to deal with
* FIXMEs internally first */
static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
@@ -240,9 +307,9 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
uint32_t *count, void *priv)
{
struct gfs2_sbd *sdp = ip->i_sbd;
- uint8_t q;
+ uint8_t q = 0;
char tmp_name[MAX_FILENAME];
- uint64_t entryblock;
+ struct gfs2_inum entry;
struct dir_status *ds = (struct dir_status *) priv;
int error;
struct gfs2_inode *entry_ip = NULL;
@@ -259,7 +326,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
clear_eattrs.check_eattr_entry = clear_eattr_entry;
clear_eattrs.check_eattr_extentry = clear_eattr_extentry;
- entryblock = de->de_inum.no_addr;
+ entry.no_addr = de->de_inum.no_addr;
+ entry.no_formal_ino = de->de_inum.no_formal_ino;
/* Start of checks */
memset(tmp_name, 0, MAX_FILENAME);
@@ -268,7 +336,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
else
strncpy(tmp_name, filename, MAX_FILENAME - 1);
- if (!valid_block(ip->i_sbd, entryblock)) {
+ if (!valid_block(ip->i_sbd, entry.no_addr)) {
log_err( _("Block # referenced by directory entry %s in inode "
"%lld (0x%llx) is invalid\n"),
tmp_name, (unsigned long long)ip->i_di.di_num.no_addr,
@@ -281,7 +349,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
(*count)++;
ds->entry_count++;
/* can't do this because the block is out of range:
- incr_link_count(entryblock); */
+ incr_link_count(entry); */
return 0;
}
}
@@ -323,7 +391,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
tmp_name);
}
- q = block_type(entryblock);
+ q = block_type(entry.no_addr);
/* Get the status of the directory inode */
/**
* 1. Blocks marked "invalid" were invalidated due to duplicate
@@ -343,8 +411,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
/* Handle bad blocks */
log_err( _("Found directory entry '%s' pointing to invalid "
"block %lld (0x%llx)\n"), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock);
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr);
if (!query( _("Delete inode containing bad blocks? (y/n)"))) {
log_warn( _("Entry to inode containing bad blocks remains\n"));
@@ -352,10 +420,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
}
if (q == gfs2_bad_block) {
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
if (ip->i_di.di_eattr) {
check_inode_eattr(entry_ip,
&pass2_fxns_delete);
@@ -364,19 +432,19 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
}
- fsck_blockmap_set(ip, entryblock,
+ fsck_blockmap_set(ip, entry.no_addr,
_("bad directory entry"), gfs2_block_free);
log_err( _("Inode %lld (0x%llx) was deleted.\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock);
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr);
goto nuke_dentry;
}
if (q < gfs2_inode_dir || q > gfs2_inode_sock) {
log_err( _("Directory entry '%s' referencing inode %llu "
"(0x%llx) in dir inode %llu (0x%llx) block type "
"%d: %s.\n"), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
q, q == gfs2_inode_invalid ?
@@ -413,8 +481,8 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
log_err( _("Error: directory entry type is "
"incompatible with block type at block %lld "
"(0x%llx) in directory inode %llu (0x%llx).\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
log_err( _("Directory entry type is %d, block type is %d.\n"),
@@ -426,17 +494,17 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
log_err( _("Type '%s' in dir entry (%s, %llu/0x%llx) conflicts"
" with type '%s' in dinode. (Dir entry is stale.)\n"),
de_type_string(de->de_type), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
block_type_string(q));
if (!query( _("Clear stale directory entry? (y/n) "))) {
log_err( _("Stale directory entry remains\n"));
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
check_inode_eattr(entry_ip, &clear_eattrs);
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
@@ -459,10 +527,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
* and check the rest of the '.' entry? */
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
check_inode_eattr(entry_ip, &clear_eattrs);
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
@@ -473,15 +541,15 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
* location */
/* check that '.' refers to this inode */
- if (entryblock != ip->i_di.di_num.no_addr) {
+ if (entry.no_addr != ip->i_di.di_num.no_addr) {
log_err( _("'.' entry's value incorrect in directory %llu"
" (0x%llx). Points to %llu"
" (0x%llx) when it should point to %llu"
" (0x%llx).\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr,
(unsigned long long)ip->i_di.di_num.no_addr);
if (!query( _("Remove '.' reference? (y/n) "))) {
@@ -490,10 +558,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
* this '.' entry is invalid */
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
check_inode_eattr(entry_ip, &clear_eattrs);
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
@@ -520,10 +588,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
check_inode_eattr(entry_ip, &clear_eattrs);
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
@@ -540,10 +608,10 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
log_err( _("Bad '..' directory entry remains\n"));
goto dentry_is_valid;
}
- if (ip->i_di.di_num.no_addr == entryblock)
+ if (ip->i_di.di_num.no_addr == entry.no_addr)
entry_ip = ip;
else
- entry_ip = fsck_load_inode(sdp, entryblock);
+ entry_ip = fsck_load_inode(sdp, entry.no_addr);
check_inode_eattr(entry_ip, &clear_eattrs);
if (entry_ip != ip)
fsck_inode_put(&entry_ip);
@@ -555,7 +623,7 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
/* Add the address this entry is pointing to
* to this inode's dotdot_parent in
* dir_info */
- if (set_dotdot_dir(sdp, ip->i_di.di_num.no_addr, entryblock)) {
+ if (set_dotdot_dir(sdp, ip->i_di.di_num.no_addr, entry)) {
stack;
return -1;
}
@@ -568,18 +636,18 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
if (q != gfs2_inode_dir) {
log_debug( _("Found non-dir inode dentry pointing to %lld "
"(0x%llx)\n"),
- (unsigned long long)entryblock,
- (unsigned long long)entryblock);
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr);
goto dentry_is_valid;
}
/*log_debug( _("Found plain directory dentry\n"));*/
- error = set_parent_dir(sdp, entryblock, ip->i_di.di_num.no_addr);
+ error = set_parent_dir(sdp, entry, ip->i_di.di_num);
if (error > 0) {
log_err( _("%s: Hard link to block %llu (0x%llx"
") detected.\n"), tmp_name,
- (unsigned long long)entryblock,
- (unsigned long long)entryblock);
+ (unsigned long long)entry.no_addr,
+ (unsigned long long)entry.no_addr);
if (query( _("Clear hard link to directory? (y/n) ")))
goto nuke_dentry;
@@ -593,8 +661,12 @@ static int check_dentry(struct gfs2_inode *ip, struct gfs2_dirent *dent,
}
dentry_is_valid:
/* This directory inode links to this inode via this dentry */
- incr_link_count(entryblock, ip->i_di.di_num.no_addr,
- _("valid reference"));
+ error = incr_link_count(entry, ip, _("valid reference"));
+ if (error > 0) {
+ if (bad_formal_ino(ip, dent, entry, tmp_name, q, de, bh) == 1)
+ goto nuke_dentry;
+ }
+
(*count)++;
ds->entry_count++;
/* End of checks */
@@ -690,8 +762,7 @@ static int check_system_dir(struct gfs2_inode *sysinode, const char *dirname,
if (cur_blks != sysinode->i_di.di_blocks)
reprocess_inode(sysinode, dirname);
/* This system inode is linked to itself via '.' */
- incr_link_count(sysinode->i_di.di_num.no_addr,
- sysinode->i_di.di_num.no_addr,
+ incr_link_count(sysinode->i_di.di_num, sysinode,
"sysinode \".\"");
ds.entry_count++;
free(filename);
@@ -906,8 +977,7 @@ int pass2(struct gfs2_sbd *sdp)
reprocess_inode(ip, dirname);
}
/* directory links to itself via '.' */
- incr_link_count(ip->i_di.di_num.no_addr,
- ip->i_di.di_num.no_addr,
+ incr_link_count(ip->i_di.di_num, ip,
_("\". (itself)\""));
ds.entry_count++;
free(filename);
diff --git a/gfs2/fsck/pass3.c b/gfs2/fsck/pass3.c
index ebf4800..f8727d3 100644
--- a/gfs2/fsck/pass3.c
+++ b/gfs2/fsck/pass3.c
@@ -80,7 +80,7 @@ static int attach_dotdot_to(struct gfs2_sbd *sdp, uint64_t newdotdot,
(unsigned long long)ip->i_di.di_num.no_addr);
reprocess_inode(ip, dirname);
}
- incr_link_count(newdotdot, block, _("new \"..\""));
+ incr_link_count(pip->i_di.di_num, ip, _("new \"..\""));
fsck_inode_put(&ip);
fsck_inode_put(&pip);
free(filename);
@@ -99,27 +99,28 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
if (!di->treewalk_parent)
return NULL;
- if (di->dotdot_parent == di->treewalk_parent) {
- q_dotdot = block_type(di->dotdot_parent);
+ if (di->dotdot_parent.no_addr == di->treewalk_parent) {
+ q_dotdot = block_type(di->dotdot_parent.no_addr);
if (q_dotdot != gfs2_inode_dir) {
log_err( _("Orphaned directory at block %llu (0x%llx) "
"moved to lost+found\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr);
return NULL;
}
goto out;
}
log_warn( _("Directory '..' and treewalk connections disagree for "
- "inode %llu (0x%llx)\n"), (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
+ "inode %llu (0x%llx)\n"),
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr);
log_notice( _("'..' has %llu (0x%llx), treewalk has %llu (0x%llx)\n"),
- (unsigned long long)di->dotdot_parent,
- (unsigned long long)di->dotdot_parent,
+ (unsigned long long)di->dotdot_parent.no_addr,
+ (unsigned long long)di->dotdot_parent.no_addr,
(unsigned long long)di->treewalk_parent,
(unsigned long long)di->treewalk_parent);
- q_dotdot = block_type(di->dotdot_parent);
+ q_dotdot = block_type(di->dotdot_parent.no_addr);
q_treewalk = block_type(di->treewalk_parent);
/* if the dotdot entry isn't a directory, but the
* treewalk is, treewalk is correct - if the treewalk
@@ -139,8 +140,9 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
(unsigned long long)di->treewalk_parent,
(unsigned long long)di->treewalk_parent);
attach_dotdot_to(sdp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
+ di->dotdot_parent.no_addr,
+ di->dinode.no_addr);
+ di->dotdot_parent.no_addr = di->treewalk_parent;
}
goto out;
}
@@ -148,8 +150,9 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
log_err( _("Both .. and treewalk parents are directories, "
"going with treewalk...\n"));
attach_dotdot_to(sdp, di->treewalk_parent,
- di->dotdot_parent, di->dinode);
- di->dotdot_parent = di->treewalk_parent;
+ di->dotdot_parent.no_addr,
+ di->dinode.no_addr);
+ di->dotdot_parent.no_addr = di->treewalk_parent;
goto out;
}
log_warn( _(".. parent is valid, but treewalk is bad - reattaching to "
@@ -159,14 +162,15 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
if (!query( _("Remove directory entry for bad inode %llu (0x%llx) in "
"%llu (0x%llx)? (y/n)"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr,
(unsigned long long)di->treewalk_parent,
(unsigned long long)di->treewalk_parent)) {
log_err( _("Directory entry to invalid inode remains\n"));
return NULL;
}
- error = remove_dentry_from_dir(sdp, di->treewalk_parent, di->dinode);
+ error = remove_dentry_from_dir(sdp, di->treewalk_parent,
+ di->dinode.no_addr);
if (error < 0) {
stack;
return NULL;
@@ -174,8 +178,8 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
if (error > 0)
log_warn( _("Unable to find dentry for block %llu"
" (0x%llx) in %llu (0x%llx)\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode,
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr,
(unsigned long long)di->treewalk_parent,
(unsigned long long)di->treewalk_parent);
log_warn( _("Directory entry removed\n"));
@@ -184,7 +188,7 @@ static struct dir_info *mark_and_return_parent(struct gfs2_sbd *sdp,
return NULL;
out:
- pdi = dirtree_find(di->dotdot_parent);
+ pdi = dirtree_find(di->dotdot_parent.no_addr);
return pdi;
}
@@ -230,13 +234,14 @@ int pass3(struct gfs2_sbd *sdp)
tdi = mark_and_return_parent(sdp, di);
if (tdi) {
- log_debug( _("Directory at block %" PRIu64
- " (0x%" PRIx64 ") connected\n"),
- di->dinode, di->dinode);
+ log_debug( _("Directory at block %llu "
+ "(0x%llx) connected\n"),
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr);
di = tdi;
continue;
}
- q = block_type(di->dinode);
+ q = block_type(di->dinode.no_addr);
if (q == gfs2_bad_block) {
log_err( _("Found unlinked directory "
"containing bad block\n"));
@@ -245,14 +250,14 @@ int pass3(struct gfs2_sbd *sdp)
log_warn( _("inode %lld (0x%llx) is "
"now marked as free\n"),
(unsigned long long)
- di->dinode,
+ di->dinode.no_addr,
(unsigned long long)
- di->dinode);
+ di->dinode.no_addr);
/* Can't use fsck_blockmap_set
because we don't have ip */
- gfs2_blockmap_set(bl, di->dinode,
+ gfs2_blockmap_set(bl, di->dinode.no_addr,
gfs2_block_free);
- check_n_fix_bitmap(sdp, di->dinode,
+ check_n_fix_bitmap(sdp, di->dinode.no_addr,
gfs2_block_free);
break;
} else
@@ -271,29 +276,31 @@ int pass3(struct gfs2_sbd *sdp)
}
log_warn( _("inode %lld (0x%llx) is now "
"marked as free\n"),
- (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr);
/* Can't use fsck_blockmap_set
because we don't have ip */
- gfs2_blockmap_set(bl, di->dinode,
+ gfs2_blockmap_set(bl, di->dinode.no_addr,
gfs2_block_free);
- check_n_fix_bitmap(sdp, di->dinode,
+ check_n_fix_bitmap(sdp, di->dinode.no_addr,
gfs2_block_free);
log_err( _("The block was cleared\n"));
break;
}
log_err( _("Found unlinked directory at block %llu"
- " (0x%llx)\n"), (unsigned long long)di->dinode,
- (unsigned long long)di->dinode);
- ip = fsck_load_inode(sdp, di->dinode);
+ " (0x%llx)\n"),
+ (unsigned long long)di->dinode.no_addr,
+ (unsigned long long)di->dinode.no_addr);
+ ip = fsck_load_inode(sdp, di->dinode.no_addr);
/* Don't skip zero size directories with eattrs */
if (!ip->i_di.di_size && !ip->i_di.di_eattr){
log_err( _("Unlinked directory has zero "
"size.\n"));
if (query( _("Remove zero-size unlinked "
"directory? (y/n) "))) {
- fsck_blockmap_set(ip, di->dinode,
+ fsck_blockmap_set(ip,
+ di->dinode.no_addr,
_("zero-sized unlinked inode"),
gfs2_block_free);
fsck_inode_put(&ip);
diff --git a/gfs2/fsck/pass4.c b/gfs2/fsck/pass4.c
index 355b88a..502dd24 100644
--- a/gfs2/fsck/pass4.c
+++ b/gfs2/fsck/pass4.c
@@ -71,21 +71,21 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
}
if (ii->counted_links == 0) {
log_err( _("Found unlinked inode at %llu (0x%llx)\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode);
- q = block_type(ii->inode);
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr);
+ q = block_type(ii->di_num.no_addr);
if (q == gfs2_bad_block) {
log_err( _("Unlinked inode %llu (0x%llx) contains "
"bad blocks\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode);
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr);
if (query( _("Delete unlinked inode with bad "
"blocks? (y/n) "))) {
- ip = fsck_load_inode(sdp, ii->inode);
+ ip = fsck_load_inode(sdp, ii->di_num.no_addr);
check_inode_eattr(ip,
&pass4_fxns_delete);
check_metatree(ip, &pass4_fxns_delete);
- fsck_blockmap_set(ip, ii->inode,
+ fsck_blockmap_set(ip, ii->di_num.no_addr,
_("bad unlinked"),
gfs2_block_free);
fsck_inode_put(&ip);
@@ -102,14 +102,14 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
log_err( _("Unlinked block %lld (0x%llx) "
"marked as inode is "
"not an inode (%d)\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode, q);
- ip = fsck_load_inode(sdp, ii->inode);
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr, q);
+ ip = fsck_load_inode(sdp, ii->di_num.no_addr);
if (query(_("Delete unlinked inode? (y/n) "))) {
check_inode_eattr(ip,
&pass4_fxns_delete);
check_metatree(ip, &pass4_fxns_delete);
- fsck_blockmap_set(ip, ii->inode,
+ fsck_blockmap_set(ip, ii->di_num.no_addr,
_("invalid unlinked"),
gfs2_block_free);
fsck_inode_put(&ip);
@@ -121,7 +121,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
}
continue;
}
- ip = fsck_load_inode(sdp, ii->inode);
+ ip = fsck_load_inode(sdp, ii->di_num.no_addr);
/* We don't want to clear zero-size files with
* eattrs - there might be relevent info in
@@ -130,7 +130,7 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
log_err( _("Unlinked inode has zero size\n"));
if (query(_("Clear zero-size unlinked inode? "
"(y/n) "))) {
- fsck_blockmap_set(ip, ii->inode,
+ fsck_blockmap_set(ip, ii->di_num.no_addr,
_("unlinked zero-length"),
gfs2_block_free);
fsck_inode_put(&ip);
@@ -155,32 +155,34 @@ static int scan_inode_list(struct gfs2_sbd *sdp) {
else if (ii->di_nlink != ii->counted_links) {
log_err( _("Link count inconsistent for inode %llu"
" (0x%llx) has %u but fsck found %u.\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode, ii->di_nlink,
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr, ii->di_nlink,
ii->counted_links);
/* Read in the inode, adjust the link count,
* and write it back out */
if (query( _("Update link count for inode %llu"
" (0x%llx) ? (y/n) "),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode)) {
- ip = fsck_load_inode(sdp, ii->inode); /* bread, inode_get */
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr)) {
+ ip = fsck_load_inode(sdp, ii->di_num.no_addr); /* bread, inode_get */
fix_link_count(ii, ip);
ii->di_nlink = ii->counted_links;
fsck_inode_put(&ip); /* out, brelse, free */
log_warn( _("Link count updated to %d for "
"inode %llu (0x%llx)\n"),
ii->di_nlink,
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode);
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr);
} else {
- log_err( _("Link count for inode %" PRIu64 " (0x%" PRIx64
- ") still incorrect\n"), ii->inode, ii->inode);
+ log_err( _("Link count for inode %llu (0x%llx"
+ ") still incorrect\n"),
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr);
}
}
log_debug( _("block %llu (0x%llx) has link count %d\n"),
- (unsigned long long)ii->inode,
- (unsigned long long)ii->inode, ii->di_nlink);
+ (unsigned long long)ii->di_num.no_addr,
+ (unsigned long long)ii->di_num.no_addr, ii->di_nlink);
} /* osi_list_foreach(tmp, list) */
if (lf_addition) {
diff --git a/gfs2/fsck/util.c b/gfs2/fsck/util.c
index 84cecec..79d76cf 100644
--- a/gfs2/fsck/util.c
+++ b/gfs2/fsck/util.c
@@ -325,7 +325,7 @@ int add_duplicate_ref(struct gfs2_inode *ip, uint64_t block,
return 0;
}
-struct dir_info *dirtree_insert(uint64_t dblock)
+struct dir_info *dirtree_insert(struct gfs2_inum inum)
{
struct osi_node **newn = &dirtree.osi_node, *parent = NULL;
struct dir_info *data;
@@ -335,9 +335,9 @@ struct dir_info *dirtree_insert(uint64_t dblock)
struct dir_info *cur = (struct dir_info *)*newn;
parent = *newn;
- if (dblock < cur->dinode)
+ if (inum.no_addr < cur->dinode.no_addr)
newn = &((*newn)->osi_left);
- else if (dblock > cur->dinode)
+ else if (inum.no_addr > cur->dinode.no_addr)
newn = &((*newn)->osi_right);
else
return cur;
@@ -353,7 +353,8 @@ struct dir_info *dirtree_insert(uint64_t dblock)
return NULL;
}
/* Add new node and rebalance tree. */
- data->dinode = dblock;
+ data->dinode.no_addr = inum.no_addr;
+ data->dinode.no_formal_ino = inum.no_formal_ino;
osi_link_node(&data->node, parent, newn);
osi_insert_color(&data->node, &dirtree);
@@ -367,9 +368,9 @@ struct dir_info *dirtree_find(uint64_t block)
while (node) {
struct dir_info *data = (struct dir_info *)node;
- if (block < data->dinode)
+ if (block < data->dinode.no_addr)
node = node->osi_left;
- else if (block > data->dinode)
+ else if (block > data->dinode.no_addr)
node = node->osi_right;
else
return data;
@@ -501,7 +502,7 @@ int set_ip_blockmap(struct gfs2_inode *ip, int instree)
if (fsck_blockmap_set(ip, block, _("directory"),
gfs2_inode_dir))
goto bad_dinode;
- if (instree && !dirtree_insert(block))
+ if (instree && !dirtree_insert(ip->i_di.di_num))
goto bad_dinode;
break;
case S_IFREG:
11 years, 2 months
cluster: RHEL510 - fsck.gfs2: Fix handling of eattr indirect blocks
by Bob Peterson
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=8687b393476...
Commit: 8687b393476d7b250da14e72121fd4f7f6b3737c
Parent: c77cd8fe7f7cd7b96106fde4ea6a411208f3a6e5
Author: Andrew Price <anprice(a)redhat.com>
AuthorDate: Fri Mar 23 17:15:37 2012 +0000
Committer: Bob Peterson <rpeterso(a)redhat.com>
CommitterDate: Fri Apr 5 06:25:01 2013 -0700
fsck.gfs2: Fix handling of eattr indirect blocks
check_indirect_eattr() was using sizeof(struct gfs2_meta_header) as the offset
for indirect eattr blocks. This patch fixes it to use sizeof(struct
gfs_indirect) for gfs1 file systems.
rhbz#877150
---
gfs2/fsck/metawalk.c | 7 +++----
1 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/gfs2/fsck/metawalk.c b/gfs2/fsck/metawalk.c
index 31ceca9..15e1b9f 100644
--- a/gfs2/fsck/metawalk.c
+++ b/gfs2/fsck/metawalk.c
@@ -957,6 +957,7 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
struct gfs2_sbd *sdp = ip->i_sbd;
int first_ea_is_bad = 0;
uint64_t di_eattr_save = ip->i_di.di_eattr;
+ uint64_t offset = ip->i_sbd->gfs1 ? sizeof(struct gfs_indirect) : sizeof(struct gfs2_meta_header);
log_debug( _("Checking EA indirect block #%"PRIu64" (0x%" PRIx64 ").\n"),
indirect, indirect);
@@ -968,10 +969,8 @@ static int check_indirect_eattr(struct gfs2_inode *ip, uint64_t indirect,
if (!error) {
int leaf_pointers = 0, leaf_pointer_errors = 0;
- ea_leaf_ptr = (uint64_t *)(indirect_buf->b_data
- + sizeof(struct gfs2_meta_header));
- end = ea_leaf_ptr + ((sdp->sd_sb.sb_bsize
- - sizeof(struct gfs2_meta_header)) / 8);
+ ea_leaf_ptr = (uint64_t *)(indirect_buf->b_data + offset);
+ end = ea_leaf_ptr + ((sdp->sd_sb.sb_bsize - offset) / 8);
while (*ea_leaf_ptr && (ea_leaf_ptr < end)){
block = be64_to_cpu(*ea_leaf_ptr);
11 years, 2 months