Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=400a5cc46d629…
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;
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=078afe992b4ad…
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;
}
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=11795482c88f4…
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;
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=183e3d6a5ea33…
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));
Gitweb: http://git.fedorahosted.org/git/?p=cluster.git;a=commitdiff;h=144f8bed07e00…
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);