]> git.proxmox.com Git - mirror_zfs.git/blobdiff - module/zfs/sa.c
Illumos 5314 - Remove "dbuf phys" db->db_data pointer aliases in ZFS
[mirror_zfs.git] / module / zfs / sa.c
index 1263d37ab0096608474bd9b1f48d809cdb5758cf..59a98b4f3db3c13cb04982a680fb93241174b032 100644 (file)
@@ -538,20 +538,30 @@ sa_copy_data(sa_data_locator_t *func, void *datastart, void *target, int buflen)
 }
 
 /*
- * Determine several different sizes
- * first the sa header size
- * the number of bytes to be stored
- * if spill would occur the index in the attribute array is returned
+ * Determine several different values pertaining to system attribute
+ * buffers.
  *
- * the boolean will_spill will be set when spilling is necessary.  It
- * is only set when the buftype is SA_BONUS
+ * Return the size of the sa_hdr_phys_t header for the buffer. Each
+ * variable length attribute except the first contributes two bytes to
+ * the header size, which is then rounded up to an 8-byte boundary.
+ *
+ * The following output parameters are also computed.
+ *
+ *  index - The index of the first attribute in attr_desc that will
+ *  spill over. Only valid if will_spill is set.
+ *
+ *  total - The total number of bytes of all system attributes described
+ *  in attr_desc.
+ *
+ *  will_spill - Set when spilling is necessary. It is only set when
+ *  the buftype is SA_BONUS.
  */
 static int
 sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
     dmu_buf_t *db, sa_buf_type_t buftype, int *index, int *total,
     boolean_t *will_spill)
 {
-       int var_size = 0;
+       int var_size_count = 0;
        int i;
        int full_space;
        int hdrsize;
@@ -577,6 +587,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, might_spill_here;
+               int tmp_hdrsize;
 
                *total = P2ROUNDUP(*total, 8);
                *total += attr_desc[i].sa_length;
@@ -584,31 +595,35 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
                        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_count++;
 
+               /*
+                * Calculate what the SA header size would be if this
+                * attribute doesn't spill.
+                */
+               tmp_hdrsize = hdrsize + ((is_var_sz && var_size_count > 1) ?
+                   sizeof (uint16_t) : 0);
+
+               /*
+                * Check whether this attribute spans into the space
+                * that would be used by the spill block pointer should
+                * a spill block be needed.
+                */
                might_spill_here =
                    buftype == SA_BONUS && *index == -1 &&
-                   (*total + P2ROUNDUP(hdrsize, 8)) >
+                   (*total + P2ROUNDUP(tmp_hdrsize, 8)) >
                    (full_space - sizeof (blkptr_t));
 
-               if (is_var_sz && var_size > 1) {
-                       /*
-                        * Don't worry that the spill block might overflow.
-                        * It will be resized if needed in sa_build_layouts().
-                        */
+               if (is_var_sz && var_size_count > 1) {
                        if (buftype == SA_SPILL ||
-                           P2ROUNDUP(hdrsize + sizeof (uint16_t), 8) +
-                           *total < full_space) {
+                           tmp_hdrsize + *total < full_space) {
                                /*
-                                * Account for header space used by array of
-                                * optional sizes of variable-length attributes.
                                 * Record the extra header size in case this
                                 * increase needs to be reversed due to
                                 * spill-over.
                                 */
-                               hdrsize += sizeof (uint16_t);
+                               hdrsize = tmp_hdrsize;
                                if (*index != -1 || might_spill_here)
                                        extra_hdrsize += sizeof (uint16_t);
                        } else {
@@ -621,10 +636,9 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
                }
 
                /*
-                * find index of where spill *could* occur.
-                * Then continue to count of remainder attribute
-                * space.  The sum is used later for sizing bonus
-                * and spill buffer.
+                * Store index of where spill *could* occur. Then
+                * continue to count the remaining attribute sizes. The
+                * sum is used later for sizing bonus and spill buffer.
                 */
                if (might_spill_here)
                        *index = i;
@@ -657,9 +671,9 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
        sa_buf_type_t buftype;
        sa_hdr_phys_t *sahdr;
        void *data_start;
-       int buf_space;
        sa_attr_type_t *attrs, *attrs_start;
        int i, lot_count;
+       int spill_idx;
        int hdrsize;
        int spillhdrsize = 0;
        int used;
@@ -674,7 +688,7 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
 
        /* first determine bonus header size and sum of all attributes */
        hdrsize = sa_find_sizes(sa, attr_desc, attr_count, hdl->sa_bonus,
-           SA_BONUS, &i, &used, &spilling);
+           SA_BONUS, &spill_idx, &used, &spilling);
 
        if (used > SPA_MAXBLOCKSIZE)
                return (SET_ERROR(EFBIG));
@@ -696,14 +710,13 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
                }
                dmu_buf_will_dirty(hdl->sa_spill, tx);
 
-               spillhdrsize = sa_find_sizes(sa, &attr_desc[i],
-                   attr_count - i, hdl->sa_spill, SA_SPILL, &i,
+               spillhdrsize = sa_find_sizes(sa, &attr_desc[spill_idx],
+                   attr_count - spill_idx, hdl->sa_spill, SA_SPILL, &i,
                    &spill_used, &dummy);
 
                if (spill_used > SPA_MAXBLOCKSIZE)
                        return (SET_ERROR(EFBIG));
 
-               buf_space = hdl->sa_spill->db_size - spillhdrsize;
                if (BUF_SPACE_NEEDED(spill_used, spillhdrsize) >
                    hdl->sa_spill->db_size)
                        VERIFY(0 == sa_resize_spill(hdl,
@@ -715,12 +728,6 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
        sahdr = (sa_hdr_phys_t *)hdl->sa_bonus->db_data;
        buftype = SA_BONUS;
 
-       if (spilling)
-               buf_space = (sa->sa_force_spill) ?
-                   0 : SA_BLKPTR_SPACE - hdrsize;
-       else
-               buf_space = hdl->sa_bonus->db_size - hdrsize;
-
        attrs_start = attrs = kmem_alloc(sizeof (sa_attr_type_t) * attr_count,
            KM_SLEEP);
        lot_count = 0;
@@ -729,14 +736,12 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
                uint16_t length;
 
                ASSERT(IS_P2ALIGNED(data_start, 8));
-               ASSERT(IS_P2ALIGNED(buf_space, 8));
                attrs[i] = attr_desc[i].sa_attr;
                length = SA_REGISTERED_LEN(sa, attrs[i]);
                if (length == 0)
                        length = attr_desc[i].sa_length;
 
-               if (buf_space < length) {  /* switch to spill buffer */
-                       VERIFY(spilling);
+               if (spilling && i == spill_idx) { /* switch to spill buffer */
                        VERIFY(bonustype == DMU_OT_SA);
                        if (buftype == SA_BONUS && !sa->sa_force_spill) {
                                sa_find_layout(hdl->sa_os, hash, attrs_start,
@@ -753,7 +758,6 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
                        data_start = (void *)((uintptr_t)sahdr +
                            spillhdrsize);
                        attrs_start = &attrs[i];
-                       buf_space = hdl->sa_spill->db_size - spillhdrsize;
                        lot_count = 0;
                }
                hash ^= SA_ATTR_HASH(attrs[i]);
@@ -766,7 +770,6 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
                }
                data_start = (void *)P2ROUNDUP(((uintptr_t)data_start +
                    length), 8);
-               buf_space -= P2ROUNDUP(length, 8);
                lot_count++;
        }
 
@@ -1109,6 +1112,9 @@ fail:
        if (sa->sa_user_table)
                kmem_free(sa->sa_user_table, sa->sa_user_table_sz);
        mutex_exit(&sa->sa_lock);
+       avl_destroy(&sa->sa_layout_hash_tree);
+       avl_destroy(&sa->sa_layout_num_tree);
+       mutex_destroy(&sa->sa_lock);
        kmem_free(sa, sizeof (sa_os_t));
        return ((error == ECKSUM) ? EIO : error);
 }
@@ -1145,6 +1151,7 @@ sa_tear_down(objset_t *os)
 
        avl_destroy(&sa->sa_layout_hash_tree);
        avl_destroy(&sa->sa_layout_num_tree);
+       mutex_destroy(&sa->sa_lock);
 
        kmem_free(sa, sizeof (sa_os_t));
        os->os_sa = NULL;
@@ -1356,7 +1363,7 @@ sa_handle_destroy(sa_handle_t *hdl)
 {
        mutex_enter(&hdl->sa_lock);
        (void) dmu_buf_update_user((dmu_buf_t *)hdl->sa_bonus, hdl,
-           NULL, NULL, NULL);
+           NULL, NULL);
 
        if (hdl->sa_bonus_tab) {
                sa_idx_tab_rele(hdl->sa_os, hdl->sa_bonus_tab);
@@ -1403,8 +1410,7 @@ sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
 
                error = sa_build_index(handle, SA_BONUS);
                newhandle = (hdl_type == SA_HDL_SHARED) ?
-                   dmu_buf_set_user_ie(db, handle,
-                   NULL, sa_evict) : NULL;
+                   dmu_buf_set_user_ie(db, handle, sa_evict) : NULL;
 
                if (newhandle != NULL) {
                        kmem_cache_free(sa_cache, handle);
@@ -1730,10 +1736,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
                        if (attr == newattr) {
                                if (length == 0)
                                        ++length_idx;
-                               if (action == SA_REMOVE) {
-                                       j++;
+                               if (action == SA_REMOVE)
                                        continue;
-                               }
                                ASSERT(length == 0);
                                ASSERT(action == SA_REPLACE);
                                SA_ADD_BULK_ATTR(attr_desc, j, attr,
@@ -1946,7 +1950,7 @@ void
 sa_update_user(sa_handle_t *newhdl, sa_handle_t *oldhdl)
 {
        (void) dmu_buf_update_user((dmu_buf_t *)newhdl->sa_bonus,
-           oldhdl, newhdl, NULL, sa_evict);
+           oldhdl, newhdl, sa_evict);
        oldhdl->sa_bonus = NULL;
 }