Ejemplo n.º 1
0
/*
 * Convert the given nv structure to network byte order and return ebuf
 * structure.
 */
struct ebuf *
nv_hton(struct nv *nv)
{
	struct nvhdr *nvh;
	unsigned char *ptr;
	size_t size;

	NV_CHECK(nv);
	PJDLOG_ASSERT(nv->nv_error == 0);

	ptr = ebuf_data(nv->nv_ebuf, &size);
	while (size > 0) {
		/*
		 * Minimum size at this point is size of nvhdr structure,
		 * one character long name plus terminating '\0'.
		 */
		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
		nvh = (struct nvhdr *)ptr;
		PJDLOG_ASSERT(NVH_SIZE(nvh) <= size);
		nv_swap(nvh, false);
		ptr += NVH_SIZE(nvh);
		size -= NVH_SIZE(nvh);
	}

	return (nv->nv_ebuf);
}
Ejemplo n.º 2
0
int
metadata_write(struct hast_resource *res)
{
	struct ebuf *eb;
	struct nv *nv;
	unsigned char *buf, *ptr;
	size_t size;
	ssize_t done;
	int ret;

	buf = calloc(1, METADATA_SIZE);
	if (buf == NULL) {
		pjdlog_error("Unable to allocate %zu bytes for metadata.",
		    (size_t)METADATA_SIZE);
		return (-1);
	}

	ret = -1;

	nv = nv_alloc();
	nv_add_string(nv, res->hr_name, "resource");
	nv_add_uint64(nv, (uint64_t)res->hr_datasize, "datasize");
	nv_add_uint32(nv, (uint32_t)res->hr_extentsize, "extentsize");
	nv_add_uint32(nv, (uint32_t)res->hr_keepdirty, "keepdirty");
	nv_add_uint64(nv, (uint64_t)res->hr_localoff, "offset");
	nv_add_uint64(nv, res->hr_resuid, "resuid");
	if (res->hr_role == HAST_ROLE_PRIMARY ||
	    res->hr_role == HAST_ROLE_INIT) {
		nv_add_uint64(nv, res->hr_primary_localcnt, "localcnt");
		nv_add_uint64(nv, res->hr_primary_remotecnt, "remotecnt");
	} else /* if (res->hr_role == HAST_ROLE_SECONDARY) */ {
		PJDLOG_ASSERT(res->hr_role == HAST_ROLE_SECONDARY);
		nv_add_uint64(nv, res->hr_secondary_localcnt, "localcnt");
		nv_add_uint64(nv, res->hr_secondary_remotecnt, "remotecnt");
	}
	nv_add_string(nv, role2str(res->hr_role), "prevrole");
	if (nv_error(nv) != 0) {
		pjdlog_error("Unable to create metadata.");
		goto end;
	}
	res->hr_previous_role = res->hr_role;
	eb = nv_hton(nv);
	PJDLOG_ASSERT(eb != NULL);
	ptr = ebuf_data(eb, &size);
	PJDLOG_ASSERT(ptr != NULL);
	PJDLOG_ASSERT(size < METADATA_SIZE);
	bcopy(ptr, buf, size);
	done = pwrite(res->hr_localfd, buf, METADATA_SIZE, 0);
	if (done == -1 || done != METADATA_SIZE) {
		pjdlog_errno(LOG_ERR, "Unable to write metadata");
		goto end;
	}
	ret = 0;
end:
	free(buf);
	nv_free(nv);
	return (ret);
}
Ejemplo n.º 3
0
/*
 * Send the given nv structure via conn.
 * We keep headers in nv structure and pass data in separate argument.
 * There can be no data at all (data is NULL then).
 */
int
hast_proto_send(const struct hast_resource *res, struct proto_conn *conn,
    struct nv *nv, const void *data, size_t size)
{
	struct hast_main_header hdr;
	struct ebuf *eb;
	bool freedata;
	void *dptr, *hptr;
	size_t hsize;
	int ret;

	dptr = (void *)(uintptr_t)data;
	freedata = false;
	ret = -1;

	if (data != NULL) {
		unsigned int ii;

		for (ii = 0; ii < sizeof(pipeline) / sizeof(pipeline[0]);
		    ii++) {
			(void)pipeline[ii].hps_send(res, nv, &dptr, &size,
			    &freedata);
		}
		nv_add_uint32(nv, size, "size");
		if (nv_error(nv) != 0) {
			errno = nv_error(nv);
			goto end;
		}
	}

