Skip to content

Commit

Permalink
Illumos 4951 - ZFS administrative commands should use reserved space
Browse files Browse the repository at this point in the history
4951 ZFS administrative commands should use reserved space, not with ENOSPC
Reviewed by: John Kennedy <[email protected]>
Reviewed by: George Wilson <[email protected]>
Reviewed by: Christopher Siden <[email protected]>
Reviewed by: Dan McDonald <[email protected]>
Approved by: Garrett D'Amore <[email protected]>

References:
  https://www.illumos.org/issues/4373
  illumos/illumos-gate@7d46dc6

Ported by: Brian Behlendorf <[email protected]>
  • Loading branch information
ahrens authored and behlendorf committed May 4, 2015
1 parent cfec5b1 commit 3d45fdd
Show file tree
Hide file tree
Showing 18 changed files with 164 additions and 67 deletions.
7 changes: 5 additions & 2 deletions cmd/zfs/zfs_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

/*
* 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) 2013 Steven Hartland. All rights reserved.
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
Expand Down Expand Up @@ -6636,6 +6636,9 @@ zfs_do_bookmark(int argc, char **argv)
case ENOTSUP:
err_msg = "bookmark feature not enabled";
break;
case ENOSPC:
err_msg = "out of space";
break;
default:
err_msg = "unknown error";
break;
Expand All @@ -6644,7 +6647,7 @@ zfs_do_bookmark(int argc, char **argv)
dgettext(TEXT_DOMAIN, err_msg));
}

return (ret);
return (ret != 0);

usage:
usage(B_FALSE);
Expand Down
7 changes: 4 additions & 3 deletions cmd/zhack/zhack.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/

Expand Down Expand Up @@ -362,7 +362,7 @@ zhack_do_feature_enable(int argc, char **argv)
feature.fi_guid);

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);

Expand Down Expand Up @@ -473,7 +473,8 @@ zhack_do_feature_ref(int argc, char **argv)
}

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);
}
Expand Down
42 changes: 36 additions & 6 deletions include/sys/dsl_synctask.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/*
* 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
Expand All @@ -38,23 +38,53 @@ struct dsl_pool;
typedef int (dsl_checkfunc_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 {
txg_node_t dst_node;
struct dsl_pool *dst_pool;
uint64_t dst_txg;
int dst_space;
zfs_space_check_t dst_space_check;
dsl_checkfunc_t *dst_checkfunc;
dsl_syncfunc_t *dst_syncfunc;
void *dst_arg;
int dst_error;
boolean_t dst_nowaiter;
} dsl_sync_task_t;

void dsl_sync_task_sync(dsl_sync_task_t *dst, dmu_tx_t *tx);
int dsl_sync_task(const char *pool, dsl_checkfunc_t *checkfunc,
dsl_syncfunc_t *syncfunc, void *arg, int blocks_modified);
void dsl_sync_task_nowait(struct dsl_pool *dp, dsl_syncfunc_t *syncfunc,
void *arg, int blocks_modified, dmu_tx_t *tx);
void dsl_sync_task_sync(dsl_sync_task_t *, dmu_tx_t *);
int dsl_sync_task(const char *, dsl_checkfunc_t *,
dsl_syncfunc_t *, void *, int, zfs_space_check_t);
void dsl_sync_task_nowait(struct dsl_pool *, dsl_syncfunc_t *,
void *, int, zfs_space_check_t, dmu_tx_t *);

#ifdef __cplusplus
}
Expand Down
6 changes: 4 additions & 2 deletions module/zfs/dmu_objset.c
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,8 @@ dmu_objset_create(const char *name, dmu_objset_type_t type, uint64_t flags,
doca.doca_type = type;

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 {
Expand Down Expand Up @@ -964,7 +965,8 @@ dmu_objset_clone(const char *clone, const char *origin)
doca.doca_cred = CRED();

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
Expand Down
6 changes: 3 additions & 3 deletions module/zfs/dmu_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -1191,7 +1191,7 @@ dmu_recv_begin(char *tofs, char *tosnap, struct drr_begin *drrb,
drba.drba_cred = CRED();

return (dsl_sync_task(tofs, dmu_recv_begin_check, dmu_recv_begin_sync,
&drba, 5));
&drba, 5, ZFS_SPACE_CHECK_NORMAL));
}

struct restorearg {
Expand Down Expand Up @@ -2108,7 +2108,7 @@ dmu_recv_existing_end(dmu_recv_cookie_t *drc)

error = dsl_sync_task(drc->drc_tofs,
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)
dmu_recv_cleanup_ds(drc);
Expand All @@ -2122,7 +2122,7 @@ dmu_recv_new_end(dmu_recv_cookie_t *drc)

error = dsl_sync_task(drc->drc_tofs,
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) {
dmu_recv_cleanup_ds(drc);
Expand Down
8 changes: 5 additions & 3 deletions module/zfs/dsl_bookmark.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* 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>
Expand Down Expand Up @@ -249,7 +249,8 @@ dsl_bookmark_create(nvlist_t *bmarks, nvlist_t *errors)
dbca.dbca_errors = errors;

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
Expand Down Expand Up @@ -454,7 +455,8 @@ dsl_bookmark_destroy(nvlist_t *bmarks, nvlist_t *errors)
dbda.dbda_success = fnvlist_alloc();

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);
return (rv);
}
18 changes: 11 additions & 7 deletions module/zfs/dsl_dataset.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,7 +1406,7 @@ dsl_dataset_snapshot(nvlist_t *snaps, nvlist_t *props, nvlist_t *errors)
if (error == 0) {
error = dsl_sync_task(firstname, dsl_dataset_snapshot_check,
dsl_dataset_snapshot_sync, &ddsa,
fnvlist_num_pairs(snaps) * 3);
fnvlist_num_pairs(snaps) * 3, ZFS_SPACE_CHECK_NORMAL);
}

if (suspended != NULL) {
Expand Down Expand Up @@ -1518,7 +1518,7 @@ dsl_dataset_snapshot_tmp(const char *fsname, const char *snapname,
}

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)
zil_resume(cookie);
Expand Down Expand Up @@ -1874,7 +1874,8 @@ dsl_dataset_rename_snapshot(const char *fsname,
ddrsa.ddrsa_recursive = recursive;

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)
return (SET_ERROR(error));
Expand Down Expand Up @@ -2064,7 +2065,8 @@ dsl_dataset_rollback(const char *fsname, void *owner, nvlist_t *result)
ddra.ddra_result = result;

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 {
Expand Down Expand Up @@ -2595,7 +2597,8 @@ dsl_dataset_promote(const char *name, char *conflsnap)
ddpa.cr = CRED();

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
Expand Down Expand Up @@ -2949,7 +2952,7 @@ dsl_dataset_set_refquota(const char *dsname, zprop_source_t source,
ddsqra.ddsqra_value = refquota;

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
Expand Down Expand Up @@ -3064,7 +3067,8 @@ dsl_dataset_set_refreservation(const char *dsname, zprop_source_t source,
ddsqra.ddsqra_value = refreservation;

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));
}

/*
Expand Down
4 changes: 2 additions & 2 deletions module/zfs/dsl_deleg.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/*
* 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.
*/

