815 VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
816 dsl_dataset_snapshot_sync_impl(ds, ORIGIN_DIR_NAME, tx);
817 VERIFY0(dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj,
818 dp, &dp->dp_origin_snap));
819 dsl_dataset_rele(ds, FTAG);
820 }
821
822 taskq_t *
823 dsl_pool_vnrele_taskq(dsl_pool_t *dp)
824 {
825 return (dp->dp_vnrele_taskq);
826 }
827
828 /*
829 * Walk through the pool-wide zap object of temporary snapshot user holds
830 * and release them.
831 */
832 void
833 dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp)
834 {
835 zap_attribute_t za;
836 zap_cursor_t zc;
837 objset_t *mos = dp->dp_meta_objset;
838 uint64_t zapobj = dp->dp_tmp_userrefs_obj;
839
840 if (zapobj == 0)
841 return;
842 ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
843
844 for (zap_cursor_init(&zc, mos, zapobj);
845 zap_cursor_retrieve(&zc, &za) == 0;
846 zap_cursor_advance(&zc)) {
847 char *htag;
848 uint64_t dsobj;
849
850 htag = strchr(za.za_name, '-');
851 *htag = '\0';
852 ++htag;
853 dsobj = strtonum(za.za_name, NULL);
854 dsl_dataset_user_release_tmp(dp, dsobj, htag);
855 }
856 zap_cursor_fini(&zc);
857 }
858
859 /*
860 * Create the pool-wide zap object for storing temporary snapshot holds.
861 */
862 void
863 dsl_pool_user_hold_create_obj(dsl_pool_t *dp, dmu_tx_t *tx)
864 {
865 objset_t *mos = dp->dp_meta_objset;
866
867 ASSERT(dp->dp_tmp_userrefs_obj == 0);
868 ASSERT(dmu_tx_is_syncing(tx));
869
870 dp->dp_tmp_userrefs_obj = zap_create_link(mos, DMU_OT_USERREFS,
871 DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_TMP_USERREFS, tx);
872 }
873
874 static int
875 dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
|
815 VERIFY0(dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds));
816 dsl_dataset_snapshot_sync_impl(ds, ORIGIN_DIR_NAME, tx);
817 VERIFY0(dsl_dataset_hold_obj(dp, ds->ds_phys->ds_prev_snap_obj,
818 dp, &dp->dp_origin_snap));
819 dsl_dataset_rele(ds, FTAG);
820 }
821
822 taskq_t *
823 dsl_pool_vnrele_taskq(dsl_pool_t *dp)
824 {
825 return (dp->dp_vnrele_taskq);
826 }
827
828 /*
829 * Walk through the pool-wide zap object of temporary snapshot user holds
830 * and release them.
831 */
832 void
833 dsl_pool_clean_tmp_userrefs(dsl_pool_t *dp)
834 {
835 char *htag;
836 zap_attribute_t za;
837 zap_cursor_t zc;
838 objset_t *mos = dp->dp_meta_objset;
839 uint64_t zapobj = dp->dp_tmp_userrefs_obj;
840 uint64_t dsobj;
841 nvlist_t *holds, *tags;
842 dsl_dataset_t *ds;
843 char name[MAXNAMELEN];
844
845 if (zapobj == 0)
846 return;
847 ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
848
849 holds = fnvlist_alloc();
850
851 dsl_pool_config_enter(dp, FTAG);
852 for (zap_cursor_init(&zc, mos, zapobj);
853 zap_cursor_retrieve(&zc, &za) == 0;
854 zap_cursor_advance(&zc)) {
855 htag = strchr(za.za_name, '-');
856 *htag = '\0';
857 ++htag;
858 dsobj = strtonum(za.za_name, NULL);
859 if (dsl_dataset_hold_obj(dp, dsobj, FTAG, &ds) == 0) {
860 dsl_dataset_name(ds, name);
861 if (nvlist_lookup_nvlist(holds, name, &tags) != 0) {
862 tags = fnvlist_alloc();
863 fnvlist_add_boolean(tags, htag);
864 fnvlist_add_nvlist(holds, name, tags);
865 fnvlist_free(tags);
866 } else {
867 fnvlist_add_boolean(tags, htag);
868 }
869 dsl_dataset_rele(ds, FTAG);
870 }
871 }
872 dsl_pool_config_exit(dp, FTAG);
873 dsl_dataset_user_release(holds, NULL);
874 fnvlist_free(holds);
875 zap_cursor_fini(&zc);
876 }
877
878 /*
879 * Create the pool-wide zap object for storing temporary snapshot holds.
880 */
881 void
882 dsl_pool_user_hold_create_obj(dsl_pool_t *dp, dmu_tx_t *tx)
883 {
884 objset_t *mos = dp->dp_meta_objset;
885
886 ASSERT(dp->dp_tmp_userrefs_obj == 0);
887 ASSERT(dmu_tx_is_syncing(tx));
888
889 dp->dp_tmp_userrefs_obj = zap_create_link(mos, DMU_OT_USERREFS,
890 DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_TMP_USERREFS, tx);
891 }
892
893 static int
894 dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
|