git: 8244dd326265 - main - tunefs: Better fix for arm64 alignment issues
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 07 Apr 2026 13:54:44 UTC
The branch main has been updated by des:
URL: https://cgit.FreeBSD.org/src/commit/?id=8244dd326265867293b2286efc3d571f06ef0dab
commit 8244dd326265867293b2286efc3d571f06ef0dab
Author: Dag-Erling Smørgrav <des@FreeBSD.org>
AuthorDate: 2026-04-07 13:54:28 +0000
Commit: Dag-Erling Smørgrav <des@FreeBSD.org>
CommitDate: 2026-04-07 13:54:28 +0000
tunefs: Better fix for arm64 alignment issues
Rather than trust that the compiler will lay out the stack frame the
way we expect it to, use a union to force the correct alignment.
MFC after: 1 week
Fixes: 616f47f176c3 ("tunefs: Fix alignment warning on arm64")
Reviewed by: kevans, mckusick
Differential Revision: https://reviews.freebsd.org/D56245
---
sbin/tunefs/tunefs.c | 64 ++++++++++++++++++++++++++++++----------------------
1 file changed, 37 insertions(+), 27 deletions(-)
diff --git a/sbin/tunefs/tunefs.c b/sbin/tunefs/tunefs.c
index 56f343a5a4db..56160dafce28 100644
--- a/sbin/tunefs/tunefs.c
+++ b/sbin/tunefs/tunefs.c
@@ -44,6 +44,7 @@
#include <ufs/ffs/fs.h>
#include <ufs/ufs/dir.h>
+#include <assert.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
@@ -51,6 +52,7 @@
#include <libufs.h>
#include <mntopts.h>
#include <paths.h>
+#include <stdalign.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
@@ -72,6 +74,11 @@ static int journal_alloc(int64_t size);
static void journal_clear(void);
static void sbdirty(void);
+typedef union {
+ char buf[MAXBSIZE];
+ struct direct dir;
+} dirblock;
+
int
main(int argc, char *argv[])
{
@@ -631,16 +638,17 @@ journal_balloc(void)
static ino_t
dir_search(ufs2_daddr_t blk, int bytes)
{
- char block[MAXBSIZE];
+ dirblock block;
struct direct *dp;
int off;
- if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) {
+ if (bread(&disk, fsbtodb(&sblock, blk), &block, bytes) <= 0) {
warn("Failed to read dir block");
return (-1);
}
for (off = 0; off < bytes; off += dp->d_reclen) {
- dp = (struct direct *)(uintptr_t)&block[off];
+ assert(off % alignof(struct direct) == 0);
+ dp = (struct direct *)(uintptr_t)(block.buf + off);
if (dp->d_reclen == 0)
break;
if (dp->d_ino == 0)
@@ -700,12 +708,13 @@ journal_findfile(void)
}
static void
-dir_clear_block(const char *block, off_t off)
+dir_clear_block(const dirblock *block, off_t off)
{
struct direct *dp;
for (; off < sblock.fs_bsize; off += DIRBLKSIZ) {
- dp = (struct direct *)(uintptr_t)&block[off];
+ assert(off % alignof(struct direct) == 0);
+ dp = (struct direct *)(uintptr_t)(block + off);
dp->d_ino = 0;
dp->d_reclen = DIRBLKSIZ;
dp->d_type = DT_UNKNOWN;
@@ -721,21 +730,23 @@ static int
dir_insert(ufs2_daddr_t blk, off_t off, ino_t ino)
{
struct direct *dp;
- char block[MAXBSIZE];
+ dirblock block;
- if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) {
+ assert((size_t)sblock.fs_bsize <= sizeof(block));
+ if (bread(&disk, fsbtodb(&sblock, blk), &block, sblock.fs_bsize) <= 0) {
warn("Failed to read dir block");
return (-1);
}
- bzero(&block[off], sblock.fs_bsize - off);
- dp = (struct direct *)(uintptr_t)&block[off];
+ assert(off % alignof(struct direct) == 0);
+ bzero(block.buf + off, sblock.fs_bsize - off);
+ dp = (struct direct *)(uintptr_t)(block.buf + off);
dp->d_ino = ino;
dp->d_reclen = DIRBLKSIZ;
dp->d_type = DT_REG;
dp->d_namlen = strlen(SUJ_FILE);
bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE));
- dir_clear_block(block, off + DIRBLKSIZ);
- if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) {
+ dir_clear_block(&block, off + DIRBLKSIZ);
+ if (bwrite(&disk, fsbtodb(&sblock, blk), &block, sblock.fs_bsize) <= 0) {
warn("Failed to write dir block");
return (-1);
}
@@ -749,15 +760,16 @@ dir_insert(ufs2_daddr_t blk, off_t off, ino_t ino)
static int
dir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino)
{
- char block[MAXBSIZE];
+ dirblock block;
- if (bread(&disk, fsbtodb(&sblock, blk), block,
+ assert((size_t)sblock.fs_bsize <= sizeof(block));
+ if (bread(&disk, fsbtodb(&sblock, blk), &block,
roundup(size, sblock.fs_fsize)) <= 0) {
warn("Failed to read dir block");
return (-1);
}
- dir_clear_block(block, size);
- if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize)
+ dir_clear_block(&block, size);
+ if (bwrite(&disk, fsbtodb(&sblock, nblk), &block, sblock.fs_bsize)
<= 0) {
warn("Failed to write dir block");
return (-1);
@@ -846,19 +858,17 @@ journal_insertfile(ino_t ino)
static int
indir_fill(ufs2_daddr_t blk, int level, int *resid)
{
- char indirbuf[MAXBSIZE];
- ufs1_daddr_t *bap1;
- ufs2_daddr_t *bap2;
+ union {
+ char buf[MAXBSIZE];
+ ufs1_daddr_t ufs1;
+ ufs2_daddr_t ufs2;
+ } indir = { 0 };
+ ufs1_daddr_t *bap1 = &indir.ufs1;
+ ufs2_daddr_t *bap2 = &indir.ufs2;
ufs2_daddr_t nblk;
- int ncnt;
- int cnt;
- int i;
+ int cnt = 0, ncnt;
- bzero(indirbuf, sizeof(indirbuf));
- bap1 = (ufs1_daddr_t *)(uintptr_t)indirbuf;
- bap2 = (void *)bap1;
- cnt = 0;
- for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) {
+ for (int i = 0; i < NINDIR(&sblock) && *resid != 0; i++) {
nblk = journal_balloc();
if (nblk <= 0)
return (-1);
@@ -875,7 +885,7 @@ indir_fill(ufs2_daddr_t blk, int level, int *resid)
} else
(*resid)--;
}
- if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf,
+ if (bwrite(&disk, fsbtodb(&sblock, blk), indir.buf,
sblock.fs_bsize) <= 0) {
warn("Failed to write indirect");
return (-1);