Annotate KM_PUSHPAGE call paths with PF_NOFS
[zfs.git] / module / zfs / sa.c
index bcef7d1..a26e5eb 100644 (file)
@@ -1334,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);
@@ -1760,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);
@@ -1774,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);
 }
 
@@ -1994,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);