zpool online, offline and clear devices

This commit is contained in:
Faruk Kasumovic 2018-06-26 14:01:39 +02:00
parent 44a53fa2e4
commit 441e099de9
4 changed files with 209 additions and 0 deletions

16
zpool.c
View File

@ -497,3 +497,19 @@ nvlist_ptr go_zpool_search_import(libzfs_handle_ptr zfsh, int paths, char **path
return zpool_search_import(zfsh, &idata); return zpool_search_import(zfsh, &idata);
} }
int do_zpool_clear(zpool_list_t *pool, const char *device, u_int32_t rewind_policy) {
nvlist_t *policy = NULL;
int ret = 0;
if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 ||
nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0)
return (1);
if (zpool_clear(pool->zph, device, policy) != 0)
ret = 1;
nvlist_free(policy);
return (ret);
}

13
zpool.h
View File

@ -5,6 +5,15 @@
#ifndef SERVERWARE_ZPOOL_H #ifndef SERVERWARE_ZPOOL_H
#define SERVERWARE_ZPOOL_H #define SERVERWARE_ZPOOL_H
/* Rewind request information */
#define ZPOOL_NO_REWIND 1 /* No policy - default behavior */
#define ZPOOL_NEVER_REWIND 2 /* Do not search for best txg or rewind */
#define ZPOOL_TRY_REWIND 4 /* Search for best txg, but do not rewind */
#define ZPOOL_DO_REWIND 8 /* Rewind to best txg w/in deferred frees */
#define ZPOOL_EXTREME_REWIND 16 /* Allow extreme measures to find best txg */
#define ZPOOL_REWIND_MASK 28 /* All the possible rewind bits */
#define ZPOOL_REWIND_POLICIES 31 /* All the possible policy bits */
struct zpool_list { struct zpool_list {
zpool_handle_t *zph; zpool_handle_t *zph;
void *pnext; void *pnext;
@ -70,6 +79,10 @@ nvlist_ptr get_zpool_vdev_tree(nvlist_ptr nv);
nvlist_ptr go_zpool_search_import(libzfs_handle_ptr zfsh, int paths, char **path, boolean_t do_scan); nvlist_ptr go_zpool_search_import(libzfs_handle_ptr zfsh, int paths, char **path, boolean_t do_scan);
__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 do_zpool_clear(zpool_list_t *pool, const char *device, u_int32_t rewind_policy);
extern char *sZPOOL_CONFIG_VERSION; extern char *sZPOOL_CONFIG_VERSION;
extern char *sZPOOL_CONFIG_POOL_NAME; extern char *sZPOOL_CONFIG_POOL_NAME;

37
zpool_vdev.c Normal file
View File

@ -0,0 +1,37 @@
#include <libzfs.h>
#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <sys/fs/zfs.h>
#include "common.h"
#include "zpool.h"
__uint64_t set_zpool_vdev_online(zpool_list_t *pool, const char *path, int flags) {
vdev_state_t newstate = VDEV_STATE_UNKNOWN;
zpool_vdev_online(pool->zph, path, flags, &newstate);
return newstate;
}
int set_zpool_vdev_offline(zpool_list_t *pool, const char *path, boolean_t istmp, boolean_t force) {
int ret = 0;
// if (force) {
// uint64_t guid = zpool_vdev_path_to_guid(pool->zph, path);
// vdev_aux_t aux;
// if (istmp == B_FALSE) {
// /* Force the fault to persist across imports */
// aux = VDEV_AUX_EXTERNAL_PERSIST;
// } else {
// aux = VDEV_AUX_EXTERNAL;
// }
// if (guid == 0 || zpool_vdev_fault(pool->zph, guid, aux) != 0)
// ret = 1;
// } else {
if (zpool_vdev_offline(pool->zph, path, istmp) != 0)
ret = 1;
// }
return ret;
}

143
zpool_vdev.go Normal file
View File

@ -0,0 +1,143 @@
package zfs
// #include <stdlib.h>
// #include <libzfs.h>
// #include "common.h"
// #include "zpool.h"
// #include "zfs.h"
import "C"
import (
"fmt"
"unsafe"
)
// Online try to set dev online
// expand - expand storage
func (pool *Pool) Online(expand bool, devs ...string) (err error) {
cflags := C.int(0)
if expand {
cflags = C.ZFS_ONLINE_EXPAND
}
for _, dev := range devs {
csdev := C.CString(dev)
var newstate VDevState
if newstate = VDevState(C.set_zpool_vdev_online(pool.list, csdev, cflags)); newstate != VDevStateUnknown {
if newstate != VDevStateHealthy {
err = fmt.Errorf(
"Device '%s' onlined, but remains in faulted state",
dev)
}
} else {
err = LastError()
}
C.free(unsafe.Pointer(csdev))
}
return
}
// Offline Take the device/s in offline state
func (pool *Pool) Offline(force bool, devs ...string) (err error) {
return pool.offline(false, force, devs...)
}
// OfflineTemp Take the device/s in offline state temporary,
// upon reboot, the specified physical device reverts to its previous state.
// force - Force the device into a faulted state.
func (pool *Pool) OfflineTemp(force bool, devs ...string) (err error) {
return pool.offline(true, force, devs...)
}
// temp - Upon reboot, the specified physical device reverts to its previous state.
// force - Force the device into a faulted state.
func (pool *Pool) offline(temp, force bool, devs ...string) (err error) {
for _, dev := range devs {
csdev := C.CString(dev)
var newstate VDevState
if newstate = VDevState(C.set_zpool_vdev_offline(pool.list, csdev, booleanT(temp), booleanT(force))); newstate != VDevStateUnknown {
if newstate != VDevStateHealthy {
err = fmt.Errorf(
"Device '%s' offlined, but remains in faulted state",
dev)
}
} else {
err = LastError()
}
C.free(unsafe.Pointer(csdev))
}
return
}
// Clear - Clear all errors associated with a pool or a particular device.
func (pool *Pool) Clear(device string) (err error) {
csdev := C.CString(device)
if len(device) == 0 {
csdev = nil
}
if sc := C.do_zpool_clear(pool.list, csdev, C.ZPOOL_NO_REWIND); sc != 0 {
err = fmt.Errorf("Pool clear failed")
}
return
}
// Attach test
// func (pool *Pool) attach(props PoolProperties, devs ...string) (err error) {
// cprops := toCPoolProperties(props)
// if cprops != nil {
// defer C.nvlist_free(cprops)
// } else {
// return fmt.Errorf("Out of memory [Pool Attach properties]")
// }
// cdevs := C.alloc_cstrings(C.int(len(devs)))
// if cdevs != nil {
// defer C.free(unsafe.Pointer(cdevs))
// } else {
// return fmt.Errorf("Out of memory [Pool Attach args]")
// }
// for i, dp := range devs {
// tmp := C.CString(dp)
// if tmp != nil {
// defer C.free(unsafe.Pointer(tmp))
// } else {
// return fmt.Errorf("Out of memory [Pool Attach dev]")
// }
// C.strings_setat(cdevs, C.int(i), tmp)
// }
// // vroot := C.make_root_vdev(pool.list.zph, cprops, 0, 0, 0, 0, len(devs), cdevs)
// var nvroot *C.struct_nvlist
// if r := C.nvlist_alloc(&nvroot, C.NV_UNIQUE_NAME, 0); r != 0 {
// err = errors.New("Failed to allocate root vdev")
// return
// }
// csTypeRoot := C.CString(string(VDevTypeRoot))
// r := C.nvlist_add_string(nvroot, C.sZPOOL_CONFIG_TYPE,
// csTypeRoot)
// C.free(unsafe.Pointer(csTypeRoot))
// if r != 0 {
// err = errors.New("Failed to allocate root vdev")
// return
// }
// defer C.nvlist_free(nvroot)
// // Now we need to build specs (vdev hierarchy)
// if err = buildVDevTree(nvroot, VDevTypeRoot, vdev.Devices, vdev.Spares, vdev.L2Cache, props); err != nil {
// return
// }
// return
// }
// func (pool *Pool) AttachForce(devs ...string) (err error) {
// return
// }
// func (pool *Pool) Detach(devs ...string) (err error) {
// return
// }
// func (pool *Pool) DetachForce(devs ...string) (err error) {
// return
// }
// func (pool *Pool) Replace(devs ...string) (err error) {
// return
// }