Author: mav
Date: Tue Jan 26 13:03:01 2016
New Revision: 294813
URL: https://svnweb.freebsd.org/changeset/base/294813

Log:
  MFV r294812: 6434 sa_find_sizes() may compute wrong SA header size
  
  Reviewed-by: Ned Bass <ba...@llnl.gov>
  Reviewed-by: Brian Behlendorf <behlendo...@llnl.gov>
  Reviewed by: Andriy Gapon <a...@freebsd.org>
  Reviewed by: Matthew Ahrens <mahr...@delphix.com>
  Approved by: Robert Mustacchi <r...@joyent.com>
  Author: James Pan <jiaming....@yahoo.com>
  
  illumos/illumos-gate@3502ed6e7cb3f3d2e781960ab8fe465fdc884834

Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
Directory Properties:
  head/sys/cddl/contrib/opensolaris/   (props changed)

Modified: head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c    Tue Jan 26 
13:02:16 2016        (r294812)
+++ head/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c    Tue Jan 26 
13:03:01 2016        (r294813)
@@ -547,10 +547,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
 {
        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;
@@ -561,10 +560,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
 
        *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);
 
@@ -576,8 +574,8 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
 
                *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) {
@@ -585,21 +583,28 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
                }
 
                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;
                        }
                }
@@ -614,22 +619,15 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_
                    (*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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to