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


 224         if (ds->ds_trysnap_txg >
 225             spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa))
 226                 trysnap = ds->ds_trysnap_txg;
 227         return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap));
 228 }
 229 
 230 boolean_t
 231 dsl_dataset_block_freeable(dsl_dataset_t *ds, const blkptr_t *bp,
 232     uint64_t blk_birth)
 233 {
 234         if (blk_birth <= dsl_dataset_prev_snap_txg(ds))
 235                 return (B_FALSE);
 236 
 237         ddt_prefetch(dsl_dataset_get_spa(ds), bp);
 238 
 239         return (B_TRUE);
 240 }
 241 
 242 /* ARGSUSED */
 243 static void
 244 dsl_dataset_evict(dmu_buf_t *db, void *dsv)
 245 {
 246         dsl_dataset_t *ds = dsv;
 247 
 248         ASSERT(ds->ds_owner == NULL);
 249 


 250         unique_remove(ds->ds_fsid_guid);
 251 
 252         if (ds->ds_objset != NULL)
 253                 dmu_objset_evict(ds->ds_objset);
 254 
 255         if (ds->ds_prev) {
 256                 dsl_dataset_rele(ds->ds_prev, ds);
 257                 ds->ds_prev = NULL;
 258         }
 259 
 260         bplist_destroy(&ds->ds_pending_deadlist);
 261         if (ds->ds_phys->ds_deadlist_obj != 0)
 262                 dsl_deadlist_close(&ds->ds_deadlist);
 263         if (ds->ds_dir)
 264                 dsl_dir_rele(ds->ds_dir, ds);
 265 
 266         ASSERT(!list_link_active(&ds->ds_synced_link));
 267 
 268         mutex_destroy(&ds->ds_lock);
 269         mutex_destroy(&ds->ds_opening_lock);
 270         refcount_destroy(&ds->ds_longholds);
 271 
 272         kmem_free(ds, sizeof (dsl_dataset_t));
 273 }
 274 







 275 int
 276 dsl_dataset_get_snapname(dsl_dataset_t *ds)
 277 {
 278         dsl_dataset_phys_t *headphys;
 279         int err;
 280         dmu_buf_t *headdbuf;
 281         dsl_pool_t *dp = ds->ds_dir->dd_pool;
 282         objset_t *mos = dp->dp_meta_objset;
 283 
 284         if (ds->ds_snapname[0])
 285                 return (0);
 286         if (ds->ds_phys->ds_next_snap_obj == 0)
 287                 return (0);
 288 
 289         err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
 290             FTAG, &headdbuf);
 291         if (err != 0)
 292                 return (err);
 293         headphys = headdbuf->db_data;
 294         err = zap_value_search(dp->dp_meta_objset,


 342 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
 343     dsl_dataset_t **dsp)
 344 {
 345         objset_t *mos = dp->dp_meta_objset;
 346         dmu_buf_t *dbuf;
 347         dsl_dataset_t *ds;
 348         int err;
 349         dmu_object_info_t doi;
 350 
 351         ASSERT(dsl_pool_config_held(dp));
 352 
 353         err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
 354         if (err != 0)
 355                 return (err);
 356 
 357         /* Make sure dsobj has the correct object type. */
 358         dmu_object_info_from_db(dbuf, &doi);
 359         if (doi.doi_type != DMU_OT_DSL_DATASET)
 360                 return (SET_ERROR(EINVAL));
 361 
 362         ds = dmu_buf_get_user(dbuf);
 363         if (ds == NULL) {
 364                 dsl_dataset_t *winner = NULL;
 365 
 366                 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
 367                 ds->ds_dbuf = dbuf;
 368                 ds->ds_object = dsobj;
 369                 ds->ds_phys = dbuf->db_data;
 370 
 371                 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
 372                 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
 373                 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
 374                 refcount_create(&ds->ds_longholds);
 375 
 376                 bplist_create(&ds->ds_pending_deadlist);
 377                 dsl_deadlist_open(&ds->ds_deadlist,
 378                     mos, ds->ds_phys->ds_deadlist_obj);
 379 
 380                 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
 381                     offsetof(dmu_sendarg_t, dsa_link));
 382 
 383                 if (err == 0) {
 384                         err = dsl_dir_hold_obj(dp,
 385                             ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
 386                 }
 387                 if (err != 0) {
 388                         mutex_destroy(&ds->ds_lock);
 389                         mutex_destroy(&ds->ds_opening_lock);


 409                                 err = zap_count(
 410                                     ds->ds_dir->dd_pool->dp_meta_objset,
 411                                     ds->ds_phys->ds_userrefs_obj,
 412                                     &ds->ds_userrefs);
 413                         }
 414                 }
 415 
 416                 if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
 417                         err = dsl_prop_get_int_ds(ds,
 418                             zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
 419                             &ds->ds_reserved);
 420                         if (err == 0) {
 421                                 err = dsl_prop_get_int_ds(ds,
 422                                     zfs_prop_to_name(ZFS_PROP_REFQUOTA),
 423                                     &ds->ds_quota);
 424                         }
 425                 } else {
 426                         ds->ds_reserved = ds->ds_quota = 0;
 427                 }
 428 
 429                 if (err != 0 || (winner = dmu_buf_set_user_ie(dbuf, ds,
 430                     &ds->ds_phys, dsl_dataset_evict)) != NULL) {




 431                         bplist_destroy(&ds->ds_pending_deadlist);
 432                         dsl_deadlist_close(&ds->ds_deadlist);
 433                         if (ds->ds_prev)
 434                                 dsl_dataset_rele(ds->ds_prev, ds);
 435                         dsl_dir_rele(ds->ds_dir, ds);
 436                         mutex_destroy(&ds->ds_lock);
 437                         mutex_destroy(&ds->ds_opening_lock);
 438                         refcount_destroy(&ds->ds_longholds);
 439                         kmem_free(ds, sizeof (dsl_dataset_t));
 440                         if (err != 0) {
 441                                 dmu_buf_rele(dbuf, tag);
 442                                 return (err);
 443                         }
 444                         ds = winner;
 445                 } else {
 446                         ds->ds_fsid_guid =
 447                             unique_insert(ds->ds_phys->ds_fsid_guid);
 448                 }
 449         }
 450         ASSERT3P(ds->ds_dbuf, ==, dbuf);


 615 }
 616 
 617 void
 618 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
 619 {
 620         dmu_buf_rele(ds->ds_dbuf, tag);
 621 }
 622 
 623 void
 624 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
 625 {
 626         ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
 627 
 628         mutex_enter(&ds->ds_lock);
 629         ds->ds_owner = NULL;
 630         mutex_exit(&ds->ds_lock);
 631         dsl_dataset_long_rele(ds, tag);
 632         if (ds->ds_dbuf != NULL)
 633                 dsl_dataset_rele(ds, tag);
 634         else
 635                 dsl_dataset_evict(NULL, ds);
 636 }
 637 
 638 boolean_t
 639 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
 640 {
 641         boolean_t gotit = FALSE;
 642 
 643         mutex_enter(&ds->ds_lock);
 644         if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
 645                 ds->ds_owner = tag;
 646                 dsl_dataset_long_hold(ds, tag);
 647                 gotit = TRUE;
 648         }
 649         mutex_exit(&ds->ds_lock);
 650         return (gotit);
 651 }
 652 
 653 uint64_t
 654 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
 655     uint64_t flags, dmu_tx_t *tx)




 224         if (ds->ds_trysnap_txg >
 225             spa_last_synced_txg(ds->ds_dir->dd_pool->dp_spa))
 226                 trysnap = ds->ds_trysnap_txg;
 227         return (MAX(ds->ds_phys->ds_prev_snap_txg, trysnap));
 228 }
 229 
 230 boolean_t
 231 dsl_dataset_block_freeable(dsl_dataset_t *ds, const blkptr_t *bp,
 232     uint64_t blk_birth)
 233 {
 234         if (blk_birth <= dsl_dataset_prev_snap_txg(ds))
 235                 return (B_FALSE);
 236 
 237         ddt_prefetch(dsl_dataset_get_spa(ds), bp);
 238 
 239         return (B_TRUE);
 240 }
 241 
 242 /* ARGSUSED */
 243 static void
 244 dsl_dataset_evict_impl(dsl_dataset_t *ds, boolean_t evict_deadlist)
 245 {

 246 
 247         ASSERT(ds->ds_owner == NULL);
 248 
 249         ds->ds_dbuf = NULL;
 250 
 251         unique_remove(ds->ds_fsid_guid);
 252 
 253         if (ds->ds_objset != NULL)
 254                 dmu_objset_evict(ds->ds_objset);
 255 
 256         if (ds->ds_prev) {
 257                 dsl_dataset_rele(ds->ds_prev, ds);
 258                 ds->ds_prev = NULL;
 259         }
 260 
 261         bplist_destroy(&ds->ds_pending_deadlist);
 262         if (evict_deadlist)
 263                 dsl_deadlist_close(&ds->ds_deadlist);
 264         if (ds->ds_dir)
 265                 dsl_dir_rele(ds->ds_dir, ds);
 266 
 267         ASSERT(!list_link_active(&ds->ds_synced_link));
 268 
 269         mutex_destroy(&ds->ds_lock);
 270         mutex_destroy(&ds->ds_opening_lock);
 271         refcount_destroy(&ds->ds_longholds);
 272 
 273         kmem_free(ds, sizeof (dsl_dataset_t));
 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 
 283 int
 284 dsl_dataset_get_snapname(dsl_dataset_t *ds)
 285 {
 286         dsl_dataset_phys_t *headphys;
 287         int err;
 288         dmu_buf_t *headdbuf;
 289         dsl_pool_t *dp = ds->ds_dir->dd_pool;
 290         objset_t *mos = dp->dp_meta_objset;
 291 
 292         if (ds->ds_snapname[0])
 293                 return (0);
 294         if (ds->ds_phys->ds_next_snap_obj == 0)
 295                 return (0);
 296 
 297         err = dmu_bonus_hold(mos, ds->ds_dir->dd_phys->dd_head_dataset_obj,
 298             FTAG, &headdbuf);
 299         if (err != 0)
 300                 return (err);
 301         headphys = headdbuf->db_data;
 302         err = zap_value_search(dp->dp_meta_objset,


 350 dsl_dataset_hold_obj(dsl_pool_t *dp, uint64_t dsobj, void *tag,
 351     dsl_dataset_t **dsp)
 352 {
 353         objset_t *mos = dp->dp_meta_objset;
 354         dmu_buf_t *dbuf;
 355         dsl_dataset_t *ds;
 356         int err;
 357         dmu_object_info_t doi;
 358 
 359         ASSERT(dsl_pool_config_held(dp));
 360 
 361         err = dmu_bonus_hold(mos, dsobj, tag, &dbuf);
 362         if (err != 0)
 363                 return (err);
 364 
 365         /* Make sure dsobj has the correct object type. */
 366         dmu_object_info_from_db(dbuf, &doi);
 367         if (doi.doi_type != DMU_OT_DSL_DATASET)
 368                 return (SET_ERROR(EINVAL));
 369 
 370         ds = (dsl_dataset_t *)dmu_buf_get_user(dbuf);
 371         if (ds == NULL) {
 372                 dsl_dataset_t *winner = NULL;
 373 
 374                 ds = kmem_zalloc(sizeof (dsl_dataset_t), KM_SLEEP);
 375                 ds->ds_dbuf = dbuf;
 376                 ds->ds_object = dsobj;

 377 
 378                 mutex_init(&ds->ds_lock, NULL, MUTEX_DEFAULT, NULL);
 379                 mutex_init(&ds->ds_opening_lock, NULL, MUTEX_DEFAULT, NULL);
 380                 mutex_init(&ds->ds_sendstream_lock, NULL, MUTEX_DEFAULT, NULL);
 381                 refcount_create(&ds->ds_longholds);
 382 
 383                 bplist_create(&ds->ds_pending_deadlist);
 384                 dsl_deadlist_open(&ds->ds_deadlist,
 385                     mos, ds->ds_phys->ds_deadlist_obj);
 386 
 387                 list_create(&ds->ds_sendstreams, sizeof (dmu_sendarg_t),
 388                     offsetof(dmu_sendarg_t, dsa_link));
 389 
 390                 if (err == 0) {
 391                         err = dsl_dir_hold_obj(dp,
 392                             ds->ds_phys->ds_dir_obj, NULL, ds, &ds->ds_dir);
 393                 }
 394                 if (err != 0) {
 395                         mutex_destroy(&ds->ds_lock);
 396                         mutex_destroy(&ds->ds_opening_lock);


 416                                 err = zap_count(
 417                                     ds->ds_dir->dd_pool->dp_meta_objset,
 418                                     ds->ds_phys->ds_userrefs_obj,
 419                                     &ds->ds_userrefs);
 420                         }
 421                 }
 422 
 423                 if (err == 0 && !dsl_dataset_is_snapshot(ds)) {
 424                         err = dsl_prop_get_int_ds(ds,
 425                             zfs_prop_to_name(ZFS_PROP_REFRESERVATION),
 426                             &ds->ds_reserved);
 427                         if (err == 0) {
 428                                 err = dsl_prop_get_int_ds(ds,
 429                                     zfs_prop_to_name(ZFS_PROP_REFQUOTA),
 430                                     &ds->ds_quota);
 431                         }
 432                 } else {
 433                         ds->ds_reserved = ds->ds_quota = 0;
 434                 }
 435 
 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) {
 442                         bplist_destroy(&ds->ds_pending_deadlist);
 443                         dsl_deadlist_close(&ds->ds_deadlist);
 444                         if (ds->ds_prev)
 445                                 dsl_dataset_rele(ds->ds_prev, ds);
 446                         dsl_dir_rele(ds->ds_dir, ds);
 447                         mutex_destroy(&ds->ds_lock);
 448                         mutex_destroy(&ds->ds_opening_lock);
 449                         refcount_destroy(&ds->ds_longholds);
 450                         kmem_free(ds, sizeof (dsl_dataset_t));
 451                         if (err != 0) {
 452                                 dmu_buf_rele(dbuf, tag);
 453                                 return (err);
 454                         }
 455                         ds = winner;
 456                 } else {
 457                         ds->ds_fsid_guid =
 458                             unique_insert(ds->ds_phys->ds_fsid_guid);
 459                 }
 460         }
 461         ASSERT3P(ds->ds_dbuf, ==, dbuf);


 626 }
 627 
 628 void
 629 dsl_dataset_rele(dsl_dataset_t *ds, void *tag)
 630 {
 631         dmu_buf_rele(ds->ds_dbuf, tag);
 632 }
 633 
 634 void
 635 dsl_dataset_disown(dsl_dataset_t *ds, void *tag)
 636 {
 637         ASSERT(ds->ds_owner == tag && ds->ds_dbuf != NULL);
 638 
 639         mutex_enter(&ds->ds_lock);
 640         ds->ds_owner = NULL;
 641         mutex_exit(&ds->ds_lock);
 642         dsl_dataset_long_rele(ds, tag);
 643         if (ds->ds_dbuf != NULL)
 644                 dsl_dataset_rele(ds, tag);
 645         else
 646                 dsl_dataset_evict_impl(ds, B_FALSE);
 647 }
 648 
 649 boolean_t
 650 dsl_dataset_tryown(dsl_dataset_t *ds, void *tag)
 651 {
 652         boolean_t gotit = FALSE;
 653 
 654         mutex_enter(&ds->ds_lock);
 655         if (ds->ds_owner == NULL && !DS_IS_INCONSISTENT(ds)) {
 656                 ds->ds_owner = tag;
 657                 dsl_dataset_long_hold(ds, tag);
 658                 gotit = TRUE;
 659         }
 660         mutex_exit(&ds->ds_lock);
 661         return (gotit);
 662 }
 663 
 664 uint64_t
 665 dsl_dataset_create_sync_dd(dsl_dir_t *dd, dsl_dataset_t *origin,
 666     uint64_t flags, dmu_tx_t *tx)