Exemple #1
0
static void
list_update(list_t *list, lwp_info_t *lwp)
{
	id_info_t *id;
	if (list->l_head == NULL) {			/* first element */
		list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
		id_update(id, lwp, list->l_type);
		list->l_count++;
		return;
	}

	for (id = list->l_head; id; id = id->id_next) {
		if ((list->l_type == LT_PROCESS) &&
			(id->id_pid != lwp->li_psinfo->pr_pid))
			continue;
		if ((list->l_type == LT_USERS) &&
			(id->id_uid != lwp->li_psinfo->pr_uid))
			continue;
		if ((list->l_type == LT_PROJECTS) &&
			(id->id_projid != lwp->li_psinfo->pr_projid))
			continue;
		id_update(id, lwp, list->l_type);
		return;
	}

	/* a new element */
	id = list->l_tail;
	id->id_next = Zalloc(sizeof (id_info_t));
	id->id_next->id_prev = list->l_tail;
	id->id_next->id_next = NULL;
	list->l_tail = id->id_next;
	id = list->l_tail;
	id_update(id, lwp, list->l_type);
	list->l_count++;
}
Exemple #2
0
/*
 * get swap info
 */
static int
get_swapinfo(
	struct swaptable	**swtpp,
	int			*nswap,
	md_error_t		*ep
)
{
	int			i;
	size_t			swtsize;

	*swtpp = NULL;

	/* get number of entries */
	if ((*nswap = swapctl(SC_GETNSWP, NULL)) < 0) {
		return (mdsyserror(ep, errno, "swapctl(SC_GETNSWP)"));
	}

	/* allocate structure */
	swtsize = sizeof ((*swtpp)->swt_n) +
	    ((*nswap) * sizeof ((*swtpp)->swt_ent[0]));
	*swtpp = (struct swaptable *)Zalloc(swtsize);
	(*swtpp)->swt_n = *nswap;
	for (i = 0; (i < (*nswap)); ++i)
		(*swtpp)->swt_ent[i].ste_path = Zalloc(MAXPATHLEN);

	/* get info */
	if (((*nswap) = swapctl(SC_LIST, (*swtpp))) < 0) {
		(void) mdsyserror(ep, errno, "swapctl(SC_LIST)");
		free_swapinfo(*swtpp);
		return (-1);
	}

	/* return success */
	return (0);
}
Exemple #3
0
/*
 * util_parse_add_replica -- (internal) add a new replica to the pool set info
 */
static int
util_parse_add_replica(struct pool_set **setp)
{
	LOG(3, "setp %p", setp);

	ASSERTne(setp, NULL);

	struct pool_set *set = *setp;
	ASSERTne(set, NULL);

	set = Realloc(set, sizeof(struct pool_set) +
			(set->nreplicas + 1) * sizeof(struct pool_replica *));
	if (set == NULL) {
		ERR("!Realloc");
		return -1;
	}
	*setp = set;

	struct pool_replica *rep;
	rep = Zalloc(sizeof(struct pool_replica));
	if (rep == NULL) {
		ERR("!Malloc");
		return -1;
	}

	unsigned r = set->nreplicas++;

	set->replica[r] = rep;

	return 0;
}
Exemple #4
0
/*
 * util_parse_add_remote_replica -- (internal) add a new remote replica
 *                                  to the pool set info
 */
static int
util_parse_add_remote_replica(struct pool_set **setp, char *node_addr,
				char *pool_desc)
{
	LOG(3, "setp %p node_addr %s pool_desc %s", setp, node_addr, pool_desc);

	ASSERTne(setp, NULL);
	ASSERTne(node_addr, NULL);
	ASSERTne(pool_desc, NULL);

	int ret = util_parse_add_replica(setp);
	if (ret != 0)
		return ret;

	/* a remote replica has one 'fake' part */
	ret = util_parse_add_part(*setp, NULL, 0);
	if (ret != 0)
		return ret;

	struct pool_set *set = *setp;
	struct pool_replica *rep = set->replica[set->nreplicas - 1];
	ASSERTne(rep, NULL);

	rep->remote = Zalloc(sizeof(struct remote_replica));
	if (rep->remote == NULL) {
		ERR("!Malloc");
		return -1;
	}
	rep->remote->node_addr = node_addr;
	rep->remote->pool_desc = pool_desc;
	set->remote = 1;

	return 0;
}
Exemple #5
0
/*
 * replica_create_poolset_health_status -- create helping structure for storing
 *                                 poolset's health status
 */
int
replica_create_poolset_health_status(struct pool_set *set,
		struct poolset_health_status **set_hsp)
{
	LOG(3, "set %p, set_hsp %p", set, set_hsp);
	unsigned nreplicas = set->nreplicas;
	struct poolset_health_status *set_hs;
	set_hs = Zalloc(sizeof(struct poolset_health_status) +
			nreplicas * sizeof(struct replica_health_status *));
	if (set_hs == NULL) {
		ERR("!Zalloc for poolset health state");
		return -1;
	}
	set_hs->nreplicas = nreplicas;
	for (unsigned i = 0; i < nreplicas; ++i) {
		struct replica_health_status *replica_hs =
				create_replica_health_status(set, i);
		if (replica_hs == NULL) {
			replica_free_poolset_health_status(set_hs);
			return -1;
		}
		set_hs->replica[i] = replica_hs;
	}
	*set_hsp = set_hs;
	return 0;
}
Exemple #6
0
/*
 * open RPC connection to rpc.metamhd
 */
