From 6ed9e9f32fa41cdc6708f0dbec3a1819a80c58e1 Mon Sep 17 00:00:00 2001 From: Andriy Gapon Date: Tue, 18 Sep 2012 08:02:54 +0000 Subject: [PATCH] zfs: correctly calculate dn_bonuslen for saving SAs to disk Since all attribute values start at 8-byte aligned boundary, we would previously incorrectly calculate dn_bonuslen if any attribute but the last had a variable-length value with length not multiple of 8. Reported by: Nicolas Rachinsky Tested by: Nicolas Rachinsky Reviewed by: Matthew Ahrens (for upstream) MFC after: 2 weeks --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c index 9bb5cbc01736..894bbc3d0deb 100644 --- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c +++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c @@ -578,7 +578,7 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count, for (i = 0; i != attr_count; i++) { boolean_t is_var_sz; - *total += attr_desc[i].sa_length; + *total += P2ROUNDUP(attr_desc[i].sa_length, 8); if (done) goto next; @@ -713,6 +713,8 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count, length = SA_REGISTERED_LEN(sa, attrs[i]); if (length == 0) length = attr_desc[i].sa_length; + else + VERIFY(length == attr_desc[i].sa_length); if (buf_space < length) { /* switch to spill buffer */ VERIFY(bonustype == DMU_OT_SA); @@ -742,6 +744,7 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count, if (sa->sa_attr_table[attrs[i]].sa_length == 0) { sahdr->sa_lengths[len_idx++] = length; } + VERIFY((uintptr_t)data_start % 8 == 0); data_start = (void *)P2ROUNDUP(((uintptr_t)data_start + length), 8); buf_space -= P2ROUNDUP(length, 8);