Skip to content

Commit

Permalink
ZIL claiming should not start user accounting
Browse files Browse the repository at this point in the history
Currently, ZIL claiming dirties objsets which causes
dsl_pool_sync() to attempt to perform user accounting on
them. This causes problems for encrypted datasets that were
raw received before the system went offline since they
cannot perform user accounting until they have their keys
loaded. This triggers an ASSERT in zio_encrypt(). Since
encryption was added, the code now depends on the fact that
data should only be written when objsets are owned. This
patch adds a check in dmu_objset_do_userquota_updates()
to ensure that useraccounting is only done when the objsets
are actually owned.

Fixes: openzfs#6916

Signed-off-by: Tom Caputi <[email protected]>
  • Loading branch information
Tom Caputi committed Feb 14, 2018
1 parent 9c5167d commit b0500b0
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 11 deletions.
19 changes: 17 additions & 2 deletions module/zfs/dmu_objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,9 +726,15 @@ dmu_objset_own(const char *name, dmu_objset_type_t type,
return (err);
}

/* user accounting requires the dataset to be decrypted */
/*
* User accounting requires the dataset to be decrypted and rw.
* We also don't begin user accounting during claiming to help
* 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);

Expand Down Expand Up @@ -1897,10 +1903,19 @@ dmu_objset_do_userquota_updates(objset_t *os, dmu_tx_t *tx)
if (!dmu_objset_userused_enabled(os))
return;

/* if this is a raw receive just return and handle accounting later */
/*
* If this is a raw receive just return and handle accounting
* later when we have the keys loaded. We also don't do user
* accounting during claiming since the datasets are not owned
* for the duration of claiming and this txg should only be
* used for recovery.
*/
if (os->os_encrypted && dmu_objset_is_receiving(os))
return;

if (tx->tx_txg <= os->os_spa->spa_claim_max_txg)
return;

/* Allocate the user/group/project used objects if necessary. */
if (DMU_USERUSED_DNODE(os)->dn_type == DMU_OT_NONE) {
VERIFY0(zap_create_claim(os,
Expand Down
9 changes: 2 additions & 7 deletions module/zfs/zfs_vfsops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1141,16 +1141,11 @@ zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
objset_t *os;
zfsvfs_t *zfsvfs;
int error;
boolean_t ro = (strchr(osname, '@') != NULL);

zfsvfs = kmem_zalloc(sizeof (zfsvfs_t), KM_SLEEP);

/*
* We claim to always be readonly so we can open snapshots;
* other ZPL code will prevent us from writing to snapshots.
*/

error = dmu_objset_own(osname, DMU_OST_ZFS, B_TRUE, B_TRUE,
zfsvfs, &os);
error = dmu_objset_own(osname, DMU_OST_ZFS, ro, B_TRUE, zfsvfs, &os);
if (error != 0) {
kmem_free(zfsvfs, sizeof (zfsvfs_t));
return (error);
Expand Down
5 changes: 3 additions & 2 deletions module/zfs/zvol.c
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,7 @@ zvol_first_open(zvol_state_t *zv)
{
objset_t *os;
int error, locked = 0;
boolean_t ro;

ASSERT(RW_READ_HELD(&zv->zv_suspend_lock));
ASSERT(MUTEX_HELD(&zv->zv_state_lock));
Expand Down Expand Up @@ -1321,8 +1322,8 @@ zvol_first_open(zvol_state_t *zv)
return (-SET_ERROR(ERESTARTSYS));
}

/* lie and say we're read-only */
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, 1, 1, zv, &os);
ro = (strchr(zv->zv_name, '@') != NULL);
error = dmu_objset_own(zv->zv_name, DMU_OST_ZVOL, ro, B_TRUE, zv, &os);
if (error)
goto out_mutex;

Expand Down

0 comments on commit b0500b0

Please sign in to comment.