extern boolean_t zfs_id_overquota(zfsvfs_t *zfsvfs, uint64_t usedobj,
uint64_t id);
extern int zfs_set_version(zfsvfs_t *zfsvfs, uint64_t newvers);
-extern int zfsvfs_create(const char *name, zfsvfs_t **zfvp);
+extern int zfsvfs_create(const char *name, boolean_t readony, zfsvfs_t **zfvp);
extern int zfsvfs_create_impl(zfsvfs_t **zfvp, zfsvfs_t *zfsvfs, objset_t *os);
extern void zfsvfs_free(zfsvfs_t *zfsvfs);
extern int zfs_check_global_label(const char *dsname, const char *hexsl);
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);
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,
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);
}
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);
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);
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;
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.
}
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));
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;
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;
}