diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c index 9a7a6968d6..1706937ade 100644 --- a/module/zfs/dmu_objset.c +++ b/module/zfs/dmu_objset.c @@ -28,6 +28,7 @@ * Copyright (c) 2015, STRATO AG, Inc. All rights reserved. * Copyright (c) 2016 Actifio, Inc. All rights reserved. * Copyright 2017 Nexenta Systems, Inc. + * Copyright (c) 2017 Open-E, Inc. All Rights Reserved. */ /* Portions Copyright 2010 Robert Milkowski */ @@ -78,6 +79,8 @@ int dmu_find_threads = 0; */ int dmu_rescan_dnode_threshold = 1 << DN_MAX_INDBLKSHIFT; +static char *upgrade_tag = "upgrade_tag"; + static void dmu_objset_find_dp_cb(void *arg); static void dmu_objset_upgrade(objset_t *os, dmu_objset_upgrade_cb_t cb); @@ -1157,6 +1160,7 @@ dmu_objset_upgrade_task_cb(void *data) os->os_upgrade_exit = B_TRUE; os->os_upgrade_id = 0; mutex_exit(&os->os_upgrade_lock); + dsl_dataset_long_rele(dmu_objset_ds(os), upgrade_tag); } static void @@ -1165,6 +1169,9 @@ dmu_objset_upgrade(objset_t *os, dmu_objset_upgrade_cb_t cb) if (os->os_upgrade_id != 0) return; + ASSERT(dsl_pool_config_held(dmu_objset_pool(os))); + dsl_dataset_long_hold(dmu_objset_ds(os), upgrade_tag); + mutex_enter(&os->os_upgrade_lock); if (os->os_upgrade_id == 0 && os->os_upgrade_status == 0) { os->os_upgrade_exit = B_FALSE; @@ -1172,8 +1179,10 @@ dmu_objset_upgrade(objset_t *os, dmu_objset_upgrade_cb_t cb) os->os_upgrade_id = taskq_dispatch( os->os_spa->spa_upgrade_taskq, dmu_objset_upgrade_task_cb, os, TQ_SLEEP); - if (os->os_upgrade_id == TASKQID_INVALID) + if (os->os_upgrade_id == TASKQID_INVALID) { + dsl_dataset_long_rele(dmu_objset_ds(os), upgrade_tag); os->os_upgrade_status = ENOMEM; + } } mutex_exit(&os->os_upgrade_lock); } @@ -1189,7 +1198,10 @@ dmu_objset_upgrade_stop(objset_t *os) os->os_upgrade_id = 0; mutex_exit(&os->os_upgrade_lock); - taskq_cancel_id(os->os_spa->spa_upgrade_taskq, id); + if ((taskq_cancel_id(os->os_spa->spa_upgrade_taskq, id)) == 0) { + dsl_dataset_long_rele(dmu_objset_ds(os), upgrade_tag); + } + txg_wait_synced(os->os_spa->spa_dsl_pool, 0); } else { mutex_exit(&os->os_upgrade_lock); } diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index d195eded76..7106576c49 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -5181,9 +5181,6 @@ zfs_ioc_userobjspace_upgrade(zfs_cmd_t *zc) if (error != 0) return (error); - dsl_dataset_long_hold(dmu_objset_ds(os), FTAG); - dsl_pool_rele(dmu_objset_pool(os), FTAG); - if (dmu_objset_userobjspace_upgradable(os)) { mutex_enter(&os->os_upgrade_lock); if (os->os_upgrade_id == 0) { @@ -5196,8 +5193,12 @@ zfs_ioc_userobjspace_upgrade(zfs_cmd_t *zc) mutex_exit(&os->os_upgrade_lock); } + dsl_pool_rele(dmu_objset_pool(os), FTAG); + taskq_wait_id(os->os_spa->spa_upgrade_taskq, os->os_upgrade_id); error = os->os_upgrade_status; + } else { + dsl_pool_rele(dmu_objset_pool(os), FTAG); } dsl_dataset_long_rele(dmu_objset_ds(os), FTAG); diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c index f97660f37a..ea7d4ee59c 100644 --- a/module/zfs/zfs_vfsops.c +++ b/module/zfs/zfs_vfsops.c @@ -834,8 +834,13 @@ zfs_fuid_overobjquota(zfsvfs_t *zfsvfs, boolean_t isgroup, uint64_t fuid) int err; if (!dmu_objset_userobjspace_present(zfsvfs->z_os)) { - if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) + if (dmu_objset_userobjspace_upgradable(zfsvfs->z_os)) { + dsl_pool_config_enter( + dmu_objset_pool(zfsvfs->z_os), FTAG); dmu_objset_userobjspace_upgrade(zfsvfs->z_os); + dsl_pool_config_exit( + dmu_objset_pool(zfsvfs->z_os), FTAG); + } return (B_FALSE); }