Illumos 4951 - ZFS administrative commands should use reserved space
4951 ZFS administrative commands should use reserved space, not with ENOSPC Reviewed by: John Kennedy <john.kennedy@delphix.com> Reviewed by: George Wilson <george.wilson@delphix.com> Reviewed by: Christopher Siden <christopher.siden@delphix.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Garrett D'Amore <garrett@damore.org> References: https://www.illumos.org/issues/4373 https://github.com/illumos/illumos-gate/commit/7d46dc6 Ported by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
cfec5b17b3
commit
3d45fdd6c0
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
|
||||||
|
@ -6636,6 +6636,9 @@ zfs_do_bookmark(int argc, char **argv)
|
||||||
case ENOTSUP:
|
case ENOTSUP:
|
||||||
err_msg = "bookmark feature not enabled";
|
err_msg = "bookmark feature not enabled";
|
||||||
break;
|
break;
|
||||||
|
case ENOSPC:
|
||||||
|
err_msg = "out of space";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
err_msg = "unknown error";
|
err_msg = "unknown error";
|
||||||
break;
|
break;
|
||||||
|
@ -6644,7 +6647,7 @@ zfs_do_bookmark(int argc, char **argv)
|
||||||
dgettext(TEXT_DOMAIN, err_msg));
|
dgettext(TEXT_DOMAIN, err_msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (ret);
|
return (ret != 0);
|
||||||
|
|
||||||
usage:
|
usage:
|
||||||
usage(B_FALSE);
|
usage(B_FALSE);
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ zhack_do_feature_enable(int argc, char **argv)
|
||||||
feature.fi_guid);
|
feature.fi_guid);
|
||||||
|
|
||||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||||
zhack_feature_enable_sync, &feature, 5));
|
zhack_feature_enable_sync, &feature, 5, ZFS_SPACE_CHECK_NORMAL));
|
||||||
|
|
||||||
spa_close(spa, FTAG);
|
spa_close(spa, FTAG);
|
||||||
|
|
||||||
|
@ -473,7 +473,8 @@ zhack_do_feature_ref(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
VERIFY0(dsl_sync_task(spa_name(spa), NULL,
|
||||||
decr ? feature_decr_sync : feature_incr_sync, &feature, 5));
|
decr ? feature_decr_sync : feature_incr_sync, &feature,
|
||||||
|
5, ZFS_SPACE_CHECK_NORMAL));
|
||||||
|
|
||||||
spa_close(spa, FTAG);
|
spa_close(spa, FTAG);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2012 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _SYS_DSL_SYNCTASK_H
|
#ifndef _SYS_DSL_SYNCTASK_H
|
||||||
|
@ -38,11 +38,41 @@ struct dsl_pool;
|
||||||
typedef int (dsl_checkfunc_t)(void *, dmu_tx_t *);
|
typedef int (dsl_checkfunc_t)(void *, dmu_tx_t *);
|
||||||
typedef void (dsl_syncfunc_t)(void *, dmu_tx_t *);
|
typedef void (dsl_syncfunc_t)(void *, dmu_tx_t *);
|
||||||
|
|
||||||
|
typedef enum zfs_space_check {
|
||||||
|
/*
|
||||||
|
* Normal space check: if there is less than 3.2% free space,
|
||||||
|
* the operation will fail. Operations which are logically
|
||||||
|
* creating things should use this (e.g. "zfs create", "zfs snapshot").
|
||||||
|
* User writes (via the ZPL / ZVOL) also fail at this point.
|
||||||
|
*/
|
||||||
|
ZFS_SPACE_CHECK_NORMAL,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Space check allows use of half the slop space. If there
|
||||||
|
* is less than 1.6% free space, the operation will fail. Most
|
||||||
|
* operations should use this (e.g. "zfs set", "zfs rename"),
|
||||||
|
* because we want them to succeed even after user writes are failing,
|
||||||
|
* so that they can be used as part of the space recovery process.
|
||||||
|
*/
|
||||||
|
ZFS_SPACE_CHECK_RESERVED,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* No space check is performed. Only operations which we expect to
|
||||||
|
* result in a net reduction in space should use this
|
||||||
|
* (e.g. "zfs destroy". Setting quotas & reservations also uses
|
||||||
|
* this because it needs to circumvent the quota/reservation checks).
|
||||||
|
*
|
||||||
|
* See also the comments above spa_slop_shift.
|
||||||
|
*/
|
||||||
|
ZFS_SPACE_CHECK_NONE,
|
||||||
|
} zfs_space_check_t;
|
||||||
|
|
||||||
typedef struct dsl_sync_task {
|
typedef struct dsl_sync_task {
|
||||||
txg_node_t dst_node;
|
txg_node_t dst_node;
|
||||||
struct dsl_pool *dst_pool;
|
struct dsl_pool *dst_pool;
|
||||||
uint64_t dst_txg;
|
uint64_t dst_txg;
|
||||||
int dst_space;
|
int dst_space;
|
||||||
|
zfs_space_check_t dst_space_check;
|
||||||
dsl_checkfunc_t *dst_checkfunc;
|
dsl_checkfunc_t *dst_checkfunc;
|
||||||
dsl_syncfunc_t *dst_syncfunc;
|
dsl_syncfunc_t *dst_syncfunc;
|
||||||
void *dst_arg;
|
void *dst_arg;
|
||||||
|
@ -50,11 +80,11 @@ typedef struct dsl_sync_task {
|
||||||
boolean_t dst_nowaiter;
|
boolean_t dst_nowaiter;
|
||||||
} dsl_sync_task_t;
|
} dsl_sync_task_t;
|
||||||
|
|
||||||
void dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx);
|
void dsl_sync_task_sync(dsl_sync_task_t *, dmu_tx_t *);
|
||||||
int dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
|
int dsl_sync_task(const char *, dsl_checkfunc_t *,
|
||||||
dsl_syncfunc_t *syncfunc, void *arg, int blocks_modified);
|
dsl_syncfunc_t *, void *, int, zfs_space_check_t);
|
||||||
void dsl_sync_task_nowait(struct dsl_pool *dp, dsl_syncfunc_t *syncfunc,
|
void dsl_sync_task_nowait(struct dsl_pool *, dsl_syncfunc_t *,
|
||||||
void *arg, int blocks_modified, dmu_tx_t *tx);
|
void *, int, zfs_space_check_t, dmu_tx_t *);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -865,7 +865,8 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
|
||||||
doca.doca_type = type;
|
doca.doca_type = type;
|
||||||
|
|
||||||
return (dsl_sync_task(name,
|
return (dsl_sync_task(name,
|
||||||
dmu_objset_create_check, dmu_objset_create_sync, &doca, 5));
|
dmu_objset_create_check, dmu_objset_create_sync, &doca,
|
||||||
|
5, ZFS_SPACE_CHECK_NORMAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct dmu_objset_clone_arg {
|
typedef struct dmu_objset_clone_arg {
|
||||||
|
@ -964,7 +965,8 @@ dmu_objset_clone(const char *clone, const char *origin)
|
||||||
doca.doca_cred = CRED();
|
doca.doca_cred = CRED();
|
||||||
|
|
||||||
return (dsl_sync_task(clone,
|
return (dsl_sync_task(clone,
|
||||||
dmu_objset_clone_check, dmu_objset_clone_sync, &doca, 5));
|
dmu_objset_clone_check, dmu_objset_clone_sync, &doca,
|
||||||
|
5, ZFS_SPACE_CHECK_NORMAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -1191,7 +1191,7 @@ dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb,
|
||||||
drba.drba_cred = CRED();
|
drba.drba_cred = CRED();
|
||||||
|
|
||||||
return (dsl_sync_task(tofs, dmu_recv_begin_check, dmu_recv_begin_sync,
|
return (dsl_sync_task(tofs, dmu_recv_begin_check, dmu_recv_begin_sync,
|
||||||
&drba, 5));
|
&drba, 5, ZFS_SPACE_CHECK_NORMAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct restorearg {
|
struct restorearg {
|
||||||
|
@ -2108,7 +2108,7 @@ dmu_recv_existing_end(dmu_recv_cookie_t *drc)
|
||||||
|
|
||||||
error = dsl_sync_task(drc->drc_tofs,
|
error = dsl_sync_task(drc->drc_tofs,
|
||||||
dmu_recv_end_check, dmu_recv_end_sync, drc,
|
dmu_recv_end_check, dmu_recv_end_sync, drc,
|
||||||
dmu_recv_end_modified_blocks);
|
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
|
||||||
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
dmu_recv_cleanup_ds(drc);
|
dmu_recv_cleanup_ds(drc);
|
||||||
|
@ -2122,7 +2122,7 @@ dmu_recv_new_end(dmu_recv_cookie_t *drc)
|
||||||
|
|
||||||
error = dsl_sync_task(drc->drc_tofs,
|
error = dsl_sync_task(drc->drc_tofs,
|
||||||
dmu_recv_end_check, dmu_recv_end_sync, drc,
|
dmu_recv_end_check, dmu_recv_end_sync, drc,
|
||||||
dmu_recv_end_modified_blocks);
|
dmu_recv_end_modified_blocks, ZFS_SPACE_CHECK_NORMAL);
|
||||||
|
|
||||||
if (error != 0) {
|
if (error != 0) {
|
||||||
dmu_recv_cleanup_ds(drc);
|
dmu_recv_cleanup_ds(drc);
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
* CDDL HEADER END
|
* CDDL HEADER END
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2013, 2014 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/zfs_context.h>
|
#include <sys/zfs_context.h>
|
||||||
|
@ -249,7 +249,8 @@ dsl_bookmark_create(nvlist_t *bmarks, nvlist_t *errors)
|
||||||
dbca.dbca_errors = errors;
|
dbca.dbca_errors = errors;
|
||||||
|
|
||||||
return (dsl_sync_task(nvpair_name(pair), dsl_bookmark_create_check,
|
return (dsl_sync_task(nvpair_name(pair), dsl_bookmark_create_check,
|
||||||
dsl_bookmark_create_sync, &dbca, fnvlist_num_pairs(bmarks)));
|
dsl_bookmark_create_sync, &dbca,
|
||||||
|
fnvlist_num_pairs(bmarks), ZFS_SPACE_CHECK_NORMAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -454,7 +455,8 @@ dsl_bookmark_destroy(nvlist_t *bmarks, nvlist_t *errors)
|
||||||
dbda.dbda_success = fnvlist_alloc();
|
dbda.dbda_success = fnvlist_alloc();
|
||||||
|
|
||||||
rv = dsl_sync_task(nvpair_name(pair), dsl_bookmark_destroy_check,
|
rv = dsl_sync_task(nvpair_name(pair), dsl_bookmark_destroy_check,
|
||||||
dsl_bookmark_destroy_sync, &dbda, fnvlist_num_pairs(bmarks));
|
dsl_bookmark_destroy_sync, &dbda, fnvlist_num_pairs(bmarks),
|
||||||
|
ZFS_SPACE_CHECK_RESERVED);
|
||||||
fnvlist_free(dbda.dbda_success);
|
fnvlist_free(dbda.dbda_success);
|
||||||
return (rv);
|
return (rv);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1406,7 +1406,7 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
|
error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
|
||||||
dsl_dataset_snapshot_sync, &ddsa,
|
dsl_dataset_snapshot_sync, &ddsa,
|
||||||
fnvlist_num_pairs(snaps) * 3);
|
fnvlist_num_pairs(snaps) * 3, ZFS_SPACE_CHECK_NORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (suspended != NULL) {
|
if (suspended != NULL) {
|
||||||
|
@ -1518,7 +1518,7 @@ dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
|
||||||
}
|
}
|
||||||
|
|
||||||
error = dsl_sync_task(fsname, dsl_dataset_snapshot_tmp_check,
|
error = dsl_sync_task(fsname, dsl_dataset_snapshot_tmp_check,
|
||||||
dsl_dataset_snapshot_tmp_sync, &ddsta, 3);
|
dsl_dataset_snapshot_tmp_sync, &ddsta, 3, ZFS_SPACE_CHECK_RESERVED);
|
||||||
|
|
||||||
if (needsuspend)
|
if (needsuspend)
|
||||||
zil_resume(cookie);
|
zil_resume(cookie);
|
||||||
|
@ -1874,7 +1874,8 @@ dsl_dataset_rename_snapshot(const char *fsname,
|
||||||
ddrsa.ddrsa_recursive = recursive;
|
ddrsa.ddrsa_recursive = recursive;
|
||||||
|
|
||||||
error = dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
|
error = dsl_sync_task(fsname, dsl_dataset_rename_snapshot_check,
|
||||||
dsl_dataset_rename_snapshot_sync, &ddrsa, 1);
|
dsl_dataset_rename_snapshot_sync, &ddrsa,
|
||||||
|
1, ZFS_SPACE_CHECK_RESERVED);
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
return (SET_ERROR(error));
|
return (SET_ERROR(error));
|
||||||
|
@ -2064,7 +2065,8 @@ dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result)
|
||||||
ddra.ddra_result = result;
|
ddra.ddra_result = result;
|
||||||
|
|
||||||
return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
|
return (dsl_sync_task(fsname, dsl_dataset_rollback_check,
|
||||||
dsl_dataset_rollback_sync, &ddra, 1));
|
dsl_dataset_rollback_sync, &ddra,
|
||||||
|
1, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct promotenode {
|
struct promotenode {
|
||||||
|
@ -2595,7 +2597,8 @@ dsl_dataset_promote(const char *name, char *conflsnap)
|
||||||
ddpa.cr = CRED();
|
ddpa.cr = CRED();
|
||||||
|
|
||||||
return (dsl_sync_task(name, dsl_dataset_promote_check,
|
return (dsl_sync_task(name, dsl_dataset_promote_check,
|
||||||
dsl_dataset_promote_sync, &ddpa, 2 + numsnaps));
|
dsl_dataset_promote_sync, &ddpa,
|
||||||
|
2 + numsnaps, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -2949,7 +2952,7 @@ dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
|
||||||
ddsqra.ddsqra_value = refquota;
|
ddsqra.ddsqra_value = refquota;
|
||||||
|
|
||||||
return (dsl_sync_task(dsname, dsl_dataset_set_refquota_check,
|
return (dsl_sync_task(dsname, dsl_dataset_set_refquota_check,
|
||||||
dsl_dataset_set_refquota_sync, &ddsqra, 0));
|
dsl_dataset_set_refquota_sync, &ddsqra, 0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
@ -3064,7 +3067,8 @@ dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
|
||||||
ddsqra.ddsqra_value = refreservation;
|
ddsqra.ddsqra_value = refreservation;
|
||||||
|
|
||||||
return (dsl_sync_task(dsname, dsl_dataset_set_refreservation_check,
|
return (dsl_sync_task(dsname, dsl_dataset_set_refreservation_check,
|
||||||
dsl_dataset_set_refreservation_sync, &ddsqra, 0));
|
dsl_dataset_set_refreservation_sync, &ddsqra,
|
||||||
|
0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -282,7 +282,7 @@ dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)
|
||||||
|
|
||||||
return (dsl_sync_task(ddname, dsl_deleg_check,
|
return (dsl_sync_task(ddname, dsl_deleg_check,
|
||||||
unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
|
unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
|
||||||
&dda, fnvlist_num_pairs(nvp)));
|
&dda, fnvlist_num_pairs(nvp), ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -520,7 +520,7 @@ dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,
|
||||||
|
|
||||||
error = dsl_sync_task(nvpair_name(pair),
|
error = dsl_sync_task(nvpair_name(pair),
|
||||||
dsl_destroy_snapshot_check, dsl_destroy_snapshot_sync,
|
dsl_destroy_snapshot_check, dsl_destroy_snapshot_sync,
|
||||||
&dsda, 0);
|
&dsda, 0, ZFS_SPACE_CHECK_NONE);
|
||||||
fnvlist_free(dsda.dsda_successful_snaps);
|
fnvlist_free(dsda.dsda_successful_snaps);
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
|
@ -918,7 +918,8 @@ dsl_destroy_head(const char *name)
|
||||||
objset_t *os;
|
objset_t *os;
|
||||||
|
|
||||||
error = dsl_sync_task(name, dsl_destroy_head_check,
|
error = dsl_sync_task(name, dsl_destroy_head_check,
|
||||||
dsl_destroy_head_begin_sync, &ddha, 0);
|
dsl_destroy_head_begin_sync, &ddha,
|
||||||
|
0, ZFS_SPACE_CHECK_NONE);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
return (error);
|
return (error);
|
||||||
|
|
||||||
|
@ -944,7 +945,7 @@ dsl_destroy_head(const char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (dsl_sync_task(name, dsl_destroy_head_check,
|
return (dsl_sync_task(name, dsl_destroy_head_check,
|
||||||
dsl_destroy_head_sync, &ddha, 0));
|
dsl_destroy_head_sync, &ddha, 0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||||
* Copyright (c) 2014 Joyent, Inc. All rights reserved.
|
* Copyright (c) 2014 Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
|
||||||
|
@ -665,7 +665,8 @@ dsl_dir_activate_fs_ss_limit(const char *ddname)
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = dsl_sync_task(ddname, dsl_dir_actv_fs_ss_limit_check,
|
error = dsl_sync_task(ddname, dsl_dir_actv_fs_ss_limit_check,
|
||||||
dsl_dir_actv_fs_ss_limit_sync, (void *)ddname, 0);
|
dsl_dir_actv_fs_ss_limit_sync, (void *)ddname, 0,
|
||||||
|
ZFS_SPACE_CHECK_RESERVED);
|
||||||
|
|
||||||
if (error == EALREADY)
|
if (error == EALREADY)
|
||||||
error = 0;
|
error = 0;
|
||||||
|
@ -1529,7 +1530,7 @@ dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
|
||||||
ddsqra.ddsqra_value = quota;
|
ddsqra.ddsqra_value = quota;
|
||||||
|
|
||||||
return (dsl_sync_task(ddname, dsl_dir_set_quota_check,
|
return (dsl_sync_task(ddname, dsl_dir_set_quota_check,
|
||||||
dsl_dir_set_quota_sync, &ddsqra, 0));
|
dsl_dir_set_quota_sync, &ddsqra, 0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -1650,7 +1651,7 @@ dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
|
||||||
ddsqra.ddsqra_value = reservation;
|
ddsqra.ddsqra_value = reservation;
|
||||||
|
|
||||||
return (dsl_sync_task(ddname, dsl_dir_set_reservation_check,
|
return (dsl_sync_task(ddname, dsl_dir_set_reservation_check,
|
||||||
dsl_dir_set_reservation_sync, &ddsqra, 0));
|
dsl_dir_set_reservation_sync, &ddsqra, 0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
static dsl_dir_t *
|
static dsl_dir_t *
|
||||||
|
@ -1932,7 +1933,8 @@ dsl_dir_rename(const char *oldname, const char *newname)
|
||||||
ddra.ddra_cred = CRED();
|
ddra.ddra_cred = CRED();
|
||||||
|
|
||||||
return (dsl_sync_task(oldname,
|
return (dsl_sync_task(oldname,
|
||||||
dsl_dir_rename_check, dsl_dir_rename_sync, &ddra, 3));
|
dsl_dir_rename_check, dsl_dir_rename_sync, &ddra,
|
||||||
|
3, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
* Copyright (c) 2013 Martin Matuska. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -865,7 +865,7 @@ dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
|
||||||
nblks = 2 * fnvlist_num_pairs(props);
|
nblks = 2 * fnvlist_num_pairs(props);
|
||||||
|
|
||||||
return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync,
|
return (dsl_sync_task(dsname, dsl_props_set_check, dsl_props_set_sync,
|
||||||
&dpsa, nblks));
|
&dpsa, nblks, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum dsl_prop_getflags {
|
typedef enum dsl_prop_getflags {
|
||||||
|
|
|
@ -388,7 +388,7 @@ int
|
||||||
dsl_scan_cancel(dsl_pool_t *dp)
|
dsl_scan_cancel(dsl_pool_t *dp)
|
||||||
{
|
{
|
||||||
return (dsl_sync_task(spa_name(dp->dp_spa), dsl_scan_cancel_check,
|
return (dsl_sync_task(spa_name(dp->dp_spa), dsl_scan_cancel_check,
|
||||||
dsl_scan_cancel_sync, NULL, 3));
|
dsl_scan_cancel_sync, NULL, 3, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
|
static void dsl_scan_visitbp(blkptr_t *bp, const zbookmark_phys_t *zb,
|
||||||
|
@ -1848,7 +1848,7 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
|
||||||
(void) spa_vdev_state_exit(spa, NULL, 0);
|
(void) spa_vdev_state_exit(spa, NULL, 0);
|
||||||
|
|
||||||
return (dsl_sync_task(spa_name(spa), dsl_scan_setup_check,
|
return (dsl_sync_task(spa_name(spa), dsl_scan_setup_check,
|
||||||
dsl_scan_setup_sync, &func, 0));
|
dsl_scan_setup_sync, &func, 0, ZFS_SPACE_CHECK_NONE));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(_KERNEL) && defined(HAVE_SPL)
|
#if defined(_KERNEL) && defined(HAVE_SPL)
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/dmu.h>
|
#include <sys/dmu.h>
|
||||||
|
@ -64,7 +64,8 @@ dsl_null_checkfunc(void *arg, dmu_tx_t *tx)
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
|
dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
|
||||||
dsl_syncfunc_t *syncfunc, void *arg, int blocks_modified)
|
dsl_syncfunc_t *syncfunc, void *arg,
|
||||||
|
int blocks_modified, zfs_space_check_t space_check)
|
||||||
{
|
{
|
||||||
spa_t *spa;
|
spa_t *spa;
|
||||||
dmu_tx_t *tx;
|
dmu_tx_t *tx;
|
||||||
|
@ -84,6 +85,7 @@ top:
|
||||||
dst.dst_pool = dp;
|
dst.dst_pool = dp;
|
||||||
dst.dst_txg = dmu_tx_get_txg(tx);
|
dst.dst_txg = dmu_tx_get_txg(tx);
|
||||||
dst.dst_space = blocks_modified << DST_AVG_BLKSHIFT;
|
dst.dst_space = blocks_modified << DST_AVG_BLKSHIFT;
|
||||||
|
dst.dst_space_check = space_check;
|
||||||
dst.dst_checkfunc = checkfunc != NULL ? checkfunc : dsl_null_checkfunc;
|
dst.dst_checkfunc = checkfunc != NULL ? checkfunc : dsl_null_checkfunc;
|
||||||
dst.dst_syncfunc = syncfunc;
|
dst.dst_syncfunc = syncfunc;
|
||||||
dst.dst_arg = arg;
|
dst.dst_arg = arg;
|
||||||
|
@ -117,13 +119,14 @@ top:
|
||||||
|
|
||||||
void
|
void
|
||||||
dsl_sync_task_nowait(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg,
|
dsl_sync_task_nowait(dsl_pool_t *dp, dsl_syncfunc_t *syncfunc, void *arg,
|
||||||
int blocks_modified, dmu_tx_t *tx)
|
int blocks_modified, zfs_space_check_t space_check, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_sync_task_t *dst = kmem_zalloc(sizeof (*dst), KM_SLEEP);
|
dsl_sync_task_t *dst = kmem_zalloc(sizeof (*dst), KM_SLEEP);
|
||||||
|
|
||||||
dst->dst_pool = dp;
|
dst->dst_pool = dp;
|
||||||
dst->dst_txg = dmu_tx_get_txg(tx);
|
dst->dst_txg = dmu_tx_get_txg(tx);
|
||||||
dst->dst_space = blocks_modified << DST_AVG_BLKSHIFT;
|
dst->dst_space = blocks_modified << DST_AVG_BLKSHIFT;
|
||||||
|
dst->dst_space_check = space_check;
|
||||||
dst->dst_checkfunc = dsl_null_checkfunc;
|
dst->dst_checkfunc = dsl_null_checkfunc;
|
||||||
dst->dst_syncfunc = syncfunc;
|
dst->dst_syncfunc = syncfunc;
|
||||||
dst->dst_arg = arg;
|
dst->dst_arg = arg;
|
||||||
|
@ -140,25 +143,34 @@ void
|
||||||
dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx)
|
dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx)
|
||||||
{
|
{
|
||||||
dsl_pool_t *dp = dst->dst_pool;
|
dsl_pool_t *dp = dst->dst_pool;
|
||||||
uint64_t quota, used;
|
|
||||||
|
|
||||||
ASSERT0(dst->dst_error);
|
ASSERT0(dst->dst_error);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check for sufficient space. We just check against what's
|
* Check for sufficient space.
|
||||||
* on-disk; we don't want any in-flight accounting to get in our
|
*
|
||||||
* way, because open context may have already used up various
|
* When the sync task was created, the caller specified the
|
||||||
* in-core limits (arc_tempreserve, dsl_pool_tempreserve).
|
* type of space checking required. See the comment in
|
||||||
|
* zfs_space_check_t for details on the semantics of each
|
||||||
|
* type of space checking.
|
||||||
|
*
|
||||||
|
* We just check against what's on-disk; we don't want any
|
||||||
|
* in-flight accounting to get in our way, because open context
|
||||||
|
* may have already used up various in-core limits
|
||||||
|
* (arc_tempreserve, dsl_pool_tempreserve).
|
||||||
*/
|
*/
|
||||||
quota = dsl_pool_adjustedsize(dp, B_FALSE) -
|
if (dst->dst_space_check != ZFS_SPACE_CHECK_NONE) {
|
||||||
metaslab_class_get_deferred(spa_normal_class(dp->dp_spa));
|
uint64_t quota = dsl_pool_adjustedsize(dp,
|
||||||
used = dsl_dir_phys(dp->dp_root_dir)->dd_used_bytes;
|
dst->dst_space_check == ZFS_SPACE_CHECK_RESERVED) -
|
||||||
/* MOS space is triple-dittoed, so we multiply by 3. */
|
metaslab_class_get_deferred(spa_normal_class(dp->dp_spa));
|
||||||
if (dst->dst_space > 0 && used + dst->dst_space * 3 > quota) {
|
uint64_t used = dsl_dir_phys(dp->dp_root_dir)->dd_used_bytes;
|
||||||
dst->dst_error = SET_ERROR(ENOSPC);
|
/* MOS space is triple-dittoed, so we multiply by 3. */
|
||||||
if (dst->dst_nowaiter)
|
if (dst->dst_space > 0 && used + dst->dst_space * 3 > quota) {
|
||||||
kmem_free(dst, sizeof (*dst));
|
dst->dst_error = SET_ERROR(ENOSPC);
|
||||||
return;
|
if (dst->dst_nowaiter)
|
||||||
|
kmem_free(dst, sizeof (*dst));
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -319,7 +319,8 @@ dsl_dataset_user_hold(nvlist_t *holds, minor_t cleanup_minor, nvlist_t *errlist)
|
||||||
dduha.dduha_minor = cleanup_minor;
|
dduha.dduha_minor = cleanup_minor;
|
||||||
|
|
||||||
ret = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
|
ret = dsl_sync_task(nvpair_name(pair), dsl_dataset_user_hold_check,
|
||||||
dsl_dataset_user_hold_sync, &dduha, fnvlist_num_pairs(holds));
|
dsl_dataset_user_hold_sync, &dduha,
|
||||||
|
fnvlist_num_pairs(holds), ZFS_SPACE_CHECK_RESERVED);
|
||||||
fnvlist_free(dduha.dduha_chkholds);
|
fnvlist_free(dduha.dduha_chkholds);
|
||||||
|
|
||||||
return (ret);
|
return (ret);
|
||||||
|
@ -609,7 +610,7 @@ dsl_dataset_user_release_impl(nvlist_t *holds, nvlist_t *errlist,
|
||||||
KM_SLEEP));
|
KM_SLEEP));
|
||||||
|
|
||||||
error = dsl_sync_task(pool, dsl_dataset_user_release_check,
|
error = dsl_sync_task(pool, dsl_dataset_user_release_check,
|
||||||
dsl_dataset_user_release_sync, &ddura, 0);
|
dsl_dataset_user_release_sync, &ddura, 0, ZFS_SPACE_CHECK_NONE);
|
||||||
fnvlist_free(ddura.ddura_todelete);
|
fnvlist_free(ddura.ddura_todelete);
|
||||||
fnvlist_free(ddura.ddura_chkholds);
|
fnvlist_free(ddura.ddura_chkholds);
|
||||||
|
|
||||||
|
|
|
@ -666,7 +666,8 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
|
||||||
* feature descriptions object.
|
* feature descriptions object.
|
||||||
*/
|
*/
|
||||||
error = dsl_sync_task(spa->spa_name, NULL,
|
error = dsl_sync_task(spa->spa_name, NULL,
|
||||||
spa_sync_version, &ver, 6);
|
spa_sync_version, &ver,
|
||||||
|
6, ZFS_SPACE_CHECK_RESERVED);
|
||||||
if (error)
|
if (error)
|
||||||
return (error);
|
return (error);
|
||||||
continue;
|
continue;
|
||||||
|
@ -678,7 +679,7 @@ spa_prop_set(spa_t *spa, nvlist_t *nvp)
|
||||||
|
|
||||||
if (need_sync) {
|
if (need_sync) {
|
||||||
return (dsl_sync_task(spa->spa_name, NULL, spa_sync_props,
|
return (dsl_sync_task(spa->spa_name, NULL, spa_sync_props,
|
||||||
nvp, 6));
|
nvp, 6, ZFS_SPACE_CHECK_RESERVED));
|
||||||
}
|
}
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
@ -759,7 +760,7 @@ spa_change_guid(spa_t *spa)
|
||||||
guid = spa_generate_guid(NULL);
|
guid = spa_generate_guid(NULL);
|
||||||
|
|
||||||
error = dsl_sync_task(spa->spa_name, spa_change_guid_check,
|
error = dsl_sync_task(spa->spa_name, spa_change_guid_check,
|
||||||
spa_change_guid_sync, &guid, 5);
|
spa_change_guid_sync, &guid, 5, ZFS_SPACE_CHECK_RESERVED);
|
||||||
|
|
||||||
if (error == 0) {
|
if (error == 0) {
|
||||||
spa_config_sync(spa, B_FALSE, B_TRUE);
|
spa_config_sync(spa, B_FALSE, B_TRUE);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sys/spa.h>
|
#include <sys/spa.h>
|
||||||
|
@ -323,7 +323,7 @@ spa_history_log_nvl(spa_t *spa, nvlist_t *nvl)
|
||||||
|
|
||||||
/* Kick this off asynchronously; errors are ignored. */
|
/* Kick this off asynchronously; errors are ignored. */
|
||||||
dsl_sync_task_nowait(spa_get_dsl(spa), spa_history_log_sync,
|
dsl_sync_task_nowait(spa_get_dsl(spa), spa_history_log_sync,
|
||||||
nvarg, 0, tx);
|
nvarg, 0, ZFS_SPACE_CHECK_NONE, tx);
|
||||||
dmu_tx_commit(tx);
|
dmu_tx_commit(tx);
|
||||||
|
|
||||||
/* spa_history_log_sync will free nvl */
|
/* spa_history_log_sync will free nvl */
|
||||||
|
@ -458,7 +458,7 @@ log_internal(nvlist_t *nvl, const char *operation, spa_t *spa,
|
||||||
spa_history_log_sync(nvl, tx);
|
spa_history_log_sync(nvl, tx);
|
||||||
} else {
|
} else {
|
||||||
dsl_sync_task_nowait(spa_get_dsl(spa),
|
dsl_sync_task_nowait(spa_get_dsl(spa),
|
||||||
spa_history_log_sync, nvl, 0, tx);
|
spa_history_log_sync, nvl, 0, ZFS_SPACE_CHECK_NONE, tx);
|
||||||
}
|
}
|
||||||
/* spa_history_log_sync() will free nvl */
|
/* spa_history_log_sync() will free nvl */
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,6 +311,32 @@ int zfs_deadman_enabled = 1;
|
||||||
*/
|
*/
|
||||||
int spa_asize_inflation = 24;
|
int spa_asize_inflation = 24;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Normally, we don't allow the last 3.2% (1/(2^spa_slop_shift)) of space in
|
||||||
|
* the pool to be consumed. This ensures that we don't run the pool
|
||||||
|
* completely out of space, due to unaccounted changes (e.g. to the MOS).
|
||||||
|
* It also limits the worst-case time to allocate space. If we have
|
||||||
|
* less than this amount of free space, most ZPL operations (e.g. write,
|
||||||
|
* create) will return ENOSPC.
|
||||||
|
*
|
||||||
|
* Certain operations (e.g. file removal, most administrative actions) can
|
||||||
|
* use half the slop space. They will only return ENOSPC if less than half
|
||||||
|
* the slop space is free. Typically, once the pool has less than the slop
|
||||||
|
* space free, the user will use these operations to free up space in the pool.
|
||||||
|
* These are the operations that call dsl_pool_adjustedsize() with the netfree
|
||||||
|
* argument set to TRUE.
|
||||||
|
*
|
||||||
|
* A very restricted set of operations are always permitted, regardless of
|
||||||
|
* the amount of free space. These are the operations that call
|
||||||
|
* dsl_sync_task(ZFS_SPACE_CHECK_NONE), e.g. "zfs destroy". If these
|
||||||
|
* operations result in a net increase in the amount of space used,
|
||||||
|
* it is possible to run the pool completely out of space, causing it to
|
||||||
|
* be permanently read-only.
|
||||||
|
*
|
||||||
|
* See also the comments in zfs_space_check_t.
|
||||||
|
*/
|
||||||
|
int spa_slop_shift = 5;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ==========================================================================
|
* ==========================================================================
|
||||||
* SPA config locking
|
* SPA config locking
|
||||||
|
@ -1564,6 +1590,18 @@ spa_get_asize(spa_t *spa, uint64_t lsize)
|
||||||
return (lsize * spa_asize_inflation);
|
return (lsize * spa_asize_inflation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return the amount of slop space in bytes. It is 1/32 of the pool (3.2%),
|
||||||
|
* or at least 32MB.
|
||||||
|
*
|
||||||
|
* See the comment above spa_slop_shift for details.
|
||||||
|
*/
|
||||||
|
uint64_t
|
||||||
|
spa_get_slop_space(spa_t *spa) {
|
||||||
|
uint64_t space = spa_get_dspace(spa);
|
||||||
|
return (MAX(space >> spa_slop_shift, SPA_MINDEVSIZE >> 1));
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
spa_get_dspace(spa_t *spa)
|
spa_get_dspace(spa_t *spa)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2012, Joyent, Inc. All rights reserved.
|
||||||
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
|
||||||
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
|
* Copyright (c) 2014, Joyent, Inc. All rights reserved.
|
||||||
* Copyright (c) 2013 by Delphix. All rights reserved.
|
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
|
||||||
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
* Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
|
||||||
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
* Copyright (c) 2013 Steven Hartland. All rights reserved.
|
||||||
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
* Copyright (c) 2014, Nexenta Systems, Inc. All rights reserved.
|
||||||
|
|
Loading…
Reference in New Issue