Beispiel #1
0
/**
 * @brief
 *	We maintain the mom_vnodeinfo data for use in constructing CPU sets and
 *	must ensure that the CPU information is correctly reflected in the
 *	vnodes' "resources_available.ncpus" attribute values before those are
 *	passed back to the server.  mom_vnodeinfo data are authoritative since
 *	they must remain unchanged across MoM reconfiguration operations (e.g.
 *	SIGHUP).  This function updates those attribute values in the vnode
 *	attribute lists hanging off the list of vnodes (see "placementsets.h")
 *	that is used in constructing the IS_UPDATE2 response to server IS_HELLO
 *	messages.
 *
 * @return Void
 *
 */
void
cpu_raresync(void)
{
	static char	ra_ncpus[] = "resources_available.ncpus";
	AVL_IX_DESC	*pix;
	int		ret;

	if ((pix = cpuctx) != NULL) {
		avl_first_key(pix);

		if (pe == NULL) {
			pe = malloc(sizeof(AVL_IX_REC) + PBS_MAXNODENAME + 1);
			if (pe == NULL) {
				log_err(errno, __func__, "malloc pe failed");
				return;
			}
		}
		while ((ret = avl_next_key(pe, pix)) == AVL_IX_OK) {
			unsigned int	i;
			mominfo_t	*mip;
			mom_vninfo_t	*mvp;

			mip = (mominfo_t *) pe->recptr;
			assert(mip != NULL);
			assert(mip->mi_data != NULL);

			mvp = (mom_vninfo_t *) mip->mi_data;
			for (i = 0; i < mvp->mvi_ncpus; i++)
				resadj(vnlp, mvp->mvi_id, ra_ncpus, RES_SET,
					mvp->mvi_acpus);
		}

		assert(ret == AVL_EOIX);
	}
}
Beispiel #2
0
/**
 * @brief	Update the AVL tree in global variable
 *			called "env_avltree" for environment variables
 *
 * @return	void
 *
 * @retval	None
 */
void
update_env_avltree()
{
	int i = 0;
	int found = 0;
	int ret = 0;
	char varname_tmp[_MAX_ENV] = {'\0'};
	char *name = NULL;
	char *value = NULL;
	AVL_IX_REC *pe = NULL;
	extern char **environ;

	if (env_avltree != NULL) {
		avl_first_key(env_avltree);
		if ((pe = malloc(sizeof(AVL_IX_REC) + WINLOG_BUF_SIZE + 1)) != NULL) {
			while ((ret = avl_next_key(pe, env_avltree)) == AVL_IX_OK) {
				found = 0;
				for (i=0; environ[i] != NULL; i++) {
					if (!strncmp(environ[i], pe->key, strlen(pe->key))) {
						found = 1;
						break;
					}
				}
				if (!found) {
					free(pe->recptr);
					pe->recptr = NULL;
					avl_delete_key(pe, env_avltree);
				}
			}
			free(pe);
			pe = NULL;
		}

		for (i=0; environ[i] != NULL; i++) {
			(void)strncpy_s(varname_tmp, sizeof(varname_tmp), environ[i], _TRUNCATE);
			if ((name = strtok_s(varname_tmp, "=", &value)) != NULL) {
				if ((pe = malloc(sizeof(AVL_IX_REC) + WINLOG_BUF_SIZE + 1)) != NULL) {
					strncpy(pe->key, name, WINLOG_BUF_SIZE);
					if (avl_find_key(pe, env_avltree) != AVL_IX_OK) {
						if ((pe->recptr = (void *)strdup(value)) != NULL)
							avl_add_key(pe, env_avltree);
					}
					free(pe);
					pe = NULL;
				}
			}
		}
	}
}
Beispiel #3
0
/**
 * @brief
 *	cpunum_free() is a context-free function to mark a CPU as available.
 *	It must previously have been marked as inuse via cpuindex_inuse().
 *	This function is used to recover from failure of make_cpuset().
 *
 * @param[in] cpunum - number of cpu
 *
 * @return Void
 *
 */
void
cpunum_free(unsigned int cpunum)
{
	AVL_IX_DESC	*pix;
	int		ret;
	char		buf[BUFSIZ];

	sprintf(buf, "mark CPU %u free", cpunum);
	log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, __func__, buf);

	if ((pix = cpuctx) != NULL) {
		avl_first_key(pix);

		if (pe == NULL) {
			pe = malloc(sizeof(AVL_IX_REC) + PBS_MAXNODENAME + 1);
			if (pe == NULL) {
				log_err(errno, __func__, "malloc pe failed");
				return;
			}
		}
		while ((ret = avl_next_key(pe, pix)) == AVL_IX_OK) {
			unsigned int	i;
			mominfo_t	*mip;
			mom_vninfo_t	*mvp;

			mip = (mominfo_t *) pe->recptr;
			assert(mip != NULL);
			assert(mip->mi_data != NULL);

			mvp = (mom_vninfo_t *) mip->mi_data;
			for (i = 0; i < mvp->mvi_ncpus; i++)
				if (mvp->mvi_cpulist[i].mvic_cpunum == cpunum) {
					cpuindex_free(mvp, i);
					return;
				}
		}

		assert(ret == AVL_EOIX);

		sprintf(log_buffer, "CPU %d not found in cpuctx", cpunum);
		log_err(PBSE_SYSTEM, __func__, log_buffer);
	}
}
Beispiel #4
0
int
entlim_free_ctx(void *ctx, void free_leaf(void *))
{
	pbs_entlim_key_t *leaf;
	int		 rc;

	leaf = entlim_create_key(NULL);	/* alloc space for max sized key */
	if (leaf == NULL)
		return -1;
	avl_first_key((AVL_IX_DESC *)ctx);

	while ((rc = avl_next_key((AVL_IX_REC *)leaf, (AVL_IX_DESC *)ctx)) == AVL_IX_OK) {
		free_leaf(leaf->recptr);
	}
	free(leaf);
	avl_destroy_index((AVL_IX_DESC *)ctx);
	free(ctx);
	return 0;
}
Beispiel #5
0
/**
 * @brief
 * 	entlim_get_next - walk the objects returning the next entry.
 *	If called with a NULL key, it allocates a key and returns
 *	the first entry; otherwise it returns the next entry.
 *
 * @param[in] keystr - key string whose key is to be built
 * @param[in] ctx - pointer to avl descending order tree info
 *
 * @return	structure handle
 * @retval	key info		success
 * @retval	NULL			error
 *		Returns NULL following the last entry or when no entry found
 *		The key needs to be freed by the caller when all is said and done.
 */
pbs_entlim_key_t *
entlim_get_next(pbs_entlim_key_t *pkey, void *ctx)
{

	if (ctx == NULL)
		return NULL;
	if (pkey == NULL) {
		pkey = entlim_create_key(NULL);
		if (pkey == NULL)
			return NULL;
		avl_first_key((AVL_IX_DESC *)ctx);
	}

	if (avl_next_key(pkey, (AVL_IX_DESC *)ctx) == AVL_IX_OK) {
		return pkey;
	} else {
		free(pkey);
		return NULL;
	}
}
Beispiel #6
0
/**
 * @brief	Destroy the global AVL tree of environment  variables created by
 *			create_env_avltree in global variable called "env_avltree"
 *
 * @return	void
 *
 * @retval	None
 */
void
destroy_env_avltree()
{
	AVL_IX_REC *pe = NULL;
	int ret = 0;

	if (env_avltree != NULL) {
		avl_first_key(env_avltree);
		if ((pe = malloc(sizeof(AVL_IX_REC) + WINLOG_BUF_SIZE + 1)) != NULL) {
			while ((ret = avl_next_key(pe, env_avltree)) == AVL_IX_OK) {
				free(pe->recptr);
				pe->recptr = NULL;
				avl_delete_key(pe, env_avltree);
			}
			free(pe);
			pe = NULL;
		}
		avl_destroy_index(env_avltree);
		free(env_avltree);
		env_avltree = NULL;
	}
}
Beispiel #7
0
/**
 * @brief
 *	Common code for cpunum_inuse() and cpunum_outofservice():  to find
 *	the given CPU in our list of CPUs per vnode, we walk the list of
 *	mom_vninfo_t structures and for each of those, the attached CPU lists
 *	looking for a match.  If taking a CPU out of service, cpu_inuse() must
 *	also adjust the "resources_available.ncpus" for the vnode that contains
 *	the CPU being taken out of service.
 * 
 * @param[in] cpunum - number of cpu
 * @param[in] pjob - pointer to job structure
 * @param[in] outofserviceflag - flag value to indicate whether cpu out of service
 *
 * @return - Void
 *
 */
