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