mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-12-25 18:59:33 +03:00
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:
parent
53864800f6
commit
59ec30a329
@ -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_diff(int argc, char **argv);
|
||||||
static int zfs_do_bookmark(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_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_load_key(int argc, char **argv);
|
||||||
static int zfs_do_unload_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);
|
static int zfs_do_change_key(int argc, char **argv);
|
||||||
@ -169,7 +168,6 @@ typedef enum {
|
|||||||
HELP_HOLDS,
|
HELP_HOLDS,
|
||||||
HELP_RELEASE,
|
HELP_RELEASE,
|
||||||
HELP_DIFF,
|
HELP_DIFF,
|
||||||
HELP_REMAP,
|
|
||||||
HELP_BOOKMARK,
|
HELP_BOOKMARK,
|
||||||
HELP_CHANNEL_PROGRAM,
|
HELP_CHANNEL_PROGRAM,
|
||||||
HELP_LOAD_KEY,
|
HELP_LOAD_KEY,
|
||||||
@ -237,7 +235,6 @@ static zfs_command_t command_table[] = {
|
|||||||
{ "holds", zfs_do_holds, HELP_HOLDS },
|
{ "holds", zfs_do_holds, HELP_HOLDS },
|
||||||
{ "release", zfs_do_release, HELP_RELEASE },
|
{ "release", zfs_do_release, HELP_RELEASE },
|
||||||
{ "diff", zfs_do_diff, HELP_DIFF },
|
{ "diff", zfs_do_diff, HELP_DIFF },
|
||||||
{ "remap", zfs_do_remap, HELP_REMAP },
|
|
||||||
{ "load-key", zfs_do_load_key, HELP_LOAD_KEY },
|
{ "load-key", zfs_do_load_key, HELP_LOAD_KEY },
|
||||||
{ "unload-key", zfs_do_unload_key, HELP_UNLOAD_KEY },
|
{ "unload-key", zfs_do_unload_key, HELP_UNLOAD_KEY },
|
||||||
{ "change-key", zfs_do_change_key, HELP_CHANGE_KEY },
|
{ "change-key", zfs_do_change_key, HELP_CHANGE_KEY },
|
||||||
@ -371,8 +368,6 @@ get_usage(zfs_help_t idx)
|
|||||||
case HELP_DIFF:
|
case HELP_DIFF:
|
||||||
return (gettext("\tdiff [-FHt] <snapshot> "
|
return (gettext("\tdiff [-FHt] <snapshot> "
|
||||||
"[snapshot|filesystem]\n"));
|
"[snapshot|filesystem]\n"));
|
||||||
case HELP_REMAP:
|
|
||||||
return (gettext("\tremap <filesystem | volume>\n"));
|
|
||||||
case HELP_BOOKMARK:
|
case HELP_BOOKMARK:
|
||||||
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
|
return (gettext("\tbookmark <snapshot> <bookmark>\n"));
|
||||||
case HELP_CHANNEL_PROGRAM:
|
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_RELEASE "release"
|
||||||
#define ZFS_DELEG_PERM_DIFF "diff"
|
#define ZFS_DELEG_PERM_DIFF "diff"
|
||||||
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
|
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
|
||||||
#define ZFS_DELEG_PERM_REMAP "remap"
|
|
||||||
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
|
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
|
||||||
#define ZFS_DELEG_PERM_CHANGE_KEY "change-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_SHARE, ZFS_DELEG_NOTE_SHARE },
|
||||||
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
|
{ ZFS_DELEG_PERM_SNAPSHOT, ZFS_DELEG_NOTE_SNAPSHOT },
|
||||||
{ ZFS_DELEG_PERM_BOOKMARK, ZFS_DELEG_NOTE_BOOKMARK },
|
{ 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_LOAD_KEY, ZFS_DELEG_NOTE_LOAD_KEY },
|
||||||
{ ZFS_DELEG_PERM_CHANGE_KEY, ZFS_DELEG_NOTE_CHANGE_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));
|
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)
|
||||||
{
|
{
|
||||||
@ -7429,55 +7407,6 @@ out:
|
|||||||
return (err != 0);
|
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>
|
* zfs bookmark <fs@snap> <fs#bmark>
|
||||||
*
|
*
|
||||||
@ -8286,13 +8215,6 @@ 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 '-?'
|
||||||
*/
|
*/
|
||||||
|
@ -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_promote/Makefile
|
||||||
tests/zfs-tests/tests/functional/cli_root/zfs_property/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_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_rename/Makefile
|
||||||
tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile
|
tests/zfs-tests/tests/functional/cli_root/zfs_reservation/Makefile
|
||||||
tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile
|
tests/zfs-tests/tests/functional/cli_root/zfs_rollback/Makefile
|
||||||
|
@ -73,7 +73,6 @@ from ._libzfs_core import (
|
|||||||
lzc_receive_with_cmdprops,
|
lzc_receive_with_cmdprops,
|
||||||
lzc_receive_with_header,
|
lzc_receive_with_header,
|
||||||
lzc_release,
|
lzc_release,
|
||||||
lzc_remap,
|
|
||||||
lzc_reopen,
|
lzc_reopen,
|
||||||
lzc_rollback,
|
lzc_rollback,
|
||||||
lzc_rollback_to,
|
lzc_rollback_to,
|
||||||
@ -129,7 +128,6 @@ __all__ = [
|
|||||||
'lzc_receive_with_cmdprops',
|
'lzc_receive_with_cmdprops',
|
||||||
'lzc_receive_with_header',
|
'lzc_receive_with_header',
|
||||||
'lzc_release',
|
'lzc_release',
|
||||||
'lzc_remap',
|
|
||||||
'lzc_reopen',
|
'lzc_reopen',
|
||||||
'lzc_rollback',
|
'lzc_rollback',
|
||||||
'lzc_rollback_to',
|
'lzc_rollback_to',
|
||||||
|
@ -550,18 +550,6 @@ def lzc_channel_program_translate_error(ret, name, error):
|
|||||||
raise _generic_exception(ret, name, "Failed to execute channel program")
|
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):
|
def lzc_pool_checkpoint_translate_error(ret, name, discard=False):
|
||||||
if ret == 0:
|
if ret == 0:
|
||||||
return
|
return
|
||||||
|
@ -1562,22 +1562,6 @@ def lzc_promote(name):
|
|||||||
errors.lzc_promote_translate_error(ret, 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()
|
@_uncommitted()
|
||||||
def lzc_pool_checkpoint(name):
|
def lzc_pool_checkpoint(name):
|
||||||
'''
|
'''
|
||||||
|
@ -127,7 +127,6 @@ CDEF = """
|
|||||||
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
||||||
int lzc_sync(const char *, nvlist_t *, nvlist_t **);
|
int lzc_sync(const char *, nvlist_t *, nvlist_t **);
|
||||||
int lzc_unload_key(const char *);
|
int lzc_unload_key(const char *);
|
||||||
int lzc_remap(const char *);
|
|
||||||
int lzc_pool_checkpoint(const char *);
|
int lzc_pool_checkpoint(const char *);
|
||||||
int lzc_pool_checkpoint_discard(const char *);
|
int lzc_pool_checkpoint_discard(const char *);
|
||||||
int lzc_rename(const char *, const char *);
|
int lzc_rename(const char *, const char *);
|
||||||
|
@ -3632,31 +3632,6 @@ zfs.sync.snapshot('""" + pool + b"""@zcp')
|
|||||||
with self.assertRaises(lzc_exc.EncryptionKeyNotLoaded):
|
with self.assertRaises(lzc_exc.EncryptionKeyNotLoaded):
|
||||||
lzc.lzc_unload_key(fs)
|
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):
|
def test_checkpoint(self):
|
||||||
pool = ZFSTest.pool.getRoot().getName()
|
pool = ZFSTest.pool.getRoot().getName()
|
||||||
|
|
||||||
|
@ -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_enable_datasets(zpool_handle_t *, const char *, int);
|
||||||
extern int zpool_disable_datasets(zpool_handle_t *, boolean_t);
|
extern int zpool_disable_datasets(zpool_handle_t *, boolean_t);
|
||||||
|
|
||||||
extern int zfs_remap_indirects(libzfs_handle_t *hdl, const char *);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -49,7 +49,6 @@ enum lzc_dataset_type {
|
|||||||
LZC_DATSET_TYPE_ZVOL
|
LZC_DATSET_TYPE_ZVOL
|
||||||
};
|
};
|
||||||
|
|
||||||
int lzc_remap(const char *fsname);
|
|
||||||
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
int lzc_snapshot(nvlist_t *, nvlist_t *, nvlist_t **);
|
||||||
int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *, uint8_t *,
|
int lzc_create(const char *, enum lzc_dataset_type, nvlist_t *, uint8_t *,
|
||||||
uint_t);
|
uint_t);
|
||||||
|
@ -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_sync_list(list_t *list, int level, dmu_tx_t *tx);
|
||||||
void dbuf_release_bp(dmu_buf_impl_t *db);
|
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,
|
void dbuf_free_range(struct dnode *dn, uint64_t start, uint64_t end,
|
||||||
struct dmu_tx *);
|
struct dmu_tx *);
|
||||||
|
|
||||||
|
@ -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);
|
void dmu_objset_byteswap(void *buf, size_t size);
|
||||||
int dsl_dataset_rename_snapshot(const char *fsname,
|
int dsl_dataset_rename_snapshot(const char *fsname,
|
||||||
const char *oldsnapname, const char *newsnapname, boolean_t recursive);
|
const char *oldsnapname, const char *newsnapname, boolean_t recursive);
|
||||||
int dmu_objset_remap_indirects(const char *fsname);
|
|
||||||
|
|
||||||
typedef struct dmu_buf {
|
typedef struct dmu_buf {
|
||||||
uint64_t db_object; /* object that this buffer is part of */
|
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,
|
void dmu_object_set_compress(objset_t *os, uint64_t object, uint8_t compress,
|
||||||
dmu_tx_t *tx);
|
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 dmu_write_embedded(objset_t *os, uint64_t object, uint64_t offset,
|
||||||
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
|
void *data, uint8_t etype, uint8_t comp, int uncompressed_size,
|
||||||
int compressed_size, int byteorder, dmu_tx_t *tx);
|
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);
|
uint64_t len);
|
||||||
void dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
|
void dmu_tx_hold_free_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off,
|
||||||
uint64_t len);
|
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(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,
|
void dmu_tx_hold_zap_by_dnode(dmu_tx_t *tx, dnode_t *dn, int add,
|
||||||
const char *name);
|
const char *name);
|
||||||
|
@ -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_dbufs(dnode_t *dn);
|
||||||
void dnode_evict_bonus(dnode_t *dn);
|
void dnode_evict_bonus(dnode_t *dn);
|
||||||
void dnode_free_interior_slots(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) \
|
#define DNODE_IS_DIRTY(_dn) \
|
||||||
((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa))
|
((_dn)->dn_dirty_txg >= spa_syncing_txg((_dn)->dn_objset->os_spa))
|
||||||
|
@ -61,7 +61,6 @@ extern "C" {
|
|||||||
#define ZFS_DELEG_PERM_RELEASE "release"
|
#define ZFS_DELEG_PERM_RELEASE "release"
|
||||||
#define ZFS_DELEG_PERM_DIFF "diff"
|
#define ZFS_DELEG_PERM_DIFF "diff"
|
||||||
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
|
#define ZFS_DELEG_PERM_BOOKMARK "bookmark"
|
||||||
#define ZFS_DELEG_PERM_REMAP "remap"
|
|
||||||
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
|
#define ZFS_DELEG_PERM_LOAD_KEY "load-key"
|
||||||
#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
|
#define ZFS_DELEG_PERM_CHANGE_KEY "change-key"
|
||||||
#define ZFS_DELEG_PERM_PROJECTUSED "projectused"
|
#define ZFS_DELEG_PERM_PROJECTUSED "projectused"
|
||||||
|
@ -49,7 +49,6 @@ struct dsl_dataset;
|
|||||||
#define DD_FIELD_FILESYSTEM_COUNT "com.joyent:filesystem_count"
|
#define DD_FIELD_FILESYSTEM_COUNT "com.joyent:filesystem_count"
|
||||||
#define DD_FIELD_SNAPSHOT_COUNT "com.joyent:snapshot_count"
|
#define DD_FIELD_SNAPSHOT_COUNT "com.joyent:snapshot_count"
|
||||||
#define DD_FIELD_CRYPTO_KEY_OBJ "com.datto:crypto_key_obj"
|
#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 {
|
typedef enum dd_used {
|
||||||
DD_USED_HEAD,
|
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,
|
uint64_t dsl_dir_space_available(dsl_dir_t *dd,
|
||||||
dsl_dir_t *ancestor, int64_t delta, int ondiskonly);
|
dsl_dir_t *ancestor, int64_t delta, int ondiskonly);
|
||||||
void dsl_dir_dirty(dsl_dir_t *dd, dmu_tx_t *tx);
|
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);
|
void dsl_dir_sync(dsl_dir_t *dd, dmu_tx_t *tx);
|
||||||
int dsl_dir_tempreserve_space(dsl_dir_t *dd, uint64_t mem,
|
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);
|
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 *,
|
int dsl_fs_ss_limit_check(dsl_dir_t *, uint64_t, zfs_prop_t, dsl_dir_t *,
|
||||||
cred_t *);
|
cred_t *);
|
||||||
void dsl_fs_ss_count_adjust(dsl_dir_t *, int64_t, const char *, dmu_tx_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_rename(const char *oldname, const char *newname);
|
||||||
int dsl_dir_transfer_possible(dsl_dir_t *sdd, dsl_dir_t *tdd,
|
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 *);
|
uint64_t fs_cnt, uint64_t ss_cnt, uint64_t space, cred_t *);
|
||||||
|
@ -181,7 +181,7 @@ typedef enum {
|
|||||||
ZFS_PROP_ENCRYPTION_ROOT,
|
ZFS_PROP_ENCRYPTION_ROOT,
|
||||||
ZFS_PROP_KEY_GUID,
|
ZFS_PROP_KEY_GUID,
|
||||||
ZFS_PROP_KEYSTATUS,
|
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_SPECIAL_SMALL_BLOCKS,
|
||||||
ZFS_PROP_IVSET_GUID, /* not exposed to the user */
|
ZFS_PROP_IVSET_GUID, /* not exposed to the user */
|
||||||
ZFS_PROP_REDACTED,
|
ZFS_PROP_REDACTED,
|
||||||
|
@ -77,7 +77,6 @@ typedef enum {
|
|||||||
ZFS_DELEG_NOTE_PROJECTQUOTA,
|
ZFS_DELEG_NOTE_PROJECTQUOTA,
|
||||||
ZFS_DELEG_NOTE_PROJECTOBJUSED,
|
ZFS_DELEG_NOTE_PROJECTOBJUSED,
|
||||||
ZFS_DELEG_NOTE_PROJECTOBJQUOTA,
|
ZFS_DELEG_NOTE_PROJECTOBJQUOTA,
|
||||||
ZFS_DELEG_NOTE_REMAP,
|
|
||||||
ZFS_DELEG_NOTE_NONE
|
ZFS_DELEG_NOTE_NONE
|
||||||
} zfs_deleg_note_t;
|
} zfs_deleg_note_t;
|
||||||
|
|
||||||
|
@ -4210,36 +4210,6 @@ zfs_snapshot_cb(zfs_handle_t *zhp, void *arg)
|
|||||||
return (rv);
|
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
|
* Creates snapshots. The keys in the snaps nvlist are the snapshots to be
|
||||||
* created.
|
* created.
|
||||||
|
@ -306,16 +306,6 @@ lzc_promote(const char *fsname, char *snapnamebuf, int snapnamelen)
|
|||||||
return (0);
|
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
|
int
|
||||||
lzc_rename(const char *source, const char *target)
|
lzc_rename(const char *source, const char *target)
|
||||||
{
|
{
|
||||||
|
@ -52,7 +52,6 @@ zfs_deleg_perm_tab_t zfs_deleg_perm_tab[] = {
|
|||||||
{ZFS_DELEG_PERM_MOUNT},
|
{ZFS_DELEG_PERM_MOUNT},
|
||||||
{ZFS_DELEG_PERM_PROMOTE},
|
{ZFS_DELEG_PERM_PROMOTE},
|
||||||
{ZFS_DELEG_PERM_RECEIVE},
|
{ZFS_DELEG_PERM_RECEIVE},
|
||||||
{ZFS_DELEG_PERM_REMAP},
|
|
||||||
{ZFS_DELEG_PERM_RENAME},
|
{ZFS_DELEG_PERM_RENAME},
|
||||||
{ZFS_DELEG_PERM_ROLLBACK},
|
{ZFS_DELEG_PERM_ROLLBACK},
|
||||||
{ZFS_DELEG_PERM_SNAPSHOT},
|
{ZFS_DELEG_PERM_SNAPSHOT},
|
||||||
|
@ -512,8 +512,6 @@ zfs_prop_init(void)
|
|||||||
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<uint64>", "GUID");
|
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<uint64>", "GUID");
|
||||||
zprop_register_number(ZFS_PROP_CREATETXG, "createtxg", 0, PROP_READONLY,
|
zprop_register_number(ZFS_PROP_CREATETXG, "createtxg", 0, PROP_READONLY,
|
||||||
ZFS_TYPE_DATASET | ZFS_TYPE_BOOKMARK, "<uint64>", "CREATETXG");
|
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",
|
zprop_register_number(ZFS_PROP_PBKDF2_ITERS, "pbkdf2iters",
|
||||||
0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
|
0, PROP_ONETIME_DEFAULT, ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME,
|
||||||
"<iters>", "PBKDF2ITERS");
|
"<iters>", "PBKDF2ITERS");
|
||||||
@ -579,11 +577,15 @@ zfs_prop_init(void)
|
|||||||
PROP_READONLY, ZFS_TYPE_DATASET, "REDACTED");
|
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",
|
zprop_register_hidden(ZFS_PROP_PRIVATE, "priv_prop",
|
||||||
PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_FILESYSTEM,
|
PROP_TYPE_NUMBER, PROP_READONLY, ZFS_TYPE_FILESYSTEM,
|
||||||
"PRIV_PROP");
|
"PRIV_PROP");
|
||||||
|
zprop_register_hidden(ZFS_PROP_REMAPTXG, "remaptxg", PROP_TYPE_NUMBER,
|
||||||
|
PROP_READONLY, ZFS_TYPE_DATASET, "REMAPTXG");
|
||||||
|
|
||||||
/* oddball properties */
|
/* oddball properties */
|
||||||
zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0,
|
zprop_register_impl(ZFS_PROP_CREATION, "creation", PROP_TYPE_NUMBER, 0,
|
||||||
|
@ -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.
|
* Remap any existing BP's to concrete vdevs, if possible.
|
||||||
*/
|
*/
|
||||||
|
138
module/zfs/dmu.c
138
module/zfs/dmu.c
@ -74,13 +74,6 @@ unsigned long zfs_per_txg_dirty_frees_percent = 5;
|
|||||||
*/
|
*/
|
||||||
int zfs_dmu_offset_next_sync = 0;
|
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
|
* 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.
|
* 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);
|
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
|
void
|
||||||
dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
dmu_prealloc(objset_t *os, uint64_t object, uint64_t offset, uint64_t size,
|
||||||
dmu_tx_t *tx)
|
dmu_tx_t *tx)
|
||||||
|
@ -1396,101 +1396,6 @@ dmu_objset_clone(const char *clone, const char *origin)
|
|||||||
6, ZFS_SPACE_CHECK_NORMAL));
|
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
|
int
|
||||||
dmu_objset_snapshot_one(const char *fsname, const char *snapname)
|
dmu_objset_snapshot_one(const char *fsname, const char *snapname)
|
||||||
{
|
{
|
||||||
|
@ -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
|
void
|
||||||
dmu_tx_hold_write_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
|
dmu_tx_hold_write_by_dnode(dmu_tx_t *tx, dnode_t *dn, uint64_t off, int len)
|
||||||
{
|
{
|
||||||
|
@ -757,35 +757,6 @@ dsl_enforce_ds_ss_limits(dsl_dir_t *dd, zfs_prop_t prop, cred_t *cr)
|
|||||||
return (enforce);
|
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
|
* Check if adding additional child filesystem(s) would exceed any filesystem
|
||||||
* limits or adding additional snapshot(s) would exceed any snapshot limits.
|
* 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
|
void
|
||||||
dsl_dir_stats(dsl_dir_t *dd, nvlist_t *nv)
|
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,
|
dsl_prop_nvlist_add_uint64(nv, ZFS_PROP_SNAPSHOT_COUNT,
|
||||||
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)) {
|
if (dsl_dir_is_clone(dd)) {
|
||||||
char buf[ZFS_MAX_DATASET_NAME_LEN];
|
char buf[ZFS_MAX_DATASET_NAME_LEN];
|
||||||
|
@ -1045,14 +1045,6 @@ zfs_secpolicy_bookmark(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
|
|||||||
return (error);
|
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 */
|
/* ARGSUSED */
|
||||||
static int
|
static int
|
||||||
zfs_secpolicy_destroy_bookmarks(zfs_cmd_t *zc, nvlist_t *innvl, cred_t *cr)
|
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
|
static int
|
||||||
zfs_ioc_remap(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
|
zfs_ioc_remap(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl)
|
||||||
{
|
{
|
||||||
if (strchr(fsname, '@') ||
|
/* This IOCTL is no longer supported. */
|
||||||
strchr(fsname, '%'))
|
return (0);
|
||||||
return (SET_ERROR(EINVAL));
|
|
||||||
|
|
||||||
return (dmu_objset_remap_indirects(fsname));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6790,7 +6779,7 @@ zfs_ioctl_init(void)
|
|||||||
zfs_keys_clone, ARRAY_SIZE(zfs_keys_clone));
|
zfs_keys_clone, ARRAY_SIZE(zfs_keys_clone));
|
||||||
|
|
||||||
zfs_ioctl_register("remap", ZFS_IOC_REMAP,
|
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,
|
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_TRUE,
|
||||||
zfs_keys_remap, ARRAY_SIZE(zfs_keys_remap));
|
zfs_keys_remap, ARRAY_SIZE(zfs_keys_remap));
|
||||||
|
|
||||||
|
@ -210,10 +210,6 @@ tests = ['zfs_receive_001_pos', 'zfs_receive_002_pos', 'zfs_receive_003_pos',
|
|||||||
'zfs_receive_raw_incremental', 'zfs_receive_-e']
|
'zfs_receive_raw_incremental', 'zfs_receive_-e']
|
||||||
tags = ['functional', 'cli_root', 'zfs_receive']
|
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/functional/cli_root/zfs_rename]
|
||||||
tests = ['zfs_rename_001_pos', 'zfs_rename_002_pos', 'zfs_rename_003_pos',
|
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',
|
'zfs_rename_004_neg', 'zfs_rename_005_neg', 'zfs_rename_006_pos',
|
||||||
@ -767,11 +763,11 @@ tags = ['functional', 'refreserv']
|
|||||||
pre =
|
pre =
|
||||||
tests = ['removal_all_vdev', 'removal_check_space',
|
tests = ['removal_all_vdev', 'removal_check_space',
|
||||||
'removal_condense_export', 'removal_multiple_indirection',
|
'removal_condense_export', 'removal_multiple_indirection',
|
||||||
'removal_remap', 'removal_remap_deadlists',
|
'removal_remap_deadlists',
|
||||||
'removal_resume_export', 'removal_sanity', 'removal_with_add',
|
'removal_resume_export', 'removal_sanity', 'removal_with_add',
|
||||||
'removal_with_create_fs', 'removal_with_dedup',
|
'removal_with_create_fs', 'removal_with_dedup',
|
||||||
'removal_with_errors', 'removal_with_export',
|
'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_remove', 'removal_with_scrub', 'removal_with_send',
|
||||||
'removal_with_send_recv', 'removal_with_snapshot',
|
'removal_with_send_recv', 'removal_with_snapshot',
|
||||||
'removal_with_write', 'removal_with_zdb', 'remove_expanded',
|
'removal_with_write', 'removal_with_zdb', 'remove_expanded',
|
||||||
|
@ -186,7 +186,6 @@ known = {
|
|||||||
'inuse/inuse_007_pos': ['SKIP', na_reason],
|
'inuse/inuse_007_pos': ['SKIP', na_reason],
|
||||||
'privilege/setup': ['SKIP', na_reason],
|
'privilege/setup': ['SKIP', na_reason],
|
||||||
'refreserv/refreserv_004_pos': ['FAIL', known_reason],
|
'refreserv/refreserv_004_pos': ['FAIL', known_reason],
|
||||||
'removal/removal_condense_export': ['SKIP', known_reason],
|
|
||||||
'removal/removal_with_zdb': ['SKIP', known_reason],
|
'removal/removal_with_zdb': ['SKIP', known_reason],
|
||||||
'rootpool/setup': ['SKIP', na_reason],
|
'rootpool/setup': ['SKIP', na_reason],
|
||||||
'rsend/rsend_008_pos': ['SKIP', '6066'],
|
'rsend/rsend_008_pos': ['SKIP', '6066'],
|
||||||
|
@ -93,14 +93,7 @@ for i in 1 2 3 4; do
|
|||||||
log_must file_in_special_vdev $dataset $inum
|
log_must file_in_special_vdev $dataset $inum
|
||||||
done
|
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 zpool remove $TESTPOOL $CLASS_DISK0
|
||||||
log_must zfs remap $TESTPOOL/$TESTFS
|
|
||||||
|
|
||||||
sleep 5
|
sleep 5
|
||||||
log_must sync_pool $TESTPOOL
|
log_must sync_pool $TESTPOOL
|
||||||
|
@ -20,7 +20,6 @@ SUBDIRS = \
|
|||||||
zfs_promote \
|
zfs_promote \
|
||||||
zfs_property \
|
zfs_property \
|
||||||
zfs_receive \
|
zfs_receive \
|
||||||
zfs_remap \
|
|
||||||
zfs_rename \
|
zfs_rename \
|
||||||
zfs_reservation \
|
zfs_reservation \
|
||||||
zfs_rollback \
|
zfs_rollback \
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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"
|
|
@ -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"
|
|
@ -18,12 +18,12 @@ pkgdatadir = $(datadir)/@PACKAGE@/zfs-tests/tests/functional/removal
|
|||||||
dist_pkgdata_SCRIPTS = \
|
dist_pkgdata_SCRIPTS = \
|
||||||
cleanup.ksh removal_all_vdev.ksh removal_check_space.ksh \
|
cleanup.ksh removal_all_vdev.ksh removal_check_space.ksh \
|
||||||
removal_condense_export.ksh removal_multiple_indirection.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_reservation.ksh removal_resume_export.ksh \
|
||||||
removal_sanity.ksh removal_with_add.ksh removal_with_create_fs.ksh \
|
removal_sanity.ksh removal_with_add.ksh removal_with_create_fs.ksh \
|
||||||
removal_with_dedup.ksh removal_with_errors.ksh \
|
removal_with_dedup.ksh removal_with_errors.ksh \
|
||||||
removal_with_export.ksh removal_with_faulted.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_remove.ksh removal_with_scrub.ksh \
|
||||||
removal_with_send.ksh removal_with_send_recv.ksh \
|
removal_with_send.ksh removal_with_send_recv.ksh \
|
||||||
removal_with_snapshot.ksh removal_with_write.ksh \
|
removal_with_snapshot.ksh removal_with_write.ksh \
|
||||||
|
@ -21,10 +21,6 @@
|
|||||||
. $STF_SUITE/include/libtest.shlib
|
. $STF_SUITE/include/libtest.shlib
|
||||||
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
. $STF_SUITE/tests/functional/removal/removal.kshlib
|
||||||
|
|
||||||
if is_linux; then
|
|
||||||
log_unsupported "ZDB fails during concurrent pool activity."
|
|
||||||
fi
|
|
||||||
|
|
||||||
function reset
|
function reset
|
||||||
{
|
{
|
||||||
log_must set_tunable64 zfs_condense_indirect_commit_entry_delay_ms 0
|
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_must wait_for_removal $TESTPOOL
|
||||||
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
|
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
|
sync_pool $TESTPOOL
|
||||||
sleep 5
|
sleep 5
|
||||||
sync_pool $TESTPOOL
|
sync_pool $TESTPOOL
|
||||||
|
@ -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."
|
|
@ -21,9 +21,6 @@
|
|||||||
. $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
|
||||||
|
|
||||||
@ -45,7 +42,14 @@ fi
|
|||||||
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
|
log_mustnot vdevs_in_pool $TESTPOOL $REMOVEDISK
|
||||||
log_must zdb -cd $TESTPOOL
|
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 zdb -cd $TESTPOOL
|
||||||
|
|
||||||
log_must zfs snapshot $TESTPOOL/$TESTFS@snap-post3
|
log_must zfs snapshot $TESTPOOL/$TESTFS@snap-post3
|
||||||
|
@ -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"
|
|
Loading…
Reference in New Issue
Block a user