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) { @@ -90,7 +81,7 @@ } return (cnt); fail: memset(data, 0, size); - if (p2 != data) { + if (p2 != NULL && p2 != data) { free(p2); } return (-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 @@ -48,26 +48,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(64); + union { + struct cg d_cg; /* cylinder group */ + char d_buf[MAXBSIZE]; /* cylinder group storage */ + } d_cgunion __aligned(64); + union { + union dinodep d_ino[1]; /* inode block */ + char d_inos[MAXBSIZE]; /* inode block as buffer */ + } d_inosunion __aligned(64); +#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 +78,18 @@ * libufs macros (internal, non-exported). */ #ifdef _LIBUFS +/* + * XXX: Various disk controllers require their buffers to be + * XXX: aligned to at least 64 bytes. This function ensures + * XXX: that the buffer is 64 byte aligned. + * XXX: This can be removed if/when the kernel is fixed. + */ +#define BUF_MALLOC(newbufpp, data, size) { \ + if (data != NULL && (((intptr_t)data) & 0x3f) == 0) \ + *newbufpp = (void *)data; \ + else \ + *newbufpp = aligned_alloc(64, 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;