From eb1020191f7743f451442096db8635643c5fddb1 Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Sep 05 2020 23:59:02 +0000 Subject: restoremeta: Fix unaligned access in restore_init() On sparc64 we get restoremeta tests failing with SIGBUS due to an unaligned access when scanning for the super block offset in the metadata file. memcpy the buffer into a gfs2_sb struct to avoid that. In most cases, if not always, this loop succeeds on the first iteration and might not even be needed, so the added overhead is minimal. diff --git a/gfs2/edit/savemeta.c b/gfs2/edit/savemeta.c index 80c11c9..32e1f70 100644 --- a/gfs2/edit/savemeta.c +++ b/gfs2/edit/savemeta.c @@ -1251,7 +1251,7 @@ nobuffer: return NULL; } -static int restore_super(struct metafd *mfd, char *buf, int printonly) +static int restore_super(struct metafd *mfd, void *buf, int printonly) { int ret; @@ -1337,7 +1337,7 @@ static void complain(const char *complaint) static int restore_init(const char *path, struct metafd *mfd, struct savemeta_header *smh, int printonly) { - struct gfs2_meta_header *sbmh; + struct gfs2_sb rsb; uint16_t sb_siglen; char *end; char *bp; @@ -1372,12 +1372,12 @@ static int restore_init(const char *path, struct metafd *mfd, struct savemeta_he return -1; } /* Scan for the position of the superblock. Required to support old formats(?). */ - end = &restore_buf[256 + sizeof(struct saved_metablock) + sizeof(*sbmh)]; + end = &restore_buf[256 + sizeof(struct saved_metablock) + sizeof(struct gfs2_meta_header)]; while (bp <= end) { + memcpy(&rsb, bp + sizeof(struct saved_metablock), sizeof(rsb)); sb_siglen = be16_to_cpu(((struct saved_metablock *)bp)->siglen); - sbmh = (struct gfs2_meta_header *)(bp + sizeof(struct saved_metablock)); - if (sbmh->mh_magic == cpu_to_be32(GFS2_MAGIC) && - sbmh->mh_type == cpu_to_be32(GFS2_METATYPE_SB)) + if (be32_to_cpu(rsb.sb_header.mh_magic) == GFS2_MAGIC && + be32_to_cpu(rsb.sb_header.mh_type) == GFS2_METATYPE_SB) break; bp++; } @@ -1386,7 +1386,7 @@ static int restore_init(const char *path, struct metafd *mfd, struct savemeta_he return -1; } bp += sizeof(struct saved_metablock); - ret = restore_super(mfd, bp, printonly); + ret = restore_super(mfd, &rsb, printonly); if (ret != 0) return ret;