-
Notifications
You must be signed in to change notification settings - Fork 510
/
Copy pathusc_ndctl.c
149 lines (122 loc) · 2.83 KB
/
usc_ndctl.c
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// SPDX-License-Identifier: BSD-3-Clause
/* Copyright 2020-2024, Intel Corporation */
/*
* usc_ndctl.c -- pmem2 usc function for platforms using ndctl
*/
#include <ndctl/libndctl.h>
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <fcntl.h>
#include "config.h"
#include "file.h"
#include "libpmem2.h"
#include "os.h"
#include "out.h"
#include "pmem2_utils.h"
#include "source.h"
#include "region_namespace_ndctl.h"
int
pmem2_source_device_usc(const struct pmem2_source *src, uint64_t *usc)
{
LOG(3, "type %d, uid %p", src->type, usc);
PMEM2_ERR_CLR();
if (src->type == PMEM2_SOURCE_ANON) {
ERR_WO_ERRNO(
"Anonymous source does not support unsafe shutdown count");
return PMEM2_E_NOSUPP;
}
ASSERTeq(src->type, PMEM2_SOURCE_FD);
struct ndctl_ctx *ctx;
int ret = PMEM2_E_NOSUPP;
*usc = 0;
errno = ndctl_new(&ctx) * (-1);
if (errno) {
ERR_W_ERRNO("ndctl_new");
return PMEM2_E_ERRNO;
}
struct ndctl_region *region = NULL;
ret = pmem2_region_namespace(ctx, src, ®ion, NULL);
if (ret < 0)
goto err;
ret = PMEM2_E_NOSUPP;
if (region == NULL) {
ERR_WO_ERRNO(
"Unsafe shutdown count is not supported for this source");
goto err;
}
struct ndctl_dimm *dimm;
ndctl_dimm_foreach_in_region(region, dimm) {
long long dimm_usc = ndctl_dimm_get_dirty_shutdown(dimm);
if (dimm_usc < 0) {
ret = PMEM2_E_NOSUPP;
ERR_WO_ERRNO(
"Unsafe shutdown count is not supported for this source");
goto err;
}
*usc += (unsigned long long)dimm_usc;
}
ret = 0;
err:
ndctl_unref(ctx);
return ret;
}
int
pmem2_source_device_id(const struct pmem2_source *src, char *id, size_t *len)
{
PMEM2_ERR_CLR();
struct ndctl_ctx *ctx;
struct ndctl_dimm *dimm;
int ret;
struct ndctl_region *region = NULL;
const char *dimm_uid;
if (src->type == PMEM2_SOURCE_ANON) {
ERR_WO_ERRNO("Anonymous source does not have device id");
return PMEM2_E_NOSUPP;
}
ASSERTeq(src->type, PMEM2_SOURCE_FD);
errno = ndctl_new(&ctx) * (-1);
if (errno) {
ERR_W_ERRNO("ndctl_new");
return PMEM2_E_ERRNO;
}
size_t len_base = 1; /* '\0' */
ret = pmem2_region_namespace(ctx, src, ®ion, NULL);
if (ret < 0)
goto err;
if (region == NULL) {
ret = PMEM2_E_NOSUPP;
goto err;
}
if (id == NULL) {
ndctl_dimm_foreach_in_region(region, dimm) {
dimm_uid = ndctl_dimm_get_unique_id(dimm);
if (dimm_uid == NULL) {
ret = PMEM2_E_NOSUPP;
goto err;
}
len_base += strlen(ndctl_dimm_get_unique_id(dimm));
}
goto end;
}
size_t count = 1;
ndctl_dimm_foreach_in_region(region, dimm) {
dimm_uid = ndctl_dimm_get_unique_id(dimm);
if (dimm_uid == NULL) {
ret = PMEM2_E_NOSUPP;
goto err;
}
count += strlen(dimm_uid);
if (count > *len) {
ret = PMEM2_E_BUFFER_TOO_SMALL;
goto err;
}
strncat(id, dimm_uid, *len);
}
end:
ret = 0;
if (id == NULL)
*len = len_base;
err:
ndctl_unref(ctx);
return ret;
}