static mhd_handle_t *
open_metamhd(
	char		*hostname,
	md_error_t	*ep
)
{
	CLIENT		*clientp;
	mhd_handle_t	*hp;

	/* default to local host */
	if ((hostname == NULL) || (*hostname == '\0'))
		hostname = mynode();

	/* open RPC connection */
	assert(hostname != NULL);
	if ((clientp = meta_client_create(hostname, METAMHD, METAMHD_VERSION,
	    "tcp")) == NULL) {
		clnt_pcreateerror(hostname);
		(void) mdrpccreateerror(ep, hostname, "metamhd clnt_create");
		return (NULL);
	} else {
		auth_destroy(clientp->cl_auth);
		clientp->cl_auth = authsys_create_default();
		assert(clientp->cl_auth != NULL);
	}

	/* return connection */
	hp = Zalloc(sizeof (*hp));
	hp->hostname = Strdup(hostname);
	hp->clientp = clientp;
	return (hp);
}
Exemple #7
0
/*
 * util_poolset_single -- (internal) create a one-part pool set
 *
 * On success returns a pointer to a newly allocated and initialized
 * pool set structure.  Otherwise, NULL is returned.
 */
static struct pool_set *
util_poolset_single(const char *path, size_t filesize, int fd, int create)
{
	LOG(3, "path %s filesize %zu fd %d create %d",
			path, filesize, fd, create);

	struct pool_set *set;
	set = Zalloc(sizeof(struct pool_set) +
			sizeof(struct pool_replica *));
	if (set == NULL) {
		ERR("!Malloc for pool set");
		return NULL;
	}

	struct pool_replica *rep;
	rep = Zalloc(sizeof(struct pool_replica) +
			sizeof(struct pool_set_part));
	if (rep == NULL) {
		ERR("!Malloc for pool set replica");
		Free(set);
		return NULL;
	}

	set->replica[0] = rep;

	rep->part[0].filesize = filesize;
	rep->part[0].path = Strdup(path);
	rep->part[0].fd = fd;
	rep->part[0].created = create;
	rep->part[0].hdr = NULL;
	rep->part[0].addr = NULL;

	rep->nparts = 1;

	/* it does not have a remote replica */
	rep->remote = NULL;
	set->remote = 0;

	/* round down to the nearest page boundary */
	rep->repsize = rep->part[0].filesize & ~(Pagesize - 1);

	set->poolsize = rep->repsize;

	set->nreplicas = 1;

	return set;
}
Exemple #8
0
void
list_alloc(list_t *list, int size)
{
	if (size > 0) {
		list->l_size = size;
		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
	}
}
Exemple #9
0
void
list_alloc(list_t *list, int size)
{
	list->l_size = size;
	if (size > 0)
		list->l_ptrs = Zalloc(sizeof (void *) * (size + 1));
	else
		list->l_ptrs = NULL;
}
Exemple #10
0
static lwp_info_t *
list_add_lwp(list_t *list, pid_t pid, id_t lwpid)
{
	lwp_info_t *lwp;

	if (list->l_head == NULL) {
		list->l_head = list->l_tail = lwp = Zalloc(sizeof (lwp_info_t));
	} else {
		lwp = Zalloc(sizeof (lwp_info_t));
		lwp->li_prev = list->l_tail;
		((lwp_info_t *)list->l_tail)->li_next = lwp;
		list->l_tail = lwp;
	}
	lwp->li_info.pr_pid = pid;
	lwp->li_info.pr_lwp.pr_lwpid = lwpid;
	lwpid_add(lwp, pid, lwpid);
	list->l_count++;
	return (lwp);
}
Exemple #11
0
static int
list_read(int listt, int elemn)
{
	char	idstr[P_MAXVAL];
	list_t	*list;
	id_info_t *id;

	if (listt == L_LWP)
		return (lwp_read(elemn));

	while (elemn-- > 0) {
		switch (listt) {
			case L_PRC_SI 	: list = &processes;
					break;
			case L_USR_SI 	: list = &users;
					break;
			case L_PRJ_SI 	: list = &projects;
					break;
		}

		if (list->l_head == NULL) { /* first element */
			list->l_head = list->l_tail = id =
					Zalloc(sizeof (id_info_t));
			list->l_count++;
		} else {
			/* a new element */
			id = list->l_tail;
			id->id_next = Zalloc(sizeof (id_info_t));
			id->id_next->id_prev = list->l_tail;
			id->id_next->id_next = NULL;
			list->l_tail = id->id_next;
			id = list->l_tail;
			list->l_count++;
		}
		if (r_element((char *)id, idstr) == -1) {
			list_clear(list);
			return (-1);
		}
	}
	return (0);
}
Exemple #12
0
void
lwpid_add(lwp_info_t *lwp, pid_t pid, id_t lwpid)
{
    plwp_t *elm = Zalloc(sizeof (plwp_t));
    int hash = pid % PLWP_TBL_SZ;

    elm->l_pid = pid;
    elm->l_lwpid = lwpid;
    elm->l_lwp = lwp;
    elm->l_next = plwp_tbl[hash]; /* add in front of chain */
    plwp_tbl[hash] = elm;
}
Exemple #13
0
/*
 * status drives in set
 */
int
mhd_status_drives(
	mhd_set_t		*mhsp,
	mhd_opts_t		options,
	mhd_drive_status_t	**status,
	mhd_error_t		*mhep
)
{
	mhd_drive_list_t	dl = mhd_null_list;
	mhd_drive_list_t	*dlp = &dl;
	mhd_drive_set_t		*sp;
	uint_t			i;
	int			rval = 0;

	/* grab global lock */
	mhd_mx_lock(&mhd_set_mx);

	/* create or update set */
	if ((sp = mhd_create_set(mhsp, options, &dl, mhep)) == NULL) {
		mhd_mx_unlock(&mhd_set_mx);
		mhd_free_list(&dl);
		return (-1);
	}

	/* lock set */
	mhd_mx_lock(&sp->sr_mx);

	/* status drives */
	if (mhd_status_set(sp, &dl, mhep) != 0) {
		rval = -1;
		goto out;
	}

	/* build list */
	*status = Zalloc(dlp->dl_ndrive * sizeof (**status));
	for (i = 0; (i < dlp->dl_ndrive); ++i) {
		mhd_drive_t		*dp = dlp->dl_drives[i];
		mhd_drive_status_t	*statusp = &(*status)[i];

		statusp->drive = Strdup(dp->dr_rname);
		statusp->errnum = dp->dr_errnum;
	}
	assert(i == dlp->dl_ndrive);
	rval = dlp->dl_ndrive;

	/* unlock, return count */
out:
	mhd_mx_unlock(&sp->sr_mx);
	mhd_mx_unlock(&mhd_set_mx);
	mhd_free_list(&dl);
	return (rval);
}
Exemple #14
0
/*
 * create_replica_health_status -- (internal) create helping structure for
 *                                 storing replica's health status
 */
static struct replica_health_status *
create_replica_health_status(struct pool_set *set, unsigned repn)
{
	unsigned nparts = set->replica[repn]->nparts;
	struct replica_health_status *replica_hs;
	replica_hs = Zalloc(sizeof(struct replica_health_status)
			+ nparts * sizeof(unsigned));
	if (replica_hs == NULL) {
		ERR("!Zalloc for replica health status");
		return NULL;
	}
	replica_hs->nparts = nparts;
	return replica_hs;
}
Exemple #15
0
/*
 * lane_boot -- initializes all lanes
 */
int
lane_boot(PMEMobjpool *pop)
{
	int err = 0;

	pop->lanes_desc.lane = Malloc(sizeof(struct lane) * pop->nlanes);
	if (pop->lanes_desc.lane == NULL) {
		err = ENOMEM;
		ERR("!Malloc of volatile lanes");
		goto error_lanes_malloc;
	}

	pop->lanes_desc.next_lane_idx = 0;

	pop->lanes_desc.lane_locks =
		Zalloc(sizeof(*pop->lanes_desc.lane_locks) * pop->nlanes);
	if (pop->lanes_desc.lane_locks == NULL) {
		ERR("!Malloc for lane locks");
		goto error_locks_malloc;
	}

	/* add lanes to pmemcheck ignored list */
	VALGRIND_ADD_TO_GLOBAL_TX_IGNORE((char *)pop + pop->lanes_offset,
		(sizeof(struct lane_layout) * pop->nlanes));

	uint64_t i;
	for (i = 0; i < pop->nlanes; ++i) {
		struct lane_layout *layout = lane_get_layout(pop, i);

		if ((err = lane_init(pop, &pop->lanes_desc.lane[i], layout))) {
			ERR("!lane_init");
			goto error_lane_init;
		}
	}

	return 0;

error_lane_init:
	for (; i >= 1; --i)
		lane_destroy(pop, &pop->lanes_desc.lane[i - 1]);
	Free(pop->lanes_desc.lane_locks);
	pop->lanes_desc.lane_locks = NULL;
error_locks_malloc:
	Free(pop->lanes_desc.lane);
	pop->lanes_desc.lane = NULL;
error_lanes_malloc:
	return err;
}
Exemple #16
0
/*
 * Add a device/device id tuple to the devname cache
 */
static void
add_to_devname_list(
	char 		*device_name,		/* fully qualified dev name */
	ddi_devid_t	devid			/* device id */
)
{
	dev_list_t	*dnlp;

	dnlp = Zalloc(sizeof (*dnlp));
	dnlp->dev_name = Strdup(device_name);
	dnlp->devid = devid;

	/* link the node into the devname list */
	dnlp->dev_nxt = devnamelist;
	devnamelist = dnlp;
}
Exemple #17
0
/*
 * shutdown_state_add_part -- adds file uuid and usc to shutdown_state struct
 *
 * if path does not exist it will fail which does NOT mean shutdown failure
 */
int
shutdown_state_add_part(struct shutdown_state *sds, const char *path,
	struct pool_replica *rep)
{
	LOG(3, "sds %p, path %s", sds, path);

	size_t len = 0;
	char *uid;
	uint64_t usc;

	if (os_dimm_usc(path, &usc)) {
		ERR("cannot read unsafe shutdown count of %s", path);
		return 1;
	}

	if (os_dimm_uid(path, NULL, &len)) {
		ERR("cannot read uuid of %s", path);
		return 1;
	}

	len += 4 - len % 4;
	uid = Zalloc(len);

	if (uid == NULL) {
		ERR("!Zalloc");
		return 1;
	}

	if (os_dimm_uid(path, uid, &len)) {
		ERR("cannot read uuid of %s", path);
		Free(uid);
		return 1;
	}

	sds->usc = htole64(le64toh(sds->usc) + usc);

	uint64_t tmp;
	util_checksum(uid, len, &tmp, 1, 0);
	sds->uuid = htole64(le64toh(sds->uuid) + tmp);

	FLUSH_SDS(sds, rep);
	Free(uid);
	shutdown_state_checksum(sds, rep);
	return 0;
}
Exemple #18
0
/*
 * calloc
 */
void *
Calloc(
	size_t	n,
	size_t	s
)
{
	unsigned long total;

	if (n == 0 || s == 0) {
		total = 0;
	} else {
		total = (unsigned long)n * s;
		/* check for overflow */
		if (total / n != s)
			return (NULL);
	}
	return (Zalloc(total));
}
Exemple #19
0
/*
 * create poolset_compare_status -- (internal) create structure for gathering
 *                                  status of poolset comparison
 */
static int
create_poolset_compare_status(struct pool_set *set,
		struct poolset_compare_status **set_sp)
{
	LOG(3, "set %p, set_sp %p", set, set_sp);
	struct poolset_compare_status *set_s;
	set_s = Zalloc(sizeof(struct poolset_compare_status)
				+ set->nreplicas * sizeof(unsigned));
	if (set_s == NULL) {
		ERR("!Zalloc for poolset status");
		return -1;
	}
	for (unsigned r = 0; r < set->nreplicas; ++r)
		set_s->replica[r] = UNDEF_REPLICA;

	set_s->nreplicas = set->nreplicas;
	*set_sp = set_s;
	return 0;
}
Exemple #20
0
int
os_execv(const char *path, char *const argv[])
{
	wchar_t *wpath = util_toUTF16(path);
	if (wpath == NULL)
		return -1;

	int argc = 0;
	while (argv[argc])
		argc++;

	int ret;
	wchar_t **wargv = Zalloc((argc + 1) * sizeof(wargv[0]));
	if (!wargv) {
		ret = -1;
		goto wargv_alloc_failed;
	}

	for (int i = 0; i < argc; ++i) {
		wargv[i] = util_toUTF16(argv[i]);
		if (!wargv[i]) {
			ret = -1;
			goto end;
		}
	}

	intptr_t iret = _wexecv(wpath, wargv);
	if (iret == 0)
		ret = 0;
	else
		ret = -1;

end:
	for (int i = 0; i < argc; ++i)
		util_free_UTF16(wargv[i]);
	Free(wargv);

wargv_alloc_failed:
	util_free_UTF16(wpath);

	return ret;
}
Exemple #21
0
/*
 * build disk status list from drivename list
 */
md_disk_status_list_t *
meta_drive_to_disk_status_list(
	mddrivenamelist_t	*dnlp
)
{
	md_disk_status_list_t	*head = NULL;
	md_disk_status_list_t	**tailp = &head;
	mddrivenamelist_t	*p;

	/* copy list */
	for (p = dnlp; (p != NULL); p = p->next) {
		md_disk_status_list_t	*dsp;

		dsp = *tailp = Zalloc(sizeof (*dsp));
		tailp = &dsp->next;
		dsp->drivenamep = p->drivenamep;
	}

	/* return list */
	return (head);
}
Exemple #22
0
static void
setmovecur()
{
	int i, n;
	if ((opts.o_outpmode & OPT_FULLSCREEN) &&
	    (opts.o_outpmode & OPT_USEHOME)) {
		movecur = t_home;
		return;
	}
	if (opts.o_outpmode & OPT_SPLIT) {
		n = opts.o_ntop + opts.o_nbottom + 2;
	} else {
		if (opts.o_outpmode & OPT_USERS)
			n = opts.o_nbottom + 1;
		else
			n = opts.o_ntop + 1;
	}
	if (movecur != NULL && movecur != empty_string && movecur != t_home)
		free(movecur);
	movecur = Zalloc(strlen(t_up) * (n + 5));
	for (i = 0; i <= n; i++)
		(void) strcat(movecur, t_up);
}
Exemple #23
0
/*
 * util_poolset_parse -- (internal) parse pool set config file
 *
 * Returns 1 if the file is a valid pool set config file, 0 if the file
 * is not a pool set header, and -1 in case of any error.
 *
 * XXX: use memory mapped file
 */
int
util_poolset_parse(const char *path, int fd, struct pool_set **setp)
{
	LOG(3, "path %s fd %d setp %p", path, fd, setp);

	struct pool_set *set;
	enum parser_codes result;
	char line[PARSER_MAX_LINE];
	char *s;
	char *ppath;
	char *pool_desc;
	char *node_addr;
	char *cp;
	size_t psize;
	FILE *fs;

	if (util_lseek(fd, 0, SEEK_SET) != 0) {
		ERR("!lseek %d", fd);
		return -1;
	}

	fd = dup(fd);
	if (fd < 0) {
		ERR("!dup");
		return -1;
	}

	/* associate a stream with the file descriptor */
	if ((fs = fdopen(fd, "r")) == NULL) {
		ERR("!fdopen %d", fd);
		close(fd);
		return -1;
	}

	unsigned nlines = 0;
	unsigned nparts = 0; /* number of parts in current replica */

	/* read the first line */
	s = fgets(line, PARSER_MAX_LINE, fs);
	nlines++;

	set = Zalloc(sizeof(struct pool_set));
	if (set == NULL) {
		ERR("!Malloc for pool set");
		goto err;
	}

	/* check also if the last character is '\n' */
	if (s && strncmp(line, POOLSET_HDR_SIG, POOLSET_HDR_SIG_LEN) == 0 &&
	    line[POOLSET_HDR_SIG_LEN] == '\n') {
		/* 'PMEMPOOLSET' signature detected */
		LOG(10, "PMEMPOOLSET");

		int ret = util_parse_add_replica(&set);
		if (ret != 0)
			goto err;

		nparts = 0;
		result = PARSER_CONTINUE;
	} else {
		result = PARSER_PMEMPOOLSET;
	}

	while (result == PARSER_CONTINUE) {
		/* read next line */
		s = fgets(line, PARSER_MAX_LINE, fs);
		nlines++;

		if (s) {
			/* chop off newline and comments */
			if ((cp = strchr(line, '\n')) != NULL)
				*cp = '\0';
			if (cp != s && (cp = strchr(line, '#')) != NULL)
				*cp = '\0';

			/* skip comments and blank lines */
			if (cp == s)
				continue;
		}

		if (!s) {
			if (nparts >= 1) {
				result = PARSER_FORMAT_OK;
			} else {
				if (set->nreplicas == 1)
					result = PARSER_SET_NO_PARTS;
				else
					result = PARSER_REP_NO_PARTS;
			}
		} else if (strncmp(line, POOLSET_REPLICA_SIG,
					POOLSET_REPLICA_SIG_LEN) == 0) {
			if (line[POOLSET_REPLICA_SIG_LEN] != '\0') {
				/* something more than 'REPLICA' */
				if (!isblank(line[POOLSET_REPLICA_SIG_LEN])) {
					result = PARSER_REPLICA;
					continue;
				}
				/* check if it is a remote replica */
				result = parser_read_replica(
						line + POOLSET_REPLICA_SIG_LEN,
						&node_addr, &pool_desc);
				if (result == PARSER_CONTINUE) {
					/* remote REPLICA */
					LOG(10, "REMOTE REPLICA "
						"node address '%s' "
						"pool set descriptor '%s'",
						node_addr, pool_desc);
					if (util_parse_add_remote_replica(&set,
							node_addr, pool_desc))
						goto err;
				}
			} else if (nparts >= 1) {
				/* 'REPLICA' signature detected */
				LOG(10, "REPLICA");

				int ret = util_parse_add_replica(&set);
				if (ret != 0)
					goto err;

				nparts = 0;
				result = PARSER_CONTINUE;
			} else {
				if (set->nreplicas == 1)
					result = PARSER_SET_NO_PARTS;
				else
					result = PARSER_REP_NO_PARTS;
			}
		} else {
			/* read size and path */
			result = parser_read_line(line, &psize, &ppath);
			if (result == PARSER_CONTINUE) {
				/* add a new pool's part to the list */
				int ret = util_parse_add_part(set,
					ppath, psize);
				if (ret != 0)
					goto err;
				nparts++;
			}
		}
	}

	if (result == PARSER_FORMAT_OK) {
		LOG(4, "set file format correct (%s)", path);
		(void) fclose(fs);
		util_poolset_set_size(set);
		*setp = set;
		return 0;
	} else {
		ERR("%s [%s:%d]", path, parser_errstr[result], nlines);
		errno = EINVAL;
	}

err:
	(void) fclose(fs);
	if (set)
		util_poolset_free(set);
	return -1;
}
Exemple #24
0
/*
 * alloc_class_collection_new -- creates a new collection of allocation classes
 */
