Add sa_spill_rele() interface
[zfs.git] / module / zfs / sa.c
index d5c985b..32b4c5b 100644 (file)
@@ -201,6 +201,7 @@ sa_attr_type_t sa_dummy_zpl_layout[] = { 0 };
 
 static int sa_legacy_attr_count = 16;
 static kmem_cache_t *sa_cache = NULL;
+static kmem_cache_t *spill_cache = NULL;
 
 /*ARGSUSED*/
 static int
@@ -232,6 +233,8 @@ sa_cache_init(void)
        sa_cache = kmem_cache_create("sa_cache",
            sizeof (sa_handle_t), 0, sa_cache_constructor,
            sa_cache_destructor, NULL, NULL, NULL, 0);
+       spill_cache = kmem_cache_create("spill_cache",
+           SPA_MAXBLOCKSIZE, 0, NULL, NULL, NULL, NULL, NULL, 0);
 }
 
 void
@@ -239,6 +242,21 @@ sa_cache_fini(void)
 {
        if (sa_cache)
                kmem_cache_destroy(sa_cache);
+
+       if (spill_cache)
+               kmem_cache_destroy(spill_cache);
+}
+
+void *
+sa_spill_alloc(int flags)
+{
+       return kmem_cache_alloc(spill_cache, flags);
+}
+
+void
+sa_spill_free(void *obj)
+{
+       kmem_cache_free(spill_cache, obj);
 }
 
 static int
@@ -398,6 +416,8 @@ sa_attr_op(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count,
                        if (error)
                                return (error);
                        break;
+               default:
+                       break;
                }
        }
        return (error);
@@ -605,14 +625,14 @@ sa_find_sizes(sa_os_t *sa, sa_bulk_attr_t *attr_desc, int attr_count,
                 * 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;
        }
