2 * Copyright (c) 2009-2010 The FreeBSD Foundation
5 * This software was developed by Pawel Jakub Dawidek under sponsorship from
6 * the FreeBSD Foundation.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
48 metadata_read(struct hast_resource *res, bool openrw)
62 * Is this first metadata_read() call for this resource?
64 if (res->hr_localfd == -1) {
65 if (provinfo(res, openrw) < 0) {
70 pjdlog_debug(1, "Obtained info about %s.", res->hr_localpath);
72 if (flock(res->hr_localfd, LOCK_EX | LOCK_NB) < 0) {
74 if (errno == EOPNOTSUPP) {
75 pjdlog_warning("Unable to lock %s (operation not supported), but continuing.",
84 pjdlog_debug(1, "Locked %s.", res->hr_localpath);
88 eb = ebuf_alloc(METADATA_SIZE);
92 "Unable to allocate memory to read metadata");
95 if (ebuf_add_tail(eb, NULL, METADATA_SIZE) < 0) {
98 "Unable to allocate memory to read metadata");
102 buf = ebuf_data(eb, NULL);
104 done = pread(res->hr_localfd, buf, METADATA_SIZE, 0);
105 if (done < 0 || done != METADATA_SIZE) {
107 pjdlog_errno(LOG_ERR, "Unable to read metadata");
114 pjdlog_errno(LOG_ERR, "Metadata read from %s is invalid",
120 str = nv_get_string(nv, "resource");
121 if (str != NULL && strcmp(str, res->hr_name) != 0) {
122 pjdlog_error("Provider %s is not part of resource %s.",
123 res->hr_localpath, res->hr_name);
128 res->hr_datasize = nv_get_uint64(nv, "datasize");
129 res->hr_extentsize = (int)nv_get_uint32(nv, "extentsize");
130 res->hr_keepdirty = (int)nv_get_uint32(nv, "keepdirty");
131 res->hr_localoff = nv_get_uint64(nv, "offset");
132 res->hr_resuid = nv_get_uint64(nv, "resuid");
133 if (res->hr_role != HAST_ROLE_PRIMARY) {
134 /* Secondary or init role. */
135 res->hr_secondary_localcnt = nv_get_uint64(nv, "localcnt");
136 res->hr_secondary_remotecnt = nv_get_uint64(nv, "remotecnt");
138 if (res->hr_role != HAST_ROLE_SECONDARY) {
139 /* Primary or init role. */
140 res->hr_primary_localcnt = nv_get_uint64(nv, "localcnt");
141 res->hr_primary_remotecnt = nv_get_uint64(nv, "remotecnt");
143 str = nv_get_string(nv, "prevrole");
145 if (strcmp(str, "primary") == 0)
146 res->hr_previous_role = HAST_ROLE_PRIMARY;
147 else if (strcmp(str, "secondary") == 0)
148 res->hr_previous_role = HAST_ROLE_SECONDARY;
151 if (nv_error(nv) != 0) {
152 errno = rerrno = nv_error(nv);
153 pjdlog_errno(LOG_ERR, "Unable to read metadata from %s",
162 close(res->hr_localfd);
163 res->hr_localfd = -1;
170 metadata_write(struct hast_resource *res)
174 unsigned char *buf, *ptr;
179 buf = calloc(1, METADATA_SIZE);
181 pjdlog_error("Unable to allocate %zu bytes for metadata.",
182 (size_t)METADATA_SIZE);
189 nv_add_string(nv, res->hr_name, "resource");
190 nv_add_uint64(nv, (uint64_t)res->hr_datasize, "datasize");
191 nv_add_uint32(nv, (uint32_t)res->hr_extentsize, "extentsize");
192 nv_add_uint32(nv, (uint32_t)res->hr_keepdirty, "keepdirty");
193 nv_add_uint64(nv, (uint64_t)res->hr_localoff, "offset");
194 nv_add_uint64(nv, res->hr_resuid, "resuid");
195 if (res->hr_role == HAST_ROLE_PRIMARY ||
196 res->hr_role == HAST_ROLE_INIT) {
197 nv_add_uint64(nv, res->hr_primary_localcnt, "localcnt");
198 nv_add_uint64(nv, res->hr_primary_remotecnt, "remotecnt");
199 } else /* if (res->hr_role == HAST_ROLE_SECONDARY) */ {
200 assert(res->hr_role == HAST_ROLE_SECONDARY);
201 nv_add_uint64(nv, res->hr_secondary_localcnt, "localcnt");
202 nv_add_uint64(nv, res->hr_secondary_remotecnt, "remotecnt");
204 nv_add_string(nv, role2str(res->hr_role), "prevrole");
205 if (nv_error(nv) != 0) {
206 pjdlog_error("Unable to create metadata.");
209 res->hr_previous_role = res->hr_role;
212 ptr = ebuf_data(eb, &size);
214 assert(size < METADATA_SIZE);
215 bcopy(ptr, buf, size);
216 done = pwrite(res->hr_localfd, buf, METADATA_SIZE, 0);
217 if (done < 0 || done != METADATA_SIZE) {
218 pjdlog_errno(LOG_ERR, "Unable to write metadata");