commit e16c5e55e999c8f928c398a7afc7f100063d0c7f Author: Abhijith Das <adas@redhat.com> Date: Thu Apr 29 21:26:05 2010 -0500 gfs2_convert: gfs2_convert segfaults when converting filesystems of blocksize 512 bytes gfs2_convert segfaults when the jindex inode is unstuffed. i.e. if the block size is small enough such that the jindex entries (directly proportional to the number of journals) don't fit in the disk inode block, the jindex inode is unstuffed. This is a journaled data file and the structures are different for such files in gfs1 and gfs2 with respect to metaheaders. gfs2_convert needs to trick the file reading code in libgfs2 to think it's dealing with a gfs2 directory (whose structure is similar to a gfs1 jdata inode) to operate on the file at the right offsets. Resolves: rhbz#568852 Signed-off-by: Abhi Das <adas@redhat.com> diff --git a/gfs2/convert/gfs2_convert.c b/gfs2/convert/gfs2_convert.c index 3a9905e..5a45c96 100644 --- a/gfs2/convert/gfs2_convert.c +++ b/gfs2/convert/gfs2_convert.c @@ -1284,6 +1284,7 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp) char buf[sizeof(struct gfs1_jindex)]; unsigned int j; int error=0; + unsigned int tmp_mode = 0; if(ip->i_di.di_size % sizeof(struct gfs1_jindex) != 0){ log_crit("The size reported in the journal index" @@ -1299,6 +1300,14 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp) log_crit("Unable to zero journal index\n"); return -1; } + /* ugly hack + * Faking the gfs1_jindex inode as a directory to gfs2_readi + * so it skips the metaheader struct in the data blocks + * in the inode. gfs2_jindex inode doesn't have metaheaders + * in the data blocks */ + tmp_mode = ip->i_di.di_mode; + ip->i_di.di_mode &= ~S_IFMT; + ip->i_di.di_mode |= S_IFDIR; for (j = 0; ; j++) { struct gfs1_jindex *journ; @@ -1315,6 +1324,7 @@ static int read_gfs1_jiindex(struct gfs2_sbd *sdp) gfs1_jindex_in(journ, buf); sdp->jsize = (journ->ji_nsegment * 16 * sdp->bsize) >> 20; } + ip->i_di.di_mode = tmp_mode; if(j * sizeof(struct gfs1_jindex) != ip->i_di.di_size){ log_crit("journal inode size invalid\n"); goto fail;