Esempio n. 1
0
static int
tap_configure(struct mic_info *mic, char *dev)
{
	pid_t pid;
	char *ifargv[7];
	int ret = 0;

	pid = fork();
	if (pid == 0) {
		ifargv[0] = "ip";
		ifargv[1] = "link";
		ifargv[2] = "set";
		ifargv[3] = dev;
		ifargv[4] = "up";
		ifargv[5] = NULL;
		ret = execvp("ip", ifargv);
		if (ret < 0)
			return ret;
	}
	if (pid < 0) {
		mpsslog(PERROR, "%s fork failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}
	ret = waitpid(pid, NULL, 0);
	if (ret < 0) {
		mpsslog(PERROR, "%s waitpid failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}
	mpsslog(PINFO, "MIC name %s %s %d DONE!\n",
		mic->name, __func__, __LINE__);
	return 0;
}
Esempio n. 2
0
static void
wait_for_card_driver(struct mic_info *mic, int fd, int type)
{
	struct pollfd pollfd;
	int err;
	struct mic_device_desc *desc = get_device_desc(mic, type);

	pollfd.fd = fd;
	mpsslog("%s %s Waiting .... desc-> type %d status 0x%x\n",
		mic->name, __func__, type, desc->status);
	while (1) {
		pollfd.events = POLLIN;
		pollfd.revents = 0;
		err = poll(&pollfd, 1, -1);
		if (err < 0) {
			mpsslog("%s %s poll failed %s\n",
				mic->name, __func__, strerror(errno));
			continue;
		}

		if (pollfd.revents) {
			mpsslog("%s %s Waiting... desc-> type %d status 0x%x\n",
				mic->name, __func__, type, desc->status);
			if (desc->status & VIRTIO_CONFIG_S_DRIVER_OK) {
				mpsslog("%s %s poll.revents %d\n",
					mic->name, __func__, pollfd.revents);
				mpsslog("%s %s desc-> type %d status 0x%x\n",
					mic->name, __func__, type,
					desc->status);
				break;
			}
		}
	}
}
Esempio n. 3
0
void
save_oops(struct mic_info *mic)
{
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;
	char buffer[4096];
	char oopsname[PATH_MAX];
	int headerdone = 0;
	int rlen;
	int fd;

	if (strcmp(mpssdi->state, "resetting"))
		return;

	snprintf(oopsname, sizeof(oopsname), "/proc/mic_ramoops/%s_prev",
								mic->name);
	if ((fd = open(oopsname, O_RDONLY)) < 0) {
		mpsslog(PINFO, "%s: open oopsname %s failed %s\n",
			mic->name, oopsname, strerror(errno));
		return;
	}

	while ((rlen = read(fd, buffer, 4096))) {
		if (!headerdone) {
			mpsslog(PINFO, "%s: Resetting MIC found oops:\n", mic->name);
			headerdone = 1;
		}
		mpsslog_dump(buffer, rlen);
	}
	close(fd);
}
Esempio n. 4
0
static struct mic_device_desc *get_device_desc(struct mic_info *mic, int type)
{
	struct mic_device_desc *d;
	int i;
	void *dp = get_dp(mic, type);

	for (i = sizeof(struct mic_bootparam); i < PAGE_SIZE;
		i += mic_total_desc_size(d)) {
		d = dp + i;

		/* End of list */
		if (d->type == 0)
			break;

		if (d->type == -1)
			continue;

		mpsslog("%s %s d-> type %d d %p\n",
			mic->name, __func__, d->type, d);

		if (d->type == (__u8)type)
			return d;
	}
	mpsslog("%s %s %d not found\n", mic->name, __func__, type);
	assert(0);
	return NULL;
}
Esempio n. 5
0
int
autoreboot(struct mic_info *mic)
{
	char value[4096];
	int fd, len, ret;
	char pathname[PATH_MAX] = "/sys/devices/virtual/mic/scif/watchdog_auto_reboot";

	if ((fd = open(pathname, O_RDONLY)) < 0) {
		mpsslog(PINFO, "%s: Failed to open %s %s\n", mic->name, pathname, strerror(errno));
		return 0;
	}

	if ((len = read(fd, value, sizeof(value) - 1)) < 0) {
		mpsslog(PINFO, "%s: Failed to read %s: %s\n", mic->name, pathname, strerror(errno));
		ret = 0;
		goto readsys_ret;
	}

	value[len] = '\0';

	ret = atoi(value);
	mpsslog(PINFO, "%s: autoreboot %d\n", mic->name, ret);
readsys_ret:
	close(fd);
	return ret;
}
Esempio n. 6
0
void
set_log_buf_info(struct mic_info *mic)
{
	int fd;
	int err;
	off_t len;
	char *map;
	char *temp;
	char log_addr[17] = {'\0'};
	char log_size[17] = {'\0'};

	if (mic->config.boot.systemmap == NULL) {
		mpsslog(PINFO, "%s: System map not correctly configured in OSimage parameter\n", mic->name);
		return;
	}

	if ((fd = open(mic->config.boot.systemmap, O_RDONLY)) < 0) {
		mpsslog(PINFO, "%s: Opening System.map failed: %s\n", mic->name, strerror(errno));
		return;
	}

	if ((len = lseek(fd, 0, SEEK_END)) < 0) {
		mpsslog(PINFO, "%s: Reading System.map size failed: %s\n", mic->name, strerror(errno));
		goto close_return;
	}

	if ((map = mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) {
		mpsslog(PINFO, "%s: mmap of System.map failed: %s\n", mic->name, strerror(errno));
		goto close_return;
	}

	if (!(temp = strstr(map, "__log_buf"))) {
		mpsslog(PINFO, "%s: __log_buf not found: %s\n", mic->name, strerror(errno));
		goto unmap_return;
	}

	strncpy(log_addr, temp - 19, 16);
	if ((err = mpss_setsysfs(mic->name, "log_buf_addr", log_addr)) != 0) {
		mpsslog(PINFO, "%s: failed set log_buf_addr sysfs: %s\n", mic->name, strerror(err));
		goto unmap_return;
	}

	if (!(temp = strstr(map, "log_buf_len"))) {
		mpsslog(PINFO, "%s: log_buf_len not found: %s\n", mic->name, strerror(errno));
		goto unmap_return;
	}
	strncpy(log_size, temp - 19, 16);

	if ((err = mpss_setsysfs(mic->name, "log_buf_len", log_size)) != 0) {
		mpsslog(PINFO, "%s: failed set log_buf_len sysfs: %s\n", mic->name, strerror(err));
		goto unmap_return;
	}

	mpsslog(PINFO, "%s: Debug log buffer addr %s len @ %s\n", mic->name, log_addr, log_size);

unmap_return:
	munmap(map, len);
close_return:
	close(fd);
}
Esempio n. 7
0
void
segv_handler(int sig, siginfo_t *siginfo, void *context)
{
	struct mic_info *mic;
	struct mpssd_info *mpssdi;
	void *addrs[100];
	char **funcs;
	void *joinval;
	int cnt;
	int i;

	cnt = backtrace(addrs, 100);
	funcs = backtrace_symbols(addrs, cnt);

	for (mic = miclist; mic != NULL; mic = mic->next) {
		mpssdi = (struct mpssd_info *)mic->data;

		if (mpssdi->boot_pth && (mpssdi->boot_pth != pthread_self())) {
			pthread_cancel(mpssdi->boot_pth);
			pthread_join(mpssdi->boot_pth, &joinval);
		}

		if (mpssdi->monitor_pth && (mpssdi->monitor_pth != pthread_self())) {
			pthread_cancel(mpssdi->monitor_pth);
			pthread_join(mpssdi->monitor_pth, &joinval);
		}

		if (mpssdi->state_pth && (mpssdi->state_pth != pthread_self())) {
			pthread_cancel(mpssdi->state_pth);
			pthread_join(mpssdi->state_pth, &joinval);
		}

		if (mpssdi->crash_pth && (mpssdi->crash_pth != pthread_self())) {
			pthread_cancel(mpssdi->crash_pth);
			pthread_join(mpssdi->crash_pth, &joinval);
		}

		if (mpssdi->stop_pth && (mpssdi->stop_pth != pthread_self())) {
			pthread_cancel(mpssdi->stop_pth);
			pthread_join(mpssdi->stop_pth, &joinval);
		}
	}

	mpsslog(PNORM, "<<<<<<<< mpssd: segmentation violation - dumping stack >>>>>>>>\n");
	for (i = 0; i < cnt; i++) {
		mpsslog(PNORM, "%s\n", funcs[i]);
	}
	mpsslog(PNORM, "<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n");
	exit(0);
}
Esempio n. 8
0
/*
 * This initialization routine requires at least one
 * vring i.e. vr0. vr1 is optional.
 */
static void *
init_vr(struct mic_info *mic, int fd, int type,
	struct mic_vring *vr0, struct mic_vring *vr1, int num_vq)
{
	int vr_size;
	char *va;

	vr_size = PAGE_ALIGN(_vring_size(MIC_VRING_ENTRIES,
					 MIC_VIRTIO_RING_ALIGN) +
			     sizeof(struct _mic_vring_info));
	va = mmap(NULL, MIC_DEVICE_PAGE_END + vr_size * num_vq,
		PROT_READ, MAP_SHARED, fd, 0);
	if (MAP_FAILED == va) {
		mpsslog("%s %s %d mmap failed errno %s\n",
			mic->name, __func__, __LINE__,
			strerror(errno));
		goto done;
	}
	set_dp(mic, type, va);
	vr0->va = (struct mic_vring *)&va[MIC_DEVICE_PAGE_END];
	vr0->info = vr0->va +
		_vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN);
	vring_init(&vr0->vr,
		   MIC_VRING_ENTRIES, vr0->va, MIC_VIRTIO_RING_ALIGN);
	mpsslog("%s %s vr0 %p vr0->info %p vr_size 0x%x vring 0x%x ",
		__func__, mic->name, vr0->va, vr0->info, vr_size,
		_vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
	mpsslog("magic 0x%x expected 0x%x\n",
		le32toh(vr0->info->magic), MIC_MAGIC + type);
	assert(le32toh(vr0->info->magic) == MIC_MAGIC + type);
	if (vr1) {
		vr1->va = (struct mic_vring *)
			&va[MIC_DEVICE_PAGE_END + vr_size];
		vr1->info = vr1->va + _vring_size(MIC_VRING_ENTRIES,
			MIC_VIRTIO_RING_ALIGN);
		vring_init(&vr1->vr,
			   MIC_VRING_ENTRIES, vr1->va, MIC_VIRTIO_RING_ALIGN);
		mpsslog("%s %s vr1 %p vr1->info %p vr_size 0x%x vring 0x%x ",
			__func__, mic->name, vr1->va, vr1->info, vr_size,
			_vring_size(MIC_VRING_ENTRIES, MIC_VIRTIO_RING_ALIGN));
		mpsslog("magic 0x%x expected 0x%x\n",
			le32toh(vr1->info->magic), MIC_MAGIC + type + 1);
		assert(le32toh(vr1->info->magic) == MIC_MAGIC + type + 1);
	}
done:
	return va;
}
Esempio n. 9
0
void
start_daemon(void)
{
	struct mic_info *mic;
	struct mpssd_info *mpssdi;
	int err;
	int sc;

	if ((err = mpssenv_aquire_lockfile(&mpssenv))) {
		fprintf(stderr, "Error aquiring lockfile %s: %s\n", mpssenv.lockfile, strerror(err));
		exit(1);
	}

	pthread_create(&mon_pth, NULL, mic_monitor, NULL);
	pthread_create(&cred_pth, NULL, mic_credentials, NULL);

	while (pthread_mutex_lock(&start_lock) != 0);

	for (mic = miclist; mic != NULL; mic = mic->next) {
		if ((mic->data = malloc(sizeof(struct mpssd_info))) == NULL) {
			fprintf(stderr, "Catastrophic memory allocation error: %s\n", strerror(err));
			exit(1);
		}

		memset(mic->data, 0, sizeof(struct mpssd_info));
		mpssdi = (struct mpssd_info *)mic->data;

		if ((mpssdi->state = mpss_readsysfs(mic->name, "state")) == NULL) {
			mpsslog(PERROR, "%s: Ignoring  - Critical failure reading state sysfs entry\n", mic->name);
			continue;
		}

		pthread_mutex_init(&mpssdi->pth_lock, NULL);
		pthread_mutex_init(&mpssdi->reset_lock, NULL);
		pthread_cond_init(&mpssdi->reset_cond, NULL);
		start_count++;
		while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
		if (is_upstream_driver())
			pthread_create(&mpssdi->state_pth, NULL, init_mic, mic);
		else
			pthread_create(&mpssdi->state_pth, NULL, mic_state, mic);
		pthread_create(&mpssdi->boot_pth, NULL, boot_mic, mic);
		while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
	}

	while (pthread_mutex_unlock(&start_lock) != 0);
	sc = start_count;
	while (sc) {
		while (pthread_mutex_lock(&start_lock) != 0);
		sc = start_count;
		while (pthread_mutex_unlock(&start_lock) != 0);
		sleep(1);
	}

	if (start_pid)
		kill(start_pid, SIGHUP);

	while (pause());
}
Esempio n. 10
0
void
quit_handler(int sig, siginfo_t *siginfo, void *context)
{
	struct mic_info *mic;
	struct mpssd_info *mpssdi;
	struct mpss_elist mpssperr;
	char *state;

	shutdown_count = 0;
	while (pthread_mutex_lock(&shutdown_lock) != 0);

	mpsslog(PINFO, "MPSS Stack Shutting down\n");
	for (mic = miclist; mic != NULL; mic = mic->next) {
		mpssdi = (struct mpssd_info *)mic->data;

		if (mic->present == FALSE) {
			mpsslog(PWARN, "%s: Configured but not present - skipping\n", mic->name);
			continue;
		}

		if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
			mpsslog(PERROR, "%s: Failed to read state - not waiting for card ready\n", mic->name);
			while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
			pthread_create(&mpssdi->stop_pth, NULL, shutdown_mic, mic);
			while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
			continue;
		}

		mpss_parse_config(&mpssenv, mic, &brlist, &mpssperr);
		mpss_clear_elist(&mpssperr);
		if (strcmp(state, "ready") && strcmp(state, "resetting")) {
			shutdown_count++;
			while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
			pthread_create(&mpssdi->stop_pth, NULL, shutdown_mic, mic);
			while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
		}
		free(state);
	}

	while (pthread_mutex_unlock(&shutdown_lock) != 0);

	if (shutdown_count == 0)
		exit(0);
	else
		pause();
}
Esempio n. 11
0
static int tun_alloc(struct mic_info *mic, char *dev)
{
	struct ifreq ifr;
	int fd, err;
#if GSO_ENABLED
	unsigned offload;
#endif
	fd = open("/dev/net/tun", O_RDWR);
	if (fd < 0) {
		mpsslog("Could not open /dev/net/tun %s\n", strerror(errno));
		goto done;
	}

	memset(&ifr, 0, sizeof(ifr));

	ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
	if (*dev)
		strncpy(ifr.ifr_name, dev, IFNAMSIZ);

	err = ioctl(fd, TUNSETIFF, (void *)&ifr);
	if (err < 0) {
		mpsslog("%s %s %d TUNSETIFF failed %s\n",
			mic->name, __func__, __LINE__, strerror(errno));
		close(fd);
		return err;
	}
#if GSO_ENABLED
	offload = TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
		TUN_F_TSO_ECN | TUN_F_UFO;

	err = ioctl(fd, TUNSETOFFLOAD, offload);
	if (err < 0) {
		mpsslog("%s %s %d TUNSETOFFLOAD failed %s\n",
			mic->name, __func__, __LINE__, strerror(errno));
		close(fd);
		return err;
	}
#endif
	strcpy(dev, ifr.ifr_name);
	mpsslog("Created TAP %s\n", dev);
done:
	return fd;
}
Esempio n. 12
0
static inline void verify_out_len(struct mic_info *mic,
	struct mic_copy_desc *copy)
{
	if (copy->out_len != sum_iovec_len(copy)) {
		mpsslog("%s %s %d BUG copy->out_len 0x%x len 0x%zx\n",
			mic->name, __func__, __LINE__,
			copy->out_len, sum_iovec_len(copy));
		assert(copy->out_len == sum_iovec_len(copy));
	}
}
Esempio n. 13
0
ssize_t
get_dir_size(struct mic_info *mic, char *dirpath)
{
	struct dirent *tmp;
	DIR *dir;
	char path[PATH_MAX];
	struct stat data;
	size_t result = 0;

	if ((dir = opendir(dirpath)) == NULL) {
		mpsslog(PINFO, "%s: Could not open dir %s\n", mic->name, dirpath);
		return -1;
	}

	while ((tmp = readdir(dir))) {
		if (!strcmp(tmp->d_name, ".") || !strcmp(tmp->d_name, ".."))
			continue;

		snprintf(path, PATH_MAX - 1, "%s/%s", dirpath, tmp->d_name);

		if (lstat(path, &data) < 0) {
			mpsslog(PINFO, "%s: Couldn't lstat %s: %s\n", mic->name, path, strerror(errno));
			continue;
		}

		if (S_ISDIR(data.st_mode) && !S_ISLNK(data.st_mode)) {
			ssize_t dirsize;
			strcat(path, "/");
			if ((dirsize = get_dir_size(mic, path)) < 0) {
				mpsslog(PINFO, "%s: getting directory size failed %s %s\n",
					mic->name, path, strerror(errno));
				return dirsize;
			}
			result += dirsize;
		} else if (S_ISREG(data.st_mode)) {
			result += data.st_size;
		}
	}

	closedir(dir);

	return result;
}
Esempio n. 14
0
/* Display an iovec */
static void
disp_iovec(struct mic_info *mic, struct mic_copy_desc *copy,
	   const char *s, int line)
{
	int i;

	for (i = 0; i < copy->iovcnt; i++)
		mpsslog("%s %s %d copy->iov[%d] addr %p len 0x%zx\n",
			mic->name, s, line, i,
			copy->iov[i].iov_base, copy->iov[i].iov_len);
}
Esempio n. 15
0
int
main(int argc, char *argv[])
{
	pid_t pid;

	mpssenv_init(&mpssenv);
	parse_cmd_args(argc, argv);
	setsighandlers();

	if (logfp != stderr) {
		if ((logfp = fopen(LOGFILE_NAME, "a+")) == NULL) {
			fprintf(stderr, "cannot open logfile '%s'\n", LOGFILE_NAME);
			exit(EBADF);
		}

	}

	mpsslog(PINFO, "MPSS Daemon start\n");

	if ((miclist = mpss_get_miclist(&mpssenv, NULL)) == NULL) {
		mpsslog(PINFO, "MIC module not loaded\n");
		exit(2);
	}

	if (logfp == stderr) {
		start_daemon();
	} else {
		start_pid = getpid();
		switch ((pid = fork())) {
		case -1:
			fprintf(stderr, "cannot fork: %s\n", strerror(errno));
			exit(ENOEXEC);
		case 0:
			start_daemon();
		default:
			pause();
		}
	}

	exit(0);
}
Esempio n. 16
0
char *
readsysfs(char *dir, char *entry)
{
	char filename[PATH_MAX];
	char value[PAGE_SIZE];
	char *string = NULL;
	int fd;
	int len;

	if (dir == NULL)
		snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
	else
		snprintf(filename, PATH_MAX,
			 "%s/%s/%s", MICSYSFSDIR, dir, entry);

	fd = open(filename, O_RDONLY);
	if (fd < 0) {
		mpsslog("Failed to open sysfs entry '%s': %s\n",
			filename, strerror(errno));
		return NULL;
	}

	len = read(fd, value, sizeof(value));
	if (len < 0) {
		mpsslog("Failed to read sysfs entry '%s': %s\n",
			filename, strerror(errno));
		goto readsys_ret;
	}
	if (len == 0)
		goto readsys_ret;

	value[len - 1] = '\0';

	string = malloc(strlen(value) + 1);
	if (string)
		strcpy(string, value);

readsys_ret:
	close(fd);
	return string;
}
Esempio n. 17
0
/* Spin till we have some descriptors */
static void
spin_for_descriptors(struct mic_info *mic, struct mic_vring *vr)
{
	__u16 avail_idx = read_avail_idx(vr);

	while (avail_idx == le16toh(ACCESS_ONCE(vr->vr.avail->idx))) {
#ifdef DEBUG
		mpsslog("%s %s waiting for desc avail %d info_avail %d\n",
			mic->name, __func__,
			le16toh(vr->vr.avail->idx), vr->info->avail_idx);
#endif
		sched_yield();
	}
}
Esempio n. 18
0
/* Central API which triggers the copies */
static int
mic_virtio_copy(struct mic_info *mic, int fd,
		struct mic_vring *vr, struct mic_copy_desc *copy)
{
	int ret;

	ret = ioctl(fd, MIC_VIRTIO_COPY_DESC, copy);
	if (ret) {
		mpsslog("%s %s %d errno %s ret %d\n",
			mic->name, __func__, __LINE__,
			strerror(errno), ret);
	}
	return ret;
}
Esempio n. 19
0
static void *get_dp(struct mic_info *mic, int type)
{
	switch (type) {
	case VIRTIO_ID_CONSOLE:
		return mic->mic_console.console_dp;
	case VIRTIO_ID_NET:
		return mic->mic_net.net_dp;
	case VIRTIO_ID_BLOCK:
		return mic->mic_virtblk.block_dp;
	}
	mpsslog("%s %s %d not found\n", mic->name, __func__, type);
	assert(0);
	return NULL;
}
Esempio n. 20
0
int
setsysfs(char *dir, char *entry, char *value)
{
	char filename[PATH_MAX];
	char *oldvalue;
	int fd, ret = 0;

	if (dir == NULL)
		snprintf(filename, PATH_MAX, "%s/%s", MICSYSFSDIR, entry);
	else
		snprintf(filename, PATH_MAX, "%s/%s/%s",
			 MICSYSFSDIR, dir, entry);

	oldvalue = readsysfs(dir, entry);

	fd = open(filename, O_RDWR);
	if (fd < 0) {
		ret = errno;
		mpsslog("Failed to open sysfs entry '%s': %s\n",
			filename, strerror(errno));
		goto done;
	}

	if (!oldvalue || strcmp(value, oldvalue)) {
		if (write(fd, value, strlen(value)) < 0) {
			ret = errno;
			mpsslog("Failed to write new sysfs entry '%s': %s\n",
				filename, strerror(errno));
		}
	}
	close(fd);
done:
	if (oldvalue)
		free(oldvalue);
	return ret;
}
Esempio n. 21
0
static void set_dp(struct mic_info *mic, int type, void *dp)
{
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;

	switch (type) {
	case VIRTIO_ID_CONSOLE:
		mpssdi->mic_console.console_dp = dp;
		return;
	case VIRTIO_ID_NET:
		mpssdi->mic_net.net_dp = dp;
		return;
	case VIRTIO_ID_BLOCK:
		mpssdi->mic_virtblk.block_dp = dp;
		return;
	}
	mpsslog(PERROR, "%s %s %d not found\n", mic->name, __func__, type);
	assert(0);
}
Esempio n. 22
0
int
check_fs_params(struct mic_info *mic)
{
	struct stat sbuf;

	if ((mic->config.filesrc.base.type == SRCTYPE_CPIO) &&
	    stat(mic->config.filesrc.base.image, &sbuf) != 0) {
		mpsslog(PINFO, "%s: Boot aborted - Base image '%s' not found\n",
			       mic->name, mic->config.filesrc.base.image);
		return 1;
	}

	if ((mic->config.filesrc.base.type == SRCTYPE_DIR) &&
	    stat(mic->config.filesrc.base.dir, &sbuf) != 0) {
		mpsslog(PINFO, "%s: Boot aborted - Base directory '%s' not found\n",
			       mic->name, mic->config.filesrc.base.image);
		return 1;
	}

	if (mic->config.filesrc.common.dir == NULL) {
		mpsslog(PINFO, "%s: Boot aborted - CommonDir not configured\n", mic->name);
		return 1;
	}

	if (stat(mic->config.filesrc.common.dir, &sbuf) != 0) {
		mpsslog(PINFO, "%s: Boot aborted - CommonDir '%s' not found\n",
			       mic->name, mic->config.filesrc.common.dir);
		return 1;
	}

	if (mic->config.filesrc.mic.dir == NULL) {
		mpsslog(PINFO, "%s: Boot aborted - MicDir not configured\n", mic->name);
		return 1;
	}

	if (stat(mic->config.filesrc.mic.dir, &sbuf) != 0) {
		mpsslog(PINFO, "%s: Boot aborted - MicDir '%s' not found\n",
			       mic->name, mic->config.filesrc.mic.dir);
		return 1;
	}

	return 0;
}
Esempio n. 23
0
void *
monitor(void *arg)
{
	struct mic_info *mic = (struct mic_info *)arg;
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;
	unsigned int proto;
	unsigned int jobid;
	struct pollfd pfds[1];
	struct jobs *jlist;
	struct jobs *job = NULL;
	uint16_t stopID;

	while (1) {
		pfds[0].fd = mpssdi->recv_ep;
		pfds[0].events = POLLIN | POLLERR | POLLPRI;
		poll(pfds, 1, -1);

		if (scif_recv(mpssdi->recv_ep, &proto, sizeof(proto), SCIF_RECV_BLOCK) < 0) {
			if (errno == ECONNRESET) {
				mpsslog(PERROR, "%s: MIC card mpssd daemon disconnect: %s\n", mic->name,strerror(errno));
				scif_close(mpssdi->recv_ep);
				scif_close(mpssdi->send_ep);
				mpssdi->recv_ep = -1;
				mpssdi->send_ep = -1;
				pthread_exit((void *)1);
			}
			continue;
		}

		switch (proto) {
		case REQ_CREDENTIAL_ACK:
		case REQ_CREDENTIAL_NACK:
			scif_recv(mpssdi->recv_ep, &jobid, sizeof(jobid), SCIF_RECV_BLOCK);

			while (pthread_mutex_lock(&jobs_lock) != 0);
			jlist = &gjobs;
			while (jlist->next) {
				if (jlist->next->jobid == jobid) {
					job = jlist->next;

					if (--job->cnt == 0) {
						jlist->next = job->next;
						while (pthread_mutex_unlock(&jobs_lock) != 0);

						proto = CRED_SUCCESS;
						scif_send(job->dep, &proto, sizeof(proto), 0);
						scif_close(job->dep);
						continue;
					}
					break;
				}

				jlist = jlist->next;
			}

			while (pthread_mutex_unlock(&jobs_lock) != 0);
			break;

		case MONITOR_STOPPING:
			scif_recv(mpssdi->recv_ep, &stopID, sizeof(stopID), SCIF_RECV_BLOCK);
			mpsslog(PERROR, "%s: card mpssd daemon exiting\n", mic->name);
			scif_close(mpssdi->recv_ep);
			scif_close(mpssdi->send_ep);
			mpssdi->recv_ep = -1;
			mpssdi->send_ep = -1;
			pthread_exit((void *)0);
		}
	}
}
Esempio n. 24
0
void *
mic_monitor(void *arg)
{
	struct mic_info *mic;
	struct mpssd_info *mpssdi;
	pthread_attr_t attr;
	struct scif_portID sendID = {0, MPSSD_MONSEND};
	struct scif_portID recvID;
	scif_epd_t lep;
	scif_epd_t recv_ep;
	scif_epd_t send_ep;
	unsigned int proto;
	uint16_t send_port;
	uint16_t remote_port = 0;
	int err;

	if ((lep = scif_open()) < 0) {
		mpsslog(PINFO, "Cannot open mpssd monitor SCIF listen port: %s\n", strerror(errno));
		pthread_exit((void *)1);
	}

	if (scif_bind(lep, MPSSD_MONRECV) < 0) {
		mpsslog(PINFO, "Cannot bind to mpssd monitor SCIF PORT: %s\n", strerror(errno));
		pthread_exit((void *)1);
	}

	if (scif_listen(lep, 16) < 0) {
		mpsslog(PINFO, "Set Listen on mpssd monitor SCIF PORT fail: %s\n", strerror(errno));
		pthread_exit((void *)1);
	}

	while (1) {
		if (scif_accept(lep, &recvID, &recv_ep, SCIF_ACCEPT_SYNC)) {
			if (errno != EINTR)
				mpsslog(PINFO, "Wait for card connect failed: %s\n", strerror(errno));
			sleep(1);
			continue;
		}

		if ((mic = mpss_find_micid_inlist(miclist, recvID.node - 1)) == NULL) {
			mpsslog(PINFO, "Cannot configure - node %d does not seem to exist\n",
				       recvID.node - 1);
			scif_close(recv_ep);
			continue;
		}

		mpssdi = (struct mpssd_info *)mic->data;

		if ((send_ep = scif_open()) < 0) {
			fprintf(logfp, "Failed to open SCIF: %s\n", strerror(errno));
			scif_close(recv_ep);
			pthread_exit((void *)1);
		}
		mpssdi->send_ep = send_ep;

		if ((err = scif_recv(recv_ep, &proto, sizeof(proto), SCIF_RECV_BLOCK)) != sizeof(proto)) {
			mpsslog(PINFO, "%s: MIC card mpssd daemon startup connection error %s\n",
					mic->name, strerror(errno));
			scif_close(recv_ep);
			mpssdi->recv_ep = -1;
			continue;
		}

		switch (proto) {
		case MONITOR_START:
			sendID.node = mic->id + 1;
			while ((send_port = scif_connect(send_ep, &sendID)) < 0) {
				fprintf(logfp, "Failed to connect to monitor thread on card: %s\n",
					strerror(errno));
				sleep(1);
			}

			// Over reliable connection, mpssd tells us which port number it uses
			// to talk back to us. If this port matches actual recv_ep remote port
			// then we know that recv_ep and send_ep reference the same client.
			// We also know that send_ep, references mpssd on mic, as port we
			// connect to on that endpoint requires privliges to listen on.
			if (scif_recv(send_ep, &remote_port, sizeof(remote_port), SCIF_RECV_BLOCK) < 0) {
				mpsslog(PINFO, "%s: MIC card mpssd daemon handshake error %s\n",
					mic->name, strerror(errno));
				scif_close(send_ep);
				scif_close(recv_ep);
				continue; // go back to next iteration of while(1), we cannot break the while loop because hosts mpssd can connect with multiple mic cards
			}

			if (remote_port != recvID.port || sendID.node != recvID.node) {
				mpsslog(PINFO, "%s: Failed to authenticate connection with mic mpssd\n",
					mic->name);
				scif_close(send_ep);
				scif_close(recv_ep);
				continue; // go back to next iteration of while(1), we cannot break the while loop because hosts mpssd can connect with multiple mic cards

			}

			// Similarily, provide info for the client, so that he can also verify
			// that both connections send_ep & recv_ep belong to us.
			if (scif_send(recv_ep, &send_port, sizeof(send_port), SCIF_SEND_BLOCK) < 0) {
				mpsslog(PINFO, "%s: MIC card mpssd daemon handshake error %s\n",
					mic->name, strerror(errno));
				scif_close(send_ep);
				scif_close(recv_ep);
				continue; // go back to next iteration of while(1), we cannot break the while loop because hosts mpssd can connect with multiple mic cards

			}

			mpssdi->recv_ep = recv_ep;
			pthread_attr_init(&attr);
			pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
			pthread_create(&mpssdi->monitor_pth, &attr, monitor, mic);
			proto = MONITOR_START_ACK;
			scif_send(send_ep, &proto, sizeof(proto), SCIF_RECV_BLOCK);
			mpsslog(PINFO, "%s: Monitor connection established\n", mic->name);
			break;
		}
	}
}
Esempio n. 25
0
int
get_cookie(struct passwd *pass, char *cookie)
{
	char cookiename[PATH_MAX];
	struct stat sbuf;
	int createcookie = TRUE;
	int len;
	int fd;
	int err = -1;

	snprintf(cookiename, PATH_MAX, "%s/.mpsscookie", pass->pw_dir);

	if (setegid(pass->pw_gid) < 0) {
		mpsslog(PERROR, "%s Cannot create: Failed to setegid to gid %d : %s\n",
				cookiename, pass->pw_gid, strerror(errno));
		return -1;
	}

	if (seteuid(pass->pw_uid) < 0) {
		mpsslog(PERROR, "%s Cannot create: Failed to seteuid to uid %d : %s\n",
				cookiename, pass->pw_uid, strerror(errno));
		setegid(0);
		return -1;
	}

	if (lstat(cookiename, &sbuf) == 0) {
		if (S_ISLNK(sbuf.st_mode)) {
			if (unlink(cookiename) < 0) {
				mpsslog(PERROR, "%s Cannot create: is a link and removal failed: %s\n",
					cookiename, strerror(errno));
				goto cookie_done;
			}

			mpsslog(PERROR, "%s: Is a link - remove and recreate\n", cookiename);

		} else if (sbuf.st_nlink != 1) {
			if (unlink(cookiename) < 0) {
				mpsslog(PERROR, "%s Cannot create: has more than one hard link and "
						"removal failed: %s\n", cookiename, strerror(errno));
				goto cookie_done;
			}

			mpsslog(PERROR, "%s: Too many hard links - remove and recreate\n", cookiename);

		} else {
			createcookie = FALSE;
		}
	}

	if (!createcookie) {
		if ((fd = open(cookiename, O_RDONLY)) < 0) {
			mpsslog(PERROR, "Failed to open %s: %s\n", cookiename, strerror(errno));
			goto cookie_done;
		}

		if ((len = read(fd, cookie, MPSS_COOKIE_SIZE)) != MPSS_COOKIE_SIZE) {
			if (unlink(cookiename) < 0) {
				mpsslog(PERROR, "Cannot create cookie file %s bad size and removal failed: %s\n",
					cookiename, strerror(errno));
				goto cookie_done;
			}

			mpsslog(PERROR, "%s: Bad size remove and recreate\n", cookiename);
			createcookie = TRUE;
		}
		close(fd);
	}

	if (createcookie) {
		if ((fd = open("/dev/urandom", O_RDONLY)) < 0) {
			mpsslog(PERROR, "Create cookie %s failed to open dev random: %s\n", cookiename, strerror(errno));
			goto cookie_done;
		}

		len = read(fd, cookie, MPSS_COOKIE_SIZE);
		close(fd);

		if ((fd = open(cookiename, O_WRONLY|O_CREAT)) < 0) {
			mpsslog(PERROR, "Failed to open %s: %s\n", cookiename, strerror(errno));
			goto cookie_done;
		}

		write(fd, cookie, len);
		fchmod(fd, S_IRUSR);
		fchown(fd, pass->pw_uid, pass->pw_gid);
		close(fd);
	}

	err = 0;

cookie_done:
	seteuid(0);
	setegid(0);
	return err;
}
Esempio n. 26
0
void *
mic_credentials(void *arg)
{
	struct mic_info *mic;
	struct mpssd_info *mpssdi;
	struct jobs *job;
	struct jobs *jlist;
	struct scif_portID portID;
	struct passwd *pass;
	char *username = NULL;
	char cookie[MPSS_COOKIE_SIZE];
	int len;
	unsigned int proto;
	scif_epd_t lep;
	scif_epd_t dep;
	uid_t uid;
	int err;

	if ((lep = scif_open()) < 0) {
		mpsslog(PINFO, "Cannot open mpssd credentials SCIF listen port: %s\n",
			       strerror(errno));
		pthread_exit((void *)1);
	}

	if (scif_bind(lep, MPSSD_CRED) < 0) {
		mpsslog(PINFO, "Cannot bind to mpssd credentials SCIF PORT: %s\n", strerror(errno));
		pthread_exit((void *)1);
	}

	if (scif_listen(lep, 16) < 0) {
		mpsslog(PINFO, "Set Listen on mpssd credentials SCIF PORT fail: %s\n", strerror(errno));
		pthread_exit((void *)1);
	}

	while (1) {
		if (scif_accept(lep, &portID, &dep, SCIF_ACCEPT_SYNC)) {
			if (errno != EINTR) {
				mpsslog(PINFO, "Wait for credentials request fail: %s\n", strerror(errno));
				scif_close(dep);
			}
			continue;
		}

		if ((err = scif_recv(dep, &uid, sizeof(uid), SCIF_RECV_BLOCK)) != sizeof(uid)) {
			mpsslog(PINFO, "Credential connect recieve error %s\n", strerror(errno));
			scif_close(dep);
			continue;
		}

		username = NULL;
		while ((pass = getpwent()) != NULL) {
			if (uid == pass->pw_uid) {
				username = pass->pw_name;
				break;
			}
		}

		endpwent();

		if (username == NULL) {
			mpsslog(PERROR, "User request unknown UID %d\n", uid);
			proto = CRED_FAIL_UNKNOWNUID;
			scif_send(dep, &proto, sizeof(proto), 0);
			scif_close(dep);
			continue;
		};

		if (get_cookie(pass, cookie) < 0) {
			proto = CRED_FAIL_READCOOKIE;
			scif_send(dep, &proto, sizeof(proto), 0);
			scif_close(dep);
			continue;
		}

		if ((job = malloc(sizeof(struct jobs))) == NULL) {
			proto = CRED_FAIL_MALLOC;
			scif_send(dep, &proto, sizeof(proto), 0);
			scif_close(dep);
			continue;
		}

		job->jobid = nextjobid++;
		job->dep = dep;
		job->cnt = 0;
		len = strlen(username);

		while (pthread_mutex_lock(&jobs_lock) != 0);

		for (mic = miclist; mic != NULL; mic = mic->next) {
			mpssdi = (struct mpssd_info *)mic->data;

			if (mpssdi->send_ep != -1) {
				job->cnt++;
				proto = REQ_CREDENTIAL;
				if ((scif_send(mpssdi->send_ep, &proto, sizeof(proto), 0)) < 0) {
					if (errno == ECONNRESET) {
						job->cnt--;
						continue;
					}
				}

				scif_send(mpssdi->send_ep, &job->jobid, sizeof(job->jobid), 0);
				scif_send(mpssdi->send_ep, &len, sizeof(len), 0);
				scif_send(mpssdi->send_ep, username, len, 0);
				len = sizeof(cookie);
				scif_send(mpssdi->send_ep, &len, sizeof(len), 0);
				scif_send(mpssdi->send_ep, cookie, len, SCIF_SEND_BLOCK);
			}
		}

		if (job->cnt == 0) {
			proto = CRED_SUCCESS;
			scif_send(job->dep, &proto, sizeof(proto), 0);
			scif_close(job->dep);
		} else {
			jlist = &gjobs;
			while (jlist->next)
				jlist = jlist->next;

			jlist->next = job;
			job->next = NULL;
		}
		while (pthread_mutex_unlock(&jobs_lock) != 0);
	}
}
Esempio n. 27
0
void *
shutdown_mic(void *arg)
{
	struct mic_info *mic = (struct mic_info *)arg;
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;
	int timeout = atoi(mic->config.misc.shutdowntimeout);
	char *state = mpss_readsysfs(mic->name, "state");
	char *mode;
	int err;
	struct timespec waittime;
	struct timeval now;

	if (is_upstream_driver())
		mode = mpss_readsysfs(mic->name, "bootmode");
	else
		mode = mpss_readsysfs(mic->name, "mode");

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);

	if (mpssdi->boot_pth)
		pthread_cancel(mpssdi->boot_pth);

	if (mpssdi->monitor_pth)
		pthread_cancel(mpssdi->monitor_pth);

	if (mpssdi->state_pth)
		pthread_cancel(mpssdi->state_pth);

	if (mpssdi->crash_pth)
		pthread_cancel(mpssdi->crash_pth);

	while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);

	if (state == NULL) {
		mpsslog(PERROR, "%s: Failed to read state of card - Leaving in current state.\n", mic->name);
	} else {
		if (!timeout || strcmp(state, "online")) {
			mpsslog(PINFO, "%s: Forced Reset\n", mic->name);
		} else if ((mode == NULL) || (strcmp(mode, "linux"))) {
			if ((err = mpss_setsysfs(mic->name, "state", "reset")) != 0) {
				mpsslog(PERROR, "%s: Failed to set state of card - Leaving in current state: %s\n",
					mic->name, strerror(err));
			} else {
				mpsslog(PINFO, "%s: Resetting online mode %s\n", mic->name, mode);
			}
		} else {
			mpsslog(PINFO, "%s: Shutting down. Timeout %d\n", mic->name, timeout);
			if ((err = mpss_setsysfs(mic->name, "state", "shutdown")) != 0) {
				mpsslog(PERROR, "%s: Failed to set state of card - Leaving in current state: %s\n",
					mic->name, strerror(err));
			} else {
				mpsslog(PINFO, "%s: Shutting down. Timeout %d\n", mic->name, timeout);
				/* In KNL, mpssd resets the card after a shutdown. This is different from
				 * KNC production stack in which the driver reset the card.
				 * The timedwait here is signaled by the mic_config thread after performing
				 * the reset
				 */
				if (is_upstream_driver()) {
					mpssdi->reset_done = 0;
					gettimeofday(&now, NULL);
					waittime.tv_sec = now.tv_sec + timeout;
					while (pthread_mutex_lock(&mpssdi->reset_lock) != 0);
					while (!mpssdi->reset_done) {
						if (!pthread_cond_timedwait(&mpssdi->reset_cond,
							&mpssdi->reset_lock, &waittime))
							break;
					}
					while (pthread_mutex_unlock(&mpssdi->reset_lock) != 0);
				}
			}
		}
	}

	while (pthread_mutex_lock(&shutdown_lock) != 0);
	if (--shutdown_count == 0)
		exit(0);

	while (pthread_mutex_unlock(&shutdown_lock) != 0);
	while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
	mpssdi->stop_pth = 0;
	while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
	pthread_exit(NULL);
}
Esempio n. 28
0
static int
tap_configure(struct mic_info *mic, char *dev)
{
	pid_t pid;
	char *ifargv[7];
	char ipaddr[IFNAMSIZ];
	int ret = 0;

	pid = fork();
	if (pid == 0) {
		ifargv[0] = "ip";
		ifargv[1] = "link";
		ifargv[2] = "set";
		ifargv[3] = dev;
		ifargv[4] = "up";
		ifargv[5] = NULL;
		mpsslog("Configuring %s\n", dev);
		ret = execvp("ip", ifargv);
		if (ret < 0) {
			mpsslog("%s execvp failed errno %s\n",
				mic->name, strerror(errno));
			return ret;
		}
	}
	if (pid < 0) {
		mpsslog("%s fork failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}

	ret = waitpid(pid, NULL, 0);
	if (ret < 0) {
		mpsslog("%s waitpid failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}

	snprintf(ipaddr, IFNAMSIZ, "172.31.%d.254/24", mic->id);

	pid = fork();
	if (pid == 0) {
		ifargv[0] = "ip";
		ifargv[1] = "addr";
		ifargv[2] = "add";
		ifargv[3] = ipaddr;
		ifargv[4] = "dev";
		ifargv[5] = dev;
		ifargv[6] = NULL;
		mpsslog("Configuring %s ipaddr %s\n", dev, ipaddr);
		ret = execvp("ip", ifargv);
		if (ret < 0) {
			mpsslog("%s execvp failed errno %s\n",
				mic->name, strerror(errno));
			return ret;
		}
	}
	if (pid < 0) {
		mpsslog("%s fork failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}

	ret = waitpid(pid, NULL, 0);
	if (ret < 0) {
		mpsslog("%s waitpid failed errno %s\n",
			mic->name, strerror(errno));
		return ret;
	}
	mpsslog("MIC name %s %s %d DONE!\n",
		mic->name, __func__, __LINE__);
	return 0;
}
Esempio n. 29
0
void *
boot_mic(void *arg)
{
	struct mic_info *mic = (struct mic_info *)arg;
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;
	struct mpss_elist mpssperr;
	struct stat sbuf;
	char *initrd = NULL;
	char *state;
	char *save;
	char *errmsg;
	char boot_string[PATH_MAX];
	char cmdline[2048];
	int shutdown_wait = 180;// Do not wait for shutdown more than 180 secs.
	int reset_wait = 180;	// Do not wait for reset more than 180 secs.
	int err = 0;
	char *shutdown_str;
	char os_image_path[PATH_MAX];
	char kernel[PATH_MAX];
	char ramdisk[PATH_MAX];
	char efiimage[PATH_MAX];
	char *sysfs_rd;

	if ((err = mpss_parse_config(&mpssenv, mic, &brlist, &mpssperr))) {
		mpsslog(PINFO, "%s: Boot aborted - no configuation file present: %s\n", mic->name, strerror(err));
		goto bootexit;
	}

	mpss_print_elist(&mpssperr, PWARN, mpsslog);
	mpss_clear_elist(&mpssperr);

	switch(mic->config.family) {
		case MIC_FAMILY_KNL_VALUE:
			if (!is_mic_knl(mic))
				mpsslog(PWARN, "%s: Family mismatch. Configuration file parameter is %s but MIC family is different\n"
						"\t Please execute micctrl --cleanconfig and --initdefaults again\n", mic->name, family_to_str(mic->config.family));
			break;
		case MIC_FAMILY_KNC_VALUE:
			if (!is_mic_knc(mic))
				mpsslog(PWARN, "%s: Family mismatch. Configuration file parameter is %s but MIC family is different\n"
						"\t Please execute micctrl --cleanconfig and --initdefaults again\n", mic->name, family_to_str(mic->config.family));
			break;
		case MIC_FAMILY_UNKNOWN_VALUE:
		default:
			mpsslog(PWARN, "%s: Family parameter is %s\n\t Please execute micctrl --cleanconfig and --initdefaults again\n", mic->name, family_to_str(mic->config.family));
	}

	if (check_fs_params(mic))
		goto bootexit;

	if (mic->config.boot.osimage == NULL) {
		mpsslog(PINFO, "%s: Boot aborted - OsImage parameter not set\n", mic->name);
		goto bootexit;
	}

	if (is_mic_knl(mic) && mic->config.boot.efiimage == NULL) {
		mpsslog(PINFO, "%s: Boot aborted - EFI Image parameter not set\n", mic->name);
		goto bootexit;
	}

	if (verify_bzImage(&mpssenv, mic->config.boot.osimage, mic->name)) {
		mpsslog(PINFO, "%s: Boot aborted - %s is not a valid Linux bzImage\n",
				mic->name, mic->config.boot.osimage);
		goto bootexit;
	}

	if ((errmsg = mpss_set_cmdline(mic, brlist, cmdline, NULL)) != NULL) {
		mpsslog(PINFO, "%s: Boot aborted - %s\n", mic->name, errmsg);
		goto bootexit;
	}

	mpsslog(PINFO, "%s: Command line: %s\n", mic->name, cmdline);

	set_log_buf_info(mic);

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	if (mic->config.boot.onstart != TRUE) {
		mpsslog(PINFO, "%s: Not set to autoboot\n", mic->name);
		goto bootmic_done;
	}

	switch (mic->config.rootdev.type) {
	case ROOT_TYPE_RAMFS:
		if (stat(mic->config.rootdev.target, &sbuf) == 0)
			unlink(mic->config.rootdev.target);
		mpsslog(PINFO, "%s: Generate %s\n", mic->name, mic->config.rootdev.target);
		mpssfs_gen_initrd(&mpssenv, mic, &mpssperr);
		mpss_print_elist(&mpssperr, PWARN, mpsslog);
		mpss_clear_elist(&mpssperr);
	case ROOT_TYPE_STATICRAMFS:
		initrd = mic->config.rootdev.target;
		break;

	case ROOT_TYPE_NFS:
	case ROOT_TYPE_SPLITNFS:
	case ROOT_TYPE_PFS:
		initrd = mic->config.filesrc.base.image;
		break;
	}

	if (initrd == NULL) {
		mpsslog(PERROR, "%s Boot aborted - initial ramdisk not set", mic->name);
		goto bootmic_done;
	}

	if (is_upstream_driver()) {
		/* request_firmware() API that is used in the upstream stack
		 * expects the firmware images to be somewhere under /lib/firmware.
		 * We create /lib/firmware/mic/micX/ and place links to micX specific
		 * images under them. */
		snprintf(os_image_path, PATH_MAX, "/lib/firmware/mic/%s", mic->name);
		mpssut_deltree(&mpssenv, os_image_path);

		if (mpssut_mksubtree(&mpssenv, "", os_image_path, 0, 0, 0755)) {
			mpsslog(PERROR, "%s Boot aborted - Failed to create boot directory. %s\n",
				mic->name, strerror(errno));
			goto bootmic_done;
		}

		snprintf(kernel, PATH_MAX, "%s/uos.img", os_image_path);
		snprintf(ramdisk, PATH_MAX, "%s/mic.image", os_image_path);
		if(is_mic_knl(mic))
			snprintf(efiimage, PATH_MAX, "%s/efi.image", os_image_path);

		if (symlink(mic->config.boot.osimage, kernel) < 0) {
			mpsslog(PERROR, "%s Boot aborted - Failed to create symlink for kernel image. %s",
				mic->name, strerror(errno));
			goto bootmic_done;
		}

		if (initrd == NULL || symlink(initrd, ramdisk) < 0) {
			mpsslog(PERROR, "%s Boot aborted - Failed to create symlink for filesystem. %s",
				mic->name, strerror(errno));
			goto bootmic_done;
		}

		if (is_mic_knl(mic) && symlink(mic->config.boot.efiimage, efiimage) < 0) {
			mpsslog(PERROR, "%s Boot aborted - Failed to create symlink for EFI image. %s",
				mic->name, strerror(errno));
			goto bootmic_done;
		}

		if (mpss_setsysfs(mic->name, "bootmode", "linux")) {
			sysfs_rd = mpss_readsysfs(mic->name, "bootmode");
			mpsslog(PERROR, "%s failed to boot. Bootmode = %s\n", mic->name, sysfs_rd);
			free(sysfs_rd);
			goto bootmic_done;
		}

		/* request_firmware doesn't like absolute paths. */
		snprintf(kernel, PATH_MAX, "mic/%s/uos.img", mic->name);
		snprintf(ramdisk, PATH_MAX, "mic/%s/mic.image", mic->name);
		if (is_mic_knl(mic))
			snprintf(efiimage, PATH_MAX, "mic/%s/efi.image", mic->name);

		if (mpss_setsysfs(mic->name, "firmware", kernel)) {
			sysfs_rd = mpss_readsysfs(mic->name, "firmware");
			mpsslog(PERROR, "%s failed to boot. Firmware = %s\n", mic->name, sysfs_rd);
			free(sysfs_rd);
			goto bootmic_done;
		}

		if (mpss_setsysfs(mic->name, "ramdisk", ramdisk)) {
			sysfs_rd = mpss_readsysfs(mic->name, "ramdisk");
			mpsslog(PERROR, "%s failed to boot. Ramdisk = %s\n", mic->name, sysfs_rd);
			free(sysfs_rd);
			goto bootmic_done;
		}

		if (is_mic_knl(mic) && mpss_setsysfs(mic->name, "efiimage", efiimage)) {
			sysfs_rd = mpss_readsysfs(mic->name, "efiimage");
			mpsslog(PERROR, "%s failed to boot. EFI image = %s\n", mic->name, sysfs_rd);
			free(sysfs_rd);
			goto bootmic_done;
		}

		snprintf(boot_string, PATH_MAX, "boot");

	} else {
		snprintf(boot_string, PATH_MAX, "boot:linux:%s:%s", mic->config.boot.osimage, initrd);
	}

	if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
		mpsslog(PERROR, "%s: Cannot access state sysfs entry - skipping\n", mic->name);
		goto bootmic_done;
	}

	if (is_upstream_driver())
		shutdown_str = "shutting_down";
	else
		shutdown_str = "shutdown";

	while (!strcmp(state, shutdown_str)) {
		save = state;

		if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
			mpsslog(PWARN, "%s: Wait for shutdown failed to read state sysfs - try again\n", mic->name);
			state = save;
		} else {
			free(save);
		}

		if (!shutdown_wait--) {
			mpsslog(PWARN, "%s: Wait for shutdown timed out\n", mic->name);
			goto bootmic_done;
		}
		mpsslog(PINFO, "%s: Waiting for shutdown to complete\n", mic->name);
		sleep(1);
	}

	while (!strcmp(state, "resetting")) {
		save = state;
		if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
			mpsslog(PWARN, "%s: Wait for reset failed to read state sysfs - try again\n", mic->name);
			state = save;
		} else {
			free(save);
		}

		if (!reset_wait--) {
			mpsslog(PINFO, "%s: Wait for reset timed out\n", mic->name);
			goto bootmic_done;
		}
		mpsslog(PINFO, "%s: Waiting for reset to complete\n", mic->name);
		sleep(1);
	}

	if (strcmp(state, "ready")) {
		mpsslog(PINFO, "%s: Current state \"%s\" cannot boot card\n", mic->name, state);
		free(state);
		goto bootmic_done;
	}

	free(state);

	if ((err = mpss_setsysfs(mic->name, "state", boot_string)) != 0) {
		mpsslog(PINFO, "%s: Booting failed - cannot set state: %s\n", mic->name, strerror(err));
	} else {
		mpsslog(PINFO, "%s: Booting %s initrd %s\n", mic->name, mic->config.boot.osimage, initrd);
	}

bootmic_done:
	while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
	mpssdi->boot_pth = 0;
	while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
bootexit:
	while (pthread_mutex_lock(&start_lock) != 0);
	start_count--;
	while (pthread_mutex_unlock(&start_lock) != 0);
	pthread_exit(NULL);
}
Esempio n. 30
0
void *
save_crashdump(void *arg)
{
	struct mic_info *mic = (struct mic_info *)arg;
	struct mpssd_info *mpssdi = (struct mpssd_info *)mic->data;
	int cdfd = -1;
	int procfd = -1;
	void *addr = NULL;
	ssize_t bytes;
	ssize_t total_bytes = 0;
	ssize_t dirlimit;
	ssize_t diractual;
	struct tm *tm = NULL;
	char pathname[PATH_MAX];
	time_t t;
	pid_t pid1 = 0;
	char *state;
	char *save;
	struct stat sbuf;
	struct statvfs vbuf;
	int err;

	pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
	pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);

	if ((dirlimit = atoi(CD_LIMIT) * (1024 * 1024 * 1024ULL)) == 0) {
		mpsslog(PWARN, "%s: [SaveCrashDump] Dump disabled\n", mic->name);
		goto reboot;
	}

	if (stat(CD_DIR, &sbuf) < 0) {
		if (mkdir(CD_DIR, 0755) < 0) {
			mpsslog(PWARN, "%s: [SaveCrashDump] Avborted - create directory %s failed: %s\n",
					mic->name, CD_DIR, strerror(errno));
			goto reboot;
		}

		diractual = dirlimit;
	} else {	/* Check size of crash directory with configured limits */
		if ((diractual = get_dir_size(mic, CD_DIR)) < 0) {
			mpsslog(PINFO, "%s: [SaveCrashDump] Avborted - get directory %s size failed: %s\n",
					mic->name, CD_DIR, strerror(errno));
			goto reboot;
		}
	}

	if (diractual > dirlimit) {
		mpsslog(PINFO, "%s: [SaveCrashDump] Avborted - %s current size 0x%lx configured limit 0x%lx\n",
			mic->name, CD_DIR, diractual, dirlimit);
		goto reboot;
	}

	/* Open core dump file with time details embedded in file name */
	time(&t);
	if ((tm = localtime(&t)) == 0) {
		mpsslog(PERROR, "%s: [SaveCrashdump] Aborted - get system date failed\n", mic->name);
		goto reboot;
	}

	/* Create crash directories if not done already */
	snprintf(pathname, PATH_MAX - 1, "%s/%s", CD_DIR, mic->name);
	if (mkdir(pathname, 0755) && errno != EEXIST) {
		mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - create directory %s failed %s\n",
					mic->name, pathname, strerror(errno));
		goto reboot;
	}

	if (statvfs(pathname, &vbuf) < 0) {
		mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - cannot read free disk size of %s: %s\n",
					mic->name, pathname, strerror(errno));
		goto reboot;
	}

	if (CD_MIN_DISK > (vbuf.f_bsize * vbuf.f_bfree)) {
		mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - free disk space less than required 32Gb\n", mic->name);
		goto reboot;
	}

	/* Open vmcore entry for crashed card */
	snprintf(pathname, PATH_MAX - 1, "/proc/mic_vmcore/%s", mic->name);
	if ((procfd = open(pathname, O_RDONLY)) < 0) {
		mpsslog(PERROR, "%s: [SaveCrashdump] Aborted - open %s failed: %s\n",
					mic->name, pathname, strerror(errno));
		goto reboot;
	}

	snprintf(pathname, PATH_MAX - 1, "%s/%s/vmcore-%d-%d-%d-%d:%d:%d", CD_DIR, mic->name,
			tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
			tm->tm_hour, tm->tm_min, tm->tm_sec);

	if ((cdfd = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) < 0) {
		mpsslog(PERROR, "%s: [SaveCrashDump] Aborted - open %s failed %s\n",
					mic->name, pathname, strerror(errno));
		goto cleanup1;
	}

	mpsslog(PINFO, "%s: [SaveCrashDump] Capturing uOS kernel crash dump\n", mic->name);

	/* Read from the proc entry and write to the core dump file */
	do {
		if (lseek(cdfd, CD_READ_CHUNK, SEEK_CUR) < 0) {
			mpsslog(PERROR, "%s: [SaveCrashDump] Aborted lseek failed %s\n", mic->name, strerror(errno));
			remove(pathname);
			goto cleanup2;
		}

		bytes = write(cdfd, "", 1);
		if (bytes != 1) {
			mpsslog(PERROR, "%s: [SaveCrashDump] Aborted write failed %s\n", mic->name, strerror(errno));
			remove(pathname);
			goto cleanup2;
		}

		if ((addr = mmap(NULL, CD_READ_CHUNK, PROT_READ|PROT_WRITE,
					MAP_SHARED, cdfd, total_bytes)) == MAP_FAILED) {
			mpsslog(PERROR, "%s: [SaveCrasdDump] Aborted mmap failed %s\n", mic->name, strerror(errno));
			remove(pathname);
			goto cleanup2;
		}

		if ((bytes = read(procfd, addr, CD_READ_CHUNK)) < 0) {
			mpsslog(PERROR, "%s: [SaveCrashDump] Aborted read failed %s\n", mic->name, strerror(errno));
			remove(pathname);
			munmap(addr, CD_READ_CHUNK);
			goto cleanup2;
		}

		total_bytes += bytes;
		munmap(addr, CD_READ_CHUNK);
		if (ftruncate(cdfd, total_bytes + 1) < 0) {
			mpsslog(PERROR, "%s: [SaveCrashDump] Aborted ftruncate failed %s\n", mic->name, strerror(errno));
			remove(pathname);
			goto cleanup2;
		}
	} while (bytes == CD_READ_CHUNK);

	mpsslog(PNORM, "%s: [SaveCrashDump] Completed raw dump size 0x%lx\n", mic->name, total_bytes);
	mpsslog(PNORM, "%s: [SaveCrashDump] Gzip started\n", mic->name);
	pid1 = gzip(pathname); /* Initiate compression of the file and reset MIC in parallel */


cleanup2:
	close(cdfd);

cleanup1:
	close(procfd);

reboot:
	if ((err = mpss_setsysfs(mic->name, "state", "reset:force")) != 0) {
		mpsslog(PINFO, "%s: [SaveCrashDump] Failed to set state sysfs - cannot reset: %s\n",
				mic->name, strerror(err));
		goto done;
	}

	if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
		mpsslog(PINFO, "%s: [SaveCrashDump] Failed to read state sysfs - state of reset unknown\n", mic->name);
		goto done;
	}

	while (strcmp(state, "ready") && strcmp(state, "reset failed")) {
		if (!strcmp(state, "online") || !strcmp(state, "booting")) {
			mpsslog(PINFO, "%s: [SaveCrashDump] External entity has already rebooted card\n", mic->name);
			free(state);
			goto done;
		}

		mpsslog(PINFO, "%s: [SaveCrashDump] Waiting for reset\n", mic->name);
		sleep(2);
		save = state;

		if ((state = mpss_readsysfs(mic->name, "state")) == NULL) {
			mpsslog(PWARN, "%s: [SaveCrashDump] wait for ready failed to read state sysfs - try again\n",
					mic->name);
			state = save;
		} else {
			free(save);
		}
	}

	if (strcmp(state, "ready")) {
		mpsslog(PERROR, "%s: [SaveCrashDump] Failed to reset card.  Aborting reboot\n", mic->name);
		free(state);
		goto done;
	}

	if (pid1 && (pid1 < 0 || ((waitpid(pid1, NULL, 0)) < 0)))
		remove(pathname);

	if (autoreboot(mic)) {
		while (pthread_mutex_lock(&start_lock) != 0);
		start_count++;
		while (pthread_mutex_lock(&mpssdi->pth_lock) != 0);
		pthread_create(&mpssdi->boot_pth, NULL, boot_mic, mic);
		while (pthread_mutex_unlock(&mpssdi->pth_lock) != 0);
		while (pthread_mutex_unlock(&start_lock) != 0);
	}
done:
	pthread_exit(NULL);
}