aboutsummaryrefslogtreecommitdiffstats
path: root/module/zfs
diff options
context:
space:
mode:
Diffstat (limited to 'module/zfs')
-rw-r--r--module/zfs/dmu_objset.c19
-rw-r--r--module/zfs/zfs_ioctl.c2
-rw-r--r--module/zfs/zfs_vfsops.c43
-rw-r--r--module/zfs/zvol.c16
4 files changed, 43 insertions, 37 deletions
diff --git a/module/zfs/dmu_objset.c b/module/zfs/dmu_objset.c
index 0d9273fbb..d7c46c3e5 100644
--- a/module/zfs/dmu_objset.c
+++ b/module/zfs/dmu_objset.c
@@ -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);
@@ -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,
diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c
index 6bee042a0..994b3af36 100644
--- a/module/zfs/zfs_ioctl.c
+++ b/module/zfs/zfs_ioctl.c
@@ -1472,7 +1472,7 @@ zfsvfs_hold(const char *name, void *tag, zfsvfs_t **zfvp, boolean_t writer)
int error = 0;
if (getzfsvfs(name, zfvp) != 0)
- error = zfsvfs_create(name, zfvp);
+ error = zfsvfs_create(name, B_FALSE, zfvp);
if (error == 0) {
rrm_enter(&(*zfvp)->z_teardown_lock, (writer) ? RW_WRITER :
RW_READER, tag);
diff --git a/module/zfs/zfs_vfsops.c b/module/zfs/zfs_vfsops.c
index 971fd54bc..2577860ac 100644
--- a/module/zfs/zfs_vfsops.c
+++ b/module/zfs/zfs_vfsops.c
@@ -1136,21 +1136,16 @@ zfsvfs_init(zfsvfs_t *zfsvfs, objset_t *os)
}
int
-zfsvfs_create(const char *osname, zfsvfs_t **zfvp)
+zfsvfs_create(const char *osname, boolean_t readonly, zfsvfs_t **zfvp)
{
objset_t *os;
zfsvfs_t *zfsvfs;
int error;
+ boolean_t ro = (readonly || (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);
@@ -1209,14 +1204,6 @@ zfsvfs_setup(zfsvfs_t *zfsvfs, boolean_t mounting)
int error;
boolean_t readonly = zfs_is_readonly(zfsvfs);
- /*
- * Check for a bad on-disk format version now since we
- * lied about owning the dataset readonly before.
- */
- if (!readonly &&
- dmu_objset_incompatible_encryption_version(zfsvfs->z_os))
- return (SET_ERROR(EROFS));
-
error = zfs_register_callbacks(zfsvfs->z_vfs);
if (error)
return (error);
@@ -1786,24 +1773,30 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
struct inode *root_inode;
uint64_t recordsize;
int error = 0;
- zfsvfs_t *zfsvfs;
+ zfsvfs_t *zfsvfs = NULL;
+ vfs_t *vfs = NULL;
ASSERT(zm);
ASSERT(osname);
- error = zfsvfs_create(osname, &zfsvfs);
+ error = zfsvfs_parse_options(zm->mnt_data, &vfs);
if (error)
return (error);
- error = zfsvfs_parse_options(zm->mnt_data, &zfsvfs->z_vfs);
- if (error)
+ error = zfsvfs_create(osname, vfs->vfs_readonly, &zfsvfs);
+ if (error) {
+ zfsvfs_vfs_free(vfs);
goto out;
+ }
if ((error = dsl_prop_get_integer(osname, "recordsize",
- &recordsize, NULL)))
+ &recordsize, NULL))) {
+ zfsvfs_vfs_free(vfs);
goto out;
+ }
- zfsvfs->z_vfs->vfs_data = zfsvfs;
+ vfs->vfs_data = zfsvfs;
+ zfsvfs->z_vfs = vfs;
zfsvfs->z_sb = sb;
sb->s_fs_info = zfsvfs;
sb->s_magic = ZFS_SUPER_MAGIC;
@@ -1875,8 +1868,10 @@ zfs_domount(struct super_block *sb, zfs_mnt_t *zm, int silent)
zfsvfs->z_arc_prune = arc_add_prune_callback(zpl_prune_sb, sb);
out:
if (error) {
- dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs);
- zfsvfs_free(zfsvfs);
+ if (zfsvfs != NULL) {
+ dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs);
+ zfsvfs_free(zfsvfs);
+ }
/*
* make sure we don't have dangling sb->s_fs_info which
* zfs_preumount will use.
diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c
index 572018d75..b0622c2ba 100644
--- a/module/zfs/zvol.c
+++ b/module/zfs/zvol.c
@@ -1289,10 +1289,11 @@ zvol_resume(zvol_state_t *zv)
}
static int
-zvol_first_open(zvol_state_t *zv)
+zvol_first_open(zvol_state_t *zv, boolean_t readonly)
{
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));
@@ -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 = (readonly || (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;
@@ -1401,17 +1402,12 @@ zvol_open(struct block_device *bdev, fmode_t flag)
ASSERT(zv->zv_open_count != 0 || RW_READ_HELD(&zv->zv_suspend_lock));
if (zv->zv_open_count == 0) {
- error = zvol_first_open(zv);
+ error = zvol_first_open(zv, !(flag & FMODE_WRITE));
if (error)
goto out_mutex;
}
- /*
- * Check for a bad on-disk format version now since we
- * lied about owning the dataset readonly before.
- */
- if ((flag & FMODE_WRITE) && ((zv->zv_flags & ZVOL_RDONLY) ||
- dmu_objset_incompatible_encryption_version(zv->zv_objset))) {
+ if ((flag & FMODE_WRITE) && (zv->zv_flags & ZVOL_RDONLY)) {
error = -EROFS;
goto out_open_count;
}