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

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/zfs/dsl_dataset.c
          +++ new/usr/src/uts/common/fs/zfs/dsl_dataset.c
↓ open down ↓ 233 lines elided ↑ open up ↑
 234  234          if (blk_birth <= dsl_dataset_prev_snap_txg(ds))
 235  235                  return (B_FALSE);
 236  236  
 237  237          ddt_prefetch(dsl_dataset_get_spa(ds), bp);
 238  238  
 239  239          return (B_TRUE);
 240  240  }
 241  241  
 242  242  /* ARGSUSED */
 243  243  static void
 244      -dsl_dataset_evict(dmu_buf_t *db, void *dsv)
      244 +dsl_dataset_evict_impl(dsl_dataset_t *ds, boolean_t evict_deadlist)
 245  245  {
 246      -        dsl_dataset_t *ds = dsv;
 247  246  
 248  247          ASSERT(ds->ds_owner == NULL);
 249  248  
      249 +        ds->ds_dbuf = NULL;
      250 +
 250  251          unique_remove(ds->ds_fsid_guid);
 251  252  
 252  253          if (ds->ds_objset != NULL)
 253  254                  dmu_objset_evict(ds->ds_objset);
 254  255  
 255  256          if (ds->ds_prev) {
 256  257                  dsl_dataset_rele(ds->ds_prev, ds);
 257  258                  ds->ds_prev = NULL;
 258  259          }
 259  260  
 260  261          bplist_destroy(&ds->ds_pending_deadlist);
 261      -        if (ds->ds_phys->ds_deadlist_obj != 0)
      262 +        if (evict_deadlist)
 262  263                  dsl_deadlist_close(&ds->ds_deadlist);
 263  264          if (ds->ds_dir)
 264  265                  dsl_dir_rele(ds->ds_dir, ds);
 265  266  
 266  267          ASSERT(!list_link_active(&ds->ds_synced_link));
 267  268  
 268  269          mutex_destroy(&ds->ds_lock);
 269  270          mutex_destroy(&ds->ds_opening_lock);
 270  271          refcount_destroy(&ds->ds_longholds);
 271  272  
 272  273          kmem_free(ds, sizeof (dsl_dataset_t));
 273  274  }
 274  275  
      276 +/* ARGSUSED */
      277 +static void
      278 +dsl_dataset_evict(dmu_buf_user_t *dbu)
      279 +{
      280 +        dsl_dataset_evict_impl((dsl_dataset_t *)dbu, B_TRUE);
      281 +}
      282 +
 275  283  int
 276  284  dsl_dataset_get_snapname(dsl_dataset_t *ds)
 277  285  {
 278  286          dsl_dataset_phys_t *headphys;
 279  287          int err;
 280  288          dmu_buf_t *headdbuf;
 281  289          dsl_pool_t *dp = ds->ds_dir->dd_pool;
 282  290          objset_t *mos = dp->dp_meta_objset;
 283  291  
 284  292          if (ds->ds_snapname[0])
↓ open down ↓ 67 lines elided ↑ open up ↑
 352  360  
 353  361          err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
 354  362          if (err != 0)
 355  363                  return (err);
 356  364  
 357  365          /* Make sure dsobj has the correct object type. */
 358  366          dmu_object_info_from_db(dbuf, &doi);
 359  367          if (doi.doi_type != DMU_OT_DSL_DATASET)
 360  368                  return (SET_ERROR(EINVAL));
 361  369  
 362      -        ds = dmu_buf_get_user(dbuf);
      370 +        ds = (dsl_dataset_t *)dmu_buf_get_user(dbuf);
 363  371          if (ds == NULL) {
 364  372                  dsl_dataset_t *winner = NULL;
 365  373  
 366  374                  ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
 367  375                  ds->ds_dbuf = dbuf;
 368  376                  ds->ds_object = dsobj;
 369      -                ds->ds_phys = dbuf->db_data;
 370  377  
 371  378                  mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
 372  379                  mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
 373  380                  mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
 374  381                  refcount_create(&ds->ds_longholds);
 375  382  
 376  383                  bplist_create(&ds->ds_pending_deadlist);
 377  384                  dsl_deadlist_open(&ds->ds_deadlist,
 378  385                      mos, ds->ds_phys->ds_deadlist_obj);
 379  386  
↓ open down ↓ 39 lines elided ↑ open up ↑
 419  426                              &ds->ds_reserved);
 420  427                          if (err == 0) {
 421  428                                  err = dsl_prop_get_int_ds(ds,
 422  429                                      zfs_prop_to_name(ZFS_PROP_REFQUOTA),
 423  430                                      &ds->ds_quota);
 424  431                          }
 425  432                  } else {
 426  433                          ds->ds_reserved = ds->ds_quota = 0;
 427  434                  }
 428  435  
 429      -                if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
 430      -                    &ds->ds_phys, dsl_dataset_evict)) != NULL) {
      436 +                dmu_buf_init_user(&ds->db_evict, dsl_dataset_evict);
      437 +                if (err == 0)
      438 +                        winner = (dsl_dataset_t *)
      439 +                            dmu_buf_set_user_ie(dbuf, &ds->db_evict);
      440 +
      441 +                if (err || winner) {
 431  442                          bplist_destroy(&ds->ds_pending_deadlist);
 432  443                          dsl_deadlist_close(&ds->ds_deadlist);
 433  444                          if (ds->ds_prev)
 434  445                                  dsl_dataset_rele(ds->ds_prev, ds);
 435  446                          dsl_dir_rele(ds->ds_dir, ds);
 436  447                          mutex_destroy(&ds->ds_lock);
 437  448                          mutex_destroy(&ds->ds_opening_lock);
 438  449                          refcount_destroy(&ds->ds_longholds);
 439  450                          kmem_free(ds, sizeof (dsl_dataset_t));
 440  451                          if (err != 0) {
↓ open down ↓ 184 lines elided ↑ open up ↑
 625  636  {
 626  637          ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
 627  638  
 628  639          mutex_enter(&ds->ds_lock);
 629  640          ds->ds_owner = NULL;
 630  641          mutex_exit(&ds->ds_lock);
 631  642          dsl_dataset_long_rele(ds, tag);
 632  643          if (ds->ds_dbuf != NULL)
 633  644                  dsl_dataset_rele(ds, tag);
 634  645          else
 635      -                dsl_dataset_evict(NULL, ds);
      646 +                dsl_dataset_evict_impl(ds, B_FALSE);
 636  647  }
 637  648  
 638  649  boolean_t
 639  650  dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
 640  651  {
 641  652          boolean_t gotit = FALSE;
 642  653  
 643  654          mutex_enter(&ds->ds_lock);
 644  655          if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
 645  656                  ds->ds_owner = tag;
↓ open down ↓ 2281 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX