X-Git-Url: https://git.camperquake.de/gitweb.cgi?a=blobdiff_plain;f=module%2Fzfs%2Fsa.c;h=a26e5ebdd6a5910b21d2356b3d8f93822b5a950a;hb=8630650a8d9cfba379a5b73bd95e903d577e0d8d;hp=4278ed7e4e509bc22a9b1e475632301bdd066c81;hpb=c47516762758c989a443c0a6a9e38ae8fb46e6f1;p=zfs.git diff --git a/module/zfs/sa.c b/module/zfs/sa.c index 4278ed7..a26e5eb 100644 --- a/module/zfs/sa.c +++ b/module/zfs/sa.c @@ -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 @@ -1316,6 +1334,19 @@ sa_idx_tab_hold(objset_t *os, sa_idx_tab_t *idx_tab) } 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); @@ -1618,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 = 0, spill_data_size = 0; + int bonus_data_size = 0; int spill_attr_count = 0; int error; uint16_t length; @@ -1648,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 = @@ -1729,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); @@ -1742,12 +1773,14 @@ sa_bulk_update_impl(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count, int error; sa_os_t *sa = hdl->sa_os->os_sa; dmu_object_type_t bonustype; - - bonustype = SA_BONUSTYPE_FROM_DB(SA_GET_DB(hdl, SA_BONUS)); + dmu_buf_t *saved_spill; ASSERT(hdl); ASSERT(MUTEX_HELD(&hdl->sa_lock)); + bonustype = SA_BONUSTYPE_FROM_DB(SA_GET_DB(hdl, SA_BONUS)); + saved_spill = hdl->sa_spill; + /* sync out registration table if necessary */ if (sa->sa_need_attr_registration) sa_attr_register_sync(hdl, tx); @@ -1756,6 +1789,24 @@ sa_bulk_update_impl(sa_handle_t *hdl, sa_bulk_attr_t *bulk, int count, if (error == 0 && !IS_SA_BONUSTYPE(bonustype) && sa->sa_update_cb) sa->sa_update_cb(hdl, tx); + /* + * If saved_spill is NULL and current sa_spill is not NULL that + * means we increased the refcount of the spill buffer through + * sa_get_spill() or dmu_spill_hold_by_dnode(). Therefore we + * must release the hold before calling dmu_tx_commit() to avoid + * making a copy of this buffer in dbuf_sync_leaf() due to the + * reference count now being greater than 1. + */ + if (!saved_spill && hdl->sa_spill) { + if (hdl->sa_spill_tab) { + sa_idx_tab_rele(hdl->sa_os, hdl->sa_spill_tab); + hdl->sa_spill_tab = NULL; + } + + dmu_buf_rele((dmu_buf_t *)hdl->sa_spill, NULL); + hdl->sa_spill = NULL; + } + return (error); } @@ -1976,6 +2027,7 @@ 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); @@ -1998,6 +2050,8 @@ 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);