Beispiel #1
0
/**
 * @brief
 *	vn_encode_DIS_V4 - encode version 4 vnode information, used by Mom.
 *
 * @par Functionality:
 *	Used to encode vnode information.  See vn_encode_DIS() above for a
 *	description of the information.  Supports version 4 only.
 *
 * @param[in]	fd   - socket descriptor to which to write the encode info.
 * @param[in]	vnlp - structure to encode and send.
 *
 * @return	int
 * @retval	DIS_SUCCESS (0) on success
 * @retval	DIS_* on error.
 *
 * @par Side Effects: None
 *
 * @par MT-safe: No, the structure pointed to by vnlp needs to be locked
 *
 */
static int
vn_encode_DIS_V4(int fd, vnl_t *vnlp)
{
	int		rc;
	unsigned int	i, j;

	if (((rc = diswui(fd, PS_DIS_V4)) != 0) ||
		((rc = diswsl(fd, (long) vnlp->vnl_modtime)) != 0) ||
		((rc = diswui(fd, vnlp->vnl_used)) != 0))
			return (rc);

	for (i = 0; i < vnlp->vnl_used; i++) {
		vnal_t	*curreslist = VNL_NODENUM(vnlp, i);

		if ((rc = diswst(fd, curreslist->vnal_id)) != 0)
			return (rc);
		if ((rc = diswui(fd, curreslist->vnal_used)) != 0)
			return (rc);

		for (j = 0; j < curreslist->vnal_used; j++) {
			vna_t	*curres = VNAL_NODENUM(curreslist, j);

			if ((rc = diswst(fd, curres->vna_name)) != 0)
				return (rc);
			if ((rc = diswst(fd, curres->vna_val)) != 0)
				return (rc);
			if ((rc = diswsi(fd, curres->vna_type)) != 0)
				return (rc);
			if ((rc = diswsi(fd, curres->vna_flag)) != 0)
				return (rc);
		}
	}

	return (DIS_SUCCESS);
}
Beispiel #2
0
/**
 * @brief
 *	free_and_return - free a vnl_t data structure.
 *
 * @par Functionality:
 *	Note that this function is nearly identical to vnl_free() (q.v.),
 *	with the exception of using the *_cur values to free partially-
 *
 * @param[in]	vnlp - pointer to structure to free
 *
 * @return	vnl_t *
 * @retval	NULL
 *
 * @par Side Effects: None
 *
 * @par MT-safe: No, vnlp needs to be locked.
 *
 */
static vnl_t *
free_and_return(vnl_t *vnlp)
{
	unsigned int	i, j;

	/* N.B. <=, not < because we may have a partially-allocated ith one */
	for (i = 0; i <= vnlp->vnl_cur; i++) {
		vnal_t	*vnrlp = VNL_NODENUM(vnlp, i);

		/* N.B. <=, not < (as above) for partially-allocated jth one */
		for (j = 0; j <= vnrlp->vnal_cur; j++) {
			vna_t	*vnrp = VNAL_NODENUM(vnrlp, j);
			free(vnrp->vna_name);
			free(vnrp->vna_val);
		}
		free(vnrlp->vnal_list);
		free(vnrlp->vnal_id);
	}
	free(vnlp->vnl_list);
	free(vnlp);

	return ((vnl_t *) NULL);
}
Beispiel #3
0
/**
 * @brief
 *	Find the vnode with ID vnid and adjust (decrement, increment, or set)
 *	the value of resource res by the amount adjval
 *
 * @param[in] vp - pointer to vnl_t structure
 * @param[in] vnid - vnode id
 * @param[in] res - resource name
 * @param[in] op - enum for resource option
 *
 * @return Void
 * 
 */
