Remove code for zfs remap

The "zfs remap" command was disabled by
6e91a72fe3, because it has little utility
and introduced some tricky bugs.  This commit removes the code for it,
the associated ZFS_IOC_REMAP ioctl, and tests.

Note that the ioctl and property will remain, but have no functionality.
This allows older software to fail gracefully if it attempts to use
these, and avoids a backwards incompatibility that would be introduced if
we renumbered the later ioctls/props.

Reviewed-by: Tom Caputi <tcaputi@datto.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Matthew Ahrens <mahrens@delphix.com>
Closes #8944
This commit is contained in:
Matthew Ahrens 2019-06-24 16:44:01 -07:00 committed by Brian Behlendorf
parent 53864800f6
commit 59ec30a329
40 changed files with 29 additions and 947 deletions

View File

@ -114,7 +114,6 @@ static int zfs_do_release(int argc, char **argv);
static int zfs_do_diff(int argc, char **argv);
static int zfs_do_bookmark(int argc, char **argv);
static int zfs_do_channel_program(int argc, char **argv);
static int zfs_do_remap(int argc, char **argv);
static int zfs_do_load_key(int argc, char **argv);
static int zfs_do_unload_key(int argc, char **argv);
static int zfs_do_change_key(int argc, char **argv);
@ -169,7 +168,6 @@ typedef enum {
HELP_HOLDS,
HELP_RELEASE,
HELP_DIFF,
HELP_REMAP,
HELP_BOOKMARK,
HELP_CHANNEL_PROGRAM,
HELP_LOAD_KEY,
@ -237,7 +235,6 @@ static zfs_command_t command_table[] = {
{ "holds", zfs_do_holds, HELP_HOLDS },
{ "release", zfs_do_release, HELP_RELEASE },
{ "diff", zfs_do_diff, HELP_DIFF },
{ "remap", zfs_do_remap, HELP_REMAP },
{ "load-key", zfs_do_load_key, HELP_LOAD_KEY },
{ "unload-key", zfs_do_unload_key, HELP_UNLOAD_KEY },
{ "change-key", zfs_do_change_key, HELP_CHANGE_KEY },
@ -371,8 +368,6 @@ get_usage(zfs_help_t idx)
case HELP_DIFF:
return (gettext("\tdiff [-FHt] <snapshot> "
"[snapshot|filesystem]\n"));
case HELP_REMAP:
return (gettext("\tremap <filesystem | volume>\n"));
case HELP_BOOKMARK:
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
case HELP_CHANNEL_PROGRAM:
@ -4587,7 +4582,6 @@ zfs_do_receive(int argc, char **argv)
#define ZFS_DELEG_PERM_RELEASE "release"
#define ZFS_DELEG_PERM_DIFF "diff"
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_DELEG_PERM_REMAP "remap"
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
@ -4615,7 +4609,6 @@ static zfs_deleg_perm_tab_t zfs_deleg_perm_tbl[] = {
{ ZFS_DELEG_PERM_SHARE, ZFS_DELEG_NOTE_SHARE },
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
{ ZFS_DELEG_PERM_REMAP, ZFS_DELEG_NOTE_REMAP },
{ ZFS_DELEG_PERM_LOAD_KEY, ZFS_DELEG_NOTE_LOAD_KEY },
{ ZFS_DELEG_PERM_CHANGE_KEY, ZFS_DELEG_NOTE_CHANGE_KEY },
@ -7311,21 +7304,6 @@ zfs_do_unshare(int argc, char **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
find_command_idx(char *command, int *idx)
{
@ -7429,55 +7407,6 @@ out:
return (err != 0);
}
/*
* zfs remap <filesystem | 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
zfs_do_remap(int argc, char **argv)
{
const char *fsname;
int err = 0;
int c;
/* check options */
while ((c = getopt(argc, argv, "")) != -1) {
switch (c) {
case '?':
(void) fprintf(stderr,
gettext("invalid option '%c'\n"), optopt);
usage(B_FALSE);
}
}
if (argc != 2) {
(void) fprintf(stderr, gettext("wrong number of arguments\n"));
usage(B_FALSE);
}
fsname = argv[1];
err = zfs_remap_indirects(g_zfs, fsname);
return (err);
}
/*
* zfs bookmark <fs@snap> <fs#bmark>
*
@ -8286,13 +8215,6 @@ main(int argc, char **argv)
if (strcmp(cmdname, "snap") == 0)
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 '-?'
*/

View File

@ -226,7 +226,6 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/functional/cli_root/zfs_promote/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_property/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_receive/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_remap/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_rename/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile
tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile

View File

@ -73,7 +73,6 @@ from ._libzfs_core import (
lzc_receive_with_cmdprops,
lzc_receive_with_header,
lzc_release,
lzc_remap,
lzc_reopen,
lzc_rollback,
lzc_rollback_to,
@ -129,7 +128,6 @@ __all__ = [
'lzc_receive_with_cmdprops',
'lzc_receive_with_header',
'lzc_release',
'lzc_remap',
'lzc_reopen',
'lzc_rollback',
'lzc_rollback_to',

View File

@ -550,18 +550,6 @@ def lzc_channel_program_translate_error(ret, name, error):
raise _generic_exception(ret, name, "Failed to execute channel program")
def lzc_remap_translate_error(ret, name):
if ret == 0:
return
if ret == errno.ENOENT:
raise lzc_exc.DatasetNotFound(name)
if ret == errno.EINVAL:
_validate_fs_name(name)
if ret == errno.ENOTSUP:
return lzc_exc.FeatureNotSupported(name)
raise _generic_exception(ret, name, "Failed to remap dataset")
def lzc_pool_checkpoint_translate_error(ret, name, discard=False):
if ret == 0:
return

View File

@ -1562,22 +1562,6 @@ def lzc_promote(name):
errors.lzc_promote_translate_error(ret, name)
@_uncommitted()
def lzc_remap(name):
'''
Remaps the ZFS dataset.
:param bytes name: the name of the dataset to remap.
:raises NameInvalid: if the dataset name is invalid.
:raises NameTooLong: if the dataset name is too long.
:raises DatasetNotFound: if the dataset does not exist.
:raises FeatureNotSupported: if the pool containing the dataset does not
have the *obsolete_counts* feature enabled.
'''
ret = _lib.lzc_remap(name)
errors.lzc_remap_translate_error(ret, name)
@_uncommitted()
def lzc_pool_checkpoint(name):
'''

View File

@ -127,7 +127,6 @@ CDEF = """
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
int lzc_sync(const char *, nvlist_t *, nvlist_t **);
int lzc_unload_key(const char *);
int lzc_remap(const char *);
int lzc_pool_checkpoint(const char *);
int lzc_pool_checkpoint_discard(const char *);
int lzc_rename(const char *, const char *);

View File

@ -3632,31 +3632,6 @@ zfs.sync.snapshot('""" + pool + b"""@zcp')
with self.assertRaises(lzc_exc.EncryptionKeyNotLoaded):
lzc.lzc_unload_key(fs)
def test_remap_missing_fs(self):
name = b"nonexistent"
with self.assertRaises(lzc_exc.DatasetNotFound):
lzc.lzc_remap(name)
def test_remap_invalid_fs(self):
ds = ZFSTest.pool.makeName(b"fs1")
snap = ds + b"@snap1"
lzc.lzc_snapshot([snap])
with self.assertRaises(lzc_exc.NameInvalid):
lzc.lzc_remap(snap)
def test_remap_too_long_fs_name(self):
name = ZFSTest.pool.makeTooLongName()
with self.assertRaises(lzc_exc.NameTooLong):
lzc.lzc_remap(name)
def test_remap(self):
name = ZFSTest.pool.makeName(b"fs1")
lzc.lzc_remap(name)
def test_checkpoint(self):
pool = ZFSTest.pool.getRoot().getName()

View File

@ -852,8 +852,6 @@ int zfs_smb_acl_rename(libzfs_handle_t *, char *, char *, char *, char *);
extern int zpool_enable_datasets(zpool_handle_t *, const char *, int);
extern int zpool_disable_datasets(zpool_handle_t *, boolean_t);
extern int zfs_remap_indirects(libzfs_handle_t *hdl, const char *);
#ifdef __cplusplus
}
#endif

View File

@ -49,7 +49,6 @@ enum lzc_dataset_type {
LZC_DATSET_TYPE_ZVOL
};
int lzc_remap(const char *fsname);
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *, uint8_t *,
uint_t);

View File

@ -336,8 +336,6 @@ void dbuf_unoverride(dbuf_dirty_record_t *dr);
void dbuf_sync_list(list_t *list, int level, dmu_tx_t *tx);
void dbuf_release_bp(dmu_buf_impl_t *db);
boolean_t dbuf_can_remap(const dmu_buf_impl_t *buf);
void dbuf_free_range(struct dnode *dn, uint64_t start, uint64_t end,
struct dmu_tx *);

View File

@ -342,7 +342,6 @@ int dmu_objset_find(char *name, int func(const char *, void *), void *arg,
void dmu_objset_byteswap(void *buf, size_t size);
int dsl_dataset_rename_snapshot(const char *fsname,
const char *oldsnapname, const char *newsnapname, boolean_t recursive);
int dmu_objset_remap_indirects(const char *fsname);
typedef struct dmu_buf {
uint64_t db_object; /* object that this buffer is part of */
@ -498,9 +497,6 @@ void dmu_object_set_checksum(objset_t *os, uint64_t object, uint8_t checksum,
void dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
dmu_tx_t *tx);
int dmu_object_remap_indirects(objset_t *os, uint64_t object, uint64_t txg);
void dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
int compressed_size, int byteorder, dmu_tx_t *tx);
@ -777,7 +773,6 @@ void dmu_tx_hold_free(dmu_tx_t *tx, uint64_t object, uint64_t off,
uint64_t len);
void dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
uint64_t len);
void dmu_tx_hold_remap_l1indirect(dmu_tx_t *tx, uint64_t object);
void dmu_tx_hold_zap(dmu_tx_t *tx, uint64_t object, int add, const char *name);
void dmu_tx_hold_zap_by_dnode(dmu_tx_t *tx, dnode_t *dn, int add,
const char *name);

View File

@ -440,7 +440,6 @@ int dnode_next_offset(dnode_t *dn, int flags, uint64_t *off,
void dnode_evict_dbufs(dnode_t *dn);
void dnode_evict_bonus(dnode_t *dn);
void dnode_free_interior_slots(dnode_t *dn);
boolean_t dnode_needs_remap(const dnode_t *dn);
#define DNODE_IS_DIRTY(_dn) \
((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa))

View File

@ -61,7 +61,6 @@ extern "C" {
#define ZFS_DELEG_PERM_RELEASE "release"
#define ZFS_DELEG_PERM_DIFF "diff"
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
#define ZFS_DELEG_PERM_REMAP "remap"
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
#define ZFS_DELEG_PERM_PROJECTUSED "projectused"

View File

@ -49,7 +49,6 @@ struct dsl_dataset;
#define DD_FIELD_FILESYSTEM_COUNT "com.joyent:filesystem_count"
#define DD_FIELD_SNAPSHOT_COUNT "com.joyent:snapshot_count"
#define DD_FIELD_CRYPTO_KEY_OBJ "com.datto:crypto_key_obj"
#define DD_FIELD_LAST_REMAP_TXG "com.delphix:last_remap_txg"
typedef enum dd_used {
DD_USED_HEAD,
@ -154,7 +153,6 @@ void dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv);
uint64_t dsl_dir_space_available(dsl_dir_t *dd,
dsl_dir_t *ancestor, int64_t delta, int ondiskonly);
void dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx);
int dsl_dir_get_remaptxg(dsl_dir_t *dd, uint64_t *count);
void dsl_dir_sync(dsl_dir_t *dd, dmu_tx_t *tx);
int dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t mem,
uint64_t asize, boolean_t netfree, void **tr_cookiep, dmu_tx_t *tx);
@ -172,7 +170,6 @@ int dsl_dir_activate_fs_ss_limit(const char *);
int dsl_fs_ss_limit_check(dsl_dir_t *, uint64_t, zfs_prop_t, dsl_dir_t *,
cred_t *);
void dsl_fs_ss_count_adjust(dsl_dir_t *, int64_t, const char *, dmu_tx_t *);
int dsl_dir_update_last_remap_txg(dsl_dir_t *, uint64_t);
int dsl_dir_rename(const char *oldname, const char *newname);
int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
uint64_t fs_cnt, uint64_t ss_cnt, uint64_t space, cred_t *);

View File

@ -181,7 +181,7 @@ typedef enum {
ZFS_PROP_ENCRYPTION_ROOT,
ZFS_PROP_KEY_GUID,
ZFS_PROP_KEYSTATUS,
ZFS_PROP_REMAPTXG, /* not exposed to the user */
ZFS_PROP_REMAPTXG, /* obsolete - no longer used */
ZFS_PROP_SPECIAL_SMALL_BLOCKS,
ZFS_PROP_IVSET_GUID, /* not exposed to the user */
ZFS_PROP_REDACTED,

View File

@ -77,7 +77,6 @@ typedef enum {
ZFS_DELEG_NOTE_PROJECTQUOTA,
ZFS_DELEG_NOTE_PROJECTOBJUSED,
ZFS_DELEG_NOTE_PROJECTOBJQUOTA,
ZFS_DELEG_NOTE_REMAP,
ZFS_DELEG_NOTE_NONE
} zfs_deleg_note_t;

View File

@ -4210,36 +4210,6 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
return (rv);
}
int
zfs_remap_indirects(libzfs_handle_t *hdl, const char *fs)
{
int err;
char errbuf[1024];
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot remap dataset '%s'"), fs);
err = lzc_remap(fs);
if (err != 0) {
switch (err) {
case ENOTSUP:
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"pool must be upgraded"));
(void) zfs_error(hdl, EZFS_BADVERSION, errbuf);
break;
case EINVAL:
(void) zfs_error(hdl, EZFS_BADTYPE, errbuf);
break;
default:
(void) zfs_standard_error(hdl, err, errbuf);
break;
}
}
return (err);
}
/*
* Creates snapshots. The keys in the snaps nvlist are the snapshots to be
* created.

View File

@ -306,16 +306,6 @@ lzc_promote(const char *fsname, char *snapnamebuf, int snapnamelen)
return (0);
}
int
lzc_remap(const char *fsname)
{
int error;
nvlist_t *args = fnvlist_alloc();
error = lzc_ioctl(ZFS_IOC_REMAP, fsname, args, NULL);
nvlist_free(args);
return (error);
}
int
lzc_rename(const char *source, const char *target)
{

View File

@ -52,7 +52,6 @@ zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = {
{ZFS_DELEG_PERM_MOUNT},
{ZFS_DELEG_PERM_PROMOTE},
{ZFS_DELEG_PERM_RECEIVE},
{ZFS_DELEG_PERM_REMAP},
{ZFS_DELEG_PERM_RENAME},
{ZFS_DELEG_PERM_ROLLBACK},
{ZFS_DELEG_PERM_SNAPSHOT},

View File

@ -512,8 +512,6 @@ zfs_prop_init(void)
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<uint64>", "GUID");
zprop_register_number(ZFS_PROP_CREATETXG, "createtxg", 0, PROP_READONLY,
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<uint64>", "CREATETXG");
zprop_register_hidden(ZFS_PROP_REMAPTXG, "remaptxg", PROP_TYPE_NUMBER,
PROP_READONLY, ZFS_TYPE_DATASET, "REMAPTXG");
zprop_register_number(ZFS_PROP_PBKDF2_ITERS, "pbkdf2iters",
0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
"<iters>", "PBKDF2ITERS");
@ -579,11 +577,15 @@ zfs_prop_init(void)
PROP_READONLY, ZFS_TYPE_DATASET, "REDACTED");
/*
* Property to be removed once libbe is integrated
* Properties that are obsolete and not used. These are retained so
* that we don't have to change the values of the zfs_prop_t enum, or
* have NULL pointers in the zfs_prop_table[].
*/
zprop_register_hidden(ZFS_PROP_PRIVATE, "priv_prop",
PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_FILESYSTEM,
"PRIV_PROP");
zprop_register_hidden(ZFS_PROP_REMAPTXG, "remaptxg", PROP_TYPE_NUMBER,
PROP_READONLY, ZFS_TYPE_DATASET, "REMAPTXG");
/* oddball properties */
zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0,

View File

@ -4444,60 +4444,6 @@ dbuf_remap_impl(dnode_t *dn, blkptr_t *bp, dmu_tx_t *tx)
}
}
/*
* Returns true if a dbuf_remap would modify the dbuf. We do this by attempting
* to remap a copy of every bp in the dbuf.
*/
boolean_t
dbuf_can_remap(const dmu_buf_impl_t *db)
{
spa_t *spa = dmu_objset_spa(db->db_objset);
blkptr_t *bp = db->db.db_data;
boolean_t ret = B_FALSE;
ASSERT3U(db->db_level, >, 0);
ASSERT3S(db->db_state, ==, DB_CACHED);
ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REMOVAL));
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
for (int i = 0; i < db->db.db_size >> SPA_BLKPTRSHIFT; i++) {
blkptr_t bp_copy = bp[i];
if (spa_remap_blkptr(spa, &bp_copy, NULL, NULL)) {
ret = B_TRUE;
break;
}
}
spa_config_exit(spa, SCL_VDEV, FTAG);
return (ret);
}
boolean_t
dnode_needs_remap(const dnode_t *dn)
{
spa_t *spa = dmu_objset_spa(dn->dn_objset);
boolean_t ret = B_FALSE;
if (dn->dn_phys->dn_nlevels == 0) {
return (B_FALSE);
}
ASSERT(spa_feature_is_active(spa, SPA_FEATURE_DEVICE_REMOVAL));
spa_config_enter(spa, SCL_VDEV, FTAG, RW_READER);
for (int j = 0; j < dn->dn_phys->dn_nblkptr; j++) {
blkptr_t bp_copy = dn->dn_phys->dn_blkptr[j];
if (spa_remap_blkptr(spa, &bp_copy, NULL, NULL)) {
ret = B_TRUE;
break;
}
}
spa_config_exit(spa, SCL_VDEV, FTAG);
return (ret);
}
/*
* Remap any existing BP's to concrete vdevs, if possible.
*/

View File

@ -74,13 +74,6 @@ unsigned long zfs_per_txg_dirty_frees_percent = 5;
*/
int zfs_dmu_offset_next_sync = 0;
/*
* This can be used for testing, to ensure that certain actions happen
* while in the middle of a remap (which might otherwise complete too
* quickly). Used by ztest(8).
*/
int zfs_object_remap_one_indirect_delay_ms = 0;
/*
* Limit the amount we can prefetch with one call to this amount. This
* helps to limit the amount of memory that can be used by prefetching.
@ -1114,137 +1107,6 @@ dmu_write_by_dnode(dnode_t *dn, uint64_t offset, uint64_t size,
dmu_buf_rele_array(dbp, numbufs, FTAG);
}
static int
dmu_object_remap_one_indirect(objset_t *os, dnode_t *dn,
uint64_t last_removal_txg, uint64_t offset)
{
uint64_t l1blkid = dbuf_whichblock(dn, 1, offset);
dnode_t *dn_tx;
int err = 0;
rw_enter(&dn->dn_struct_rwlock, RW_READER);
dmu_buf_impl_t *dbuf = dbuf_hold_level(dn, 1, l1blkid, FTAG);
ASSERT3P(dbuf, !=, NULL);
/*
* If the block hasn't been written yet, this default will ensure
* we don't try to remap it.
*/
uint64_t birth = UINT64_MAX;
ASSERT3U(last_removal_txg, !=, UINT64_MAX);
if (dbuf->db_blkptr != NULL)
birth = dbuf->db_blkptr->blk_birth;
rw_exit(&dn->dn_struct_rwlock);
/*
* If this L1 was already written after the last removal, then we've
* already tried to remap it. An additional hold is taken after the
* dmu_tx_assign() to handle the case where the dnode is freed while
* waiting for the next open txg.
*/
if (birth <= last_removal_txg &&
dbuf_read(dbuf, NULL, DB_RF_MUST_SUCCEED) == 0 &&
dbuf_can_remap(dbuf)) {
dmu_tx_t *tx = dmu_tx_create(os);
dmu_tx_hold_remap_l1indirect(tx, dn->dn_object);
err = dmu_tx_assign(tx, TXG_WAIT);
if (err == 0) {
err = dnode_hold(os, dn->dn_object, FTAG, &dn_tx);
if (err == 0) {
(void) dbuf_dirty(dbuf, tx);
dnode_rele(dn_tx, FTAG);
}
dmu_tx_commit(tx);
} else {
dmu_tx_abort(tx);
}
}
dbuf_rele(dbuf, FTAG);
delay(MSEC_TO_TICK(zfs_object_remap_one_indirect_delay_ms));
return (err);
}
/*
* Remap all blockpointers in the object, if possible, so that they reference
* only concrete vdevs.
*
* To do this, iterate over the L0 blockpointers and remap any that reference
* an indirect vdev. Note that we only examine L0 blockpointers; since we
* cannot guarantee that we can remap all blockpointer anyways (due to split
* blocks), we do not want to make the code unnecessarily complicated to
* catch the unlikely case that there is an L1 block on an indirect vdev that
* contains no indirect blockpointers.
*/
int
dmu_object_remap_indirects(objset_t *os, uint64_t object,
uint64_t last_removal_txg)
{
uint64_t offset, l1span;
int err;
dnode_t *dn, *dn_tx;
err = dnode_hold(os, object, FTAG, &dn);
if (err != 0) {
return (err);
}
if (dn->dn_nlevels <= 1) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
err = SET_ERROR(EINTR);
}
/*
* If the dnode has no indirect blocks, we cannot dirty them.
* We still want to remap the blkptr(s) in the dnode if
* appropriate, so mark it as dirty. An additional hold is
* taken after the dmu_tx_assign() to handle the case where
* the dnode is freed while waiting for the next open txg.
*/
if (err == 0 && dnode_needs_remap(dn)) {
dmu_tx_t *tx = dmu_tx_create(os);
dmu_tx_hold_bonus(tx, object);
err = dmu_tx_assign(tx, TXG_WAIT);
if (err == 0) {
err = dnode_hold(os, object, FTAG, &dn_tx);
if (err == 0) {
dnode_setdirty(dn_tx, tx);
dnode_rele(dn_tx, FTAG);
}
dmu_tx_commit(tx);
} else {
dmu_tx_abort(tx);
}
}
dnode_rele(dn, FTAG);
return (err);
}
offset = 0;
l1span = 1ULL << (dn->dn_indblkshift - SPA_BLKPTRSHIFT +
dn->dn_datablkshift);
/*
* Find the next L1 indirect that is not a hole.
*/
while (dnode_next_offset(dn, 0, &offset, 2, 1, 0) == 0) {
if (issig(JUSTLOOKING) && issig(FORREAL)) {
err = SET_ERROR(EINTR);
break;
}
if ((err = dmu_object_remap_one_indirect(os, dn,
last_removal_txg, offset)) != 0) {
break;
}
offset += l1span;
}
dnode_rele(dn, FTAG);
return (err);
}
void
dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
dmu_tx_t *tx)

View File

@ -1396,101 +1396,6 @@ dmu_objset_clone(const char *clone, const char *origin)
6, ZFS_SPACE_CHECK_NORMAL));
}
static int
dmu_objset_remap_indirects_impl(objset_t *os, uint64_t last_removed_txg)
{
int error = 0;
uint64_t object = 0;
while ((error = dmu_object_next(os, &object, B_FALSE, 0)) == 0) {
error = dmu_object_remap_indirects(os, object,
last_removed_txg);
/*
* If the ZPL removed the object before we managed to dnode_hold
* it, we would get an ENOENT. If the ZPL declares its intent
* to remove the object (dnode_free) before we manage to
* dnode_hold it, we would get an EEXIST. In either case, we
* want to continue remapping the other objects in the objset;
* in all other cases, we want to break early.
*/
if (error != 0 && error != ENOENT && error != EEXIST) {
break;
}
}
if (error == ESRCH) {
error = 0;
}
return (error);
}
int
dmu_objset_remap_indirects(const char *fsname)
{
int error = 0;
objset_t *os = NULL;
uint64_t last_removed_txg;
uint64_t remap_start_txg;
dsl_dir_t *dd;
error = dmu_objset_hold(fsname, FTAG, &os);
if (error != 0) {
return (error);
}
dd = dmu_objset_ds(os)->ds_dir;
if (!spa_feature_is_enabled(dmu_objset_spa(os),
SPA_FEATURE_OBSOLETE_COUNTS)) {
dmu_objset_rele(os, FTAG);
return (SET_ERROR(ENOTSUP));
}
if (dsl_dataset_is_snapshot(dmu_objset_ds(os))) {
dmu_objset_rele(os, FTAG);
return (SET_ERROR(EINVAL));
}
/*
* If there has not been a removal, we're done.
*/
last_removed_txg = spa_get_last_removal_txg(dmu_objset_spa(os));
if (last_removed_txg == -1ULL) {
dmu_objset_rele(os, FTAG);
return (0);
}
/*
* If we have remapped since the last removal, we're done.
*/
if (dsl_dir_is_zapified(dd)) {
uint64_t last_remap_txg;
if (zap_lookup(spa_meta_objset(dmu_objset_spa(os)),
dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
sizeof (last_remap_txg), 1, &last_remap_txg) == 0 &&
last_remap_txg > last_removed_txg) {
dmu_objset_rele(os, FTAG);
return (0);
}
}
dsl_dataset_long_hold(dmu_objset_ds(os), FTAG);
dsl_pool_rele(dmu_objset_pool(os), FTAG);
remap_start_txg = spa_last_synced_txg(dmu_objset_spa(os));
error = dmu_objset_remap_indirects_impl(os, last_removed_txg);
if (error == 0) {
/*
* We update the last_remap_txg to be the start txg so that
* we can guarantee that every block older than last_remap_txg
* that can be remapped has been remapped.
*/
error = dsl_dir_update_last_remap_txg(dd, remap_start_txg);
}
dsl_dataset_long_rele(dmu_objset_ds(os), FTAG);
dsl_dataset_rele(dmu_objset_ds(os), FTAG);
return (error);
}
int
dmu_objset_snapshot_one(const char *fsname, const char *snapname)
{

View File

@ -316,23 +316,6 @@ dmu_tx_hold_write(dmu_tx_t *tx, uint64_t object, uint64_t off, int len)
}
}
void
dmu_tx_hold_remap_l1indirect(dmu_tx_t *tx, uint64_t object)
{
dmu_tx_hold_t *txh;
ASSERT(tx->tx_txg == 0);
txh = dmu_tx_hold_object_impl(tx, tx->tx_objset,
object, THT_WRITE, 0, 0);
if (txh == NULL)
return;
dnode_t *dn = txh->txh_dnode;
(void) zfs_refcount_add_many(&txh->txh_space_towrite,
1ULL << dn->dn_indblkshift, FTAG);
dmu_tx_count_dnode(txh);
}
void
dmu_tx_hold_write_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
{

View File

@ -757,35 +757,6 @@ dsl_enforce_ds_ss_limits(dsl_dir_t *dd, zfs_prop_t prop, cred_t *cr)
return (enforce);
}
static void
dsl_dir_update_last_remap_txg_sync(void *varg, dmu_tx_t *tx)
{
ddulrt_arg_t *arg = varg;
uint64_t last_remap_txg;
dsl_dir_t *dd = arg->ddulrta_dd;
objset_t *mos = dd->dd_pool->dp_meta_objset;
dsl_dir_zapify(dd, tx);
if (zap_lookup(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
sizeof (last_remap_txg), 1, &last_remap_txg) != 0 ||
last_remap_txg < arg->ddlrta_txg) {
VERIFY0(zap_update(mos, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
sizeof (arg->ddlrta_txg), 1, &arg->ddlrta_txg, tx));
}
}
int
dsl_dir_update_last_remap_txg(dsl_dir_t *dd, uint64_t txg)
{
ddulrt_arg_t arg;
arg.ddulrta_dd = dd;
arg.ddlrta_txg = txg;
return (dsl_sync_task(spa_name(dd->dd_pool->dp_spa),
NULL, dsl_dir_update_last_remap_txg_sync, &arg,
1, ZFS_SPACE_CHECK_RESERVED));
}
/*
* Check if adding additional child filesystem(s) would exceed any filesystem
* limits or adding additional snapshot(s) would exceed any snapshot limits.
@ -1083,19 +1054,6 @@ dsl_dir_get_snapshot_count(dsl_dir_t *dd, uint64_t *count)
}
}
int
dsl_dir_get_remaptxg(dsl_dir_t *dd, uint64_t *count)
{
if (dsl_dir_is_zapified(dd)) {
objset_t *os = dd->dd_pool->dp_meta_objset;
return (zap_lookup(os, dd->dd_object, DD_FIELD_LAST_REMAP_TXG,
sizeof (*count), 1, count));
} else {
return (ENOENT);
}
}
void
dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
{
@ -1127,10 +1085,6 @@ dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOT_COUNT,
count);
}
if (dsl_dir_get_remaptxg(dd, &count) == 0) {
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_REMAPTXG,
count);
}
if (dsl_dir_is_clone(dd)) {
char buf[ZFS_MAX_DATASET_NAME_LEN];

View File

@ -1045,14 +1045,6 @@ zfs_secpolicy_bookmark(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
return (error);
}
/* ARGSUSED */
static int
zfs_secpolicy_remap(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
{
return (zfs_secpolicy_write_perms(zc->zc_name,
ZFS_DELEG_PERM_REMAP, cr));
}
/* ARGSUSED */
static int
zfs_secpolicy_destroy_bookmarks(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
@ -3447,11 +3439,8 @@ static const zfs_ioc_key_t zfs_keys_remap[] = {
static int
zfs_ioc_remap(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
{
if (strchr(fsname, '@') ||
strchr(fsname, '%'))
return (SET_ERROR(EINVAL));
return (dmu_objset_remap_indirects(fsname));
/* This IOCTL is no longer supported. */
return (0);
}
/*
@ -6790,7 +6779,7 @@ zfs_ioctl_init(void)
zfs_keys_clone, ARRAY_SIZE(zfs_keys_clone));
zfs_ioctl_register("remap", ZFS_IOC_REMAP,
zfs_ioc_remap, zfs_secpolicy_remap, DATASET_NAME,
zfs_ioc_remap, zfs_secpolicy_none, DATASET_NAME,
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE,
zfs_keys_remap, ARRAY_SIZE(zfs_keys_remap));

View File

@ -210,10 +210,6 @@ tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
'zfs_receive_raw_incremental', 'zfs_receive_-e']
tags = ['functional', 'cli_root', 'zfs_receive']
[tests/functional/cli_root/zfs_remap]
tests = ['zfs_remap_cliargs', 'zfs_remap_obsolete_counts']
tags = ['functional', 'cli_root', 'zfs_remap']
[tests/functional/cli_root/zfs_rename]
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',
'zfs_rename_004_neg', 'zfs_rename_005_neg', 'zfs_rename_006_pos',
@ -767,11 +763,11 @@ tags = ['functional', 'refreserv']
pre =
tests = ['removal_all_vdev', 'removal_check_space',
'removal_condense_export', 'removal_multiple_indirection',
'removal_remap', 'removal_remap_deadlists',
'removal_remap_deadlists',
'removal_resume_export', 'removal_sanity', 'removal_with_add',
'removal_with_create_fs', 'removal_with_dedup',
'removal_with_errors', 'removal_with_export',
'removal_with_ganging', 'removal_with_faulted', 'removal_with_remap',
'removal_with_ganging', 'removal_with_faulted',
'removal_with_remove', 'removal_with_scrub', 'removal_with_send',
'removal_with_send_recv', 'removal_with_snapshot',
'removal_with_write', 'removal_with_zdb', 'remove_expanded',

View File

@ -186,7 +186,6 @@ known = {
'inuse/inuse_007_pos': ['SKIP', na_reason],
'privilege/setup': ['SKIP', na_reason],
'refreserv/refreserv_004_pos': ['FAIL', known_reason],
'removal/removal_condense_export': ['SKIP', known_reason],
'removal/removal_with_zdb': ['SKIP', known_reason],
'rootpool/setup': ['SKIP', na_reason],
'rsend/rsend_008_pos': ['SKIP', '6066'],

View File

@ -93,14 +93,7 @@ for i in 1 2 3 4; do
log_must file_in_special_vdev $dataset $inum
done
#
# 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 zfs remap $TESTPOOL/$TESTFS
sleep 5
log_must sync_pool $TESTPOOL

View File

@ -20,7 +20,6 @@ SUBDIRS = \
zfs_promote \
zfs_property \
zfs_receive \
zfs_remap \
zfs_rename \
zfs_reservation \
zfs_rollback \

View File

@ -1,7 +0,0 @@
pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/cli_root/zfs_remap
dist_pkgdata_SCRIPTS = \
setup.ksh \
cleanup.ksh \
zfs_remap_cliargs.ksh \
zfs_remap_obsolete_counts.ksh

View File

@ -1,19 +0,0 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
default_cleanup

View File

@ -1,17 +0,0 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib

View File

@ -1,81 +0,0 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/removal/removal.kshlib
#
# DESCRIPTION:
# 'zfs remap' should only work with supported parameters.
#
# STRATEGY:
# 1. Prepare a pool where a top-level VDEV has been removed
# 2. Verify every supported parameter to 'zfs remap' is accepted
# 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"
function cleanup
{
destroy_pool $TESTPOOL
rm -f $DISK1 $DISK2
}
log_assert "'zfs remap' should only work with supported parameters"
log_onexit cleanup
f="$TESTPOOL/fs"
v="$TESTPOOL/vol"
s="$TESTPOOL/fs@snap"
b="$TESTPOOL/fs#bmark"
c="$TESTPOOL/clone"
typeset goodparams=("$f" "$v" "$c")
typeset badparams=("-H" "-p" "-?" "$s" "$b" "$f $f" "$f $v" "$f $s")
DISK1="$TEST_BASE_DIR/zfs_remap-1"
DISK2="$TEST_BASE_DIR/zfs_remap-2"
# 1. Prepare a pool where a top-level VDEV has been removed
log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK1
log_must zpool create $TESTPOOL $DISK1
log_must zfs create $f
log_must zfs create -V 1M -s $v
log_must zfs snap $s
log_must zfs bookmark $s $b
log_must zfs clone $s $c
log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK2
log_must zpool add $TESTPOOL $DISK2
log_must zpool remove $TESTPOOL $DISK1
log_must wait_for_removal $TESTPOOL
# 2. Verify every supported parameter to 'zfs remap' is accepted
for param in "${goodparams[@]}"
do
log_must zfs remap $param
done
# 3. Verify other unsupported parameters raise an error
for param in "${badparams[@]}"
do
log_mustnot zfs remap $param
done
log_pass "'zfs remap' only works with supported parameters"

View File

@ -1,79 +0,0 @@
#!/bin/ksh -p
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
#
# Copyright 2018, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/removal/removal.kshlib
#
# DESCRIPTION:
# 'zfs remap' depends on 'feature@obsolete_counts' being active
#
# STRATEGY:
# 1. Prepare a pool where a top-level VDEV has been removed and with
# feature@obsolete_counts disabled
# 2. Verify any 'zfs remap' command cannot be executed
# 3. Verify the same commands complete successfully when
# 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"
function cleanup
{
destroy_pool $TESTPOOL
rm -f $DISK1 $DISK2
}
log_assert "'zfs remap' depends on feature@obsolete_counts being active"
log_onexit cleanup
f="$TESTPOOL/fs"
v="$TESTPOOL/vol"
s="$TESTPOOL/fs@snap"
c="$TESTPOOL/clone"
DISK1="$TEST_BASE_DIR/zfs_remap-1"
DISK2="$TEST_BASE_DIR/zfs_remap-2"
# 1. Prepare a pool where a top-level VDEV has been removed with
# feature@obsolete_counts disabled
log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK1
log_must zpool create -o feature@obsolete_counts=disabled $TESTPOOL $DISK1
log_must zfs create $f
log_must zfs create -V 1M -s $v
log_must zfs snap $s
log_must zfs clone $s $c
log_must truncate -s $(($MINVDEVSIZE * 2)) $DISK2
log_must zpool add $TESTPOOL $DISK2
log_must zpool remove $TESTPOOL $DISK1
log_must wait_for_removal $TESTPOOL
# 2. Verify any 'zfs remap' command cannot be executed
log_mustnot zfs remap $f
log_mustnot zfs remap $v
log_mustnot zfs remap $c
# 3. Verify the same commands complete successfully when
# feature@obsolete_counts is enabled
log_must zpool set feature@obsolete_counts=enabled $TESTPOOL
log_must zfs remap $f
log_must zfs remap $v
log_must zfs remap $c
log_pass "'zfs remap' correctly depends on feature@obsolete_counts being active"

View File

@ -18,12 +18,12 @@ pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/removal
dist_pkgdata_SCRIPTS = \
cleanup.ksh removal_all_vdev.ksh removal_check_space.ksh \
removal_condense_export.ksh removal_multiple_indirection.ksh \
removal_remap_deadlists.ksh removal_remap.ksh \
removal_remap_deadlists.ksh \
removal_reservation.ksh removal_resume_export.ksh \
removal_sanity.ksh removal_with_add.ksh removal_with_create_fs.ksh \
removal_with_dedup.ksh removal_with_errors.ksh \
removal_with_export.ksh removal_with_faulted.ksh \
removal_with_ganging.ksh removal_with_remap.ksh \
removal_with_ganging.ksh \
removal_with_remove.ksh removal_with_scrub.ksh \
removal_with_send.ksh removal_with_send_recv.ksh \
removal_with_snapshot.ksh removal_with_write.ksh \

View File

@ -21,10 +21,6 @@
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/removal/removal.kshlib
if is_linux; then
log_unsupported "ZDB fails during concurrent pool activity."
fi
function reset
{
log_must set_tunable64 zfs_condense_indirect_commit_entry_delay_ms 0
@ -77,7 +73,14 @@ log_must zpool remove $TESTPOOL $REMOVEDISK
log_must wait_for_removal $TESTPOOL
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
log_must zfs remap $TESTPOOL/$TESTFS
#
# Touch one block under each L1 indirect block, so that the other data blocks
# will be remapped to their concrete locations. These parameters assume
# recordsize=512, indirect block size of 128K (1024 block pointers per
# indirect block), and file size of less than 20*1024 blocks (10MB).
#
log_must stride_dd -i /dev/urandom -o $TESTDIR/file -b 512 -c 20 -s 1024
sync_pool $TESTPOOL
sleep 5
sync_pool $TESTPOOL

View File

@ -1,126 +0,0 @@
#! /bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2015, 2016 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $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"
function cleanup
{
set_tunable64 zfs_condense_min_mapping_bytes 131072
default_cleanup_noexit
}
log_onexit cleanup
log_must set_tunable64 zfs_condense_min_mapping_bytes 1
log_must zfs set recordsize=512 $TESTPOOL/$TESTFS
#
# Create a large file so that we know some of the blocks will be on the
# removed device, and hence eligible for remapping.
#
log_must dd if=/dev/urandom of=$TESTDIR/file bs=$((2**12)) count=$((2**9))
#
# Randomly rewrite some of blocks in the file so that there will be holes and
# we will not be able to remap the entire file in a few huge chunks.
#
for i in $(seq $((2**12))); do
#
# We have to sync periodically so that all the writes don't end up in
# the same txg. If they were all in the same txg, only the last write
# would go through and we would not have as many allocations to
# fragment the file.
#
((i % 100 > 0 )) || sync_pool || log_fail "Could not sync."
random_write $TESTDIR/file $((2**9)) || \
log_fail "Could not random write."
done
#
# Remap should quietly succeed as a noop before a removal.
#
log_must zfs remap $TESTPOOL/$TESTFS
remaptxg_before=$(zfs get -H -o value remaptxg $TESTPOOL/$TESTFS)
(( $? == 0 )) || log_fail "Could not get remaptxg."
[[ $remaptxg_before == "-" ]] || \
log_fail "remaptxg ($remaptxg_before) had value before a removal"
log_must zpool remove $TESTPOOL $REMOVEDISK
log_must wait_for_removal $TESTPOOL
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
#
# remaptxg should not be set if we haven't done a remap.
#
remaptxg_before=$(zfs get -H -o value remaptxg $TESTPOOL/$TESTFS)
(( $? == 0 )) || log_fail "Could not get remaptxg."
[[ $remaptxg_before == "-" ]] || \
log_fail "remaptxg ($remaptxg_before) had value before a removal"
mapping_size_before=$(indirect_vdev_mapping_size $TESTPOOL)
log_must zfs remap $TESTPOOL/$TESTFS
# Try to wait for a condense to finish.
for i in {1..5}; do
sleep 5
sync_pool
done
mapping_size_after=$(indirect_vdev_mapping_size $TESTPOOL)
#
# After the remap, there should not be very many blocks referenced. The reason
# why our threshold is as high as 512 is because our ratio of metadata to
# user data is relatively high, with only 64M of user data on the file system.
#
(( mapping_size_after < mapping_size_before )) || \
log_fail "Mapping size did not decrease after remap: " \
"$mapping_size_before before to $mapping_size_after after."
(( mapping_size_after < 512 )) || \
log_fail "Mapping size not small enough after remap: " \
"$mapping_size_before before to $mapping_size_after after."
#
# After a remap, the remaptxg should be set to a non-zero value.
#
remaptxg_after=$(zfs get -H -o value remaptxg $TESTPOOL/$TESTFS)
(( $? == 0 )) || log_fail "Could not get remaptxg."
log_note "remap txg after remap is $remaptxg_after"
(( remaptxg_after > 0 )) || log_fail "remaptxg not increased"
#
# Remap should quietly succeed as a noop if there have been no removals since
# the last remap.
#
log_must zfs remap $TESTPOOL/$TESTFS
remaptxg_again=$(zfs get -H -o value remaptxg $TESTPOOL/$TESTFS)
(( $? == 0 )) || log_fail "Could not get remaptxg."
log_note "remap txg after second remap is $remaptxg_again"
(( remaptxg_again == remaptxg_after )) || \
log_fail "remap not noop if there has been no removal"
log_pass "Remapping a fs caused mapping size to decrease."

View File

@ -21,9 +21,6 @@
. $STF_SUITE/include/libtest.shlib
. $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"
log_onexit default_cleanup_noexit
@ -45,7 +42,14 @@ fi
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
log_must zdb -cd $TESTPOOL
log_must zfs remap $TESTPOOL/$TESTFS
#
# Touch one block under each L1 indirect block, so that the other data blocks
# will be remapped to their concrete locations. These parameters assume
# recordsize=128K, indirect block size of 128K (1024 block pointers per
# indirect block), and file size of less than 3*1024 blocks (384MB).
#
log_must stride_dd -i /dev/urandom -o $TESTDIR/file -b 131072 -c 3 -s 1024
log_must zdb -cd $TESTPOOL
log_must zfs snapshot $TESTPOOL/$TESTFS@snap-post3

View File

@ -1,32 +0,0 @@
#! /bin/ksh -p
#
# CDDL HEADER START
#
# This file and its contents are supplied under the terms of the
# Common Development and Distribution License ("CDDL"), version 1.0.
# You may only use this file in accordance with the terms of version
# 1.0 of the CDDL.
#
# A full copy of the text of the CDDL should have accompanied this
# source. A copy of the CDDL is also available via the Internet at
# http://www.illumos.org/license/CDDL.
#
# CDDL HEADER END
#
#
# Copyright (c) 2015, 2017 by Delphix. All rights reserved.
#
. $STF_SUITE/include/libtest.shlib
. $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"
log_onexit default_cleanup_noexit
test_removal_with_operation zfs remap $TESTPOOL/$TESTFS
log_pass "Can remap a filesystem during removal"