aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dmu_objset.c35
-rw-r--r--module/zfs/zfs_ioctl.c46
2 files changed, 64 insertions, 17 deletions
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index af5935e23..6c1d23f2b 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -778,11 +778,15 @@ dmu_objset_own(const char *name, dmu_objset_type_t type,
* speed up pool import times and to keep this txg reserved
* completely for recovery work.
*/
- if ((dmu_objset_userobjspace_upgradable(*osp) ||
- dmu_objset_projectquota_upgradable(*osp)) &&
- !readonly && !dp->dp_spa->spa_claiming &&
- (ds->ds_dir->dd_crypto_obj == 0 || decrypt))
- dmu_objset_id_quota_upgrade(*osp);
+ if (!readonly && !dp->dp_spa->spa_claiming &&
+ (ds->ds_dir->dd_crypto_obj == 0 || decrypt)) {
+ if (dmu_objset_userobjspace_upgradable(*osp) ||
+ dmu_objset_projectquota_upgradable(*osp)) {
+ dmu_objset_id_quota_upgrade(*osp);
+ } else if (dmu_objset_userused_enabled(*osp)) {
+ dmu_objset_userspace_upgrade(*osp);
+ }
+ }
dsl_pool_rele(dp, FTAG);
return (0);
@@ -2285,8 +2289,8 @@ dmu_objset_space_upgrade(objset_t *os)
return (0);
}
-int
-dmu_objset_userspace_upgrade(objset_t *os)
+static int
+dmu_objset_userspace_upgrade_cb(objset_t *os)
{
int err = 0;
@@ -2306,6 +2310,12 @@ dmu_objset_userspace_upgrade(objset_t *os)
return (0);
}
+void
+dmu_objset_userspace_upgrade(objset_t *os)
+{
+ dmu_objset_upgrade(os, dmu_objset_userspace_upgrade_cb);
+}
+
static int
dmu_objset_id_quota_upgrade_cb(objset_t *os)
{
@@ -2316,14 +2326,15 @@ dmu_objset_id_quota_upgrade_cb(objset_t *os)
return (0);
if (dmu_objset_is_snapshot(os))
return (SET_ERROR(EINVAL));
- if (!dmu_objset_userobjused_enabled(os))
+ if (!dmu_objset_userused_enabled(os))
return (SET_ERROR(ENOTSUP));
if (!dmu_objset_projectquota_enabled(os) &&
dmu_objset_userobjspace_present(os))
return (SET_ERROR(ENOTSUP));
- dmu_objset_ds(os)->ds_feature_activation[
- SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE;
+ if (dmu_objset_userobjused_enabled(os))
+ dmu_objset_ds(os)->ds_feature_activation[
+ SPA_FEATURE_USEROBJ_ACCOUNTING] = (void *)B_TRUE;
if (dmu_objset_projectquota_enabled(os))
dmu_objset_ds(os)->ds_feature_activation[
SPA_FEATURE_PROJECT_QUOTA] = (void *)B_TRUE;
@@ -2332,7 +2343,9 @@ dmu_objset_id_quota_upgrade_cb(objset_t *os)
if (err)
return (err);
- os->os_flags |= OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE;
+ os->os_flags |= OBJSET_FLAG_USERACCOUNTING_COMPLETE;
+ if (dmu_objset_userobjused_enabled(os))
+ os->os_flags |= OBJSET_FLAG_USEROBJACCOUNTING_COMPLETE;
if (dmu_objset_projectquota_enabled(os))
os->os_flags |= OBJSET_FLAG_PROJECTQUOTA_COMPLETE;
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 7f2cf2a75..33bd39aa2 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -5856,7 +5856,6 @@ zfs_ioc_userspace_many(zfs_cmd_t *zc)
static int
zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
{
- objset_t *os;
int error = 0;
zfsvfs_t *zfsvfs;
@@ -5877,19 +5876,54 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc)
error = zfs_resume_fs(zfsvfs, newds);
}
}
- if (error == 0)
- error = dmu_objset_userspace_upgrade(zfsvfs->z_os);
+ if (error == 0) {
+ mutex_enter(&zfsvfs->z_os->os_upgrade_lock);
+ if (zfsvfs->z_os->os_upgrade_id == 0) {
+ /* clear potential error code and retry */
+ zfsvfs->z_os->os_upgrade_status = 0;
+ mutex_exit(&zfsvfs->z_os->os_upgrade_lock);
+
+ dsl_pool_config_enter(
+ dmu_objset_pool(zfsvfs->z_os), FTAG);
+ dmu_objset_userspace_upgrade(zfsvfs->z_os);
+ dsl_pool_config_exit(
+ dmu_objset_pool(zfsvfs->z_os), FTAG);
+ } else {
+ mutex_exit(&zfsvfs->z_os->os_upgrade_lock);
+ }
+
+ taskq_wait_id(zfsvfs->z_os->os_spa->spa_upgrade_taskq,
+ zfsvfs->z_os->os_upgrade_id);
+ error = zfsvfs->z_os->os_upgrade_status;
+ }
zfs_vfs_rele(zfsvfs);
} else {
+ objset_t *os;
+
/* XXX kind of reading contents without owning */
error = dmu_objset_hold_flags(zc->zc_name, B_TRUE, FTAG, &os);
if (error != 0)
return (error);
- error = dmu_objset_userspace_upgrade(os);
- dmu_objset_rele_flags(os, B_TRUE, FTAG);
- }
+ mutex_enter(&os->os_upgrade_lock);
+ if (os->os_upgrade_id == 0) {
+ /* clear potential error code and retry */
+ os->os_upgrade_status = 0;
+ mutex_exit(&os->os_upgrade_lock);
+
+ dmu_objset_userspace_upgrade(os);
+ } else {
+ 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;
+
+ dsl_dataset_rele_flags(dmu_objset_ds(os), DS_HOLD_FLAG_DECRYPT,
+ FTAG);
+ }
return (error);
}