static void
resadj(vnl_t *vp, const char *vnid, const char *res, enum res_op op,
	unsigned int adjval)
{
	int		i, j;

	sprintf(log_buffer, "vnode %s, resource %s, res_op %u, adjval %u",
		vnid, res, (int) op, adjval);
	log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, __func__, log_buffer);
	for (i = 0; i < vp->vnl_used; i++) {
		vnal_t	*vnalp;

		vnalp = VNL_NODENUM(vp, i);
		if (strcmp(vnalp->vnal_id, vnid) != 0)
			continue;
		for (j = 0; j < vnalp->vnal_used; j++) {
			vna_t		*vnap;
			unsigned int	resval;
			char		valbuf[BUFSIZ];

			vnap = VNAL_NODENUM(vnalp, j);
			if (strcmp(vnap->vna_name, res) == 0) {
				resval = strtoul(vnap->vna_val, NULL, 0);
				switch ((int) op) {
					case RES_DECR:
						resval -= adjval;
						break;
					case RES_INCR:
						resval += adjval;
						break;
					case RES_SET:
						resval = adjval;
						break;
					default:
						sprintf(log_buffer, "unknown res_op %u",
							(int) op);
						log_event(PBSEVENT_ERROR, 0, LOG_ERR, __func__,
							log_buffer);
						return;
				}

				/*
				 *	Deal with two things that should never
				 *	happen:  first, the result of adjusting
				 *	the resource value should never be
				 *	negative.  Second, BUFSIZ should always
				 *	be sufficient to hold any unsigned
				 *	quantity PBS deals with.
				 */
				if (((int) resval) < 0) {
					log_event(PBSEVENT_ERROR, 0, LOG_ERR,
						__func__, "res underflow");
					return;
				}
				if (snprintf(valbuf, sizeof(valbuf), "%u",
					resval) >= sizeof(valbuf)) {
					log_event(PBSEVENT_ERROR, 0, LOG_ERR,
						__func__, "res overflow");
					return;
				}

				/*
				 *	We now replace the current value with
				 *	the adjusted one.  This may involve
				 *	surgery on the vna_t.
				 */
				if (op == RES_DECR) {
					/*
					 *	Since the resource value is now
					 *	smaller than before, it ought to
					 *	fit in the space that holds the
					 *	current value.
					 */
					strcpy(vnap->vna_val, valbuf);
				} else {
					char	*vna_newval = strdup(valbuf);

					if (vna_newval != NULL) {
						free(vnap->vna_val);
						vnap->vna_val = vna_newval;
					} else {
						log_event(PBSEVENT_ERROR, 0,
							LOG_ERR, __func__,
							"vna_newval strdup failed");
					}
				}
				return;
			}
		}
	}

	sprintf(log_buffer, "vnode %s, resource %s not found", vnid, res);
	log_event(PBSEVENT_DEBUG, 0, LOG_DEBUG, __func__, log_buffer);
}
Beispiel #4
0
/**
 * @brief
 *	Log debugging information containing a description of the vnode list
 *	in 'vnl'.
 *	(a rather complicated structure described in "placementsets.h").
 *
 * @param[in]	vnl  - vnode list we're interested in
 * @param[in] 	header - heading of the log message
 *
 * @return void
 *
 */