	eb = nv_hton(nv);
	if (eb == NULL)
		goto end;

	hdr.version = res != NULL ? res->hr_version : HAST_PROTO_VERSION;
	hdr.size = htole32((uint32_t)ebuf_size(eb));
	if (ebuf_add_head(eb, &hdr, sizeof(hdr)) == -1)
		goto end;

	hptr = ebuf_data(eb, &hsize);
	if (proto_send(conn, hptr, hsize) == -1)
		goto end;
	if (data != NULL && proto_send(conn, dptr, size) == -1)
		goto end;

	ret = 0;
end:
	if (freedata)
		free(dptr);
	return (ret);
}
Ejemplo n.º 4
0
static struct nvhdr *
nv_find(struct nv *nv, int type, const char *namefmt, va_list nameap)
{
	char name[255];
	struct nvhdr *nvh;
	unsigned char *ptr;
	size_t size, namesize;

	if (nv == NULL) {
		errno = ENOMEM;
		return (NULL);
	}

	NV_CHECK(nv);

	namesize = vsnprintf(name, sizeof(name), namefmt, nameap);
	PJDLOG_ASSERT(namesize > 0 && namesize < sizeof(name));
	namesize++;

	ptr = ebuf_data(nv->nv_ebuf, &size);
	while (size > 0) {
		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
		nvh = (struct nvhdr *)ptr;
		PJDLOG_ASSERT(size >= NVH_SIZE(nvh));
		nv_swap(nvh, true);
		if (strcmp(nvh->nvh_name, name) == 0) {
			if (type != NV_TYPE_NONE &&
			    (nvh->nvh_type & NV_TYPE_MASK) != type) {
				errno = EINVAL;
				if (nv->nv_error == 0)
					nv->nv_error = EINVAL;
				return (NULL);
			}
			return (nvh);
		}
		ptr += NVH_SIZE(nvh);
		size -= NVH_SIZE(nvh);
	}
	errno = ENOENT;
	if (nv->nv_error == 0)
		nv->nv_error = ENOENT;
	return (NULL);
}
Ejemplo n.º 5
0
int
hast_proto_recv_hdr(const struct proto_conn *conn, struct nv **nvp)
{
	struct hast_main_header hdr;
	struct nv *nv;
	struct ebuf *eb;
	void *hptr;

	eb = NULL;
	nv = NULL;

	if (proto_recv(conn, &hdr, sizeof(hdr)) == -1)
		goto fail;

	if (hdr.version > HAST_PROTO_VERSION) {
		errno = ERPCMISMATCH;
		goto fail;
	}

	hdr.size = le32toh(hdr.size);

	eb = ebuf_alloc(hdr.size);
	if (eb == NULL)
		goto fail;
	if (ebuf_add_tail(eb, NULL, hdr.size) == -1)
		goto fail;
	hptr = ebuf_data(eb, NULL);
	PJDLOG_ASSERT(hptr != NULL);
	if (proto_recv(conn, hptr, hdr.size) == -1)
		goto fail;
	nv = nv_ntoh(eb);
	if (nv == NULL)
		goto fail;

	*nvp = nv;
	return (0);
fail:
	if (eb != NULL)
		ebuf_free(eb);
	return (-1);
}
Ejemplo n.º 6
0
int
metadata_read(struct hast_resource *res, bool openrw)
{
	unsigned char *buf;
	struct ebuf *eb;
	struct nv *nv;
	ssize_t done;
	const char *str;
	int rerrno;
	bool opened_here;

	opened_here = false;
	rerrno = 0;

	/*
	 * Is this first metadata_read() call for this resource?
	 */
	if (res->hr_localfd == -1) {
		if (provinfo(res, openrw) == -1) {
			rerrno = errno;
			goto fail;
		}
		opened_here = true;
		pjdlog_debug(1, "Obtained info about %s.", res->hr_localpath);
		if (openrw) {
			if (flock(res->hr_localfd, LOCK_EX | LOCK_NB) == -1) {
				rerrno = errno;
				if (errno == EOPNOTSUPP) {
					pjdlog_warning("Unable to lock %s (operation not supported), but continuing.",
					    res->hr_localpath);
				} else {
					pjdlog_errno(LOG_ERR,
					    "Unable to lock %s",
					    res->hr_localpath);
					goto fail;
				}
			}
			pjdlog_debug(1, "Locked %s.", res->hr_localpath);
		}
	}

	eb = ebuf_alloc(METADATA_SIZE);
	if (eb == NULL) {
		rerrno = errno;
		pjdlog_errno(LOG_ERR,
		    "Unable to allocate memory to read metadata");
		goto fail;
	}
	if (ebuf_add_tail(eb, NULL, METADATA_SIZE) == -1) {
		rerrno = errno;
		pjdlog_errno(LOG_ERR,
		    "Unable to allocate memory to read metadata");
		ebuf_free(eb);
		goto fail;
	}
	buf = ebuf_data(eb, NULL);
	PJDLOG_ASSERT(buf != NULL);
	done = pread(res->hr_localfd, buf, METADATA_SIZE, 0);
	if (done == -1 || done != METADATA_SIZE) {
		rerrno = errno;
		pjdlog_errno(LOG_ERR, "Unable to read metadata");
		ebuf_free(eb);
		goto fail;
	}
	nv = nv_ntoh(eb);
	if (nv == NULL) {
		rerrno = errno;
		pjdlog_errno(LOG_ERR, "Metadata read from %s is invalid",
		    res->hr_localpath);
		ebuf_free(eb);
		goto fail;
	}

	str = nv_get_string(nv, "resource");
	if (str != NULL && strcmp(str, res->hr_name) != 0) {
		pjdlog_error("Provider %s is not part of resource %s.",
		    res->hr_localpath, res->hr_name);
		nv_free(nv);
		goto fail;
	}

	res->hr_datasize = nv_get_uint64(nv, "datasize");
	res->hr_extentsize = (int)nv_get_uint32(nv, "extentsize");
	res->hr_keepdirty = (int)nv_get_uint32(nv, "keepdirty");
	res->hr_localoff = nv_get_uint64(nv, "offset");
	res->hr_resuid = nv_get_uint64(nv, "resuid");
	if (res->hr_role != HAST_ROLE_PRIMARY) {
		/* Secondary or init role. */
		res->hr_secondary_localcnt = nv_get_uint64(nv, "localcnt");
		res->hr_secondary_remotecnt = nv_get_uint64(nv, "remotecnt");
	}
	if (res->hr_role != HAST_ROLE_SECONDARY) {
		/* Primary or init role. */
		res->hr_primary_localcnt = nv_get_uint64(nv, "localcnt");
		res->hr_primary_remotecnt = nv_get_uint64(nv, "remotecnt");
	}
	str = nv_get_string(nv, "prevrole");
	if (str != NULL) {
		if (strcmp(str, "primary") == 0)
			res->hr_previous_role = HAST_ROLE_PRIMARY;
		else if (strcmp(str, "secondary") == 0)
			res->hr_previous_role = HAST_ROLE_SECONDARY;
	}

	if (nv_error(nv) != 0) {
		errno = rerrno = nv_error(nv);
		pjdlog_errno(LOG_ERR, "Unable to read metadata from %s",
		    res->hr_localpath);
		nv_free(nv);
		goto fail;
	}
	nv_free(nv);
	return (0);
fail:
	if (opened_here) {
		close(res->hr_localfd);
		res->hr_localfd = -1;
	}
	errno = rerrno;
	return (-1);
}
Ejemplo n.º 7
0
/*
 * Dump content of the nv structure.
 */
