From 9c0db059b6585959e151f7acce845de280952c55 Mon Sep 17 00:00:00 2001 From: Michael Meffie Date: Mon, 26 Sep 2016 11:19:13 -0400 Subject: [PATCH] vol: convert vnode macros to inline functions Convert the vnode macros to inline functions to fix integer overflows for very large vnode numbers (and generally improve the code robustness and readability). The macro version of vnodeIndexOffset() will evaluate to an incorrect offset for very large vnode numbers due to 32-bit integer overflow. The vnode index file will then be corrupted when writing to the incorrect offset. In code paths where the vnode number incorrectly defined as a signed 32-bit integer, this change prevents vnodeIndexOffset() from evaluating to a negative result when a vnode number is larger than 2^31. Thanks to Mark Vitale for reporting and providing analysis. Change-Id: Ia6e0f2d2f97fa1091e0b5a4029d40098692ee681 Reviewed-on: https://gerrit.openafs.org/12397 Tested-by: BuildBot Reviewed-by: Benjamin Kaduk --- src/vol/vnode.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 76 insertions(+), 11 deletions(-) diff --git a/src/vol/vnode.h b/src/vol/vnode.h index d0f2c1d..b287573 100644 --- a/src/vol/vnode.h +++ b/src/vol/vnode.h @@ -28,8 +28,25 @@ typedef struct ViceLock { int lockTime; } ViceLock; -#define ViceLockCheckLocked(vptr) ((vptr)->lockTime == 0) -#define ViceLockClear(vptr) ((vptr)->lockCount = (vptr)->lockTime = 0) +/** + * Return non-zero if unlocked. + */ +static_inline int +ViceLockCheckLocked(struct ViceLock *vptr) +{ + return (vptr->lockTime == 0); +} + +/** + * Clear the lock. + */ +static_inline int +ViceLockClear(struct ViceLock *vptr) +{ + vptr->lockCount = 0; + vptr->lockTime = 0; + return 0; +} #define ROOTVNODE 1 @@ -67,15 +84,63 @@ struct VnodeClassInfo { extern struct VnodeClassInfo VnodeClassInfo[nVNODECLASSES]; -#define vnodeTypeToClass(type) ((type) == vDirectory? vLarge: vSmall) -#define vnodeIdToClass(vnodeId) ((vnodeId-1)&VNODECLASSMASK) -#define vnodeIdToBitNumber(v) (((v)-1)>>VNODECLASSWIDTH) -/* The following calculation allows for a header record at the beginning - of the index. The header record is the same size as a vnode */ -#define vnodeIndexOffset(vcp,vnodeNumber) \ - ((vnodeIdToBitNumber(vnodeNumber)+1)<<(vcp)->logSize) -#define bitNumberToVnodeNumber(b,class) ((VnodeId)(((b)<> VNODECLASSWIDTH); +} + +/** + * Return the index file offset of this vnode class and number. + * + * The following calculation allows for a header record at the beginning of + * the index. The header record is the same size as a vnode. + */ +static_inline afs_foff_t +vnodeIndexOffset(struct VnodeClassInfo* vcp, VnodeId vnodeNumber) +{ + return (((afs_foff_t)(vnodeIdToBitNumber(vnodeNumber) + 1)) << vcp->logSize); +} + +/** + * Return the vnode number of this vnode index. + */ +static_inline VnodeId +bitNumberToVnodeNumber(afs_uint32 bitNumber, VnodeClass vnodeClass) +{ + return ((((VnodeId)bitNumber) << VNODECLASSWIDTH) + vnodeClass + 1); +} + +/** + * Return non-zero if this vnode number is a directory. + */ +static_inline int +vnodeIsDirectory(VnodeId vnodeNumber) +{ + return (vnodeIdToClass(vnodeNumber) == vLarge); +} + typedef struct VnodeDiskObject { unsigned int type:3; /* Vnode is file, directory, symbolic link -- 1.9.4