Skip to content

Commit

Permalink
Implemented zpool sync command
Browse files Browse the repository at this point in the history
This addition will enable us to sync an open TXG to the main pool
on demand. The functionality is similar to 'sync(2)' but 'zpool sync'
will return when data has hit the main storage instead of potentially
just the ZIL as is the case with the 'sync(2)' cmd.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Signed-off-by: Alek Pinchuk <apinchuk@datto.com>
  • Loading branch information
alek-p authored and lundman committed Jan 29, 2019
1 parent 149f015 commit be5efa7
Show file tree
Hide file tree
Showing 19 changed files with 681 additions and 8 deletions.
46 changes: 46 additions & 0 deletions cmd/zpool/zpool_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
* Copyright (c) 2012 by Cyril Plisko. All rights reserved.
* Copyright (c) 2013 by Prasad Joshi (sTec). All rights reserved.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>.
* Copyright (c) 2017 Datto Inc.
*/

Expand Down Expand Up @@ -111,6 +112,8 @@ static int zpool_do_events(int, char **);
static int zpool_do_get(int, char **);
static int zpool_do_set(int, char **);

static int zpool_do_sync(int, char **);

/*
* These libumem hooks provide a reasonable set of defaults for the allocator's
* debugging facilities.
Expand Down Expand Up @@ -156,6 +159,7 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
HELP_SYNC,
HELP_REGUID,
HELP_REOPEN
} zpool_help_t;
Expand Down Expand Up @@ -288,6 +292,7 @@ static zpool_command_t command_table[] = {
{ NULL },
{ "get", zpool_do_get, HELP_GET },
{ "set", zpool_do_set, HELP_SET },
{ "sync", zpool_do_sync, HELP_SYNC },
};

#define NCOMMAND (ARRAY_SIZE(command_table))
Expand Down Expand Up @@ -378,6 +383,8 @@ get_usage(zpool_help_t idx) {
"[<device> ...]\n"));
case HELP_REGUID:
return (gettext("\treguid <pool>\n"));
case HELP_SYNC:
return (gettext("\tsync [pool] ...\n"));
}

abort();
Expand Down Expand Up @@ -2966,6 +2973,45 @@ zpool_do_import(int argc, char **argv)
return (err ? 1 : 0);
}

/*
* zpool sync [-f] [pool] ...
*
* -f (undocumented) force uberblock (and config including zpool cache file)
* update.
*
* Sync the specified pool(s).
* Without arguments "zpool sync" will sync all pools.
* This command initiates TXG sync(s) and will return after the TXG(s) commit.
*
*/
static int
zpool_do_sync(int argc, char **argv)
{
int ret;
boolean_t force = B_FALSE;

/* check options */
while ((ret = getopt(argc, argv, "f")) != -1) {
switch (ret) {
case 'f':
force = B_TRUE;
break;
case '?':
(void) fprintf(stderr, gettext("invalid option '%c'\n"),
optopt);
usage(B_FALSE);
}
}

argc -= optind;
argv += optind;

/* if argc == 0 we will execute zpool_sync_one on all pools */
ret = for_each_pool(argc, argv, B_FALSE, NULL, zpool_sync_one, &force);

return (ret);
}