struct alloc_class_collection *
alloc_class_collection_new()
{
	LOG(10, NULL);

	struct alloc_class_collection *ac = Zalloc(sizeof(*ac));
	if (ac == NULL)
		return NULL;

	memset(ac->aclasses, 0, sizeof(ac->aclasses));

	ac->granularity = ALLOC_BLOCK_SIZE;
	ac->last_run_max_size = MAX_RUN_SIZE;
	ac->fail_on_missing_class = 0;
	ac->autogenerate_on_missing_class = 1;

	size_t maps_size = (MAX_RUN_SIZE / ac->granularity) + 1;

	if ((ac->class_map_by_alloc_size = Malloc(maps_size)) == NULL)
		goto error;
	if ((ac->class_map_by_unit_size = cuckoo_new()) == NULL)
		goto error;

	memset(ac->class_map_by_alloc_size, 0xFF, maps_size);

	if (alloc_class_new(-1, ac, CLASS_HUGE, HEADER_COMPACT,
		CHUNKSIZE, 0, 1) == NULL)
		goto error;

	struct alloc_class *predefined_class =
		alloc_class_new(-1, ac, CLASS_RUN, HEADER_COMPACT,
			MIN_RUN_SIZE, 0, 1);
	if (predefined_class == NULL)
		goto error;

	for (size_t i = 0; i < FIRST_GENERATED_CLASS_SIZE / ac->granularity;
		++i) {
		ac->class_map_by_alloc_size[i] = predefined_class->id;
	}

	/*
	 * Based on the defined categories, a set of allocation classes is
	 * created. The unit size of those classes is depended on the category
	 * initial size and step.
	 */
	size_t granularity_mask = ALLOC_BLOCK_SIZE_GEN - 1;
	for (int c = 1; c < MAX_ALLOC_CATEGORIES; ++c) {
		size_t n = categories[c - 1].size + ALLOC_BLOCK_SIZE_GEN;
		do {
			if (alloc_class_find_or_create(ac, n) == NULL)
				goto error;

			float stepf = (float)n * categories[c].step;
			size_t stepi = (size_t)stepf;
			stepi = (stepf - (float)stepi < FLT_EPSILON) ?
				stepi : stepi + 1;

			n += (stepi + (granularity_mask)) & ~granularity_mask;
		} while (n <= categories[c].size);
	}

	/*
	 * Find the largest alloc class and use it's unit size as run allocation
	 * threshold.
	 */
	uint8_t largest_aclass_slot;
	for (largest_aclass_slot = MAX_ALLOCATION_CLASSES - 1;
			largest_aclass_slot > 0 &&
			ac->aclasses[largest_aclass_slot] == NULL;
			--largest_aclass_slot) {
		/* intentional NOP */
	}

	struct alloc_class *c = ac->aclasses[largest_aclass_slot];

	/*
	 * The actual run might contain less unit blocks than the theoretical
	 * unit max variable. This may be the case for very large unit sizes.
	 */
	size_t real_unit_max = c->run.bitmap_nallocs < RUN_UNIT_MAX_ALLOC ?
		c->run.bitmap_nallocs : RUN_UNIT_MAX_ALLOC;

	size_t theoretical_run_max_size = c->unit_size * real_unit_max;

	ac->last_run_max_size = MAX_RUN_SIZE > theoretical_run_max_size ?
		theoretical_run_max_size : MAX_RUN_SIZE;

#ifdef DEBUG
	/*
	 * Verify that each bucket's unit size points back to the bucket by the
	 * bucket map. This must be true for the default allocation classes,
	 * otherwise duplicate buckets will be created.
	 */
	for (size_t i = 0; i < MAX_ALLOCATION_CLASSES; ++i) {
		struct alloc_class *c = ac->aclasses[i];

		if (c != NULL && c->type == CLASS_RUN) {
			ASSERTeq(i, c->id);
			ASSERTeq(alloc_class_by_run(ac, c->unit_size,
				c->flags, c->run.size_idx), c);
		}
	}
#endif

	return ac;

error:
	alloc_class_collection_delete(ac);

	return NULL;
}
/*
 * FUNCTION:	meta_replicaslice()
 * INPUT:	dnp	- the name of the drive to check
 * OUTPUT:	slicep	- pointer to slice number
 *		ep	- pointer to an md_error_t structure in which
 *			  to return errors to the caller
 * RETURNS:	int	-  0 - value pointed to by slicep is valid
 *			  -1 - otherwise
 *
 * PURPOSE:	Determine which slice of the specified drive to
 *		reserve, presumably for metadb replica usage.
 *
 * NOTE:	If slicep is NULL, the return code will indicate
 *		whether or not the slice number could be determined
 */
int
meta_replicaslice(
	mddrivename_t	*dnp,
	uint_t		*slicep,
	md_error_t	*ep
)
{
	int		err = 0;
	int		ioctl_return;
	int		fd;
	char		*rname;
	struct dk_geom	geom;

	rname = dnp->rname;
	if ((fd = open(rname, (O_RDONLY|O_NDELAY), 0)) < 0) {
		char	*n;
		int	open_errno;
		size_t	len;

		if (errno != ENOENT)
			return (mdsyserror(ep, errno, rname));

		len = strlen(rname) + 3;
		n = Zalloc(len);
		(void) snprintf(n, len, "%ss0", rname);
		fd = open(n, (O_RDONLY|O_NDELAY), 0);
		open_errno = errno;
		Free(n);
		if (fd < 0) {
			return (mdsyserror(ep, open_errno, rname));
		}
	}

	/*
	 * if our drivenamep points to a device not supporting
	 * DKIOCGGEOM, we have an EFI label.
	 */
	errno = 0;
	ioctl_return = ioctl(fd, DKIOCGGEOM, &geom);
	err = errno;

	(void) close(fd);

	/*
	 * If the DKIOCGGEOM ioctl succeeded, then the device has a
	 * VTOC style label.  In this case, we use slice 7.
	 */
	if (ioctl_return == 0) {
		if (slicep != NULL) {
			*slicep = MD_SLICE7;
		}
		return (0);
	}

	/*
	 * ENOTSUP indicates an EFI style label, in which case slice 7
	 * cannot be used because its minor number is reserved.  In
	 * this case, use slice 6.
	 */
	if (err == ENOTSUP) {
		if (slicep != NULL) {
			*slicep = MD_SLICE6;
		}
		return (0);
	}

	/*
	 * Those are the only two cases we know how to deal with;
	 * either the drivenamep didn't point to a disk, or the ioctl
	 * failed for some other reason.
	 */
	if (err == ENOTTY) {
		return (mddeverror(ep, MDE_NOT_DISK, NODEV, rname));
	}

	return (mdsyserror(ep, err, rname));
}
Exemple #26
0
/*
 * os_badblocks_get -- returns 0 and bad blocks in the 'bbs' array
 *                     (that has to be pre-allocated)
 *                     or -1 in case of an error
 */
int
os_badblocks_get(const char *file, struct badblocks *bbs)
{
	LOG(3, "file %s badblocks %p", file, bbs);

	ASSERTne(bbs, NULL);

	VEC(bbsvec, struct bad_block) bbv = VEC_INITIALIZER;
	struct extents *exts = NULL;
	long extents = 0;

	unsigned long long bb_beg;
	unsigned long long bb_end;
	unsigned long long bb_len;
	unsigned long long bb_off;
	unsigned long long ext_beg;
	unsigned long long ext_end;
	unsigned long long not_block_aligned;

	int bb_found = -1; /* -1 means an error */

	memset(bbs, 0, sizeof(*bbs));

	if (os_dimm_files_namespace_badblocks(file, bbs)) {
		LOG(1, "checking the file for bad blocks failed -- '%s'", file);
		goto error_free_all;
	}

	if (bbs->bb_cnt == 0) {
		bb_found = 0;
		goto exit_free_all;
	}

	exts = Zalloc(sizeof(struct extents));
	if (exts == NULL) {
		ERR("!Zalloc");
		goto error_free_all;
	}

	extents = os_extents_count(file, exts);
	if (extents < 0) {
		LOG(1, "counting file's extents failed -- '%s'", file);
		goto error_free_all;
	}

	if (extents == 0) {
		/* dax device has no extents */
		bb_found = (int)bbs->bb_cnt;

		for (unsigned b = 0; b < bbs->bb_cnt; b++) {
			LOG(4, "bad block found: offset: %llu, length: %u",
				bbs->bbv[b].offset,
				bbs->bbv[b].length);
		}

		goto exit_free_all;
	}

	exts->extents = Zalloc(exts->extents_count * sizeof(struct extent));
	if (exts->extents == NULL) {
		ERR("!Zalloc");
		goto error_free_all;
	}

	if (os_extents_get(file, exts)) {
		LOG(1, "getting file's extents failed -- '%s'", file);
		goto error_free_all;
	}

	bb_found = 0;

	for (unsigned b = 0; b < bbs->bb_cnt; b++) {

		bb_beg = bbs->bbv[b].offset;
		bb_end = bb_beg + bbs->bbv[b].length - 1;

		for (unsigned e = 0; e < exts->extents_count; e++) {

			ext_beg = exts->extents[e].offset_physical;
			ext_end = ext_beg + exts->extents[e].length - 1;

			/* check if the bad block overlaps with file's extent */
			if (bb_beg > ext_end || ext_beg > bb_end)
				continue;

			bb_found++;

			bb_beg = (bb_beg > ext_beg) ? bb_beg : ext_beg;
			bb_end = (bb_end < ext_end) ? bb_end : ext_end;
			bb_len = bb_end - bb_beg + 1;
			bb_off = bb_beg + exts->extents[e].offset_logical
					- exts->extents[e].offset_physical;

			LOG(10,
				"bad block found: physical offset: %llu, length: %llu",
				bb_beg, bb_len);

			/* check if offset is block-aligned */
			not_block_aligned = bb_off & (exts->blksize - 1);
			if (not_block_aligned) {
				bb_off -= not_block_aligned;
				bb_len += not_block_aligned;
			}

			/* check if length is block-aligned */
			bb_len = ALIGN_UP(bb_len, exts->blksize);

			LOG(4,
				"bad block found: logical offset: %llu, length: %llu",
				bb_off, bb_len);

			/*
			 * Form a new bad block structure with offset and length
			 * expressed in bytes and offset relative
			 * to the beginning of the file.
			 */
			struct bad_block bb;
			bb.offset = bb_off;
			bb.length = (unsigned)(bb_len);
			/* unknown healthy replica */
			bb.nhealthy = NO_HEALTHY_REPLICA;

			/* add the new bad block to the vector */
			if (VEC_PUSH_BACK(&bbv, bb)) {
				VEC_DELETE(&bbv);
				bb_found = -1;
				goto error_free_all;
			}
		}
	}

error_free_all:
	Free(bbs->bbv);
	bbs->bbv = NULL;
	bbs->bb_cnt = 0;

exit_free_all:
	if (exts) {
		Free(exts->extents);
		Free(exts);
	}

	if (extents > 0 && bb_found > 0) {
		bbs->bbv = VEC_ARR(&bbv);
		bbs->bb_cnt = (unsigned)VEC_SIZE(&bbv);

		LOG(10, "number of bad blocks detected: %u", bbs->bb_cnt);

		/* sanity check */
		ASSERTeq((unsigned)bb_found, bbs->bb_cnt);
	}

	return (bb_found >= 0) ? 0 : -1;
}
Exemple #27
0
/*
 * list all the drives
 */
int
mhd_list_drives(
	char		*path,
	mhd_did_flags_t	flags,
	mhd_list_res_t	*resultsp,
	mhd_error_t	*mhep
)
{
	mhd_state_t	state;
	uint_t		ndrive, i, j, c;

	/* grab lock */
	mhd_mx_lock(&mhd_set_mx);

	/* add path to list */
	if (mhd_create_drives(path, mhep) != 0) {
		mhd_mx_unlock(&mhd_set_mx);
		return (-1);
	}

	/* get what we want */
	state = 0;
	if (flags & MHD_DID_SERIAL)
		state |= DRIVE_SERIALING;
	if (flags & MHD_DID_TIME)
		state |= DRIVE_VTOCING;
	if (flags & MHD_DID_CINFO)
		state |= DRIVE_CINFOING;

	/* ident and count drives */
	for (ndrive = 0, i = 0; (i < mhd_nset); ++i) {
		mhd_drive_set_t		*sp = mhd_sets[i];
		mhd_drive_list_t	*dlp = &sp->sr_drives;

		/* count drives */
		ndrive += dlp->dl_ndrive;

		/* ident drives */
		if (state != 0) {
			mhd_mx_lock(&sp->sr_mx);
			for (j = 0; (j < dlp->dl_ndrive); ++j) {
				mhd_drive_t	*dp = dlp->dl_drives[j];

				if (mhd_state_set(dp, state, mhep) != 0) {
					mhd_mx_unlock(&sp->sr_mx);
					mhd_mx_unlock(&mhd_set_mx);
					return (-1);
				}
			}
			mhd_wait_set(sp, dlp, state);
			mhd_mx_unlock(&sp->sr_mx);
		}
	}

	/* build list */
	assert(resultsp->results.mhd_drive_info_list_t_len == 0);
	assert(resultsp->results.mhd_drive_info_list_t_val == NULL);
	resultsp->results.mhd_drive_info_list_t_len = ndrive;
	resultsp->results.mhd_drive_info_list_t_val = Zalloc(
	    ndrive * sizeof (*resultsp->results.mhd_drive_info_list_t_val));
	for (c = 0, i = 0; (i < mhd_nset); ++i) {
		mhd_drive_set_t		*sp = mhd_sets[i];
		mhd_drive_list_t	*dlp = &sp->sr_drives;

		mhd_mx_lock(&sp->sr_mx);
		for (j = 0; (j < dlp->dl_ndrive); ++j) {
			mhd_drive_t	*dp = dlp->dl_drives[j];
			mhd_drive_info_t *ip =
			    &resultsp->results.mhd_drive_info_list_t_val[c++];

			ip->dif_name = Strdup(dp->dr_rname);
			ip->dif_id = dp->dr_drive_id;
		}
		mhd_mx_unlock(&sp->sr_mx);
	}
	assert(c == ndrive);

	/* unlock, return count */
	mhd_mx_unlock(&mhd_set_mx);
	return (ndrive);
}
Exemple #28
0
/*
 * create or update new set
 */
