aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
authorloli10K <[email protected]>2020-11-16 18:10:29 +0100
committerGitHub <[email protected]>2020-11-16 09:10:29 -0800
commit4072f465bc3630bbab50afccfd6c7baf41afcc4c (patch)
tree3eabc85191eb9d0fb9dd788fe1e1305596d2a728 /module/zfs
parent2c210f68189c6f781be050bfdc890cd6dc231fea (diff)
Fix 'zfs userspace' for received datasets in encrypted root
For encrypted receives, where user accounting is initially disabled on creation, both 'zfs userspace' and 'zfs groupspace' fails with EOPNOTSUPP: this is because dmu_objset_id_quota_upgrade_cb() forgets to set OBJSET_FLAG_USERACCOUNTING_COMPLETE on the objset flags after a successful dmu_objset_space_upgrade(). Reviewed-by: Brian Behlendorf <[email protected]> Co-authored-by: Brian Behlendorf <[email protected]> Signed-off-by: loli10K <[email protected]> Closes #9501 Closes #9596
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);
}