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 <[email protected]>
Reviewed by: Matthew Ahrens <[email protected]>
Signed-off-by: Alek Pinchuk <[email protected]>
Closes #6122
  • Loading branch information
alek-p authored and behlendorf committed May 19, 2017
1 parent 4a283c7 commit bec1067
Show file tree
Hide file tree
Showing 20 changed files with 397 additions and 70 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 Igor Kozhukhov <[email protected]>.
* Copyright (c) 2017 Datto Inc.
*/

#include <assert.h>
Expand Down Expand Up @@ -100,6 +101,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 @@ -143,6 +146,7 @@ typedef enum {
HELP_GET,
HELP_SET,
HELP_SPLIT,
HELP_SYNC,
HELP_REGUID,
HELP_REOPEN
} zpool_help_t;
Expand Down Expand Up @@ -272,6 +276,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 @@ -358,6 +363,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 @@ -2693,6 +2700,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
1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ AC_CONFIG_FILES([
tests/zfs-tests/tests/functional/cli_root/zpool_scrub/Makefile
tests/zfs-tests/tests/functional/cli_root/zpool_set/Makefile
tests/zfs-tests/tests/functional/cli_root/zpool_status/Makefile
tests/zfs-tests/tests/functional/cli_root/zpool_sync/Makefile
tests/zfs-tests/tests/functional/cli_root/zpool_upgrade/Makefile
tests/zfs-tests/tests/functional/cli_user/Makefile
tests/zfs-tests/tests/functional/cli_user/misc/Makefile
Expand Down
3 changes: 3 additions & 0 deletions include/libzfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2016, Intel Corporation.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2017 Datto Inc.
*/

#ifndef _LIBZFS_H
Expand Down Expand Up @@ -264,6 +265,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
3 changes: 3 additions & 0 deletions include/libzfs_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2017 Datto Inc.
*/

#ifndef _LIBZFS_CORE_H
Expand Down Expand Up @@ -89,6 +90,8 @@ boolean_t lzc_exists(const char *);

int lzc_rollback(const char *, char *, int);

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

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/sys/fs/zfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2017 Datto Inc.
*/

/* Portions Copyright 2010 Robert Milkowski */
Expand Down Expand Up @@ -1020,6 +1021,7 @@ typedef enum zfs_ioc {
ZFS_IOC_GET_BOOKMARKS,
ZFS_IOC_DESTROY_BOOKMARKS,
ZFS_IOC_RECV_NEW,
ZFS_IOC_POOL_SYNC,

/*
* Linux - 3/64 numbers reserved.
Expand Down
22 changes: 22 additions & 0 deletions lib/libzfs/libzfs_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2014 by Delphix. All rights reserved.
* Copyright 2016 Igor Kozhukhov <[email protected]>
* Copyright (c) 2017 Datto Inc.
*/

#include <ctype.h>
Expand Down Expand Up @@ -3288,6 +3289,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);
}

#if defined(__sun__) || defined(__sun)
/*
* Convert from a devid string to a path.
Expand Down
34 changes: 23 additions & 11 deletions lib/libzfs_core/libzfs_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
/*
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2017 Datto Inc.
*/

/*
Expand Down Expand Up @@ -126,17 +127,20 @@ lzc_ioctl(zfs_ioc_t ioc, const char *name,
{
zfs_cmd_t zc = {"\0"};
int error = 0;
char *packed;
size_t size;
char *packed = NULL;
size_t size = 0;

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

packed = fnvlist_pack(source, &size);
zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
zc.zc_nvlist_src_size = size;
if (source != NULL) {
packed = fnvlist_pack(source, &size);
zc.zc_nvlist_src = (uint64_t)(uintptr_t)packed;
zc.zc_nvlist_src_size = size;
}

if (resultp != NULL) {
*resultp = NULL;
Expand Down Expand Up @@ -340,6 +344,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 @@ -440,11 +456,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
22 changes: 21 additions & 1 deletion man/man8/zpool.8
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
.\" Copyright 2011 Nexenta Systems, Inc. All rights reserved.
.\" Copyright (c) 2013 by Delphix. All rights reserved.
.\" Copyright (c) 2012 Cyril Plisko. All Rights Reserved.
.\" Copyright (c) 2017 Datto Inc.
.\" The contents of this file are subject to the terms of the Common Development
.\" and Distribution License (the "License"). You may not use this file except
.\" in compliance with the License. You can obtain a copy of the license at
Expand All @@ -15,7 +16,7 @@
.\" CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your
.\" own identifying information:
.\" Portions Copyright [yyyy] [name of copyright owner]
.TH zpool 8 "May 11, 2016" "ZFS pool 28, filesystem 5" "System Administration Commands"
.TH zpool 8 "April 12, 2017" "ZFS pool 28, filesystem 5" "System Administration Commands"
.SH NAME
zpool \- configures ZFS storage pools
.SH SYNOPSIS
Expand Down Expand Up @@ -162,6 +163,11 @@ zpool \- configures ZFS storage pools
\fBzpool status\fR [\fB-c\fR \fBSCRIPT\fR] [\fB-gLPvxD\fR] [\fB-T\fR d | u] [\fIpool\fR] ... [\fIinterval\fR [\fIcount\fR]]
.fi

.LP
.nf
\fBzpool sync\fR [\fBpool\fR] ...
.fi

.LP
.nf
\fBzpool upgrade\fR
Expand Down Expand Up @@ -2240,6 +2246,20 @@ Specify \fBu\fR for a printed representation of the internal representation of t

.RE

.sp
.ne 2
.na
\fB\fBzpool sync\fR\fR [\fBpool\fR] ...
.ad
.sp .6
.RS 4n
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, \fBzpool sync\fR will sync all pools on the system.
Otherwise, it will sync only the specified pool(s).
.RE

.sp
.ne 2
.na
Expand Down
44 changes: 44 additions & 0 deletions module/zfs/zfs_ioctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
* Copyright 2016 Toomas Soome <[email protected]>
* Copyright (c) 2016 Actifio, Inc. All rights reserved.
* Copyright (c) 2017, loli10K <[email protected]>. All rights reserved.
* Copyright (c) 2017 Datto Inc.
*/

/*
Expand Down Expand Up @@ -5466,6 +5467,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 @@ -5823,6 +5825,44 @@ zfs_ioc_send_space(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
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];

static void
Expand Down Expand Up @@ -5995,6 +6035,10 @@ zfs_ioctl_init(void)
zfs_ioc_recv_new, zfs_secpolicy_recv_new, DATASET_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 @@ -319,6 +319,9 @@ tests = ['zpool_upgrade_001_pos', 'zpool_upgrade_002_pos',
'zpool_upgrade_007_pos', '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
Loading

0 comments on commit bec1067

Please sign in to comment.