Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/ufs/lfs Avoid misaligned access to lfs64 on-disk records...



details:   https://anonhg.NetBSD.org/src/rev/ecdb85611190
branches:  trunk
changeset: 746054:ecdb85611190
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Mar 21 06:11:05 2020 +0000

description:
Avoid misaligned access to lfs64 on-disk records in memory.

lfs64 directory entries are only 32-bit aligned in order to conserve
space in directory blocks, and we had a hack to stuff a 64-bit inode
in them.  This replaces the hack by __aligned(4) __packed, and goes
further:

1. It's not clear that all the other lfs64 data structures are 64-bit
   aligned on disk to begin with.  We can go through these later and
   upgrade them from

        struct foo64 {
                ...
        } __aligned(4) __packed;

        union foo {
                struct foo64 f64;
                ...
        };

   to

        struct foo64 {
                ...
        };

        union foo {
                struct foo64 f64 __aligned(8);
                ...
        } __aligned(4) __packed;

   if we really want to take advantage of 64-bit memory accesses.

   However, the __aligned(4) __packed must remain on the union
   because:

2. We access even the lfs32 data structures via a union that has
   lfs64 members, and it turns out that compilers will assume access
   through a union with 64-bit aligned members implies the whole
   union has 64-bit alignment, even if we're only accessing a 32-bit
   aligned member.

diffstat:

 sys/ufs/lfs/lfs.h           |  38 +++++++++++++++++++++++++++-----------
 sys/ufs/lfs/lfs_accessors.h |  25 +++----------------------
 2 files changed, 30 insertions(+), 33 deletions(-)

diffs (198 lines):

diff -r b960d63e5da9 -r ecdb85611190 sys/ufs/lfs/lfs.h
--- a/sys/ufs/lfs/lfs.h Sat Mar 21 06:09:33 2020 +0000
+++ b/sys/ufs/lfs/lfs.h Sat Mar 21 06:11:05 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs.h,v 1.206 2020/03/21 06:09:33 riastradh Exp $      */
+/*     $NetBSD: lfs.h,v 1.207 2020/03/21 06:11:05 riastradh Exp $      */
 
 /*  from NetBSD: dinode.h,v 1.25 2016/01/22 23:06:10 dholland Exp  */
 /*  from NetBSD: dir.h,v 1.25 2015/09/01 06:16:03 dholland Exp  */
@@ -358,18 +358,19 @@
 __CTASSERT(sizeof(struct lfs_dirheader32) == 8);
 
 struct lfs_dirheader64 {
-       uint32_t dh_inoA;               /* inode number of entry */
-       uint32_t dh_inoB;               /* inode number of entry */
+       uint64_t dh_ino;                /* inode number of entry */
        uint16_t dh_reclen;             /* length of this record */
        uint8_t  dh_type;               /* file type, see below */
        uint8_t  dh_namlen;             /* length of string in d_name */
-};
+} __aligned(4) __packed;
 __CTASSERT(sizeof(struct lfs_dirheader64) == 12);
 
 union lfs_dirheader {
        struct lfs_dirheader64 u_64;
        struct lfs_dirheader32 u_32;
 };
+__CTASSERT(__alignof(union lfs_dirheader) == __alignof(struct lfs_dirheader64));
+__CTASSERT(__alignof(union lfs_dirheader) == __alignof(struct lfs_dirheader32));
 
 typedef union lfs_dirheader LFS_DIRHEADER;
 
@@ -481,6 +482,8 @@
        struct lfs64_dinode u_64;
        struct lfs32_dinode u_32;
 };
+__CTASSERT(__alignof(union lfs_dinode) == __alignof(struct lfs64_dinode));
+__CTASSERT(__alignof(union lfs_dinode) == __alignof(struct lfs32_dinode));
 
 /*
  * The di_db fields may be overlaid with other information for
@@ -563,7 +566,7 @@
        uint64_t fi_ino;                /* inode number */
        uint32_t fi_lastlength;         /* length of last block in array */
        uint32_t fi_pad;                /* unused */
-};
+} __aligned(4) __packed;
 __CTASSERT(sizeof(struct finfo64) == 24);
 
 typedef struct finfo32 FINFO32;
@@ -579,6 +582,8 @@
        struct finfo64 u_64;
        struct finfo32 u_32;
 } FINFO;
+__CTASSERT(__alignof(union finfo) == __alignof(struct finfo64));
+__CTASSERT(__alignof(union finfo) == __alignof(struct finfo32));
 
 /*
  * inode info (part of the segment summary)
@@ -590,7 +595,7 @@
 
 typedef struct iinfo64 {
        uint64_t ii_block;              /* block number */
-} IINFO64;
+} __aligned(4) __packed IINFO64;
 __CTASSERT(sizeof(struct iinfo64) == 8);
 
 typedef struct iinfo32 {
@@ -602,6 +607,8 @@
        struct iinfo64 u_64;
        struct iinfo32 u_32;
 } IINFO;
+__CTASSERT(__alignof(union iinfo) == __alignof(struct iinfo64));
+__CTASSERT(__alignof(union iinfo) == __alignof(struct iinfo32));
 
 /*
  * Index file inode entries.
@@ -620,7 +627,7 @@
        uint64_t if_atime_sec;          /* Last access time, seconds */
        int64_t   if_daddr;             /* inode disk address */
        uint64_t if_nextfree;           /* next-unallocated inode */
-};
+} __aligned(4) __packed;
 __CTASSERT(sizeof(struct ifile64) == 32);
 
 typedef struct ifile32 IFILE32;
