Print this page
3752 want more verifiable dbuf user eviction
Submitted by:   Justin Gibbs <justing@spectralogic.com>
Submitted by:   Will Andrews <willa@spectralogic.com>

@@ -239,16 +239,17 @@
         return (B_TRUE);
 }
 
 /* ARGSUSED */
 static void
-dsl_dataset_evict(dmu_buf_t *db, void *dsv)
+dsl_dataset_evict_impl(dsl_dataset_t *ds, boolean_t evict_deadlist)
 {
-        dsl_dataset_t *ds = dsv;
 
         ASSERT(ds->ds_owner == NULL);
 
+        ds->ds_dbuf = NULL;
+
         unique_remove(ds->ds_fsid_guid);
 
         if (ds->ds_objset != NULL)
                 dmu_objset_evict(ds->ds_objset);
 

@@ -256,11 +257,11 @@
                 dsl_dataset_rele(ds->ds_prev, ds);
                 ds->ds_prev = NULL;
         }
 
         bplist_destroy(&ds->ds_pending_deadlist);
-        if (ds->ds_phys->ds_deadlist_obj != 0)
+        if (evict_deadlist)
                 dsl_deadlist_close(&ds->ds_deadlist);
         if (ds->ds_dir)
                 dsl_dir_rele(ds->ds_dir, ds);
 
         ASSERT(!list_link_active(&ds->ds_synced_link));

@@ -270,10 +271,17 @@
         refcount_destroy(&ds->ds_longholds);
 
         kmem_free(ds, sizeof (dsl_dataset_t));
 }
 
+/* ARGSUSED */
+static void
+dsl_dataset_evict(dmu_buf_user_t *dbu)
+{
+        dsl_dataset_evict_impl((dsl_dataset_t *)dbu, B_TRUE);
+}
+
 int
 dsl_dataset_get_snapname(dsl_dataset_t *ds)
 {
         dsl_dataset_phys_t *headphys;
         int err;

@@ -357,18 +365,17 @@
         /* Make sure dsobj has the correct object type. */
         dmu_object_info_from_db(dbuf, &doi);
         if (doi.doi_type != DMU_OT_DSL_DATASET)
                 return (SET_ERROR(EINVAL));
 
-        ds = dmu_buf_get_user(dbuf);
+        ds = (dsl_dataset_t *)dmu_buf_get_user(dbuf);
         if (ds == NULL) {
                 dsl_dataset_t *winner = NULL;
 
                 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
                 ds->ds_dbuf = dbuf;
                 ds->ds_object = dsobj;
-                ds->ds_phys = dbuf->db_data;
 
                 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
                 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
                 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
                 refcount_create(&ds->ds_longholds);

@@ -424,12 +431,16 @@
                         }
                 } else {
                         ds->ds_reserved = ds->ds_quota = 0;
                 }
 
-                if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
-                    &ds->ds_phys, dsl_dataset_evict)) != NULL) {
+                dmu_buf_init_user(&ds->db_evict, dsl_dataset_evict);
+                if (err == 0)
+                        winner = (dsl_dataset_t *)
+                            dmu_buf_set_user_ie(dbuf, &ds->db_evict);
+
+                if (err || winner) {
                         bplist_destroy(&ds->ds_pending_deadlist);
                         dsl_deadlist_close(&ds->ds_deadlist);
                         if (ds->ds_prev)
                                 dsl_dataset_rele(ds->ds_prev, ds);
                         dsl_dir_rele(ds->ds_dir, ds);

@@ -630,11 +641,11 @@
         mutex_exit(&ds->ds_lock);
         dsl_dataset_long_rele(ds, tag);
         if (ds->ds_dbuf != NULL)
                 dsl_dataset_rele(ds, tag);
         else
-                dsl_dataset_evict(NULL, ds);
+                dsl_dataset_evict_impl(ds, B_FALSE);
 }
 
 boolean_t
 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
 {