diff --git a/lib/libufs/Makefile b/lib/libufs/Makefile --- a/lib/libufs/Makefile +++ b/lib/libufs/Makefile @@ -2,7 +2,7 @@ PACKAGE= ufs LIB= ufs SHLIBDIR?= /lib -SHLIB_MAJOR= 7 +SHLIB_MAJOR= 8 SRCS= block.c cgroup.c gsb_crc32.c inode.c sblock.c type.c ffs_subr.c SRCS+= ffs_tables.c diff --git a/lib/libufs/block.c b/lib/libufs/block.c --- a/lib/libufs/block.c +++ b/lib/libufs/block.c @@ -57,19 +57,10 @@ ERROR(disk, NULL); - p2 = data; - /* - * XXX: various disk controllers require alignment of our buffer - * XXX: which is stricter than struct alignment. - * XXX: Bounce the buffer if not 64 byte aligned. - * XXX: this can be removed if/when the kernel is fixed - */ - if (((intptr_t)data) & 0x3f) { - p2 = malloc(size); - if (p2 == NULL) { - ERROR(disk, "allocate bounce buffer"); - goto fail; - } + BUF_MALLOC(&p2, data, size); + if (p2 == NULL) { + ERROR(disk, "allocate bounce buffer"); + goto fail; } cnt = pread(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize)); if (cnt == -1) { @@ -101,7 +92,7 @@ { ssize_t cnt; int rv; - void *p2 = NULL; + void *p2; ERROR(disk, NULL); @@ -110,24 +101,15 @@ ERROR(disk, "failed to open disk for writing"); return (-1); } - - /* - * XXX: various disk controllers require alignment of our buffer - * XXX: which is stricter than struct alignment. - * XXX: Bounce the buffer if not 64 byte aligned. - * XXX: this can be removed if/when the kernel is fixed - */ - if (((intptr_t)data) & 0x3f) { - p2 = malloc(size); - if (p2 == NULL) { - ERROR(disk, "allocate bounce buffer"); - return (-1); - } - memcpy(p2, data, size); - data = p2; + BUF_MALLOC(&p2, data, size); + if (p2 == NULL) { + ERROR(disk, "allocate bounce buffer"); + return (-1); } - cnt = pwrite(disk->d_fd, data, size, (off_t)(blockno * disk->d_bsize)); - if (p2 != NULL) + if (p2 != data) + memcpy(p2, data, size); + cnt = pwrite(disk->d_fd, p2, size, (off_t)(blockno * disk->d_bsize)); + if (p2 != data) free(p2); if (cnt == -1) { ERROR(disk, "write error to block device"); @@ -137,7 +119,6 @@ ERROR(disk, "short write to block device"); return (-1); } - return (cnt); } diff --git a/lib/libufs/inode.c b/lib/libufs/inode.c --- a/lib/libufs/inode.c +++ b/lib/libufs/inode.c @@ -62,18 +62,10 @@ ERROR(disk, "inode number out of range"); return (-1); } - inoblock = disk->d_inoblock; + inoblock = (caddr_t)&disk->d_inos[0]; min = disk->d_inomin; max = disk->d_inomax; - if (inoblock == NULL) { - inoblock = malloc(fs->fs_bsize); - if (inoblock == NULL) { - ERROR(disk, "unable to allocate inode block"); - return (-1); - } - disk->d_inoblock = inoblock; - } if (inum >= min && inum < max) goto gotit; bread(disk, fsbtodb(fs, ino_to_fsba(fs, inum)), inoblock, @@ -107,14 +99,10 @@ struct fs *fs; fs = &disk->d_fs; - if (disk->d_inoblock == NULL) { - ERROR(disk, "No inode block allocated"); - return (-1); - } if (disk->d_ufs == 2) ffs_update_dinode_ckhash(fs, disk->d_dp.dp2); if (bwrite(disk, fsbtodb(fs, ino_to_fsba(&disk->d_fs, disk->d_inomin)), - disk->d_inoblock, disk->d_fs.fs_bsize) <= 0) + (caddr_t)&disk->d_inos[0], disk->d_fs.fs_bsize) <= 0) return (-1); return (0); } diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h --- a/lib/libufs/libufs.h +++ b/lib/libufs/libufs.h @@ -30,6 +30,15 @@ #ifndef __LIBUFS_H__ #define __LIBUFS_H__ +/* + * Various disk controllers require their buffers to be aligned to the size + * of a cache line. The LIBUFS_BUFALIGN defines the required alignment size. + * The alignment must be a power of 2. + */ +#define LIBUFS_BUFALIGN 64 +_Static_assert(powerof2(LIBUFS_BUFALIGN), + "LIBUFS_BUFALIGN must be a power of 2"); + /* * libufs structures. */ @@ -48,26 +57,29 @@ long d_bsize; /* device bsize */ ufs2_daddr_t d_sblock; /* superblock location */ struct fs_summary_info *d_si; /* Superblock summary info */ - caddr_t d_inoblock; /* inode block */ uint32_t d_inomin; /* low ino, not ino_t for ABI compat */ uint32_t d_inomax; /* high ino, not ino_t for ABI compat */ union dinodep d_dp; /* pointer to currently active inode */ - union { - struct fs d_fs; /* filesystem information */ - char d_sb[MAXBSIZE]; /* superblock as buffer */ - } d_sbunion; - union { - struct cg d_cg; /* cylinder group */ - char d_buf[MAXBSIZE]; /* cylinder group storage */ - } d_cgunion; int d_ccg; /* current cylinder group */ int d_lcg; /* last cylinder group (in d_cg) */ const char *d_error; /* human readable disk error */ off_t d_sblockloc; /* where to look for the superblock */ int d_lookupflags; /* flags to superblock lookup */ int d_mine; /* internal flags */ + union { + struct fs d_fs; /* filesystem information */ + char d_sb[SBLOCKSIZE]; /* superblock as buffer */ + } d_sbunion __aligned(LIBUFS_BUFALIGN); + union { + struct cg d_cg; /* cylinder group */ + char d_buf[MAXBSIZE]; /* cylinder group storage */ + } d_cgunion __aligned(LIBUFS_BUFALIGN); + union { + union dinodep d_ino[1]; /* inode block */ + char d_inos[MAXBSIZE]; /* inode block as buffer */ + } d_inosunion __aligned(LIBUFS_BUFALIGN); +#define d_inos d_inosunion.d_inos #define d_fs d_sbunion.d_fs -#define d_sb d_sbunion.d_sb #define d_cg d_cgunion.d_cg }; @@ -75,6 +87,15 @@ * libufs macros (internal, non-exported). */ #ifdef _LIBUFS +/* + * Ensure that the buffer is aligned to the I/O subsystem requirements. + */ +#define BUF_MALLOC(newbufpp, data, size) { \ + if (data != NULL && (((intptr_t)data) & (LIBUFS_BUFALIGN - 1)) == 0) \ + *newbufpp = (void *)data; \ + else \ + *newbufpp = aligned_alloc(LIBUFS_BUFALIGN, size); \ +} /* * Trace steps through libufs, to be used at entry and erroneous return. */ diff --git a/lib/libufs/sblock.c b/lib/libufs/sblock.c --- a/lib/libufs/sblock.c +++ b/lib/libufs/sblock.c @@ -228,7 +228,8 @@ int fd; fd = *(int *)devfd; - if ((*bufp = malloc(size)) == NULL) + BUF_MALLOC(bufp, NULL, size); + if (*bufp == NULL) return (ENOSPC); if (pread(fd, *bufp, size, loc) != size) return (EIO); diff --git a/lib/libufs/type.c b/lib/libufs/type.c --- a/lib/libufs/type.c +++ b/lib/libufs/type.c @@ -61,10 +61,6 @@ ERROR(disk, NULL); close(disk->d_fd); disk->d_fd = -1; - if (disk->d_inoblock != NULL) { - free(disk->d_inoblock); - disk->d_inoblock = NULL; - } if (disk->d_mine & MINE_NAME) { free((char *)(uintptr_t)disk->d_name); disk->d_name = NULL; @@ -158,7 +154,6 @@ disk->d_bsize = 1; disk->d_ccg = 0; disk->d_fd = fd; - disk->d_inoblock = NULL; disk->d_inomin = 0; disk->d_inomax = 0; disk->d_lcg = 0;