Disable 'zfs remap' command
The implementation of 'zfs remap' has proven to be problematic since it modifies the objset (but not its logical contents) by dirtying metadata without owning it. The consequence of which is that dmu_objset_remap_indirects() is vulnerable to certain races. For example, if we are in the middle of receiving into the filesystem while it is being remapped. Then it is possible we could evict the objset when the receive completes (see dsl_dataset_clone_swap_sync_impl, or dmu_recv_end_sync), but dmu_objset_remap_indirects() may be still using the objset. The result of which would be a panic. Extended runs of ztest(8) have exposed other possible races which can occur when using 'zfs remap'. Several of these have been fixed but there may be others which have not yet been encountered and diagnosed. Furthermore, the ability to manually remap a filesystem is no longer particularly useful now that the removal code can map large chunks. Coupled with the fact that explaining what this command does and why it may be useful requires a detailed understanding of the internals of device removal. These are details users should not be bothered with. Therefore, the 'zfs remap' command is being disabled but not entirely removed. It may be removed in the future or potentially reworked to address the issues described above. Since 'zfs remap' has never been part of a tagged release its removal is expected to have minimal impact. The ZTS tests have been updated to continue to exercise the command to prevent atrophy, but it has been removed entirely from ztest(8). Reviewed by: Matt Ahrens <mahrens@delphix.com> Reviewed by: Tom Caputi <tcaputi@datto.com> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Closes #8238
This commit is contained in:
parent
5e7f3ace58
commit
6e91a72fe3
|
@ -7083,6 +7083,21 @@ zfs_do_unshare(int argc, char **argv)
|
||||||
return (unshare_unmount(OP_SHARE, argc, argv));
|
return (unshare_unmount(OP_SHARE, argc, argv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
disable_command_idx(char *command)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NCOMMAND; i++) {
|
||||||
|
if (command_table[i].name == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(command, command_table[i].name) == 0) {
|
||||||
|
command_table[i].name = NULL;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
find_command_idx(char *command, int *idx)
|
find_command_idx(char *command, int *idx)
|
||||||
{
|
{
|
||||||
|
@ -7180,7 +7195,22 @@ zfs_do_diff(int argc, char **argv)
|
||||||
/*
|
/*
|
||||||
* zfs remap <filesystem | volume>
|
* zfs remap <filesystem | volume>
|
||||||
*
|
*
|
||||||
* Remap the indirect blocks in the given fileystem or volume.
|
* N.B. The remap command has been disabled and may be removed in the future.
|
||||||
|
*
|
||||||
|
* Remap the indirect blocks in the given filesystem or volume so that they no
|
||||||
|
* longer reference blocks on previously removed vdevs and we can eventually
|
||||||
|
* shrink the size of the indirect mapping objects for the previously removed
|
||||||
|
* vdevs. Note that remapping all blocks might not be possible and that
|
||||||
|
* references from snapshots will still exist and cannot be remapped.
|
||||||
|
*
|
||||||
|
* This functionality is no longer particularly useful now that the removal
|
||||||
|
* code can map large chunks. Furthermore, explaining what this command
|
||||||
|
* does and why it may be useful requires a detailed understanding of the
|
||||||
|
* internals of device removal. These are details users should not be
|
||||||
|
* bothered with. If required, the remap command can be re-enabled by
|
||||||
|
* setting the ZFS_REMAP_ENABLED environment variable.
|
||||||
|
*
|
||||||
|
* > ZFS_REMAP_ENABLED=yes zfs remap <filesystem | volume>
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
zfs_do_remap(int argc, char **argv)
|
zfs_do_remap(int argc, char **argv)
|
||||||
|
@ -8006,6 +8036,13 @@ main(int argc, char **argv)
|
||||||
if (strcmp(cmdname, "snap") == 0)
|
if (strcmp(cmdname, "snap") == 0)
|
||||||
cmdname = "snapshot";
|
cmdname = "snapshot";
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The 'remap' command has been disabled and may be removed in the
|
||||||
|
* future. See the comment above zfs_do_remap() for details.
|
||||||
|
*/
|
||||||
|
if (!libzfs_envvar_is_set("ZFS_REMAP_ENABLED"))
|
||||||
|
disable_command_idx("remap");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Special case '-?'
|
* Special case '-?'
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -216,7 +216,6 @@ extern int dmu_object_alloc_chunk_shift;
|
||||||
extern boolean_t zfs_force_some_double_word_sm_entries;
|
extern boolean_t zfs_force_some_double_word_sm_entries;
|
||||||
extern unsigned long zio_decompress_fail_fraction;
|
extern unsigned long zio_decompress_fail_fraction;
|
||||||
extern unsigned long zfs_reconstruct_indirect_damage_fraction;
|
extern unsigned long zfs_reconstruct_indirect_damage_fraction;
|
||||||
extern int zfs_object_remap_one_indirect_delay_ms;
|
|
||||||
|
|
||||||
|
|
||||||
static ztest_shared_opts_t *ztest_shared_opts;
|
static ztest_shared_opts_t *ztest_shared_opts;
|
||||||
|
@ -373,7 +372,6 @@ ztest_func_t ztest_split_pool;
|
||||||
ztest_func_t ztest_reguid;
|
ztest_func_t ztest_reguid;
|
||||||
ztest_func_t ztest_spa_upgrade;
|
ztest_func_t ztest_spa_upgrade;
|
||||||
ztest_func_t ztest_device_removal;
|
ztest_func_t ztest_device_removal;
|
||||||
ztest_func_t ztest_remap_blocks;
|
|
||||||
ztest_func_t ztest_spa_checkpoint_create_discard;
|
ztest_func_t ztest_spa_checkpoint_create_discard;
|
||||||
ztest_func_t ztest_initialize;
|
ztest_func_t ztest_initialize;
|
||||||
ztest_func_t ztest_fletcher;
|
ztest_func_t ztest_fletcher;
|
||||||
|
@ -427,7 +425,6 @@ ztest_info_t ztest_info[] = {
|
||||||
ZTI_INIT(ztest_vdev_class_add, 1, &ztest_opts.zo_vdevtime),
|
ZTI_INIT(ztest_vdev_class_add, 1, &ztest_opts.zo_vdevtime),
|
||||||
ZTI_INIT(ztest_vdev_aux_add_remove, 1, &ztest_opts.zo_vdevtime),
|
ZTI_INIT(ztest_vdev_aux_add_remove, 1, &ztest_opts.zo_vdevtime),
|
||||||
ZTI_INIT(ztest_device_removal, 1, &zopt_sometimes),
|
ZTI_INIT(ztest_device_removal, 1, &zopt_sometimes),
|
||||||
ZTI_INIT(ztest_remap_blocks, 1, &zopt_sometimes),
|
|
||||||
ZTI_INIT(ztest_spa_checkpoint_create_discard, 1, &zopt_rarely),
|
ZTI_INIT(ztest_spa_checkpoint_create_discard, 1, &zopt_rarely),
|
||||||
ZTI_INIT(ztest_initialize, 1, &zopt_sometimes),
|
ZTI_INIT(ztest_initialize, 1, &zopt_sometimes),
|
||||||
ZTI_INIT(ztest_fletcher, 1, &zopt_rarely),
|
ZTI_INIT(ztest_fletcher, 1, &zopt_rarely),
|
||||||
|
@ -5550,20 +5547,6 @@ ztest_dsl_prop_get_set(ztest_ds_t *zd, uint64_t id)
|
||||||
(void) pthread_rwlock_unlock(&ztest_name_lock);
|
(void) pthread_rwlock_unlock(&ztest_name_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
void
|
|
||||||
ztest_remap_blocks(ztest_ds_t *zd, uint64_t id)
|
|
||||||
{
|
|
||||||
(void) pthread_rwlock_rdlock(&ztest_name_lock);
|
|
||||||
|
|
||||||
int error = dmu_objset_remap_indirects(zd->zd_name);
|
|
||||||
if (error == ENOSPC)
|
|
||||||
error = 0;
|
|
||||||
ASSERT0(error);
|
|
||||||
|
|
||||||
(void) pthread_rwlock_unlock(&ztest_name_lock);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
/* ARGSUSED */
|
||||||
void
|
void
|
||||||
ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
|
ztest_spa_prop_get_set(ztest_ds_t *zd, uint64_t id)
|
||||||
|
@ -6629,12 +6612,6 @@ ztest_resume_thread(void *arg)
|
||||||
*/
|
*/
|
||||||
if (ztest_random(10) == 0)
|
if (ztest_random(10) == 0)
|
||||||
zfs_abd_scatter_enabled = ztest_random(2);
|
zfs_abd_scatter_enabled = ztest_random(2);
|
||||||
|
|
||||||
/*
|
|
||||||
* Periodically inject remapping delays (10% of the time).
|
|
||||||
*/
|
|
||||||
zfs_object_remap_one_indirect_delay_ms =
|
|
||||||
ztest_random(10) == 0 ? ztest_random(1000) + 1 : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_exit();
|
thread_exit();
|
||||||
|
|
|
@ -475,8 +475,7 @@ DEPENDENCIES device_removal
|
||||||
This feature is an enhancement of device_removal, which will over time
|
This feature is an enhancement of device_removal, which will over time
|
||||||
reduce the memory used to track removed devices. When indirect blocks
|
reduce the memory used to track removed devices. When indirect blocks
|
||||||
are freed or remapped, we note that their part of the indirect mapping
|
are freed or remapped, we note that their part of the indirect mapping
|
||||||
is "obsolete", i.e. no longer needed. See also the \fBzfs remap\fR
|
is "obsolete", i.e. no longer needed.
|
||||||
subcommand in \fBzfs\fR(1M).
|
|
||||||
|
|
||||||
This feature becomes \fBactive\fR when the "zpool remove" command is
|
This feature becomes \fBactive\fR when the "zpool remove" command is
|
||||||
used on a top-level vdev, and will never return to being \fBenabled\fR.
|
used on a top-level vdev, and will never return to being \fBenabled\fR.
|
||||||
|
|
|
@ -103,9 +103,6 @@
|
||||||
.Oo Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... Oc
|
.Oo Fl t Ar type Ns Oo , Ns Ar type Oc Ns ... Oc
|
||||||
.Oo Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Oc Ns ...
|
.Oo Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Oc Ns ...
|
||||||
.Nm
|
.Nm
|
||||||
.Cm remap
|
|
||||||
.Ar filesystem Ns | Ns Ar volume
|
|
||||||
.Nm
|
|
||||||
.Cm set
|
.Cm set
|
||||||
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns ...
|
.Ar property Ns = Ns Ar value Oo Ar property Ns = Ns Ar value Oc Ns ...
|
||||||
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ...
|
.Ar filesystem Ns | Ns Ar volume Ns | Ns Ar snapshot Ns ...
|
||||||
|
@ -3037,16 +3034,6 @@ option was not specified.
|
||||||
.El
|
.El
|
||||||
.It Xo
|
.It Xo
|
||||||
.Nm
|
.Nm
|
||||||
.Cm remap
|
|
||||||
.Ar filesystem Ns | Ns Ar volume
|
|
||||||
.Xc
|
|
||||||
Remap the indirect blocks in the given fileystem or volume so that they no
|
|
||||||
longer reference blocks on previously removed vdevs and we can eventually
|
|
||||||
shrink the size of the indirect mapping objects for the previously removed
|
|
||||||
vdevs. Note that remapping all blocks might not be possible and that
|
|
||||||
references from snapshots will still exist and cannot be remapped.
|
|
||||||
.It Xo
|
|
||||||
.Nm
|
|
||||||
.Cm upgrade
|
.Cm upgrade
|
||||||
.Xc
|
.Xc
|
||||||
Displays a list of file systems that are not the most recent version.
|
Displays a list of file systems that are not the most recent version.
|
||||||
|
|
|
@ -55,7 +55,10 @@ log_must zpool list -v $TESTPOOL
|
||||||
|
|
||||||
#
|
#
|
||||||
# remove a special allocation vdev and force a remapping
|
# remove a special allocation vdev and force a remapping
|
||||||
|
# N.B. The 'zfs remap' command has been disabled and may be removed.
|
||||||
#
|
#
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
log_must zpool remove $TESTPOOL $CLASS_DISK0
|
log_must zpool remove $TESTPOOL $CLASS_DISK0
|
||||||
log_must zfs remap $TESTPOOL/$TESTFS
|
log_must zfs remap $TESTPOOL/$TESTFS
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,9 @@
|
||||||
# 3. Verify other unsupported parameters raise an error
|
# 3. Verify other unsupported parameters raise an error
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# The 'zfs remap' command has been disabled and may be removed.
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
verify_runnable "both"
|
verify_runnable "both"
|
||||||
|
|
||||||
function cleanup
|
function cleanup
|
||||||
|
|
|
@ -29,6 +29,9 @@
|
||||||
# feature@obsolete_counts is enabled
|
# feature@obsolete_counts is enabled
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# N.B. The 'zfs remap' command has been disabled and may be removed.
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
verify_runnable "both"
|
verify_runnable "both"
|
||||||
|
|
||||||
function cleanup
|
function cleanup
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
. $STF_SUITE/include/libtest.shlib
|
. $STF_SUITE/include/libtest.shlib
|
||||||
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
||||||
|
|
||||||
|
# N.B. The 'zfs remap' command has been disabled and may be removed.
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
default_setup_noexit "$DISKS"
|
default_setup_noexit "$DISKS"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
. $STF_SUITE/include/libtest.shlib
|
. $STF_SUITE/include/libtest.shlib
|
||||||
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
||||||
|
|
||||||
|
# N.B. The 'zfs remap' command has been disabled and may be removed.
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
default_setup_noexit "$DISKS"
|
default_setup_noexit "$DISKS"
|
||||||
log_onexit default_cleanup_noexit
|
log_onexit default_cleanup_noexit
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
. $STF_SUITE/include/libtest.shlib
|
. $STF_SUITE/include/libtest.shlib
|
||||||
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
||||||
|
|
||||||
|
# N.B. The 'zfs remap' command has been disabled and may be removed.
|
||||||
|
export ZFS_REMAP_ENABLED=YES
|
||||||
|
|
||||||
default_setup_noexit "$DISKS"
|
default_setup_noexit "$DISKS"
|
||||||
log_onexit default_cleanup_noexit
|
log_onexit default_cleanup_noexit
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue