Skip to content

Commit 71d7abc

Browse files
committed
MFV r294812: 6434 sa_find_sizes() may compute wrong SA header size
Reviewed-by: Ned Bass <bass6@llnl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Reviewed by: Andriy Gapon <avg@freebsd.org> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Approved by: Robert Mustacchi <rm@joyent.com> Author: James Pan <jiaming.pan@yahoo.com> illumos/illumos-gate@3502ed6
1 parent 7a16fdf commit 71d7abc

File tree

1 file changed

+22
-24
lines changed
  • sys/cddl/contrib/opensolaris/uts/common/fs/zfs

1 file changed

+22
-24
lines changed

sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c

Lines changed: 22 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -547,10 +547,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
547547
{
548548
int var_size = 0;
549549
int i;
550-
int j = -1;
551550
int full_space;
552551
int hdrsize;
553-
boolean_t done = B_FALSE;
552+
int extra_hdrsize;
554553

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

562561
*index = -1;
563562
*total = 0;
563+
*will_spill = B_FALSE;
564564

565-
if (buftype == SA_BONUS)
566-
*will_spill = B_FALSE;
567-
565+
extra_hdrsize = 0;
568566
hdrsize = (SA_BONUSTYPE_FROM_DB(db) == DMU_OT_ZNODE) ? 0 :
569567
sizeof (sa_hdr_phys_t);
570568

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

577575
*total = P2ROUNDUP(*total, 8);
578576
*total += attr_desc[i].sa_length;
579-
if (done)
580-
goto next;
577+
if (*will_spill)
578+
continue;
581579

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

587585
if (is_var_sz && var_size > 1) {
588-
if (P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
586+
/*
587+
* Don't worry that the spill block might overflow.
588+
* It will be resized if needed in sa_build_layouts().
589+
*/
590+
if (buftype == SA_SPILL ||
591+
P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
589592
*total < full_space) {
590593
/*
591594
* Account for header space used by array of
592595
* optional sizes of variable-length attributes.
593-
* Record the index in case this increase needs
594-
* to be reversed due to spill-over.
596+
* Record the extra header size in case this
597+
* increase needs to be reversed due to
598+
* spill-over.
595599
*/
596600
hdrsize += sizeof (uint16_t);
597-
j = i;
601+
if (*index != -1)
602+
extra_hdrsize += sizeof (uint16_t);
598603
} else {
599-
done = B_TRUE;
600-
*index = i;
601-
if (buftype == SA_BONUS)
602-
*will_spill = B_TRUE;
604+
ASSERT(buftype == SA_BONUS);
605+
if (*index == -1)
606+
*index = i;
607+
*will_spill = B_TRUE;
603608
continue;
604609
}
605610
}
@@ -614,22 +619,15 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
614619
(*total + P2ROUNDUP(hdrsize, 8)) >
615620
(full_space - sizeof (blkptr_t))) {
616621
*index = i;
617-
done = B_TRUE;
618622
}
619623

620-
next:
621624
if ((*total + P2ROUNDUP(hdrsize, 8)) > full_space &&
622625
buftype == SA_BONUS)
623626
*will_spill = B_TRUE;
624627
}
625628

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

634632
hdrsize = P2ROUNDUP(hdrsize, 8);
635633
return (hdrsize);

0 commit comments

Comments
 (0)