typedef struct iostat_cbdata {
uint64_t cb_flags;
int cb_name_flags;
Expand Down
2 changes: 2 additions & 0 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,8 @@ extern int zpool_clear(zpool_handle_t *, const char *, nvlist_t *);
extern int zpool_reguid(zpool_handle_t *);
extern int zpool_reopen(zpool_handle_t *);

extern int zpool_sync_one(zpool_handle_t *, void *);

extern int zpool_vdev_online(zpool_handle_t *, const char *, int,
vdev_state_t *);
extern int zpool_vdev_offline(zpool_handle_t *, const char *, boolean_t);
Expand Down
2 changes: 2 additions & 0 deletions include/libzfs_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ int lzc_channel_program_nosync(const char *, const char *, uint64_t,
int lzc_sync(const char *, nvlist_t *, nvlist_t **);
int lzc_reopen(const char *, boolean_t);

int lzc_sync(const char *, nvlist_t *, nvlist_t **);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/sys/zfs_ioctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,8 @@ typedef enum zfs_ioc {
ZFS_IOC_POOL_INITIALIZE,

ZFS_IOC_CHANNEL_PROGRAM,
ZFS_IOC_POOL_SYNC,

/*
* Linux - 3/64 numbers reserved.
*/
Expand Down
21 changes: 21 additions & 0 deletions lib/libzfs/libzfs_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -3679,6 +3679,27 @@ zpool_reopen(zpool_handle_t *zhp)
return (zpool_standard_error(hdl, errno, msg));
}

/* call into libzfs_core to execute the sync IOCTL per pool */
int
zpool_sync_one(zpool_handle_t *zhp, void *data)
{
int ret;
libzfs_handle_t *hdl = zpool_get_handle(zhp);
const char *pool_name = zpool_get_name(zhp);
boolean_t *force = data;
nvlist_t *innvl = fnvlist_alloc();

fnvlist_add_boolean_value(innvl, "force", *force);
if ((ret = lzc_sync(pool_name, innvl, NULL)) != 0) {
nvlist_free(innvl);
return (zpool_standard_error_fmt(hdl, ret,
dgettext(TEXT_DOMAIN, "sync '%s' failed"), pool_name));
}
nvlist_free(innvl);

return (0);
}

/*
* Convert from a devid string to a path.
*/
Expand Down
22 changes: 16 additions & 6 deletions lib/libzfs_core/libzfs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2017 RackTop Systems.
* Copyright (c) 2017 Datto Inc.
*/

/*
Expand Down Expand Up @@ -135,7 +136,8 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
ASSERT3S(g_refcount, >, 0);
VERIFY3S(g_fd, !=, -1);

(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));
if (name != NULL)
(void) strlcpy(zc.zc_name, name, sizeof (zc.zc_name));

if (source != NULL) {
packed = fnvlist_pack(source, &size);
Expand Down Expand Up @@ -410,6 +412,18 @@ lzc_exists(const char *dataset)
return (ioctl(g_fd, ZFS_IOC_OBJSET_STATS, &zc) == 0);
}

/*
* outnvl is unused.
* It was added to preserve the function signature in case it is
* needed in the future.
*/
/*ARGSUSED*/
int
lzc_sync(const char *pool_name, nvlist_t *innvl, nvlist_t **outnvl)
{
return (lzc_ioctl(ZFS_IOC_POOL_SYNC, pool_name, innvl, NULL));
}

/*
* Create "user holds" on snapshots. If there is a hold on a snapshot,
* the snapshot can not be destroyed. (However, it can be marked for deletion
Expand Down Expand Up @@ -510,11 +524,7 @@ lzc_release(nvlist_t *holds, nvlist_t **errlist)
int
lzc_get_holds(const char *snapname, nvlist_t **holdsp)
{
int error;
nvlist_t *innvl = fnvlist_alloc();
error = lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, innvl, holdsp);
fnvlist_free(innvl);
return (error);
return (lzc_ioctl(ZFS_IOC_GET_HOLDS, snapname, NULL, holdsp));
}

/*
Expand Down
15 changes: 15 additions & 0 deletions man/man8/zpool.8
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,9 @@
.Oo Ar pool Oc Ns ...
.Op Ar interval Op Ar count
.Nm
.Cm sync
.Oo Ar pool Oc Ns ...
.Nm
.Cm upgrade
.Nm
.Cm upgrade
Expand Down Expand Up @@ -1803,6 +1806,18 @@ Warnings about pools not using the latest on-disk format will not be included.
.El
.It Xo
.Nm
.Cm sync
.Oo Ar pool Oc Ns ...
.Xc
This command forces all in-core dirty data to be written to the primary pool
storage and not the ZIL.
It will also update administrative information including quota reporting.
Without arguments,
.Sx zpool sync
will sync all pools on the system.
Otherwise, it will sync only the specified pool(s).
.It Xo
.Nm
.Cm upgrade
.Xc
Displays pools which do not have all supported features enabled and pools
Expand Down
45 changes: 44 additions & 1 deletion module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@
* Copyright (c) 2014 Integros [integros.com]
* Copyright 2016 Toomas Soome <tsoome@me.com>
* Copyright 2017 RackTop Systems.
* Copyright (c) 2017 Datto Inc.
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
* Copyright (c) 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
*/

#define __APPLE_API_PRIVATE
Expand Down Expand Up @@ -5315,6 +5316,7 @@ zfs_ioc_hold(const char *pool, nvlist_t *args, nvlist_t *errlist)
static int
zfs_ioc_get_holds(const char *snapname, nvlist_t *args, nvlist_t *outnvl)
{
ASSERT3P(args, ==, NULL);
return (dsl_dataset_get_holds(snapname, outnvl));
}

Expand Down Expand Up @@ -5843,6 +5845,43 @@ zfs_ioc_osx_proxy_dataset(zfs_cmd_t *zc)
return (error);
}

/*
* Sync the currently open TXG to disk for the specified pool.
* This is somewhat similar to 'zfs_sync()'.
* For cases that do not result in error this ioctl will wait for
* the currently open TXG to commit before returning back to the caller.
*
* innvl: {
* "force" -> when true, force uberblock update even if there is no dirty data.
* In addition this will cause the vdev configuration to be written
* out including updating the zpool cache file. (boolean_t)
* }
*
* onvl is unused
*/
/* ARGSUSED */
static int
zfs_ioc_pool_sync(const char *pool, nvlist_t *innvl, nvlist_t *onvl)
{
int err;
boolean_t force;
spa_t *spa;

if ((err = spa_open(pool, &spa, FTAG)) != 0)
return (err);

force = fnvlist_lookup_boolean_value(innvl, "force");
if (force) {
spa_config_enter(spa, SCL_CONFIG, FTAG, RW_WRITER);
vdev_config_dirty(spa->spa_root_vdev);
spa_config_exit(spa, SCL_CONFIG, FTAG);
}
txg_wait_synced(spa_get_dsl(spa), 0);

spa_close(spa, FTAG);

return (err);
}

static zfs_ioc_vec_t zfs_ioc_vec[ZFS_IOC_LAST - ZFS_IOC_FIRST];

Expand Down Expand Up @@ -6045,6 +6084,10 @@ zfs_ioctl_init(void)
POOL_NAME, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_TRUE,
B_TRUE);