@@ -640,7 +660,7 @@ sa_build_layouts(sa_handle_t *hdl, sa_bulk_attr_t *attr_desc, int attr_count,
        int buf_space;
        sa_attr_type_t *attrs, *attrs_start;
        int i, lot_count;
-       int hdrsize, spillhdrsize;
+       int hdrsize, spillhdrsize = 0;
        int used;
        dmu_object_type_t bonustype;
        sa_lot_t *lot;
@@ -811,7 +831,7 @@ sa_attr_table_setup(objset_t *os, sa_attr_reg_t *reg_attrs, int count)
 {
        sa_os_t *sa = os->os_sa;
        uint64_t sa_attr_count = 0;
-       uint64_t sa_reg_count;
+       uint64_t sa_reg_count = 0;
        int error = 0;
        uint64_t attr_value;
        sa_attr_table_t *tb;
@@ -1103,16 +1123,16 @@ sa_tear_down(objset_t *os)
        sa_free_attr_table(sa);
 
        cookie = NULL;
-       while (layout = avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie)) {
+       while ((layout = avl_destroy_nodes(&sa->sa_layout_hash_tree, &cookie))){
                sa_idx_tab_t *tab;
-               while (tab = list_head(&layout->lot_idx_tab)) {
+               while ((tab = list_head(&layout->lot_idx_tab))) {
                        ASSERT(refcount_count(&tab->sa_refcount));
                        sa_idx_tab_rele(os, tab);
                }
        }
 
        cookie = NULL;
-       while (layout = avl_destroy_nodes(&sa->sa_layout_num_tree, &cookie)) {
+       while ((layout = avl_destroy_nodes(&sa->sa_layout_num_tree, &cookie))){
                kmem_free(layout->lot_attrs,
                    sizeof (sa_attr_type_t) * layout->lot_attr_count);
                kmem_free(layout, sizeof (sa_lot_t));
@@ -1204,9 +1224,9 @@ sa_byteswap(sa_handle_t *hdl, sa_buf_type_t buftype)
 {
        sa_hdr_phys_t *sa_hdr_phys = SA_GET_HDR(hdl, buftype);
        dmu_buf_impl_t *db;
-       sa_os_t *sa = hdl->sa_os->os_sa;
        int num_lengths = 1;
        int i;
+       ASSERTV(sa_os_t *sa = hdl->sa_os->os_sa);
 
        ASSERT(MUTEX_HELD(&sa->sa_lock));
        if (sa_hdr_phys->sa_magic == SA_MAGIC)
@@ -1307,13 +1327,26 @@ sa_idx_tab_rele(objset_t *os, void *arg)
 static void
 sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab)
 {
-       sa_os_t *sa = os->os_sa;
+       ASSERTV(sa_os_t *sa = os->os_sa);
 
        ASSERT(MUTEX_HELD(&sa->sa_lock));
        (void) refcount_add(&idx_tab->sa_refcount, NULL);
 }
 
 void
+sa_spill_rele(sa_handle_t *hdl)
+{
+       mutex_enter(&hdl->sa_lock);
+       if (hdl->sa_spill) {
+               sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab);
+               dmu_buf_rele(hdl->sa_spill, NULL);
+               hdl->sa_spill = NULL;
+               hdl->sa_spill_tab = NULL;
+       }
+       mutex_exit(&hdl->sa_lock);
+}
+
+void
 sa_handle_destroy(sa_handle_t *hdl)
 {
        mutex_enter(&hdl->sa_lock);
@@ -1343,10 +1376,10 @@ sa_handle_get_from_db(objset_t *os, dmu_buf_t *db, void *userp,
     sa_handle_type_t hdl_type, sa_handle_t **handlepp)
 {
        int error = 0;
-       dmu_object_info_t doi;
        sa_handle_t *handle;
-
 #ifdef ZFS_DEBUG
+       dmu_object_info_t doi;
+
        dmu_object_info_from_db(db, &doi);
        ASSERT(doi.doi_bonus_type == DMU_OT_SA ||
            doi.doi_bonus_type == DMU_OT_ZNODE);
@@ -1385,7 +1418,7 @@ sa_handle_get(objset_t *objset, uint64_t objid, void *userp,
        dmu_buf_t *db;
        int error;
 
-       if (error = dmu_bonus_hold(objset, objid, NULL, &db))
+       if ((error = dmu_bonus_hold(objset, objid, NULL, &db)))
                return (error);
 
        return (sa_handle_get_from_db(objset, db, userp, hdl_type,
@@ -1450,7 +1483,6 @@ sa_lookup_uio(sa_handle_t *hdl, sa_attr_type_t attr, uio_t *uio)
        }
        mutex_exit(&hdl->sa_lock);
        return (error);
-
 }
 #endif
 
@@ -1545,12 +1577,12 @@ sa_attr_register_sync(sa_handle_t *hdl, dmu_tx_t *tx)
 
        mutex_enter(&sa->sa_lock);
 
-       if (!sa->sa_need_attr_registration || sa->sa_master_obj == NULL) {
+       if (!sa->sa_need_attr_registration || sa->sa_master_obj == 0) {
                mutex_exit(&sa->sa_lock);
                return;
        }
 
-       if (sa->sa_reg_attr_obj == NULL) {
+       if (sa->sa_reg_attr_obj == 0) {
                sa->sa_reg_attr_obj = zap_create(hdl->sa_os,
                    DMU_OT_SA_ATTR_REGISTRATION, DMU_OT_NONE, 0, tx);
                VERIFY(zap_add(hdl->sa_os, sa->sa_master_obj,
@@ -1617,7 +1649,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
        sa_bulk_attr_t *attr_desc;
        void *old_data[2];
        int bonus_attr_count = 0;
-       int bonus_data_size, spill_data_size;
+       int bonus_data_size = 0;
        int spill_attr_count = 0;
        int error;
        uint16_t length;
@@ -1647,8 +1679,8 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
        /* Bring spill buffer online if it isn't currently */
 
        if ((error = sa_get_spill(hdl)) == 0) {
-               spill_data_size = hdl->sa_spill->db_size;
-               old_data[1] = kmem_alloc(spill_data_size, KM_SLEEP);
+               ASSERT3U(hdl->sa_spill->db_size, <=, SPA_MAXBLOCKSIZE);
+               old_data[1] = sa_spill_alloc(KM_SLEEP);
                bcopy(hdl->sa_spill->db_data, old_data[1],
                    hdl->sa_spill->db_size);
                spill_attr_count =
@@ -1728,7 +1760,7 @@ sa_modify_attrs(sa_handle_t *hdl, sa_attr_type_t newattr,
        if (old_data[0])
                kmem_free(old_data[0], bonus_data_size);
        if (old_data[1])
-               kmem_free(old_data[1], spill_data_size);
+               sa_spill_free(old_data[1]);
        kmem_free(attr_desc, sizeof (sa_bulk_attr_t) * attr_count);
 
        return (error);
@@ -1968,3 +2000,41 @@ sa_handle_unlock(sa_handle_t *hdl)
        ASSERT(hdl);
        mutex_exit(&hdl->sa_lock);
 }
+
+#ifdef _KERNEL
+EXPORT_SYMBOL(sa_handle_get);
+EXPORT_SYMBOL(sa_handle_get_from_db);
+EXPORT_SYMBOL(sa_handle_destroy);
+EXPORT_SYMBOL(sa_buf_hold);
+EXPORT_SYMBOL(sa_buf_rele);
+EXPORT_SYMBOL(sa_spill_rele);
+EXPORT_SYMBOL(sa_lookup);
+EXPORT_SYMBOL(sa_update);
+EXPORT_SYMBOL(sa_remove);
+EXPORT_SYMBOL(sa_bulk_lookup);
+EXPORT_SYMBOL(sa_bulk_lookup_locked);
+EXPORT_SYMBOL(sa_bulk_update);
+EXPORT_SYMBOL(sa_size);
+EXPORT_SYMBOL(sa_update_from_cb);
+EXPORT_SYMBOL(sa_object_info);
+EXPORT_SYMBOL(sa_object_size);
+EXPORT_SYMBOL(sa_update_user);
+EXPORT_SYMBOL(sa_get_userdata);
+EXPORT_SYMBOL(sa_set_userp);
+EXPORT_SYMBOL(sa_get_db);
+EXPORT_SYMBOL(sa_handle_object);
+EXPORT_SYMBOL(sa_register_update_callback);
+EXPORT_SYMBOL(sa_setup);
+EXPORT_SYMBOL(sa_replace_all_by_template);
+EXPORT_SYMBOL(sa_replace_all_by_template_locked);
+EXPORT_SYMBOL(sa_enabled);
+EXPORT_SYMBOL(sa_cache_init);
+EXPORT_SYMBOL(sa_cache_fini);
+EXPORT_SYMBOL(sa_spill_alloc);
+EXPORT_SYMBOL(sa_spill_free);
+EXPORT_SYMBOL(sa_set_sa_object);
+EXPORT_SYMBOL(sa_hdrsize);
+EXPORT_SYMBOL(sa_handle_lock);
+EXPORT_SYMBOL(sa_handle_unlock);
+EXPORT_SYMBOL(sa_lookup_uio);
+#endif /* _KERNEL */