- Implemented pool initialization actions

This commit is contained in:
Asmir Selimovic 2020-04-22 15:41:23 +02:00
parent e24c488fee
commit 5a4d618fa5
5 changed files with 129 additions and 1 deletions

View File

@ -13,6 +13,7 @@ func Test(t *testing.T) {
zpoolTestExport(t) zpoolTestExport(t)
zpoolTestPoolImportSearch(t) zpoolTestPoolImportSearch(t)
zpoolTestImport(t) zpoolTestImport(t)
zpoolTestInitialization(t)
zpoolTestExportForce(t) zpoolTestExportForce(t)
zpoolTestImportByGUID(t) zpoolTestImportByGUID(t)
zpoolTestPoolProp(t) zpoolTestPoolProp(t)

24
zpool.c
View File

@ -526,3 +526,27 @@ int do_zpool_clear(zpool_list_t *pool, const char *device, u_int32_t load_policy
return (ret); return (ret);
} }
void collect_zpool_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *nv){
uint_t children = 0;
nvlist_t **child;
uint_t i;
(void) nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_CHILDREN,
&child, &children);
if (children == 0) {
char *path = zpool_vdev_name(libzfsHandle, zhp, nvroot,
VDEV_NAME_PATH);
if (strcmp(path, VDEV_TYPE_INDIRECT) != 0)
fnvlist_add_boolean(nv, path);
free(path);
return;
}
for (i = 0; i < children; i++) {
collect_zpool_leaves(zhp, child[i], nv);
}
}

View File

@ -59,6 +59,16 @@ const (
PoolScanFuncs // Number of scan functions PoolScanFuncs // Number of scan functions
) )
// PoolInitializeAction type representing pool initialize action
type PoolInitializeAction int
// Initialize actions
const (
PoolInitializeStart PoolInitializeAction = iota // start initialization
PoolInitializeCancel // cancel initialization
PoolInitializeSuspend // suspend initialization
)
// VDevStat - Vdev statistics. Note: all fields should be 64-bit because this // VDevStat - Vdev statistics. Note: all fields should be 64-bit because this
// is passed between kernel and userland as an nvlist uint64 array. // is passed between kernel and userland as an nvlist uint64 array.
type VDevStat struct { type VDevStat struct {
@ -1055,6 +1065,50 @@ func (pool *Pool) VDevTree() (vdevs VDevTree, err error) {
return return
} }
// Initialize - initializes pool
func (pool *Pool) Initialize() (err error) {
return pool.initialize(PoolInitializeStart)
}
// CancelInitialization - cancels ongoing initialization
func (pool *Pool) CancelInitialization() (err error) {
return pool.initialize(PoolInitializeCancel)
}
// SuspendInitialization - suspends ongoing initialization
func (pool *Pool) SuspendInitialization() (err error) {
return pool.initialize(PoolInitializeSuspend)
}
func (pool *Pool) initialize(action PoolInitializeAction) (err error) {
var nvroot *C.struct_nvlist
config := C.zpool_get_config(pool.list.zph, nil)
if config == nil {
err = fmt.Errorf("Failed zpool_get_config")
return
}
if C.nvlist_lookup_nvlist(config, C.sZPOOL_CONFIG_VDEV_TREE, &nvroot) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_TREE)
return
}
var vds *C.nvlist_t
if r := C.nvlist_alloc(&vds, C.NV_UNIQUE_NAME, 0); r != 0 {
err = errors.New("Failed to allocate vdev")
return
}
defer C.nvlist_free(vds)
C.collect_zpool_leaves(pool.list.zph, nvroot, vds)
if C.zpool_initialize(pool.list.zph, C.pool_initialize_func_t(action), vds) != 0 {
err = fmt.Errorf("Initialization action %s failed", action.String())
return
}
return
}
func (s PoolState) String() string { func (s PoolState) String() string {
switch s { switch s {
case PoolStateActive: case PoolStateActive:
@ -1186,3 +1240,16 @@ func (s PoolStatus) String() string {
return "OK" return "OK"
} }
} }
func (s PoolInitializeAction) String() string {
switch s {
case PoolInitializeStart:
return "START"
case PoolInitializeCancel:
return "CANCEL"
case PoolInitializeSuspend:
return "SUSPEND"
default:
return "UNKNOWN"
}
}

View File

@ -82,6 +82,7 @@ nvlist_ptr go_zpool_search_import(libzfs_handle_ptr zfsh, int paths, char **path
uint64_t set_zpool_vdev_online(zpool_list_t *pool, const char *path, int flags); uint64_t set_zpool_vdev_online(zpool_list_t *pool, const char *path, int flags);
int set_zpool_vdev_offline(zpool_list_t *pool, const char *path, boolean_t istmp, boolean_t force); int set_zpool_vdev_offline(zpool_list_t *pool, const char *path, boolean_t istmp, boolean_t force);
int do_zpool_clear(zpool_list_t *pool, const char *device, u_int32_t rewind_policy); int do_zpool_clear(zpool_list_t *pool, const char *device, u_int32_t rewind_policy);
void collect_zpool_leaves(zpool_handle_t *zhp, nvlist_t *nvroot, nvlist_t *nv);
extern char *sZPOOL_CONFIG_VERSION; extern char *sZPOOL_CONFIG_VERSION;

View File

@ -5,8 +5,9 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
"time"
"github.com/bicomsystems/go-libzfs" zfs "github.com/bicomsystems/go-libzfs"
) )
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
@ -362,6 +363,40 @@ func zpoolTestPoolVDevTree(t *testing.T) {
print("PASS\n\n") print("PASS\n\n")
} }
func zpoolTestInitialization(t *testing.T) {
println("TEST POOL Initialization ( ", TSTPoolName, " ) ... ")
pool, err := zfs.PoolOpen(TSTPoolName)
if err != nil {
t.Error(err.Error())
return
}
defer pool.Close()
err = pool.Initialize()
if err != nil {
t.Error(err.Error())
return
}
time.Sleep(1 * time.Second)
err = pool.SuspendInitialization()
if err != nil {
t.Error(err.Error())
return
}
err = pool.Initialize()
if err != nil {
t.Error(err.Error())
return
}
time.Sleep(1 * time.Second)
err = pool.CancelInitialization()
if err != nil {
t.Error(err.Error())
return
}
print("PASS\n\n")
}
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
// EXAMPLES: // EXAMPLES: