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,
|
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 nvlist_t *holds;
840
841 if (zapobj == 0)
842 return;
843 ASSERT(spa_version(dp->dp_spa) >= SPA_VERSION_USERREFS);
844
845 holds = fnvlist_alloc();
846
847 for (zap_cursor_init(&zc, mos, zapobj);
848 zap_cursor_retrieve(&zc, &za) == 0;
849 zap_cursor_advance(&zc)) {
850 char *htag;
851 uint64_t dsobj;
852 nvlist_t *tags;
853
854 htag = strchr(za.za_name, '-');
855 *htag = '\0';
856 ++htag;
857 if (nvlist_lookup_nvlist(holds, za.za_name, &tags) != 0) {
858 tags = fnvlist_alloc();
859 fnvlist_add_boolean(tags, htag);
860 fnvlist_add_nvlist(holds, za.za_name, tags);
861 fnvlist_free(tags);
862 } else {
863 fnvlist_add_boolean(tags, htag);
864 }
865 }
866 dsl_dataset_user_release_tmp(dp, holds);
867 fnvlist_free(holds);
868 zap_cursor_fini(&zc);
869 }
870
871 /*
872 * Create the pool-wide zap object for storing temporary snapshot holds.
873 */
874 void
875 dsl_pool_user_hold_create_obj(dsl_pool_t *dp, dmu_tx_t *tx)
876 {
877 objset_t *mos = dp->dp_meta_objset;
878
879 ASSERT(dp->dp_tmp_userrefs_obj == 0);
880 ASSERT(dmu_tx_is_syncing(tx));
881
882 dp->dp_tmp_userrefs_obj = zap_create_link(mos, DMU_OT_USERREFS,
883 DMU_POOL_DIRECTORY_OBJECT, DMU_POOL_TMP_USERREFS, tx);
884 }
885
886 static int
887 dsl_pool_user_hold_rele_impl(dsl_pool_t *dp, uint64_t dsobj,
|