mhd_drive_set_t *
mhd_create_set(
	mhd_set_t		*mhsp,
	mhd_opts_t		options,
	mhd_drive_list_t	*dlp,
	mhd_error_t		*mhep
)
{
	char			*setname;
	mhd_drive_set_t		*sp;
	mhd_drive_list_t	*sp_dlp;
	mhd_drive_set_t		*null_sp;
	uint_t			i;

	/* check locks */
	assert(MUTEX_HELD(&mhd_set_mx));

	/* get setname */
	if (mhsp == NULL)
		setname = "";
	else
		setname = mhsp->setname;

	/* find or create set */
	if ((sp = mhd_find_set(setname)) == NULL) {
		/* allocate and initialize set */
		sp = Zalloc(sizeof (*sp));
		sp->sr_name = Strdup(setname);
		mhd_mx_init(&sp->sr_mx);
		mhd_cv_init(&sp->sr_cv);
		sp->sr_ff = -1;

		/* append to set list */
		++mhd_nset;
		mhd_sets = Realloc(mhd_sets, (mhd_nset * sizeof (*mhd_sets)));
		mhd_sets[mhd_nset - 1] = sp;
	}
	sp_dlp = &sp->sr_drives;

	/* if just grabbing null set, return */
	if (mhsp == NULL)
		return (sp);
	assert(strcmp(setname, "") != 0);
	assert(mhep != NULL);

	/* get null set */
	null_sp = mhd_create_set(NULL, 0, NULL, NULL);
	assert(null_sp != NULL);
	assert(sp != null_sp);

	/* grab set lock */
	mhd_mx_lock(&sp->sr_mx);

	/* save options */
	if (options & MHD_SERIAL)
		sp->sr_options |= MHD_SERIAL;
	else
		sp->sr_options &= ~MHD_SERIAL;

	/* move drives no longer in set to null set */
	if (! (options & MHD_PARTIAL_SET)) {
		for (i = 0; (i < sp_dlp->dl_ndrive); /* void */) {
			mhd_drive_t	*dp = sp_dlp->dl_drives[i];
			uint_t		j;

			/* check still there */
			for (j = 0; (j < mhsp->drives.drives_len); ++j) {
				mhd_drivename_t	mhdp;

				mhdp = mhsp->drives.drives_val[j];
				if (strcmp(dp->dr_rname, mhdp) == 0)
					break;
			}
			if (j < mhsp->drives.drives_len) {
				++i;
				continue;
			}

			/* idle the drive */
			if (mhd_idle(dp, mhep) != 0)
				mhd_clrerror(mhep);

			/* move to null set */
			mhd_del_drive_from_set(dp);
			mhd_mx_unlock(&sp->sr_mx);
			mhd_mx_lock(&null_sp->sr_mx);
			mhd_add_drive_to_set(null_sp, dp);
			mhd_mx_unlock(&null_sp->sr_mx);
			mhd_mx_lock(&sp->sr_mx);
		}
	}

	/* add new drives to lists */
	for (i = 0; (i < mhsp->drives.drives_len); ++i) {
		mhd_drivename_t	mhdp = mhsp->drives.drives_val[i];
		uint_t		j;
		mhd_drive_t	*dp;

		/* check already there */
		for (j = 0; (j < dlp->dl_ndrive); ++j) {
			dp = dlp->dl_drives[j];
			if (strcmp(mhdp, dp->dr_rname) == 0)
				break;
		}
		if (j < dlp->dl_ndrive) {
			mhd_add_drive(dlp, dp);
			continue;
		}

		/* add drive to set */
		if ((dp = mhd_create_drive(sp, mhdp, NULL, mhep)) == NULL) {
			mhde_perror(mhep, "mhd_create_drive: %s", mhdp);
			continue;
		}
		mhd_add_drive(dlp, dp);
	}

	/* debug */
#ifdef	MHD_DEBUG
	if (mhd_debug > 0) {
		for (i = 0; (i < mhd_nset); ++i) {
			mhd_drive_set_t		*sp = mhd_sets[i];
			mhd_drive_list_t	*dlp = &sp->sr_drives;
			char			buf[10240];
			uint_t			j;

			(void) snprintf(buf, sizeof (buf), "set '%s':",
			    sp->sr_name);
			for (j = 0; (j < dlp->dl_ndrive); ++j) {
				mhd_drive_t	*dp = dlp->dl_drives[j];
				char		*p;

				if ((p = strrchr(dp->dr_rname, '/')) != NULL)
					++p;
				else
					p = dp->dr_rname;
				(void) strncat(buf, " ", sizeof (buf));
				(void) strncat(buf, p, sizeof (buf));
			}
			buf[sizeof (buf) - 1] = '\0';
			mhd_eprintf("%s\n", buf);
		}
	}
#endif	/* MHD_DEBUG */

	/* unlock, return set */
	mhd_mx_unlock(&sp->sr_mx);
	return (sp);
}
Exemple #29
0
static void
list_update(list_t *list, lwp_info_t *lwp)
{
	id_info_t *id;

	if (list->l_head == NULL) {			/* first element */
		list->l_head = list->l_tail = id = Zalloc(sizeof (id_info_t));
		goto update;
	}

	for (id = list->l_head; id; id = id->id_next) {
		if ((list->l_type == LT_USERS) &&
		    (id->id_uid != lwp->li_info.pr_uid))
			continue;
		if ((list->l_type == LT_TASKS) &&
		    (id->id_taskid != lwp->li_info.pr_taskid))
			continue;
		if ((list->l_type == LT_PROJECTS) &&
		    (id->id_projid != lwp->li_info.pr_projid))
			continue;
		if ((list->l_type == LT_ZONES) &&
		    (id->id_zoneid != lwp->li_info.pr_zoneid))
			continue;
		id->id_nproc++;
		id->id_taskid	= lwp->li_info.pr_taskid;
		id->id_projid	= lwp->li_info.pr_projid;
		id->id_zoneid	= lwp->li_info.pr_zoneid;
		if (lwp->li_flags & LWP_REPRESENT) {
			id->id_size	+= lwp->li_info.pr_size;
			id->id_rssize	+= lwp->li_info.pr_rssize;
		}
		id->id_pctcpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
		if (opts.o_outpmode & OPT_LWPS)
			id->id_time += TIME2SEC(lwp->li_info.pr_lwp.pr_time);
		else
			id->id_time += TIME2SEC(lwp->li_info.pr_time);
		id->id_pctmem	+= FRC2PCT(lwp->li_info.pr_pctmem);
		id->id_key	+= lwp->li_key;
		total_cpu	+= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
		total_mem	+= FRC2PCT(lwp->li_info.pr_pctmem);
		return;
	}

	id = list->l_tail;
	id->id_next = Zalloc(sizeof (id_info_t));
	id->id_next->id_prev = list->l_tail;
	id->id_next->id_next = NULL;
	list->l_tail = id->id_next;
	id = list->l_tail;
update:
	id->id_uid	= lwp->li_info.pr_uid;
	id->id_projid	= lwp->li_info.pr_projid;
	id->id_taskid	= lwp->li_info.pr_taskid;
	id->id_zoneid	= lwp->li_info.pr_zoneid;
	id->id_nproc++;
	if (lwp->li_flags & LWP_REPRESENT) {
		id->id_size	= lwp->li_info.pr_size;
		id->id_rssize	= lwp->li_info.pr_rssize;
	}
	id->id_pctcpu	= FRC2PCT(lwp->li_info.pr_lwp.pr_pctcpu);
	if (opts.o_outpmode & OPT_LWPS)
		id->id_time = TIME2SEC(lwp->li_info.pr_lwp.pr_time);
	else
		id->id_time = TIME2SEC(lwp->li_info.pr_time);
	id->id_pctmem	= FRC2PCT(lwp->li_info.pr_pctmem);
	id->id_key	= lwp->li_key;
	total_cpu	+= id->id_pctcpu;
	total_mem	+= id->id_pctmem;
	list->l_count++;
}