From: Dave Chinner <dchinner@xxxxxxxxxx> The sizing of the attri name and value log iovecs is incorrect. This results in memory corruption and crashes on a kernel with the current CIL scalability patchset applied as it relies on the callers playing by slightly different alignment rules. Convert the attri code to the new xlog_calc_iovec_size() API to fix these issues. Signed-off-by: Dave Chinner <dchinner@xxxxxxxxxx> --- fs/xfs/xfs_attr_item.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/fs/xfs/xfs_attr_item.c b/fs/xfs/xfs_attr_item.c index 4072972a2ed8..bd4089eb8087 100644 --- a/fs/xfs/xfs_attr_item.c +++ b/fs/xfs/xfs_attr_item.c @@ -42,13 +42,6 @@ static const struct xfs_item_ops xfs_attri_item_ops; static const struct xfs_item_ops xfs_attrd_item_ops; -/* iovec length must be 32-bit aligned */ -static inline size_t ATTR_NVEC_SIZE(size_t size) -{ - return size == sizeof(int32_t) ? size : - sizeof(int32_t) + round_up(size, sizeof(int32_t)); -} - static inline struct xfs_attri_log_item *ATTRI_ITEM(struct xfs_log_item *lip) { return container_of(lip, struct xfs_attri_log_item, attri_item); @@ -89,19 +82,15 @@ xfs_attri_item_size( { struct xfs_attri_log_item *attrip = ATTRI_ITEM(lip); - *nvecs += 1; - *nbytes += sizeof(struct xfs_attri_log_format); + *nvecs += 2; + *nbytes += sizeof(struct xfs_attri_log_format) + + xlog_calc_iovec_len(attrip->attri_name_len); - /* Attr set and remove operations require a name */ - ASSERT(attrip->attri_name_len > 0); + if (!attrip->attri_value_len) + return; *nvecs += 1; - *nbytes += ATTR_NVEC_SIZE(attrip->attri_name_len); - - if (attrip->attri_value_len > 0) { - *nvecs += 1; - *nbytes += ATTR_NVEC_SIZE(attrip->attri_value_len); - } + *nbytes += xlog_calc_iovec_len(attrip->attri_value_len); } /* @@ -137,12 +126,10 @@ xfs_attri_item_format( &attrip->attri_format, sizeof(struct xfs_attri_log_format)); xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTR_NAME, - attrip->attri_name, - ATTR_NVEC_SIZE(attrip->attri_name_len)); + attrip->attri_name, attrip->attri_name_len); if (attrip->attri_value_len > 0) xlog_copy_iovec(lv, &vecp, XLOG_REG_TYPE_ATTR_VALUE, - attrip->attri_value, - ATTR_NVEC_SIZE(attrip->attri_value_len)); + attrip->attri_value, attrip->attri_value_len); } /* -- 2.31.1