/*
Expand Down Expand Up @@ -282,7 +282,7 @@ dsl_deleg_set(const char *ddname, nvlist_t *nvp, boolean_t unset)

return (dsl_sync_task(ddname, dsl_deleg_check,
unset ? dsl_deleg_unset_sync : dsl_deleg_set_sync,
&dda, fnvlist_num_pairs(nvp)));
&dda, fnvlist_num_pairs(nvp), ZFS_SPACE_CHECK_RESERVED));
}

/*
Expand Down
7 changes: 4 additions & 3 deletions module/zfs/dsl_destroy.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@ dsl_destroy_snapshots_nvl(nvlist_t *snaps, boolean_t defer,

error = dsl_sync_task(nvpair_name(pair),
dsl_destroy_snapshot_check, dsl_destroy_snapshot_sync,
&dsda, 0);
&dsda, 0, ZFS_SPACE_CHECK_NONE);
fnvlist_free(dsda.dsda_successful_snaps);

return (error);
Expand Down Expand Up @@ -918,7 +918,8 @@ dsl_destroy_head(const char *name)
objset_t *os;

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)
return (error);

Expand All @@ -944,7 +945,7 @@ dsl_destroy_head(const char *name)
}

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));
}

/*
Expand Down
12 changes: 7 additions & 5 deletions module/zfs/dsl_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/*
* 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) 2014 Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Spectra Logic Corporation, All rights reserved.
Expand Down Expand Up @@ -665,7 +665,8 @@ dsl_dir_activate_fs_ss_limit(const char *ddname)
int error;

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)
error = 0;
Expand Down Expand Up @@ -1529,7 +1530,7 @@ dsl_dir_set_quota(const char *ddname, zprop_source_t source, uint64_t quota)
ddsqra.ddsqra_value = quota;

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
Expand Down Expand Up @@ -1650,7 +1651,7 @@ dsl_dir_set_reservation(const char *ddname, zprop_source_t source,
ddsqra.ddsqra_value = reservation;

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 *
Expand Down Expand Up @@ -1932,7 +1933,8 @@ dsl_dir_rename(const char *oldname, const char *newname)
ddra.ddra_cred = CRED();

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
Expand Down
4 changes: 2 additions & 2 deletions module/zfs/dsl_prop.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
*/
/*
* 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.
*/

Expand Down Expand Up @@ -865,7 +865,7 @@ dsl_props_set(const char *dsname, zprop_source_t source, nvlist_t *props)
nblks = 2 * fnvlist_num_pairs(props);

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 {
Expand Down
4 changes: 2 additions & 2 deletions module/zfs/dsl_scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -388,7 +388,7 @@ int
dsl_scan_cancel(dsl_pool_t *dp)
{
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,
Expand Down Expand Up @@ -1848,7 +1848,7 @@ dsl_scan(dsl_pool_t *dp, pool_scan_func_t func)
(void) spa_vdev_state_exit(spa, NULL, 0);

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)
Expand Down
Loading

0 comments on commit 3d45fdd

Please sign in to comment.