zfs_ioctl_register("sync", ZFS_IOC_POOL_SYNC,
zfs_ioc_pool_sync, zfs_secpolicy_none, POOL_NAME,
POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY, B_FALSE, B_FALSE);

/* IOCTLS that use the legacy function signature */

zfs_ioctl_register_legacy(ZFS_IOC_POOL_FREEZE, zfs_ioc_pool_freeze,
Expand Down
3 changes: 3 additions & 0 deletions tests/runfiles/linux.run
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,9 @@ tests = ['zpool_upgrade_001_pos',
'zpool_upgrade_006_neg', 'zpool_upgrade_008_pos',
'zpool_upgrade_009_neg']

[tests/functional/cli_root/zpool_sync]
tests = ['zpool_sync_001_pos', 'zpool_sync_002_neg']

# DISABLED:
# zfs_share_001_neg - requires additional dependencies
# zfs_unshare_001_neg - requires additional dependencies
Expand Down
41 changes: 41 additions & 0 deletions tests/zfs-tests/include/libtest.shlib
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
# Use is subject to license terms.
# Copyright (c) 2012, 2017 by Delphix. All rights reserved.
# Copyright 2016 Nexenta Systems, Inc.
# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
# Copyright (c) 2017 Datto Inc.
#

Expand Down Expand Up @@ -3274,6 +3275,46 @@ function format_zvol # volume_name blockdev mountpoint
fi
}

#
# Sync data to the pool
#
# $1 pool name
# $2 boolean to force uberblock (and config including zpool cache file) update
#
function sync_pool #pool <force>
{
typeset pool=${1:-$TESTPOOL}
typeset force=${2:-false}

if [[ $force == true ]]; then
log_must zpool sync -f $pool
else
log_must zpool sync $pool
fi

return 0
}

#
# Sync data to the pool
#
# $1 pool name
# $2 boolean to force uberblock (and config including zpool cache file) update
#
function sync_pool #pool <force>
{
typeset pool=${1:-$TESTPOOL}
typeset force=${2:-false}

if [[ $force == true ]]; then
log_must zpool sync -f $pool
else
log_must zpool sync $pool
fi

return 0
}

function unmount_fs_mountpoint # mountpoint
{
typeset mountpoint=$1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@
#

#
# Copyright (c) 2013 by Delphix. All rights reserved.
# Copyright (c) 2013, 2016 by Delphix. All rights reserved.
# Copyright (c) 2017 Datto Inc.
#

. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/clean_mirror/default.cfg

# Most of the code related to the clearing of mirrors is duplicated in all
Expand Down
Loading

0 comments on commit be5efa7

Please sign in to comment.