Skip to content

Commit

Permalink
6434 sa_find_sizes() may compute wrong SA header size
Browse files Browse the repository at this point in the history
Reviewed-by: Ned Bass <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed by: Andriy Gapon <[email protected]>
Reviewed by: Matthew Ahrens <[email protected]>
Approved by: Robert Mustacchi <[email protected]>
  • Loading branch information
James Pan authored and ahrens committed Nov 5, 2015
1 parent 3bc3cac commit 3502ed6
Showing 1 changed file with 22 additions and 24 deletions.
46 changes: 22 additions & 24 deletions usr/src/uts/common/fs/zfs/sa.c
Original file line number Diff line number Diff line change
Expand Up @@ -547,10 +547,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
{
int var_size = 0;
int i;
int j = -1;
int full_space;
int hdrsize;
boolean_t done = B_FALSE;
int extra_hdrsize;

if (buftype == SA_BONUS && sa->sa_force_spill) {
*total = 0;
Expand All @@ -561,10 +560,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,

*index = -1;
*total = 0;
*will_spill = B_FALSE;

if (buftype == SA_BONUS)
*will_spill = B_FALSE;

extra_hdrsize = 0;
hdrsize = (SA_BONUSTYPE_FROM_DB(db) == DMU_OT_ZNODE) ? 0 :
sizeof (sa_hdr_phys_t);

Expand All @@ -576,30 +574,37 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,

*total = P2ROUNDUP(*total, 8);
*total += attr_desc[i].sa_length;
if (done)
goto next;
if (*will_spill)
continue;

is_var_sz = (SA_REGISTERED_LEN(sa, attr_desc[i].sa_attr) == 0);
if (is_var_sz) {
var_size++;
}

if (is_var_sz && var_size > 1) {
if (P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
/*
* Don't worry that the spill block might overflow.
* It will be resized if needed in sa_build_layouts().
*/
if (buftype == SA_SPILL ||
P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
*total < full_space) {
/*
* Account for header space used by array of
* optional sizes of variable-length attributes.
* Record the index in case this increase needs
* to be reversed due to spill-over.
* Record the extra header size in case this
* increase needs to be reversed due to
* spill-over.
*/
hdrsize += sizeof (uint16_t);
j = i;
if (*index != -1)
extra_hdrsize += sizeof (uint16_t);
} else {
done = B_TRUE;
*index = i;
if (buftype == SA_BONUS)
*will_spill = B_TRUE;
ASSERT(buftype == SA_BONUS);
if (*index == -1)
*index = i;
*will_spill = B_TRUE;
continue;
}
}
Expand All @@ -614,22 +619,15 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
*total + P2ROUNDUP(hdrsize, 8) >
(full_space - sizeof (blkptr_t))) {
*index = i;
done = B_TRUE;
}

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

/*
* j holds the index of the last variable-sized attribute for
* which hdrsize was increased. Reverse the increase if that
* attribute will be relocated to the spill block.
*/
if (*will_spill && j == *index)
hdrsize -= sizeof (uint16_t);
if (*will_spill)
hdrsize -= extra_hdrsize;

hdrsize = P2ROUNDUP(hdrsize, 8);
return (hdrsize);
Expand Down

0 comments on commit 3502ed6

Please sign in to comment.