diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -3676,15 +3676,8 @@ * before we get to evaluate the condition. If this happens, we will * populate part of the buffer and descend to vn_fullpath_dir with * vp == vp_crossmp. Prevent the problem by checking for VBAD. - * - * This should be atomic_load(&vp->v_type) but it is illegal to take - * an address of a bit field, even if said field is sized to char. - * Work around the problem by reading the value into a full-sized enum - * and then re-reading it with atomic_load which will still prevent - * the compiler from re-reading down the road. */ - type = vp->v_type; - type = atomic_load_int(&type); + type = atomic_load_char(&type); if (type == VBAD) { error = ENOENT; goto out_bad; diff --git a/sys/sys/cdefs.h b/sys/sys/cdefs.h --- a/sys/sys/cdefs.h +++ b/sys/sys/cdefs.h @@ -932,4 +932,22 @@ #define __align_down(x, y) __builtin_align_down(x, y) #define __is_aligned(x, y) __builtin_is_aligned(x, y) +#ifdef _KERNEL +/* + * TODO: figure out how to do checking at compilation time that consumers don't + * use mere 'enum' + */ +#if defined(__clang__) || (defined(__GNUC__) && __GNUC__ >= 13) +#define enum_uint8_decl(name) enum name : uint8_t +#define enum_uint8(name) enum name +#else +/* + * Note: there is no real size checking here, but the code below is uspposed to + * die off. + */ +#define enum_uint8_decl(name) enum __attribute__((packed)) name +#define enum_uint8(name) enum __attribute__((packed)) name +#endif +#endif + #endif /* !_SYS_CDEFS_H_ */ diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -56,11 +56,11 @@ /* * Vnode types. VNON means no type. */ -enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD, +enum_uint8_decl(vtype) { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD, VMARKER }; #define VLASTTYPE VMARKER -enum vstate { VSTATE_UNINITIALIZED, VSTATE_CONSTRUCTED, VSTATE_DESTROYING, +enum_uint8_decl(vstate) { VSTATE_UNINITIALIZED, VSTATE_CONSTRUCTED, VSTATE_DESTROYING, VSTATE_DEAD }; #define VLASTSTATE VSTATE_DEAD @@ -110,8 +110,8 @@ * Fields which define the identity of the vnode. These fields are * owned by the filesystem (XXX: and vgone() ?) */ - enum vtype v_type:8; /* u vnode type */ - enum vstate v_state:8; /* u vnode state */ + enum_uint8(vtype) v_type; /* u vnode type */ + enum_uint8(vstate) v_state; /* u vnode state */ short v_irflag; /* i frequently read flags */ seqc_t v_seqc; /* i modification count */ uint32_t v_nchash; /* u namecache hash */