@@ -655,6 +662,9 @@
        struct ifile32 u_32;
        struct ifile_v1 u_v1;
 } IFILE;
+__CTASSERT(__alignof(union ifile) == __alignof(struct ifile64));
+__CTASSERT(__alignof(union ifile) == __alignof(struct ifile32));
+__CTASSERT(__alignof(union ifile) == __alignof(struct ifile_v1));
 
 /*
  * Cleaner information structure.  This resides in the ifile and is used
@@ -684,7 +694,7 @@
        uint64_t free_tail;             /* 32: tail of the inode free list */
        uint32_t flags;                 /* 40: status word from the kernel */
        uint32_t pad;                   /* 44: must be 64-bit aligned */
-} CLEANERINFO64;
+} __aligned(4) __packed CLEANERINFO64;
 __CTASSERT(sizeof(struct _cleanerinfo64) == 48);
 
 /* this must not go to disk directly of course */
@@ -692,6 +702,8 @@
        CLEANERINFO32 u_32;
        CLEANERINFO64 u_64;
 } CLEANERINFO;
+__CTASSERT(__alignof(union _cleanerinfo) == __alignof(struct _cleanerinfo32));
+__CTASSERT(__alignof(union _cleanerinfo) == __alignof(struct _cleanerinfo64));
 
 /*
  * On-disk segment summary information
@@ -740,7 +752,7 @@
        uint64_t ss_serial;             /* 32: serial number */
        uint64_t ss_create;             /* 40: time stamp */
        /* FINFO's and inode daddr's... */
-};
+} __aligned(4) __packed;
 __CTASSERT(sizeof(struct segsum32) == 48);
 
 typedef struct segsum64 SEGSUM64;
@@ -758,7 +770,7 @@
        uint64_t ss_serial;             /* 40: serial number */
        uint64_t ss_create;             /* 48: time stamp */
        /* FINFO's and inode daddr's... */
-};
+} __aligned(4) __packed;
 __CTASSERT(sizeof(struct segsum64) == 56);
 
 typedef union segsum SEGSUM;
@@ -767,7 +779,9 @@
        struct segsum32 u_32;
        struct segsum_v1 u_v1;
 };
-
+__CTASSERT(__alignof(union segsum) == __alignof(struct segsum64));
+__CTASSERT(__alignof(union segsum) == __alignof(struct segsum32));
+__CTASSERT(__alignof(union segsum) == __alignof(struct segsum_v1));
 
 /*
  * On-disk super block.
@@ -956,6 +970,8 @@
        uint32_t dlfs_cksum;      /* 508: checksum for superblock checking */
 };
 
+__CTASSERT(__alignof(struct dlfs) == __alignof(struct dlfs64));
+
 /* Type used for the inode bitmap */
 typedef uint32_t lfs_bm_t;
 
diff -r b960d63e5da9 -r ecdb85611190 sys/ufs/lfs/lfs_accessors.h
--- a/sys/ufs/lfs/lfs_accessors.h       Sat Mar 21 06:09:33 2020 +0000
+++ b/sys/ufs/lfs/lfs_accessors.h       Sat Mar 21 06:11:05 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: lfs_accessors.h,v 1.48 2017/06/10 05:29:36 maya Exp $  */
+/*     $NetBSD: lfs_accessors.h,v 1.49 2020/03/21 06:11:05 riastradh Exp $     */
 
 /*  from NetBSD: lfs.h,v 1.165 2015/07/24 06:59:32 dholland Exp  */
 /*  from NetBSD: dinode.h,v 1.25 2016/01/22 23:06:10 dholland Exp  */
@@ -274,17 +274,7 @@
 lfs_dir_getino(const STRUCT_LFS *fs, const LFS_DIRHEADER *dh)
 {
        if (fs->lfs_is64) {
-               uint64_t ino;
-
-               /*
-                * XXX we can probably write this in a way that's both
-                * still legal and generates better code.
-                */
-               memcpy(&ino, &dh->u_64.dh_inoA, sizeof(dh->u_64.dh_inoA));
-               memcpy((char *)&ino + sizeof(dh->u_64.dh_inoA),
-                      &dh->u_64.dh_inoB,
-                      sizeof(dh->u_64.dh_inoB));
-               return LFS_SWAP_uint64_t(fs, ino);
+               return LFS_SWAP_uint64_t(fs, dh->u_64.dh_ino);
        } else {
                return LFS_SWAP_uint32_t(fs, dh->u_32.dh_ino);
        }
@@ -331,16 +321,7 @@
 lfs_dir_setino(STRUCT_LFS *fs, LFS_DIRHEADER *dh, uint64_t ino)
 {
        if (fs->lfs_is64) {
-
-               ino = LFS_SWAP_uint64_t(fs, ino);
-               /*
-                * XXX we can probably write this in a way that's both
-                * still legal and generates better code.
-                */
-               memcpy(&dh->u_64.dh_inoA, &ino, sizeof(dh->u_64.dh_inoA));
-               memcpy(&dh->u_64.dh_inoB,
-                      (char *)&ino + sizeof(dh->u_64.dh_inoA),
-                      sizeof(dh->u_64.dh_inoB));
+               dh->u_64.dh_ino = LFS_SWAP_uint64_t(fs, ino);
        } else {
                dh->u_32.dh_ino = LFS_SWAP_uint32_t(fs, ino);
        }



Home | Main Index | Thread Index | Old Index