Merge pull request #5 from ncabatoff/master

Fix bug where VDevTree.Stat wasn't being populated , add pool.RefreshStats and fix memory leaks
This commit is contained in:
Faruk Kasumovic 2016-07-20 16:35:07 +02:00 committed by GitHub
commit 631236eb5e
3 changed files with 218 additions and 34 deletions

87
zpool.c
View File

@ -9,6 +9,80 @@
#include "zpool.h" #include "zpool.h"
char *sZPOOL_CONFIG_VERSION = ZPOOL_CONFIG_VERSION;
char *sZPOOL_CONFIG_POOL_NAME = ZPOOL_CONFIG_POOL_NAME;
char *sZPOOL_CONFIG_POOL_STATE = ZPOOL_CONFIG_POOL_STATE;
char *sZPOOL_CONFIG_POOL_TXG = ZPOOL_CONFIG_POOL_TXG;
char *sZPOOL_CONFIG_POOL_GUID = ZPOOL_CONFIG_POOL_GUID;
char *sZPOOL_CONFIG_CREATE_TXG = ZPOOL_CONFIG_CREATE_TXG;
char *sZPOOL_CONFIG_TOP_GUID = ZPOOL_CONFIG_TOP_GUID;
char *sZPOOL_CONFIG_VDEV_TREE = ZPOOL_CONFIG_VDEV_TREE;
char *sZPOOL_CONFIG_TYPE = ZPOOL_CONFIG_TYPE;
char *sZPOOL_CONFIG_CHILDREN = ZPOOL_CONFIG_CHILDREN;
char *sZPOOL_CONFIG_ID = ZPOOL_CONFIG_ID;
char *sZPOOL_CONFIG_GUID = ZPOOL_CONFIG_GUID;
char *sZPOOL_CONFIG_PATH = ZPOOL_CONFIG_PATH;
char *sZPOOL_CONFIG_DEVID = ZPOOL_CONFIG_DEVID;
char *sZPOOL_CONFIG_METASLAB_ARRAY = ZPOOL_CONFIG_METASLAB_ARRAY;
char *sZPOOL_CONFIG_METASLAB_SHIFT = ZPOOL_CONFIG_METASLAB_SHIFT;
char *sZPOOL_CONFIG_ASHIFT = ZPOOL_CONFIG_ASHIFT;
char *sZPOOL_CONFIG_ASIZE = ZPOOL_CONFIG_ASIZE;
char *sZPOOL_CONFIG_DTL = ZPOOL_CONFIG_DTL;
char *sZPOOL_CONFIG_SCAN_STATS = ZPOOL_CONFIG_SCAN_STATS;
char *sZPOOL_CONFIG_VDEV_STATS = ZPOOL_CONFIG_VDEV_STATS;
char *sZPOOL_CONFIG_WHOLE_DISK = ZPOOL_CONFIG_WHOLE_DISK;
char *sZPOOL_CONFIG_ERRCOUNT = ZPOOL_CONFIG_ERRCOUNT;
char *sZPOOL_CONFIG_NOT_PRESENT = ZPOOL_CONFIG_NOT_PRESENT;
char *sZPOOL_CONFIG_SPARES = ZPOOL_CONFIG_SPARES;
char *sZPOOL_CONFIG_IS_SPARE = ZPOOL_CONFIG_IS_SPARE;
char *sZPOOL_CONFIG_NPARITY = ZPOOL_CONFIG_NPARITY;
char *sZPOOL_CONFIG_HOSTID = ZPOOL_CONFIG_HOSTID;
char *sZPOOL_CONFIG_HOSTNAME = ZPOOL_CONFIG_HOSTNAME;
char *sZPOOL_CONFIG_LOADED_TIME = ZPOOL_CONFIG_LOADED_TIME;
char *sZPOOL_CONFIG_UNSPARE = ZPOOL_CONFIG_UNSPARE;
char *sZPOOL_CONFIG_PHYS_PATH = ZPOOL_CONFIG_PHYS_PATH;
char *sZPOOL_CONFIG_IS_LOG = ZPOOL_CONFIG_IS_LOG;
char *sZPOOL_CONFIG_L2CACHE = ZPOOL_CONFIG_L2CACHE;
char *sZPOOL_CONFIG_HOLE_ARRAY = ZPOOL_CONFIG_HOLE_ARRAY;
char *sZPOOL_CONFIG_VDEV_CHILDREN = ZPOOL_CONFIG_VDEV_CHILDREN;
char *sZPOOL_CONFIG_IS_HOLE = ZPOOL_CONFIG_IS_HOLE;
char *sZPOOL_CONFIG_DDT_HISTOGRAM = ZPOOL_CONFIG_DDT_HISTOGRAM;
char *sZPOOL_CONFIG_DDT_OBJ_STATS = ZPOOL_CONFIG_DDT_OBJ_STATS;
char *sZPOOL_CONFIG_DDT_STATS = ZPOOL_CONFIG_DDT_STATS;
char *sZPOOL_CONFIG_SPLIT = ZPOOL_CONFIG_SPLIT;
char *sZPOOL_CONFIG_ORIG_GUID = ZPOOL_CONFIG_ORIG_GUID;
char *sZPOOL_CONFIG_SPLIT_GUID = ZPOOL_CONFIG_SPLIT_GUID;
char *sZPOOL_CONFIG_SPLIT_LIST = ZPOOL_CONFIG_SPLIT_LIST;
char *sZPOOL_CONFIG_REMOVING = ZPOOL_CONFIG_REMOVING;
char *sZPOOL_CONFIG_RESILVER_TXG = ZPOOL_CONFIG_RESILVER_TXG;
char *sZPOOL_CONFIG_COMMENT = ZPOOL_CONFIG_COMMENT;
char *sZPOOL_CONFIG_SUSPENDED = ZPOOL_CONFIG_SUSPENDED;
char *sZPOOL_CONFIG_TIMESTAMP = ZPOOL_CONFIG_TIMESTAMP;
char *sZPOOL_CONFIG_BOOTFS = ZPOOL_CONFIG_BOOTFS;
char *sZPOOL_CONFIG_MISSING_DEVICES = ZPOOL_CONFIG_MISSING_DEVICES;
char *sZPOOL_CONFIG_LOAD_INFO = ZPOOL_CONFIG_LOAD_INFO;
char *sZPOOL_CONFIG_REWIND_INFO = ZPOOL_CONFIG_REWIND_INFO;
char *sZPOOL_CONFIG_UNSUP_FEAT = ZPOOL_CONFIG_UNSUP_FEAT;
char *sZPOOL_CONFIG_ENABLED_FEAT = ZPOOL_CONFIG_ENABLED_FEAT;
char *sZPOOL_CONFIG_CAN_RDONLY = ZPOOL_CONFIG_CAN_RDONLY;
char *sZPOOL_CONFIG_FEATURES_FOR_READ = ZPOOL_CONFIG_FEATURES_FOR_READ;
char *sZPOOL_CONFIG_FEATURE_STATS = ZPOOL_CONFIG_FEATURE_STATS;
char *sZPOOL_CONFIG_ERRATA = ZPOOL_CONFIG_ERRATA;
char *sZPOOL_CONFIG_OFFLINE = ZPOOL_CONFIG_OFFLINE;
char *sZPOOL_CONFIG_FAULTED = ZPOOL_CONFIG_FAULTED;
char *sZPOOL_CONFIG_DEGRADED = ZPOOL_CONFIG_DEGRADED;
char *sZPOOL_CONFIG_REMOVED = ZPOOL_CONFIG_REMOVED;
char *sZPOOL_CONFIG_FRU = ZPOOL_CONFIG_FRU;
char *sZPOOL_CONFIG_AUX_STATE = ZPOOL_CONFIG_AUX_STATE;
char *sZPOOL_REWIND_POLICY = ZPOOL_REWIND_POLICY;
char *sZPOOL_REWIND_REQUEST = ZPOOL_REWIND_REQUEST;
char *sZPOOL_REWIND_REQUEST_TXG = ZPOOL_REWIND_REQUEST_TXG;
char *sZPOOL_REWIND_META_THRESH = ZPOOL_REWIND_META_THRESH;
char *sZPOOL_REWIND_DATA_THRESH = ZPOOL_REWIND_DATA_THRESH;
char *sZPOOL_CONFIG_LOAD_TIME = ZPOOL_CONFIG_LOAD_TIME;
char *sZPOOL_CONFIG_LOAD_DATA_ERRORS = ZPOOL_CONFIG_LOAD_DATA_ERRORS;
char *sZPOOL_CONFIG_REWIND_TIME = ZPOOL_CONFIG_REWIND_TIME;
static char _lasterr_[1024]; static char _lasterr_[1024];
const char *lasterr(void) { const char *lasterr(void) {
@ -395,3 +469,16 @@ void free_cstring(char *str) {
nvlist_t *nvlist_array_at(nvlist_t **a, uint_t i) { nvlist_t *nvlist_array_at(nvlist_t **a, uint_t i) {
return a[i]; return a[i];
} }
int refresh_stats(zpool_list_t *pool)
{
boolean_t missing;
int err = zpool_refresh_stats(pool->zph, &missing);
if ( err != 0 ) {
return err;
}
if ( missing == B_TRUE ) {
return -1;
}
return 0;
}

View File

@ -129,7 +129,10 @@ type Pool struct {
// Returns Pool object, requires Pool.Close() to be called explicitly // Returns Pool object, requires Pool.Close() to be called explicitly
// for memory cleanup after object is not needed anymore. // for memory cleanup after object is not needed anymore.
func PoolOpen(name string) (pool Pool, err error) { func PoolOpen(name string) (pool Pool, err error) {
pool.list = C.zpool_list_open(libzfsHandle, C.CString(name)) namestr := C.CString(name)
pool.list = C.zpool_list_open(libzfsHandle, namestr)
C.free_cstring(namestr)
if pool.list != nil { if pool.list != nil {
err = pool.ReloadProperties() err = pool.ReloadProperties()
return return
@ -145,8 +148,7 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
var vs *C.vdev_stat_t var vs *C.vdev_stat_t
var ps *C.pool_scan_stat_t var ps *C.pool_scan_stat_t
var child **C.nvlist_t var child **C.nvlist_t
var vdev VDevTree if 0 != C.nvlist_lookup_string(nv, C.sZPOOL_CONFIG_TYPE, &dtype) {
if 0 != C.nvlist_lookup_string(nv, C.CString(C.ZPOOL_CONFIG_TYPE), &dtype) {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_TYPE) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_TYPE)
return return
} }
@ -157,7 +159,7 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
} }
// Fetch vdev state // Fetch vdev state
if 0 != C.nvlist_lookup_uint64_array_vds(nv, C.CString(C.ZPOOL_CONFIG_VDEV_STATS), if 0 != C.nvlist_lookup_uint64_array_vds(nv, C.sZPOOL_CONFIG_VDEV_STATS,
&vs, &c) { &vs, &c) {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_STATS) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_STATS)
return return
@ -171,8 +173,8 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
vdevs.Stat.RSize = uint64(vs.vs_rsize) vdevs.Stat.RSize = uint64(vs.vs_rsize)
vdevs.Stat.ESize = uint64(vs.vs_esize) vdevs.Stat.ESize = uint64(vs.vs_esize)
for z := 0; z < ZIOTypes; z++ { for z := 0; z < ZIOTypes; z++ {
vdev.Stat.Ops[z] = uint64(vs.vs_ops[z]) vdevs.Stat.Ops[z] = uint64(vs.vs_ops[z])
vdev.Stat.Bytes[z] = uint64(vs.vs_bytes[z]) vdevs.Stat.Bytes[z] = uint64(vs.vs_bytes[z])
} }
vdevs.Stat.ReadErrors = uint64(vs.vs_read_errors) vdevs.Stat.ReadErrors = uint64(vs.vs_read_errors)
vdevs.Stat.WriteErrors = uint64(vs.vs_write_errors) vdevs.Stat.WriteErrors = uint64(vs.vs_write_errors)
@ -183,7 +185,7 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
vdevs.Stat.Fragmentation = uint64(vs.vs_fragmentation) vdevs.Stat.Fragmentation = uint64(vs.vs_fragmentation)
// Fetch vdev scan stats // Fetch vdev scan stats
if 0 == C.nvlist_lookup_uint64_array_ps(nv, C.CString(C.ZPOOL_CONFIG_SCAN_STATS), if 0 == C.nvlist_lookup_uint64_array_ps(nv, C.sZPOOL_CONFIG_SCAN_STATS,
&ps, &c) { &ps, &c) {
vdevs.ScanStat.Func = uint64(ps.pss_func) vdevs.ScanStat.Func = uint64(ps.pss_func)
vdevs.ScanStat.State = uint64(ps.pss_state) vdevs.ScanStat.State = uint64(ps.pss_state)
@ -199,17 +201,17 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
} }
// Fetch the children // Fetch the children
if C.nvlist_lookup_nvlist_array(nv, C.CString(C.ZPOOL_CONFIG_CHILDREN), if C.nvlist_lookup_nvlist_array(nv, C.sZPOOL_CONFIG_CHILDREN,
&child, &children) != 0 { &child, &children) != 0 {
return return
} }
if children > 0 { if children > 0 {
vdevs.Devices = make([]VDevTree, 0, children) vdevs.Devices = make([]VDevTree, 0, children)
} }
if C.nvlist_lookup_uint64(nv, C.CString(C.ZPOOL_CONFIG_NOT_PRESENT), if C.nvlist_lookup_uint64(nv, C.sZPOOL_CONFIG_NOT_PRESENT,
&notpresent) == 0 { &notpresent) == 0 {
var path *C.char var path *C.char
if 0 != C.nvlist_lookup_string(nv, C.CString(C.ZPOOL_CONFIG_PATH), &path) { if 0 != C.nvlist_lookup_string(nv, C.sZPOOL_CONFIG_PATH, &path) {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_PATH) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_PATH)
return return
} }
@ -219,12 +221,14 @@ func poolGetConfig(name string, nv *C.nvlist_t) (vdevs VDevTree, err error) {
var islog = C.uint64_t(C.B_FALSE) var islog = C.uint64_t(C.B_FALSE)
C.nvlist_lookup_uint64(C.nvlist_array_at(child, c), C.nvlist_lookup_uint64(C.nvlist_array_at(child, c),
C.CString(C.ZPOOL_CONFIG_IS_LOG), &islog) C.sZPOOL_CONFIG_IS_LOG, &islog)
if islog != C.B_FALSE { if islog != C.B_FALSE {
continue continue
} }
vname := C.zpool_vdev_name(libzfsHandle, nil, C.nvlist_array_at(child, c), vname := C.zpool_vdev_name(libzfsHandle, nil, C.nvlist_array_at(child, c),
C.B_TRUE) C.B_TRUE)
var vdev VDevTree
vdev, err = poolGetConfig(C.GoString(vname), vdev, err = poolGetConfig(C.GoString(vname),
C.nvlist_array_at(child, c)) C.nvlist_array_at(child, c))
C.free_cstring(vname) C.free_cstring(vname)
@ -262,18 +266,18 @@ func PoolImportSearch(searchpaths []string) (epools []ExportedPool, err error) {
err = LastError() err = LastError()
return return
} }
if C.nvlist_lookup_uint64(config, C.CString(C.ZPOOL_CONFIG_POOL_STATE), if C.nvlist_lookup_uint64(config, C.sZPOOL_CONFIG_POOL_STATE,
&poolState) != 0 { &poolState) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_STATE) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_STATE)
return return
} }
ep.State = PoolState(poolState) ep.State = PoolState(poolState)
if C.nvlist_lookup_string(config, C.CString(C.ZPOOL_CONFIG_POOL_NAME), &cname) != 0 { if C.nvlist_lookup_string(config, C.sZPOOL_CONFIG_POOL_NAME, &cname) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_NAME) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_NAME)
return return
} }
ep.Name = C.GoString(cname) ep.Name = C.GoString(cname)
if C.nvlist_lookup_uint64(config, C.CString(C.ZPOOL_CONFIG_POOL_GUID), &guid) != 0 { if C.nvlist_lookup_uint64(config, C.sZPOOL_CONFIG_POOL_GUID, &guid) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_GUID) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_POOL_GUID)
return return
} }
@ -281,11 +285,11 @@ func PoolImportSearch(searchpaths []string) (epools []ExportedPool, err error) {
reason = C.zpool_import_status(config, &msgid, &errata) reason = C.zpool_import_status(config, &msgid, &errata)
ep.Status = PoolStatus(reason) ep.Status = PoolStatus(reason)
if C.nvlist_lookup_string(config, C.CString(C.ZPOOL_CONFIG_COMMENT), &comment) == 0 { if C.nvlist_lookup_string(config, C.sZPOOL_CONFIG_COMMENT, &comment) == 0 {
ep.Comment = C.GoString(comment) ep.Comment = C.GoString(comment)
} }
if C.nvlist_lookup_nvlist(config, C.CString(C.ZPOOL_CONFIG_VDEV_TREE), if C.nvlist_lookup_nvlist(config, C.sZPOOL_CONFIG_VDEV_TREE,
&nvroot) != 0 { &nvroot) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_TREE) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_TREE)
return return
@ -324,7 +328,7 @@ func poolSearchImport(q string, searchpaths []string, guid bool) (name string,
if guid { if guid {
var iguid C.uint64_t var iguid C.uint64_t
if retcode = C.nvlist_lookup_uint64(tconfig, if retcode = C.nvlist_lookup_uint64(tconfig,
C.CString(C.ZPOOL_CONFIG_POOL_GUID), &iguid); retcode != 0 { C.sZPOOL_CONFIG_POOL_GUID, &iguid); retcode != 0 {
err = errPoolList err = errPoolList
return return
} }
@ -335,7 +339,7 @@ func poolSearchImport(q string, searchpaths []string, guid bool) (name string,
} }
} else { } else {
if retcode = C.nvlist_lookup_string(tconfig, if retcode = C.nvlist_lookup_string(tconfig,
C.CString(C.ZPOOL_CONFIG_POOL_NAME), &cq); retcode != 0 { C.sZPOOL_CONFIG_POOL_NAME, &cq); retcode != 0 {
err = errPoolList err = errPoolList
return return
} }
@ -354,7 +358,7 @@ func poolSearchImport(q string, searchpaths []string, guid bool) (name string,
if guid { if guid {
// We need to get name so we can open pool by name // We need to get name so we can open pool by name
if retcode := C.nvlist_lookup_string(config, if retcode := C.nvlist_lookup_string(config,
C.CString(C.ZPOOL_CONFIG_POOL_NAME), &cname); retcode != 0 { C.sZPOOL_CONFIG_POOL_NAME, &cname); retcode != 0 {
err = errPoolList err = errPoolList
return return
} }
@ -442,6 +446,14 @@ func PoolStateToName(state PoolState) (name string) {
return return
} }
// Refresh the pool's vdev statistics, e.g. bytes read/written.
func (pool *Pool) RefreshStats() (err error) {
if 0 != C.refresh_stats(pool.list) {
return errors.New("error refreshing stats")
}
return nil
}
// ReloadProperties re-read ZFS pool properties and features, refresh // ReloadProperties re-read ZFS pool properties and features, refresh
// Pool.Properties and Pool.Features map // Pool.Properties and Pool.Features map
func (pool *Pool) ReloadProperties() (err error) { func (pool *Pool) ReloadProperties() (err error) {
@ -473,7 +485,10 @@ func (pool *Pool) ReloadProperties() (err error) {
"filesystem_limits": "disabled", "filesystem_limits": "disabled",
"large_blocks": "disabled"} "large_blocks": "disabled"}
for name := range pool.Features { for name := range pool.Features {
pool.GetFeature(name) _, ferr := pool.GetFeature(name)
if ferr != nil {
// tolerate it
}
} }
return return
} }
@ -505,8 +520,11 @@ func (pool *Pool) GetProperty(p Prop) (prop Property, err error) {
// feature in Features map. // feature in Features map.
func (pool *Pool) GetFeature(name string) (value string, err error) { func (pool *Pool) GetFeature(name string) (value string, err error) {
var fvalue [512]C.char var fvalue [512]C.char
sname := fmt.Sprint("feature@", name) var sname *C.char
r := C.zpool_prop_get_feature(pool.list.zph, C.CString(sname), &(fvalue[0]), 512) sname = C.CString(fmt.Sprint("feature@", name))
r := C.zpool_prop_get_feature(pool.list.zph, sname, &(fvalue[0]), 512)
C.free_cstring(sname)
if r != 0 { if r != 0 {
err = errors.New(fmt.Sprint("Unknown zpool feature: ", name)) err = errors.New(fmt.Sprint("Unknown zpool feature: ", name))
return return
@ -673,12 +691,12 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
vdev.Type, mindevs, maxdevs) vdev.Type, mindevs, maxdevs)
return return
} }
if r := C.nvlist_add_string(child, C.CString(C.ZPOOL_CONFIG_TYPE), if r := C.nvlist_add_string(child, C.sZPOOL_CONFIG_TYPE,
C.CString(string(vdev.Type))); r != 0 { C.CString(string(vdev.Type))); r != 0 {
err = errors.New("Failed to set vdev type") err = errors.New("Failed to set vdev type")
return return
} }
if r := C.nvlist_add_uint64(child, C.CString(C.ZPOOL_CONFIG_IS_LOG), if r := C.nvlist_add_uint64(child, C.sZPOOL_CONFIG_IS_LOG,
vdev.isLog()); r != 0 { vdev.isLog()); r != 0 {
err = errors.New("Failed to allocate vdev (is_log)") err = errors.New("Failed to allocate vdev (is_log)")
return return
@ -686,7 +704,7 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
if grouping { if grouping {
if vdev.Type == VDevTypeRaidz { if vdev.Type == VDevTypeRaidz {
r := C.nvlist_add_uint64(child, r := C.nvlist_add_uint64(child,
C.CString(C.ZPOOL_CONFIG_NPARITY), C.sZPOOL_CONFIG_NPARITY,
C.uint64_t(mindevs-1)) C.uint64_t(mindevs-1))
if r != 0 { if r != 0 {
err = errors.New("Failed to allocate vdev (parity)") err = errors.New("Failed to allocate vdev (parity)")
@ -700,14 +718,14 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
} else { } else {
// if vdev.Type == VDevTypeDisk { // if vdev.Type == VDevTypeDisk {
if r := C.nvlist_add_uint64(child, if r := C.nvlist_add_uint64(child,
C.CString(C.ZPOOL_CONFIG_WHOLE_DISK), 1); r != 0 { C.sZPOOL_CONFIG_WHOLE_DISK, 1); r != 0 {
err = errors.New("Failed to allocate vdev child (whdisk)") err = errors.New("Failed to allocate vdev child (whdisk)")
return return
} }
// } // }
if len(vdev.Path) > 0 { if len(vdev.Path) > 0 {
if r := C.nvlist_add_string( if r := C.nvlist_add_string(
child, C.CString(C.ZPOOL_CONFIG_PATH), child, C.sZPOOL_CONFIG_PATH,
C.CString(vdev.Path)); r != 0 { C.CString(vdev.Path)); r != 0 {
err = errors.New("Failed to allocate vdev child (type)") err = errors.New("Failed to allocate vdev child (type)")
return return
@ -715,7 +733,7 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
ashift, _ := strconv.Atoi(props[PoolPropAshift]) ashift, _ := strconv.Atoi(props[PoolPropAshift])
if ashift > 0 { if ashift > 0 {
if r := C.nvlist_add_uint64(child, if r := C.nvlist_add_uint64(child,
C.CString(C.ZPOOL_CONFIG_ASHIFT), C.sZPOOL_CONFIG_ASHIFT,
C.uint64_t(ashift)); r != 0 { C.uint64_t(ashift)); r != 0 {
err = errors.New("Failed to allocate vdev child (ashift)") err = errors.New("Failed to allocate vdev child (ashift)")
return return
@ -738,7 +756,7 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
} }
if count > 0 { if count > 0 {
if r := C.nvlist_add_nvlist_array(root, if r := C.nvlist_add_nvlist_array(root,
C.CString(C.ZPOOL_CONFIG_CHILDREN), childrens, C.sZPOOL_CONFIG_CHILDREN, childrens,
C.uint_t(count)); r != 0 { C.uint_t(count)); r != 0 {
err = errors.New("Failed to allocate vdev children") err = errors.New("Failed to allocate vdev children")
return return
@ -748,7 +766,7 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
} }
if nl2cache > 0 { if nl2cache > 0 {
if r := C.nvlist_add_nvlist_array(root, if r := C.nvlist_add_nvlist_array(root,
C.CString(C.ZPOOL_CONFIG_L2CACHE), l2cache, C.sZPOOL_CONFIG_L2CACHE, l2cache,
C.uint_t(nl2cache)); r != 0 { C.uint_t(nl2cache)); r != 0 {
err = errors.New("Failed to allocate vdev cache") err = errors.New("Failed to allocate vdev cache")
return return
@ -756,7 +774,7 @@ func buildVDevTree(root *C.nvlist_t, rtype VDevType, vdevs []VDevTree,
} }
if nspares > 0 { if nspares > 0 {
if r := C.nvlist_add_nvlist_array(root, if r := C.nvlist_add_nvlist_array(root,
C.CString(C.ZPOOL_CONFIG_SPARES), spares, C.sZPOOL_CONFIG_SPARES, spares,
C.uint_t(nspares)); r != 0 { C.uint_t(nspares)); r != 0 {
err = errors.New("Failed to allocate vdev spare") err = errors.New("Failed to allocate vdev spare")
return return
@ -775,7 +793,7 @@ func PoolCreate(name string, vdevs []VDevTree, features map[string]string,
err = errors.New("Failed to allocate root vdev") err = errors.New("Failed to allocate root vdev")
return return
} }
if r := C.nvlist_add_string(nvroot, C.CString(C.ZPOOL_CONFIG_TYPE), if r := C.nvlist_add_string(nvroot, C.sZPOOL_CONFIG_TYPE,
C.CString(string(VDevTypeRoot))); r != 0 { C.CString(string(VDevTypeRoot))); r != 0 {
err = errors.New("Failed to allocate root vdev") err = errors.New("Failed to allocate root vdev")
return return
@ -874,9 +892,11 @@ func (pool *Pool) Export(force bool, log string) (err error) {
// ExportForce hard force export of the pool from the system. // ExportForce hard force export of the pool from the system.
func (pool *Pool) ExportForce(log string) (err error) { func (pool *Pool) ExportForce(log string) (err error) {
if rc := C.zpool_export_force(pool.list.zph, C.CString(log)); rc != 0 { logstr := C.CString(log)
if rc := C.zpool_export_force(pool.list.zph, logstr); rc != 0 {
err = LastError() err = LastError()
} }
C.free_cstring(logstr)
return return
} }
@ -889,7 +909,7 @@ func (pool *Pool) VDevTree() (vdevs VDevTree, err error) {
err = fmt.Errorf("Failed zpool_get_config") err = fmt.Errorf("Failed zpool_get_config")
return return
} }
if C.nvlist_lookup_nvlist(config, C.CString(C.ZPOOL_CONFIG_VDEV_TREE), if C.nvlist_lookup_nvlist(config, C.sZPOOL_CONFIG_VDEV_TREE,
&nvroot) != 0 { &nvroot) != 0 {
err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_TREE) err = fmt.Errorf("Failed to fetch %s", C.ZPOOL_CONFIG_VDEV_TREE)
return return

77
zpool.h
View File

@ -61,5 +61,82 @@ int nvlist_lookup_uint64_array_vds(nvlist_t *nv, const char *p,
int nvlist_lookup_uint64_array_ps(nvlist_t *nv, const char *p, int nvlist_lookup_uint64_array_ps(nvlist_t *nv, const char *p,
pool_scan_stat_t **vds, uint_t *c); pool_scan_stat_t **vds, uint_t *c);
int refresh_stats(zpool_list_t *pool);
char *sZPOOL_CONFIG_VERSION;
char *sZPOOL_CONFIG_POOL_NAME;
char *sZPOOL_CONFIG_POOL_STATE;
char *sZPOOL_CONFIG_POOL_TXG;
char *sZPOOL_CONFIG_POOL_GUID;
char *sZPOOL_CONFIG_CREATE_TXG;
char *sZPOOL_CONFIG_TOP_GUID;
char *sZPOOL_CONFIG_VDEV_TREE;
char *sZPOOL_CONFIG_TYPE;
char *sZPOOL_CONFIG_CHILDREN;
char *sZPOOL_CONFIG_ID;
char *sZPOOL_CONFIG_GUID;
char *sZPOOL_CONFIG_PATH;
char *sZPOOL_CONFIG_DEVID;
char *sZPOOL_CONFIG_METASLAB_ARRAY;
char *sZPOOL_CONFIG_METASLAB_SHIFT;
char *sZPOOL_CONFIG_ASHIFT;
char *sZPOOL_CONFIG_ASIZE;
char *sZPOOL_CONFIG_DTL;
char *sZPOOL_CONFIG_SCAN_STATS;
char *sZPOOL_CONFIG_VDEV_STATS;
char *sZPOOL_CONFIG_WHOLE_DISK;
char *sZPOOL_CONFIG_ERRCOUNT;
char *sZPOOL_CONFIG_NOT_PRESENT;
char *sZPOOL_CONFIG_SPARES;
char *sZPOOL_CONFIG_IS_SPARE;
char *sZPOOL_CONFIG_NPARITY;
char *sZPOOL_CONFIG_HOSTID;
char *sZPOOL_CONFIG_HOSTNAME;
char *sZPOOL_CONFIG_LOADED_TIME;
char *sZPOOL_CONFIG_UNSPARE;
char *sZPOOL_CONFIG_PHYS_PATH;
char *sZPOOL_CONFIG_IS_LOG;
char *sZPOOL_CONFIG_L2CACHE;
char *sZPOOL_CONFIG_HOLE_ARRAY;
char *sZPOOL_CONFIG_VDEV_CHILDREN;
char *sZPOOL_CONFIG_IS_HOLE;
char *sZPOOL_CONFIG_DDT_HISTOGRAM;
char *sZPOOL_CONFIG_DDT_OBJ_STATS;
char *sZPOOL_CONFIG_DDT_STATS;
char *sZPOOL_CONFIG_SPLIT;
char *sZPOOL_CONFIG_ORIG_GUID;
char *sZPOOL_CONFIG_SPLIT_GUID;
char *sZPOOL_CONFIG_SPLIT_LIST;
char *sZPOOL_CONFIG_REMOVING;
char *sZPOOL_CONFIG_RESILVER_TXG;
char *sZPOOL_CONFIG_COMMENT;
char *sZPOOL_CONFIG_SUSPENDED;
char *sZPOOL_CONFIG_TIMESTAMP;
char *sZPOOL_CONFIG_BOOTFS;
char *sZPOOL_CONFIG_MISSING_DEVICES;
char *sZPOOL_CONFIG_LOAD_INFO;
char *sZPOOL_CONFIG_REWIND_INFO;
char *sZPOOL_CONFIG_UNSUP_FEAT;
char *sZPOOL_CONFIG_ENABLED_FEAT;
char *sZPOOL_CONFIG_CAN_RDONLY;
char *sZPOOL_CONFIG_FEATURES_FOR_READ;
char *sZPOOL_CONFIG_FEATURE_STATS;
char *sZPOOL_CONFIG_ERRATA;
char *sZPOOL_CONFIG_OFFLINE;
char *sZPOOL_CONFIG_FAULTED;
char *sZPOOL_CONFIG_DEGRADED;
char *sZPOOL_CONFIG_REMOVED;
char *sZPOOL_CONFIG_FRU;
char *sZPOOL_CONFIG_AUX_STATE;
char *sZPOOL_REWIND_POLICY;
char *sZPOOL_REWIND_REQUEST;
char *sZPOOL_REWIND_REQUEST_TXG;
char *sZPOOL_REWIND_META_THRESH;
char *sZPOOL_REWIND_DATA_THRESH;
char *sZPOOL_CONFIG_LOAD_TIME;
char *sZPOOL_CONFIG_LOAD_DATA_ERRORS;
char *sZPOOL_CONFIG_REWIND_TIME;
#endif #endif
/* SERVERWARE_ZPOOL_H */ /* SERVERWARE_ZPOOL_H */