static void
cpu_inuse(unsigned int cpunum, job *pjob, int outofserviceflag)
{
	static char	ra_ncpus[] = "resources_available.ncpus";
	AVL_IX_DESC	*pix;
	int		ret;

	if ((pix = cpuctx) != NULL) {
		avl_first_key(pix);

		if (pe == NULL) {
			pe = malloc(sizeof(AVL_IX_REC) + PBS_MAXNODENAME + 1);
			if (pe == NULL) {
				log_err(errno, __func__, "malloc pe failed");
				return;
			}
		}
		while ((ret = avl_next_key(pe, pix)) == AVL_IX_OK) {
			unsigned int	i;
			mominfo_t	*mip;
			mom_vninfo_t	*mvp;

			mip = (mominfo_t *) pe->recptr;
			assert(mip != NULL);
			assert(mip->mi_data != NULL);

			mvp = (mom_vninfo_t *) mip->mi_data;
			for (i = 0; i < mvp->mvi_ncpus; i++)
				if (mvp->mvi_cpulist[i].mvic_cpunum == cpunum) {
					if (MVIC_CPUISFREE(mvp, i)) {
						cpuindex_inuse(mvp, i, pjob);
						if (outofserviceflag != 0) {
							assert(vnlp != NULL);
							assert(mvp->mvi_id != NULL);
							resadj(vnlp, mvp->mvi_id,
								ra_ncpus, RES_DECR,
								1);
							mvp->mvi_acpus--;
						}
					}
					return;
				}
		}

		assert(ret == AVL_EOIX);

		/*
		 *	If we get here, we didn't find the CPU in question.
		 *	Requests to mark a CPU for which we have no record
		 *	out of service may be benign;  we may never have
		 *	known about it because we were never told about it
		 *	in a vnode definitions file, and the caller may
		 *	simply not have checked first.  So, we silently
		 *	ignore those requests.  However, if we're asked
		 *	to mark a CPU in use but haven't heard of it, that's
		 *	an error.
		 */
		if (outofserviceflag == 0) {
			sprintf(log_buffer, "CPU %d not found in cpuctx",
				cpunum);
			log_err(PBSE_SYSTEM, __func__, log_buffer);
		}
	}
}
Beispiel #8
0
/**
 * @brief
 *	Log debugging information pertaining to each CPU that we are managing.
 *	Each CPU may be in one of three states:  free for use, in use by a job,
 *	or in use but not assigned to a job (the last of these is used for CPUs
 *	declared unusable by cpunum_outofservice()).
 *
 * @return Void
 *
 */
void
mom_CPUs_report(void)
{
	AVL_IX_DESC	*pix;
	int		ret;
	char		reportbuf[LOG_BUF_SIZE];
	int		bufspace;	/* space remaining in reportbuf[] */

	if ((pix = cpuctx) != NULL) {
		char	*p;

		avl_first_key(pix);

		if (pe == NULL) {
			pe = malloc(sizeof(AVL_IX_REC) + PBS_MAXNODENAME + 1);
			if (pe == NULL) {
				log_err(errno, __func__, "malloc pe failed");
				return;
			}
		}
		while ((ret = avl_next_key(pe, pix)) == AVL_IX_OK) {
			unsigned int	i;
			int		first;
			mominfo_t	*mip;
			mom_vninfo_t	*mvp;

			mip = (mominfo_t *) pe->recptr;
			assert(mip != NULL);
			assert(mip->mi_data != NULL);

			mvp = (mom_vninfo_t *) mip->mi_data;
			p = reportbuf;
			bufspace = sizeof(reportbuf);
			ret = snprintf(p, bufspace, "%s:  cpus = ", mvp->mvi_id);
			if (ret >= bufspace) {
				truncate_and_log(__func__, reportbuf,
					sizeof(reportbuf));
				continue;
			}
			p += ret, bufspace -= ret;
			for (i = 0, first = 1; i < mvp->mvi_ncpus; i++) {
				if (first) {
					first = 0;
				} else {
					if (bufspace < 1) {
						truncate_and_log(__func__, reportbuf,
							sizeof(reportbuf));
						goto line_done;
					}
					sprintf(p, ",");
					p++, bufspace--;
				}

				ret = snprintf(p, bufspace, "%d",
					mvp->mvi_cpulist[i].mvic_cpunum);
				if (ret >= bufspace) {
					truncate_and_log(__func__, reportbuf,
						sizeof(reportbuf));
					goto line_done;
				}
				p += ret, bufspace -= ret;

				if (MVIC_CPUISFREE(mvp, i))
					ret = snprintf(p, bufspace, " (free)");
				else {
					if (mvp->mvi_cpulist[i].mvic_job == NULL)
						ret = snprintf(p, bufspace,
							" (inuse, no job)");
					else
						ret = snprintf(p, bufspace,
							" (inuse, job %s)",
							mvp->mvi_cpulist[i].mvic_job->ji_qs.ji_jobid);
				}
				if (ret >= bufspace) {
					truncate_and_log(__func__, reportbuf,
						sizeof(reportbuf));
					goto line_done;
				}
				p += ret, bufspace -= ret;
			}
			log_event(PBSEVENT_DEBUG3, 0, LOG_DEBUG, __func__, reportbuf);
line_done:
			;
		}

		assert(ret == AVL_EOIX);
	}
}