void
nv_dump(struct nv *nv)
{
	struct nvhdr *nvh;
	unsigned char *data, *ptr;
	size_t dsize, size;
	unsigned int ii;
	bool swap;

	if (nv_validate(nv, NULL) == -1) {
		printf("error: %d\n", errno);
		return;
	}

	NV_CHECK(nv);
	PJDLOG_ASSERT(nv->nv_error == 0);

	ptr = ebuf_data(nv->nv_ebuf, &size);
	while (size > 0) {
		PJDLOG_ASSERT(size >= sizeof(*nvh) + 2);
		nvh = (struct nvhdr *)ptr;
		PJDLOG_ASSERT(size >= NVH_SIZE(nvh));
		swap = ((nvh->nvh_type & NV_ORDER_MASK) == NV_ORDER_NETWORK);
		dsize = NVH_DSIZE(nvh);
		data = NVH_DATA(nvh);
		printf("  %s", nvh->nvh_name);
		switch (nvh->nvh_type & NV_TYPE_MASK) {
		case NV_TYPE_INT8:
			printf("(int8): %jd", (intmax_t)(*(int8_t *)data));
			break;
		case NV_TYPE_UINT8:
			printf("(uint8): %ju", (uintmax_t)(*(uint8_t *)data));
			break;
		case NV_TYPE_INT16:
			printf("(int16): %jd", swap ?
			    (intmax_t)le16toh(*(int16_t *)(void *)data) :
			    (intmax_t)*(int16_t *)(void *)data);
			break;
		case NV_TYPE_UINT16:
			printf("(uint16): %ju", swap ?
			    (uintmax_t)le16toh(*(uint16_t *)(void *)data) :
			    (uintmax_t)*(uint16_t *)(void *)data);
			break;
		case NV_TYPE_INT32:
			printf("(int32): %jd", swap ?
			    (intmax_t)le32toh(*(int32_t *)(void *)data) :
			    (intmax_t)*(int32_t *)(void *)data);
			break;
		case NV_TYPE_UINT32:
			printf("(uint32): %ju", swap ?
			    (uintmax_t)le32toh(*(uint32_t *)(void *)data) :
			    (uintmax_t)*(uint32_t *)(void *)data);
			break;
		case NV_TYPE_INT64:
			printf("(int64): %jd", swap ?
			    (intmax_t)le64toh(*(int64_t *)(void *)data) :
			    (intmax_t)*(int64_t *)(void *)data);
			break;
		case NV_TYPE_UINT64:
			printf("(uint64): %ju", swap ?
			    (uintmax_t)le64toh(*(uint64_t *)(void *)data) :
			    (uintmax_t)*(uint64_t *)(void *)data);
			break;
		case NV_TYPE_INT8_ARRAY:
			printf("(int8 array):");
			for (ii = 0; ii < dsize; ii++)
				printf(" %jd", (intmax_t)((int8_t *)data)[ii]);
			break;
		case NV_TYPE_UINT8_ARRAY:
			printf("(uint8 array):");
			for (ii = 0; ii < dsize; ii++)
				printf(" %ju", (uintmax_t)((uint8_t *)data)[ii]);
			break;
		case NV_TYPE_INT16_ARRAY:
			printf("(int16 array):");
			for (ii = 0; ii < dsize / 2; ii++) {
				printf(" %jd", swap ?
				    (intmax_t)le16toh(((int16_t *)(void *)data)[ii]) :
				    (intmax_t)((int16_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_UINT16_ARRAY:
			printf("(uint16 array):");
			for (ii = 0; ii < dsize / 2; ii++) {
				printf(" %ju", swap ?
				    (uintmax_t)le16toh(((uint16_t *)(void *)data)[ii]) :
				    (uintmax_t)((uint16_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_INT32_ARRAY:
			printf("(int32 array):");
			for (ii = 0; ii < dsize / 4; ii++) {
				printf(" %jd", swap ?
				    (intmax_t)le32toh(((int32_t *)(void *)data)[ii]) :
				    (intmax_t)((int32_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_UINT32_ARRAY:
			printf("(uint32 array):");
			for (ii = 0; ii < dsize / 4; ii++) {
				printf(" %ju", swap ?
				    (uintmax_t)le32toh(((uint32_t *)(void *)data)[ii]) :
				    (uintmax_t)((uint32_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_INT64_ARRAY:
			printf("(int64 array):");
			for (ii = 0; ii < dsize / 8; ii++) {
				printf(" %ju", swap ?
				    (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) :
				    (uintmax_t)((uint64_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_UINT64_ARRAY:
			printf("(uint64 array):");
			for (ii = 0; ii < dsize / 8; ii++) {
				printf(" %ju", swap ?
				    (uintmax_t)le64toh(((uint64_t *)(void *)data)[ii]) :
				    (uintmax_t)((uint64_t *)(void *)data)[ii]);
			}
			break;
		case NV_TYPE_STRING:
			printf("(string): %s", (char *)data);
			break;
		default:
			PJDLOG_ABORT("invalid condition");
		}
		printf("\n");
		ptr += NVH_SIZE(nvh);
		size -= NVH_SIZE(nvh);
	}
}
Ejemplo n.º 8
0
/*
 * Validate correctness of the entire nv structure and all its elements.
 * If extrap is not NULL, store number of extra bytes at the end of the buffer.
 */
int
nv_validate(struct nv *nv, size_t *extrap)
{
	struct nvhdr *nvh;
	unsigned char *data, *ptr;
	size_t dsize, size, vsize;
	int error;

	if (nv == NULL) {
		errno = ENOMEM;
		return (-1);
	}

	NV_CHECK(nv);
	PJDLOG_ASSERT(nv->nv_error == 0);

	/* TODO: Check that names are unique? */

	error = 0;
	ptr = ebuf_data(nv->nv_ebuf, &size);
	while (size > 0) {
		/*
		 * Zeros at the end of the buffer are acceptable.
		 */
		if (ptr[0] == '\0')
			break;
		/*
		 * Minimum size at this point is size of nvhdr structure, one
		 * character long name plus terminating '\0'.
		 */
		if (size < sizeof(*nvh) + 2) {
			error = EINVAL;
			break;
		}
		nvh = (struct nvhdr *)ptr;
		if (size < NVH_HSIZE(nvh)) {
			error = EINVAL;
			break;
		}
		if (nvh->nvh_name[nvh->nvh_namesize - 1] != '\0') {
			error = EINVAL;
			break;
		}
		if (strlen(nvh->nvh_name) !=
		    (size_t)(nvh->nvh_namesize - 1)) {
			error = EINVAL;
			break;
		}
		if ((nvh->nvh_type & NV_TYPE_MASK) < NV_TYPE_FIRST ||
		    (nvh->nvh_type & NV_TYPE_MASK) > NV_TYPE_LAST) {
			error = EINVAL;
			break;
		}
		dsize = NVH_DSIZE(nvh);
		if (dsize == 0) {
			error = EINVAL;
			break;
		}
		if (size < NVH_SIZE(nvh)) {
			error = EINVAL;
			break;
		}
		vsize = 0;
		switch (nvh->nvh_type & NV_TYPE_MASK) {
		case NV_TYPE_INT8:
		case NV_TYPE_UINT8:
			if (vsize == 0)
				vsize = 1;
			/* FALLTHROUGH */
		case NV_TYPE_INT16:
		case NV_TYPE_UINT16:
			if (vsize == 0)
				vsize = 2;
			/* FALLTHROUGH */
		case NV_TYPE_INT32:
		case NV_TYPE_UINT32:
			if (vsize == 0)
				vsize = 4;
			/* FALLTHROUGH */
		case NV_TYPE_INT64:
		case NV_TYPE_UINT64:
			if (vsize == 0)
				vsize = 8;
			if (dsize != vsize) {
				error = EINVAL;
				break;
			}
			break;
		case NV_TYPE_INT8_ARRAY:
		case NV_TYPE_UINT8_ARRAY:
			break;
		case NV_TYPE_INT16_ARRAY:
		case NV_TYPE_UINT16_ARRAY:
			if (vsize == 0)
				vsize = 2;
			/* FALLTHROUGH */
		case NV_TYPE_INT32_ARRAY:
		case NV_TYPE_UINT32_ARRAY:
			if (vsize == 0)
				vsize = 4;
			/* FALLTHROUGH */
		case NV_TYPE_INT64_ARRAY:
		case NV_TYPE_UINT64_ARRAY:
			if (vsize == 0)
				vsize = 8;
			if ((dsize % vsize) != 0) {
				error = EINVAL;
				break;
			}
			break;
		case NV_TYPE_STRING:
			data = NVH_DATA(nvh);
			if (data[dsize - 1] != '\0') {
				error = EINVAL;
				break;
			}
			if (strlen((char *)data) != dsize - 1) {
				error = EINVAL;
				break;
			}
			break;
		default:
			PJDLOG_ABORT("invalid condition");
		}
		if (error != 0)
			break;
		ptr += NVH_SIZE(nvh);
		size -= NVH_SIZE(nvh);
	}
	if (error != 0) {
		errno = error;
		if (nv->nv_error == 0)
			nv->nv_error = error;
		return (-1);
	}
	if (extrap != NULL)
		*extrap = size;
	return (0);
}