forked from daos-stack/daos
-
Notifications
You must be signed in to change notification settings - Fork 0
/
nvm.go
119 lines (105 loc) · 3.55 KB
/
nvm.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// (C) Copyright 2018-2020 Intel Corporation.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// GOVERNMENT LICENSE RIGHTS-OPEN SOURCE SOFTWARE
// The Government's rights to use, modify, reproduce, release, perform, display,
// or disclose this software are subject to the terms of the Apache License as
// provided in Contract No. 8F-30005.
// Any reproduction of computer software, computer software documentation, or
// portions thereof marked with this legend must also reproduce the markings.
//
// Package ipmctl provides Go bindings for libipmctl Native Management API
package ipmctl
// CGO_CFLAGS & CGO_LDFLAGS env vars can be used
// to specify additional dirs.
/*
#cgo LDFLAGS: -lipmctl
#include "stdlib.h"
#include "nvm_management.h"
#include "nvm_types.h"
#include "NvmSharedDefs.h"
#include "export_api.h"
*/
import "C"
import (
"fmt"
"unsafe"
)
// IpmCtl is the interface that provides access to libipmctl.
type IpmCtl interface {
// SetInterleaved mode for app-direct regions
// process referred to as "set goal" in NVM API
//SetRegion(...)
// Discover persistent memory modules
Discover() ([]DeviceDiscovery, error)
// Update persistent memory module firmware
//Update(...)
// Cleanup persistent memory references
//Cleanup()
}
// NvmMgmt is an implementation of the IpmCtl interface which exercises
// libipmctl's NVM API.
type NvmMgmt struct{}
// Discover queries number of SCM modules and retrieves device_discovery structs
// for each.
func (n *NvmMgmt) Discover() (devices []DeviceDiscovery, err error) {
var count C.uint
if err = Rc2err(
"get_number_of_devices",
C.nvm_get_number_of_devices(&count)); err != nil {
return
}
if count == 0 {
return
}
devs := make([]C.struct_device_discovery, int(count))
// println(len(devs))
// don't need to defer free on devs as we allocated in go
if err = Rc2err(
"get_devices",
C.nvm_get_devices(&devs[0], C.NVM_UINT8(count))); err != nil {
return
}
// defer C.free(unsafe.Pointer(&devs))
// cast struct array to slice of go equivalent struct
// (get equivalent go struct def from cgo -godefs)
devices = (*[1 << 30]DeviceDiscovery)(unsafe.Pointer(&devs[0]))[:count:count]
if len(devices) != int(count) {
err = fmt.Errorf("expected %d devices but got %d", len(devices), int(count))
}
return
}
// Rc2err returns an failure if rc != NVM_SUCCESS.
//
// TODO: print human readable error with provided lib macros
func Rc2err(label string, rc C.int) error {
if rc != C.NVM_SUCCESS {
// e := errors.Error(C.NVDIMM_ERR_W(FORMAT_STR_NL, rc))
return fmt.Errorf("%s: rc=%d", label, int(rc)) // e
}
return nil
}
// example unit test from NVM API source
//TEST_F(NvmApi_Tests, GetDeviceStatus)
//{
// unsigned int dimm_cnt = 0;
// nvm_get_number_of_devices(&dimm_cnt);
// device_discovery *p_devices = (device_discovery *)malloc(sizeof(device_discovery) * dimm_cnt);
// nvm_get_devices(p_devices, dimm_cnt);
// device_status *p_status = (device_status *)malloc(sizeof(device_status));
// EXPECT_EQ(nvm_get_device_status(p_devices->uid, p_status), NVM_SUCCESS);
// free(p_status);
// free(p_devices);
//}