void
mom_vnlp_report(vnl_t *vnl, char *header)
{
	int		i, j, k;
	char		reportbuf[LOG_BUF_SIZE+1];
	char		*p = NULL;
	vnl_t		*vp;
	char		attrprefix[] = ", attrs[]:  ";
	int		bytes_left;

	if (vnl == NULL)
		return;

	vp = vnl;

	for (i = 0; i < vp->vnl_used; i++) {
		vnal_t	*vnalp;

		vnalp = VNL_NODENUM(vp, i);
		bytes_left = LOG_BUF_SIZE;
		p = reportbuf;
		k = snprintf(p, bytes_left, "vnode %s:  nelem %lu", vnalp->vnal_id,
			vnalp->vnal_used);
		if (k < 0)
			break;
		bytes_left -= k;
		if (bytes_left <= 0)
			break;
		p += k;
		if (vnalp->vnal_used > 0) {
			k = snprintf(p, bytes_left, attrprefix);
			if (k < 0)
				break;
			bytes_left -= k;
			if (bytes_left <= 0)
				break;
			p += k;
		}
		for (j = 0; j < vnalp->vnal_used; j++) {
			vna_t		*vnap;

			vnap = VNAL_NODENUM(vnalp, j);
			if (j > 0) {
				snprintf(p, bytes_left, ", ");
				bytes_left -= 2;
				if (bytes_left <= 0)
					break;
				p += 2;
			}
			k = snprintf(p, bytes_left, "\"%s\" = \"%s\"", vnap->vna_name,
				vnap->vna_val);
			if (k < 0)
				break;
			bytes_left -= k;
			if (bytes_left <= 0)
				break;
			p += k;
		}
		log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, header?header:__func__, reportbuf);
		p = NULL;
	}
	if (p != NULL) { /* log any remaining item */
		log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, header?header:__func__, reportbuf);
	}
}
Beispiel #5
0
/**
 * @brief
 *	vn_decode_DIS_V3 - decode version 3 vnode information from Mom
 *
 * @par Functionality:
 *	See vn_decode_DIS() above, This is called from there to decode
 *	V3 information.
 *
 * @param[in]	fd  -     socket descriptor from which to read
 * @param[out]	rcp -     pointer to place to return error code if error.
 *
 * @return	vnl_t *
 * @retval	pointer to decoded vnode information which has been malloc-ed.
 * @retval	NULL on error, see rcp value
 *
 * @par Side Effects: None
 *
 * @par MT-safe: yes
 *
 */
static vnl_t *
vn_decode_DIS_V3(int fd, int *rcp)
{
	unsigned int	i, j;
	unsigned int	size;
	time_t		t;
	vnl_t		*vnlp;

	if ((vnlp = malloc(sizeof(vnl_t))) == NULL) {
		*rcp = DIS_NOMALLOC;
		return ((vnl_t *) NULL);
	}

	t = (time_t) disrsl(fd, rcp);
	if (*rcp != DIS_SUCCESS)
		return ((vnl_t *) NULL);
	else
		vnlp->vnl_modtime = t;
	size = disrui(fd, rcp);
	if (*rcp != DIS_SUCCESS)
		return ((vnl_t *) NULL);
	else
		vnlp->vnl_nelem = vnlp->vnl_used = size;

	if ((vnlp->vnl_list = calloc(vnlp->vnl_nelem,
		sizeof(vnal_t))) == NULL) {
		free(vnlp);
		*rcp = DIS_NOMALLOC;
		return ((vnl_t *) NULL);
	}

	for (i = 0; i < vnlp->vnl_used; i++) {
		vnal_t		*curreslist = VNL_NODENUM(vnlp, i);

		/*
		 *	In case an error occurs and we need to free
		 *	whatever's been allocated so far, we use the
		 *	vnal_cur entry to record the number of vnal_t
		 *	entries to free.
		 */
		vnlp->vnl_cur = i;

		curreslist->vnal_id = disrst(fd, rcp);
		if (*rcp != DIS_SUCCESS)
			return (free_and_return(vnlp));

		size = disrui(fd, rcp);
		if (*rcp != DIS_SUCCESS)
			return (free_and_return(vnlp));
		else
			curreslist->vnal_nelem = curreslist->vnal_used = size;
		if ((curreslist->vnal_list = calloc(curreslist->vnal_nelem,
			sizeof(vna_t))) == NULL)
			return (free_and_return(vnlp));

		for (j = 0; j < size; j++) {
			vna_t	*curres = VNAL_NODENUM(curreslist, j);

			/*
			 *	In case an error occurs and we need to free
			 *	whatever's been allocated so far, we use the
			 *	vnal_cur entry to record the number of vna_t
			 *	entries to free.
			 */
			curreslist->vnal_cur = j;

			curres->vna_name = disrst(fd, rcp);
			if (*rcp != DIS_SUCCESS)
				return (free_and_return(vnlp));
			curres->vna_val = disrst(fd, rcp);
			if (*rcp != DIS_SUCCESS)
				return (free_and_return(vnlp));
		}
	}

	*rcp = DIS_SUCCESS;
	return (vnlp);
}