Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sbin/hastd/metadata.c
39475 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2009-2010 The FreeBSD Foundation
5
*
6
* This software was developed by Pawel Jakub Dawidek under sponsorship from
7
* the FreeBSD Foundation.
8
*
9
* Redistribution and use in source and binary forms, with or without
10
* modification, are permitted provided that the following conditions
11
* are met:
12
* 1. Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
14
* 2. Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in the
16
* documentation and/or other materials provided with the distribution.
17
*
18
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
* SUCH DAMAGE.
29
*/
30
31
#include <sys/cdefs.h>
32
#include <errno.h>
33
#include <fcntl.h>
34
#include <string.h>
35
#include <strings.h>
36
#include <unistd.h>
37
38
#include <ebuf.h>
39
#include <nv.h>
40
#include <pjdlog.h>
41
#include <subr.h>
42
43
#include "metadata.h"
44
45
int
46
metadata_read(struct hast_resource *res, bool openrw)
47
{
48
unsigned char *buf;
49
struct ebuf *eb;
50
struct nv *nv;
51
ssize_t done;
52
const char *str;
53
int rerrno;
54
bool opened_here;
55
56
opened_here = false;
57
rerrno = 0;
58
59
/*
60
* Is this first metadata_read() call for this resource?
61
*/
62
if (res->hr_localfd == -1) {
63
if (provinfo(res, openrw) == -1) {
64
rerrno = errno;
65
goto fail;
66
}
67
opened_here = true;
68
pjdlog_debug(1, "Obtained info about %s.", res->hr_localpath);
69
if (openrw) {
70
if (flock(res->hr_localfd, LOCK_EX | LOCK_NB) == -1) {
71
rerrno = errno;
72
if (errno == EOPNOTSUPP) {
73
pjdlog_warning("Unable to lock %s (operation not supported), but continuing.",
74
res->hr_localpath);
75
} else {
76
pjdlog_errno(LOG_ERR,
77
"Unable to lock %s",
78
res->hr_localpath);
79
goto fail;
80
}
81
}
82
pjdlog_debug(1, "Locked %s.", res->hr_localpath);
83
}
84
}
85
86
eb = ebuf_alloc(METADATA_SIZE);
87
if (eb == NULL) {
88
rerrno = errno;
89
pjdlog_errno(LOG_ERR,
90
"Unable to allocate memory to read metadata");
91
goto fail;
92
}
93
if (ebuf_add_tail(eb, NULL, METADATA_SIZE) == -1) {
94
rerrno = errno;
95
pjdlog_errno(LOG_ERR,
96
"Unable to allocate memory to read metadata");
97
ebuf_free(eb);
98
goto fail;
99
}
100
buf = ebuf_data(eb, NULL);
101
PJDLOG_ASSERT(buf != NULL);
102
done = pread(res->hr_localfd, buf, METADATA_SIZE, 0);
103
if (done == -1 || done != METADATA_SIZE) {
104
rerrno = errno;
105
pjdlog_errno(LOG_ERR, "Unable to read metadata");
106
ebuf_free(eb);
107
goto fail;
108
}
109
nv = nv_ntoh(eb);
110
if (nv == NULL) {
111
rerrno = errno;
112
pjdlog_errno(LOG_ERR, "Metadata read from %s is invalid",
113
res->hr_localpath);
114
ebuf_free(eb);
115
goto fail;
116
}
117
118
str = nv_get_string(nv, "resource");
119
if (str != NULL && strcmp(str, res->hr_name) != 0) {
120
pjdlog_error("Provider %s is not part of resource %s.",
121
res->hr_localpath, res->hr_name);
122
nv_free(nv);
123
goto fail;
124
}
125
126
res->hr_datasize = nv_get_uint64(nv, "datasize");
127
res->hr_extentsize = (int)nv_get_uint32(nv, "extentsize");
128
res->hr_keepdirty = (int)nv_get_uint32(nv, "keepdirty");
129
res->hr_localoff = nv_get_uint64(nv, "offset");
130
res->hr_resuid = nv_get_uint64(nv, "resuid");
131
if (res->hr_role != HAST_ROLE_PRIMARY) {
132
/* Secondary or init role. */
133
res->hr_secondary_localcnt = nv_get_uint64(nv, "localcnt");
134
res->hr_secondary_remotecnt = nv_get_uint64(nv, "remotecnt");
135
}
136
if (res->hr_role != HAST_ROLE_SECONDARY) {
137
/* Primary or init role. */
138
res->hr_primary_localcnt = nv_get_uint64(nv, "localcnt");
139
res->hr_primary_remotecnt = nv_get_uint64(nv, "remotecnt");
140
}
141
str = nv_get_string(nv, "prevrole");
142
if (str != NULL) {
143
if (strcmp(str, "primary") == 0)
144
res->hr_previous_role = HAST_ROLE_PRIMARY;
145
else if (strcmp(str, "secondary") == 0)
146
res->hr_previous_role = HAST_ROLE_SECONDARY;
147
}
148
149
if (nv_error(nv) != 0) {
150
errno = rerrno = nv_error(nv);
151
pjdlog_errno(LOG_ERR, "Unable to read metadata from %s",
152
res->hr_localpath);
153
nv_free(nv);
154
goto fail;
155
}
156
nv_free(nv);
157
return (0);
158
fail:
159
if (opened_here) {
160
close(res->hr_localfd);
161
res->hr_localfd = -1;
162
}
163
errno = rerrno;
164
return (-1);
165
}
166
167
int
168
metadata_write(struct hast_resource *res)
169
{
170
struct ebuf *eb;
171
struct nv *nv;
172
unsigned char *buf, *ptr;
173
size_t size;
174
ssize_t done;
175
int ret;
176
177
buf = calloc(1, METADATA_SIZE);
178
if (buf == NULL) {
179
pjdlog_error("Unable to allocate %zu bytes for metadata.",
180
(size_t)METADATA_SIZE);
181
return (-1);
182
}
183
184
ret = -1;
185
186
nv = nv_alloc();
187
nv_add_string(nv, res->hr_name, "resource");
188
nv_add_uint64(nv, (uint64_t)res->hr_datasize, "datasize");
189
nv_add_uint32(nv, (uint32_t)res->hr_extentsize, "extentsize");
190
nv_add_uint32(nv, (uint32_t)res->hr_keepdirty, "keepdirty");
191
nv_add_uint64(nv, (uint64_t)res->hr_localoff, "offset");
192
nv_add_uint64(nv, res->hr_resuid, "resuid");
193
if (res->hr_role == HAST_ROLE_PRIMARY ||
194
res->hr_role == HAST_ROLE_INIT) {
195
nv_add_uint64(nv, res->hr_primary_localcnt, "localcnt");
196
nv_add_uint64(nv, res->hr_primary_remotecnt, "remotecnt");
197
} else /* if (res->hr_role == HAST_ROLE_SECONDARY) */ {
198
PJDLOG_ASSERT(res->hr_role == HAST_ROLE_SECONDARY);
199
nv_add_uint64(nv, res->hr_secondary_localcnt, "localcnt");
200
nv_add_uint64(nv, res->hr_secondary_remotecnt, "remotecnt");
201
}
202
nv_add_string(nv, role2str(res->hr_role), "prevrole");
203
if (nv_error(nv) != 0) {
204
pjdlog_error("Unable to create metadata.");
205
goto end;
206
}
207
res->hr_previous_role = res->hr_role;
208
eb = nv_hton(nv);
209
PJDLOG_ASSERT(eb != NULL);
210
ptr = ebuf_data(eb, &size);
211
PJDLOG_ASSERT(ptr != NULL);
212
PJDLOG_ASSERT(size < METADATA_SIZE);
213
bcopy(ptr, buf, size);
214
done = pwrite(res->hr_localfd, buf, METADATA_SIZE, 0);
215
if (done == -1 || done != METADATA_SIZE) {
216
pjdlog_errno(LOG_ERR, "Unable to write metadata");
217
goto end;
218
}
219
ret = 0;
220
end:
221
free(buf);
222
nv_free(nv);
223
return (ret);
224
}
225
226