zfsonlinux/zfs — Issue #426: Incorrect sa_find_sizes() size
Author: behlendorf
Created: 2011-10-21 20:55:55+00:00
State: open
Labels: Bug

Reported by Marcin Miroslaw and fixed in FreeBSD. We just need to review this change and make sure it's right for Linux before merging it in.

When calculating space needed for SA_BONUS buffers, hdrsize is always rounded
up to next 8-aligned boundary. However, in two places the round up was done
against sum of 'total' plus hdrsize. On the other hand, hdrsize increments by 4 each
time, which means in certain conditions, we would end up returning with
will_spill == 0 and (total + hdrsize) larger than full_space, leading to a failed
assertion because it's invalid for dmu_set_bonus.

Fix by: Xin Li
Sponsored by: iXsystems, Inc.

--- a/usr/src/uts/common/fs/zfs/sa.c Fri Jul 22 09:27:57 2011 -0700
+++ b/usr/src/uts/common/fs/zfs/sa.c Tue Oct 18 01:50:46 2011 +0200
@@ -605,14 +605,14 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
* and spill buffer.
*/
if (buftype == SA_BONUS && *index == -1 &&
- P2ROUNDUP(*total + hdrsize, 8) >
+ *total + P2ROUNDUP(hdrsize, 8) >
(full_space - sizeof (blkptr_t))) {
*index = i;
done = B_TRUE;
}

next:
- if (P2ROUNDUP(*total + hdrsize, 8) > full_space &&
+ if (*total + P2ROUNDUP(hdrsize, 8) > full_space &&
buftype == SA_BONUS)
*will_spill = B_TRUE;
}