Beispiel #1
1
/*
 * Dump debugging state to a result string
 */
bool_t
rcmd_debug_dump_to_string_1_svc(char **result, struct svc_req *rqstp)
{
	char* buffer = NULL;
	size_t buffer_size = 0;
	FILE* fp = NULL;

	fp = open_memstream(&buffer, &buffer_size);
	if (!fp)
	{
		error_perror("unable to create in-memory file");
		*result = xstrdup("Error: out of memory");
		goto cleanup;
	}

	show_debugging_info(fp);
	fclose(fp);

	*result = buffer ? buffer : xstrdup("Error: out of memory");

cleanup:

	return true;
}
Beispiel #2
0
/*
 * Commit current xenstore transaction.
 *
 * Returns:
 * 	XSTS_OK	       success
 * 	XSTS_RETRY     retry the transaction
 *	XSTS_NORETRY   out of retry limit (message logged)
 *	XSTS_FAIL      commit failed (message logged)
 */
static XsTransactionStatus commit_xs(int* p_nretries)
{
	if (xst == XS_TRANSACTION_NULL)
		fatal_msg("bug: commit_xs outside of a transaction");

	if (xs_transaction_end(xs, xst, FALSE))
	{
		debug_msg(15, "committed transaction");
		xst = XS_TRANSACTION_NULL;
		return XSTS_OK;
	}

	xst = XS_TRANSACTION_NULL;

	if (errno == EAGAIN)
	{
		if (++(*p_nretries) > max_xs_retries)
		{
			error_perror("unable to write xenstore (transaction retry limit exceeded)");
			return XSTS_NORETRY;
		}

		retry_wait(*p_nretries);

		debug_msg(2, "restarting xenstore transaction");
		return XSTS_RETRY;
	}
	else
	{
		error_perror("unable to write xenstore (xs_transaction_end)");
		return XSTS_FAIL;
	}
}
Beispiel #3
0
int net_packet_push_lua(int len, const char *data, int sockfd, packet_t **head, packet_t **tail)
{
	if(len+4 > PACKET_LEN_MAX)
	{
		fprintf(stderr, "net_packet_new: packet too large (%i > %i)\n"
			, len, PACKET_LEN_MAX-4);
		return 1;
	}
	
	if(len < 1)
	{
		fprintf(stderr, "net_packet_new: packet too small (%i < 1)\n"
			, len);
		return 1;
	}
	
	int poffs = (len >= 64 ? 3 : 1);
	
	packet_t *pkt = (packet_t*)malloc(sizeof(packet_t)+len+poffs);
	if(pkt == NULL)
	{
		error_perror("net_packet_new");
		return 1;
	}
	
	pkt->data[0] = (poffs == 1 ? len+0x3F : 0x7F);
	if(poffs != 1)
	{
		pkt->data[1] = len&255;
		pkt->data[2] = len>>8;
	}
Beispiel #4
0
/*
 * Start XenStore transaction.
 * If successful, return @true.
 * On error, return @false and log error message.     		      .
 */
static bool begin_xs(void)
{
	int nretries = 0;

	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: begin_xs inside a transaction");

	for (;;)
	{
		xst = xs_transaction_start(xs);
		if (xst != XS_TRANSACTION_NULL)
			break;

		/*
		 * ENOSPC means too many concurrent transactions from the domain
		 */
		if (errno == ENOSPC)
		{
			if (++nretries > max_xs_retries)
			{
				error_perror("unable to start xenstore transaction (retry limit exceeded)");
				break;
			}

			retry_wait(nretries);
			debug_msg(2, "retrying to start xenstore transaction");
		}
		else
		{
			error_perror("unable to start xenstore transaction");
			break;
		}
	}

	if (xst != XS_TRANSACTION_NULL)
	{
		debug_msg(15, "started transaction");
		return true;
	}
	else
	{
		return false;
	}
}
Beispiel #5
0
int net_packet_push(int len, const char *data, int neth, packet_t **head, packet_t **tail)
{
	if(len > PACKET_LEN_MAX)
	{
		fprintf(stderr, "net_packet_new: packet too large (%i > %i)\n"
			, len, PACKET_LEN_MAX);
		return 1;
	}
	
	client_t *cli = net_neth_get_client(neth);

	if(cli == NULL)
	{
		fprintf(stderr, "Note: NULL client in packet pusher, ignoring\n");
		return 0;
		//fflush(stderr);
		//abort();
	}

	if(cli->sockfd == SOCKFD_ENET)
	{
		ENetPacket *ep = enet_packet_create(data, len, ENET_PACKET_FLAG_RELIABLE);
		enet_peer_send(cli->peer, 1, ep);
	} else {
		if(len < 1)
		{
			fprintf(stderr, "net_packet_new: packet too small (%i < 1)\n"
				, len);
			return 1;
		}
		
		packet_t *pkt = (packet_t*)malloc(sizeof(packet_t)+len);
		if(pkt == NULL)
		{
			error_perror("net_packet_new");
			return 1;
		}
		
		memcpy(pkt->data, data, len);
		pkt->len = len;
		pkt->neth = neth;
		if(*head == NULL)
		{
			pkt->p = pkt->n = NULL;
			*head = *tail = pkt;
		} else {
			(*tail)->n = pkt;
			pkt->p = (*tail);
			pkt->n = NULL;
			*tail = pkt;
		}
	}
	
	return 0;
}
Beispiel #6
0
/*
 * Handle poll(...) completion.
 * Return @true if any event was processed,
 * @false otherwise.
 */
bool rcmd_handle_pollfds(struct pollfd* pollfds)
{
	struct pollfd* pollfd;
	int nfds = svc_max_pollfd;
	int k, fd;
	struct sockaddr_un addr;
	socklen_t addrlen = sizeof addr;
	bool res = false;

	/* any events on RPC connection sockets? */
	for (k = 0;  k < nfds;  k++)
	{
		if (pollfds[k].revents && pollfds[k].fd != -1)
			res = true;
	}

	/* handle events on RPC connection sockets */
	if (res)
	{
		debug_msg(40, "calling svc_getreq_poll");
		svc_getreq_poll(pollfds, nfds);
		debug_msg(40, "finished svc_getreq_poll");
	}

	/* handle events (if any) on the listener socket */
	if (sock != -1)
	{
		pollfd = pollfds + nfds;

		if (pollfd->revents & pollfd->events)
		{
			res = true;
			debug_msg(12, "accepting RPC connection");
			DO_RESTARTABLE(fd, accept(sock, (struct sockaddr*) &addr, &addrlen));
			if (fd == -1)
			{
				error_perror("unable to accept RPC connection");
			}
			else
			{
				debug_msg(12, "accepted RPC connection");
				SVCXPRT* transp = svcunixfd_create(fd, 0, 0);
				if (transp == NULL)
				{
					error_msg("unable to accept RPC connection (svcunixfd_create failed)");
					close(fd);
				}
			}
		}
	}

	return res;
}
Beispiel #7
0
/*
 * Read and apply updated membalance settings
 */
static void update_membalance_settings(void)
{
	char *pv = NULL;
	unsigned int len;
	long v;
	char* ep = NULL;

	if (!subscribed_membalance)
		return;

	pv = xs_read(xs, xst, membalance_interval_path, &len);
	if (!pv)
	{
		/*
		 * In the event of a temporary glitch, schedule to read the
		 * settings a little later. Could be a temporary shortage
		 * of resources, or membalanced did not yet add this VM to the
		 * permission list on the key.
		 */
		error_perror("unable to read xenstore (%s)", membalance_interval_path);
		need_update_membalance_settings = true;
		return;
	}

	need_update_membalance_settings = false;

	errno = 0;
	v = strtol(pv, &ep, 10);
	if (errno || ep == pv || *ep || v <= 0)
	{
		error_msg("ignoring invalid refresh interval setting");
		goto cleanup;
	}

	/* sanity check */
	if (v > max_interval)
	{
		error_msg("restricting value of refresh interval to %d seconds", max_interval);
		v = max_interval;
	}

	interval = v;

	debug_msg(2, "updated interval to %d seconds", interval);

cleanup:

	if (pv)
		free(pv);
}
Beispiel #8
0
int model_save_pmf(model_t *pmf, const char *fname)
{
	int i,j;
	
	FILE *fp = fopen(fname, "wb");
	
	// check for errors
	if(fp == NULL)
		return error_perror("model_save_pmf");
	
	// and now we crawl through the spec.
	
	// start with the header of "PMF",0x1A,1,0,0,0
	char head[8];
	
	fwrite("PMF\x1A\x01\x00\x00\x00", 8, 1, fp);
	
	// then there's a uint32_t denoting how many body parts there are
	uint32_t bone_count = pmf->bonelen;
	fwrite(&bone_count, 4, 1, fp);
	
	// then, for each body part,
	for(i = 0; i < (int)bone_count; i++)
	{
		// there's a null-terminated 16-byte string (max 15 chars) denoting the part
		fwrite(pmf->bones[i]->name, 16, 1, fp);
		
		// then there's a uint32_t denoting how many points there are in this body part
		uint32_t pt_count = pmf->bones[i]->ptlen;
		fwrite(&pt_count, 4, 1, fp);
		
		// then there's a whole bunch of this:
		//   uint16_t radius;
		//   int16_t x,y,z;
		//   uint8_t b,g,r,reserved;
		fwrite(pmf->bones[i]->pts, sizeof(model_point_t), pt_count, fp);
		
		// rinse, lather, repeat
		
		// units are 8:8 fixed point in terms of the vxl grid by default
	}
	
	fclose(fp);
	
	return 0;
}
Beispiel #9
0
int net_packet_push_lua_enet(int len, const char *data, int neth, packet_t **head, packet_t **tail)
{
	if(len+4 > PACKET_LEN_MAX)
	{
		fprintf(stderr, "net_packet_new: packet too large (%i > %i)\n"
			, len, PACKET_LEN_MAX-4);
		return 1;
	}
	
	if(len < 1)
	{
		fprintf(stderr, "net_packet_new: packet too small (%i < 1)\n"
			, len);
		return 1;
	}
	
	client_t *cli = net_neth_get_client(neth);

	if(cli == NULL)
	{
		fprintf(stderr, "Note: NULL client in packet pusher, ignoring\n");
		return 0;
		//fflush(stderr);
		//abort();
	}

	int poffs = (len >= 64 ? 3 : 1);
	
	packet_t *pkt = (packet_t*)malloc(sizeof(packet_t)+len+poffs);
	if(pkt == NULL)
	{
		error_perror("net_packet_new");
		return 1;
	}
	
	pkt->data[0] = (poffs == 1 ? len+0x3F : 0x7F);
	if(poffs != 1)
	{
		pkt->data[1] = len&255;
		pkt->data[2] = len>>8;
	}
Beispiel #10
0
int net_packet_push(int len, const char *data, int sockfd, packet_t **head, packet_t **tail)
{
	if(len > PACKET_LEN_MAX)
	{
		fprintf(stderr, "net_packet_new: packet too large (%i > %i)\n"
			, len, PACKET_LEN_MAX);
		return 1;
	}
	
	if(len < 1)
	{
		fprintf(stderr, "net_packet_new: packet too small (%i < 1)\n"
			, len);
		return 1;
	}
	
	packet_t *pkt = (packet_t*)malloc(sizeof(packet_t)+len);
	if(pkt == NULL)
	{
		error_perror("net_packet_new");
		return 1;
	}
	
	memcpy(pkt->data, data, len);
	pkt->len = len;
	pkt->sockfd = sockfd;
	if(*head == NULL)
	{
		pkt->p = pkt->n = NULL;
		*head = *tail = pkt;
	} else {
		(*tail)->n = pkt;
		pkt->p = (*tail);
		pkt->n = NULL;
		*tail = pkt;
	}
	
	return 0;
}
Beispiel #11
0
model_t *model_parse_pmf(int len, const char *data)
{
	int i,j;
	
	const char *p = data;
	const char *dend = data + len;
	
	// and now we crawl through the spec.
	
	// start with the header of "PMF",0x1A,1,0,0,0
	char head[8];
	
	if(memcmp(p, "PMF\x1A\x01\x00\x00\x00", 8))
	{
		fprintf(stderr, "model_load_pmf: not a valid PMF v1 file\n");
		return NULL;
	}
	p += 8;
	
	// then there's a uint32_t denoting how many body parts there are
	uint32_t bone_count = *(uint32_t *)p;
	p += 4;
	if(bone_count > MODEL_BONE_MAX)
	{
		fprintf(stderr, "model_parse_pmf: too many bones (%i > %i)\n"
			, bone_count, MODEL_BONE_MAX);
		return NULL;
	}
	
	model_t *pmf = model_new(bone_count);
	if(pmf == NULL)
	{
		error_perror("model_parse_pmf");
		return NULL;
	}
	pmf->udtype = UD_PMF;
	
	// then, for each body part,
	for(i = 0; i < (int)bone_count; i++)
	{
		// there's a null-terminated 16-byte string (max 15 chars) denoting the part
		const char *namebuf = p;
		p += 16;
		
		if(namebuf[15] != '\x00')
		{
			fprintf(stderr, "model_load_pmf: name not null terminated\n");
			model_free(pmf);
			return NULL;
		}
		
		// then there's a uint32_t denoting how many points there are in this body part
		uint32_t pt_count = *(uint32_t *)p;
		p += 4;
		
		// (just allocating the bone here)
		model_bone_t *bone = model_bone_new(pmf, pt_count);
		pmf = bone->parent;
		memcpy(bone->name, namebuf, 16);
		if(bone == NULL)
		{
			error_perror("model_parse_pmf");
			model_free(pmf);
			return NULL;
		}
		
		// then there's a whole bunch of this:
		//   uint16_t radius;
		//   int16_t x,y,z;
		//   uint8_t b,g,r,reserved;
		int bonelen = sizeof(model_point_t)*pt_count;
		memcpy(bone->pts, p, bonelen);
		p += bonelen;
		bone->ptlen = pt_count;
		
		// "reserved" needs to be 0 or else you suck
		// NO SIDECHANNELING YOUR NAME IN THERE
		// i'm going to enforce this in the loader
		// and will outright reject files which don't have 0 in ALL of these slots
		for(j = 0; j < bone->ptmax; j++)
			if(bone->pts[j].resv1 != 0)
			{
				fprintf(stderr, "model_load_pmf: file corrupted or made by a smartass\n");
				model_free(pmf);
				return NULL;
			}
		
		// rinse, lather, repeat
		
		// units are 8:8 fixed point in terms of the vxl grid by default
	}
	
	return pmf;
}
Beispiel #12
0
/*
 * Initialize xenstore structure.
 * May have to be called multiple times.
 *
 * On the very first call always opens xs connection.
 * Aborts if unable to open xs connection in a reasonable time.
 * Always returns the very first time with xs != null.
 *
 * Also tries to initialize other xs structures.
 * If successful, returns with @initialized_xs = true.
 * If unsuccessful, returns with @initialized_xs = false and must be called
 * again later to retry the initialization.
 *
 * @pollfds defines of signal-handling descriptors to be watched if has to wait
 * during the initialization. Better be non-NULL on the first call, but can be
 * left NULL on subsequent calls (as they do not wait long).
 *
 * Will not touch pollfds[NPFD_XS].
 */
static void initialize_xs(struct pollfd *pollfds)
{
	XsTransactionStatus status;
	char *keyvalue = NULL;
	unsigned int len;
	int nretries;

	/* already initialized? */
	if (initialized_xs)
		return;

	/* open a connection to xenstore*/
	open_xs_connection(pollfds);

	/*
	 * Try to reset the report key.
	 */
	for (nretries = 0; ;)
	{
		/*
		 * Wait until xenstore "membalance/report_path" key and the key it points
		 * to have been created by membalanced with appropriate access permissions.
		 *
		 * First try without actual transaction, to make the cost for
		 * xenstore cheaper.
		 */
		if (membalance_report_path == NULL)
		{
			CHECK(begin_singleop_xs());

			keyvalue = xs_read(xs, xst, membalance_report_link_path, &len);
			if (keyvalue == NULL)
			{
				if (errno != ENOENT)
					error_perror("cannot read xenstore (%s)", membalance_report_link_path);
				debug_msg(3, "%s does not exist yet", membalance_report_link_path);
				/*
				 * Leave initialzed_xs = false, so will retry later
				 */
				abort_singleop_xs();
				return;
			}

			membalance_report_path = keyvalue;
			abort_singleop_xs();
		}

		if (nretries == 0)
		{
			CHECK(begin_singleop_xs());

			keyvalue = xs_read(xs, xst, membalance_report_path, &len);
			if (keyvalue == NULL)
			{
				if (errno != ENOENT)
					error_perror("cannot read xenstore (%s)", membalance_report_path);
				debug_msg(3, "%s does not exist yet", membalance_report_path);
				/*
				 * Leave initialzed_xs = false, so will retry later
				 */
				abort_singleop_xs();
				return;
			}

			free(keyvalue);
			abort_singleop_xs();
		}

		/*
		 * Wait until a key for data reporting has been created in
		 * xenstore by membalanced with appropriate access permissions.
		 *
		 * Now within a real transaction.
		 */
		CHECK(begin_xs());

		keyvalue = xs_read(xs, xst, membalance_report_path, &len);
		if (keyvalue == NULL)
		{
			if (errno != ENOENT)
				error_perror("cannot read xenstore (%s)", membalance_report_path);
			debug_msg(3, "%s does not exist yet", membalance_report_path);
			/*
			 * Leave initialzed_xs = false, so will retry later
			 */
			abort_xs();
			return;
		}

		free(keyvalue);

		PCHECK(xs_write(xs, xst, membalance_report_path, "", strlen("")),
		       "cannot write to xenstore");

		status = commit_xs(&nretries);

		switch (status)
		{
		case XSTS_OK:       break;	    /* done */
		case XSTS_RETRY:    continue;	    /* keep retrying */
		case XSTS_NORETRY:  CHECK(false);   /* abort */
		case XSTS_FAIL:     CHECK(false);   /* abort */
		}

		break;
	}

	initialized_xs = true;

	try_subscribe_membalance_settings();

	return;

cleanup:

	terminate();
}
Beispiel #13
0
/*
 * Process next sample of memory statistics data taken after another @interval.
 * @pd1 = current reading
 * @pd0 = reading taken @interval ago
 */
static void process_sample(const struct paging_data *pd1, const struct paging_data *pd0)
{
	int64_t ms;
	int64_t kbs, kbs_sec;
	double free_pct;
	char report[512];
	char struct_version = 'A';
	int nretries = 0;

	/* discard sample if weird timing */
	ms = timespec_diff_ms(pd1->ts, pd0->ts);
	if (ms < tolerance_ms || ms > interval * MSEC_PER_SEC * 10)
		return;

	/* discard the sample if weird data */
	kbs = (int64_t) (pd1->pgpgin - pd0->pgpgin);
	if (kbs < 0)
		return;
	kbs_sec = (kbs * MSEC_PER_SEC) / ms;

	free_pct = 100.0 * (double) pd1->nr_free_pages / (double) pd1->mem_pages;

	/* manual override (development time only) */
	if (simulated_kbs >= 0)
		kbs_sec = simulated_kbs;

	if (simulated_free_pct >= 0)
		free_pct = simulated_free_pct;

	if (log_fp && debug_level >= 3)
	{
		fprintf(log_fp, "pgpgin=%llu, nr_free_pages=%llu, kbs=%lu, kbs_sec=%lu, free%%=%f\n",
			(unsigned long long) pd1->pgpgin,
			(unsigned long long) pd1->nr_free_pages,
			(unsigned long) kbs,
			(unsigned long) kbs_sec,
			free_pct);
	}

	/* format memory pressure report string */
	/* (could use json if data structure were more complicated and changeable) */
	sprintf(report, "%c\n"
			"action: report\n"
			"progname: %s\n"
			"progversion: %s\n"
			"seq: %llu\n"
			"kb: %lu\n"
			"kbsec: %lu\n"
			"freepct: %f\n",
		struct_version,
		progname,
		progversion,
		report_seq++,
		(unsigned long) kbs,
		(unsigned long) kbs_sec,
		free_pct);

	/* write report data to xenstore */
	for (;;)
	{
		if (!begin_singleop_xs())
			break;

		if (!xs_write(xs, xst, membalance_report_path, report, strlen(report)))
		{
			error_perror("unable to write xenstore");
			abort_singleop_xs();
			break;
		}

		if (commit_singleop_xs(&nretries) != XSTS_RETRY)
			break;
	}
}