Example #1
0
/**
 * remove_lmbs
 *
 * @param nr_lmbs
 * @param lmb_list
 * @return 0 on success, !0 otherwise
 */
static int remove_lmbs(struct lmb_list_head *lmb_list)
{
	struct dr_node *lmb_head = lmb_list->lmbs;
	struct dr_node *lmb;
	int rc;

	while (lmb_list->lmbs_modified < usr_drc_count) {
		if (drmgr_timed_out())
			break;

		lmb = get_available_lmb(lmb_head);
		if (!lmb)
			return -1;

		/* Iterate only over the remaining LMBs */
		lmb_head = lmb->next;

		rc = set_lmb_state(lmb, OFFLINE);
		if (rc) {
			lmb->unusable = 1;
			continue;
		}

		rc = remove_device_tree_lmb(lmb, lmb_list);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			set_lmb_state(lmb, ONLINE);
			lmb->unusable = 1;
			continue;
		}

		while (lmb->lmb_mem_scns) {
			struct mem_scn *scn = lmb->lmb_mem_scns;
			lmb->lmb_mem_scns = scn->next;
			free(scn);
		}

		rc = release_drc(lmb->drc_index, 0);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			add_device_tree_lmb(lmb, lmb_list);
			set_lmb_state(lmb, ONLINE);
			lmb->unusable = 1;
			continue;
		}

		lmb->is_removable = 0;
		lmb_list->lmbs_modified++;
	}

	return 0;
}
Example #2
0
int
pci_remove_device(struct dr_node *node)
{
	int rc = 0;
	FILE *file;
	char path[DR_PATH_MAX];
	int wait_time = 0;

	sprintf(path, "%s/%s", node->sysfs_dev_path, "remove");
	file = fopen(path, "w");
	if (file == NULL) {
		say(ERROR, "failed to open %s: %s\n", path, strerror(errno));
		return -ENODEV;
	}

	rc = fwrite("1", 1, 1, file);
	if (rc != 1)
		rc = -EACCES;

	fclose(file);

	if (rc == -EACCES)
		return rc;

	do {
		struct stat sb;

		rc = stat(node->sysfs_dev_path, &sb);
		if (rc) {
			rc = -errno;
		} else {
			say(DEBUG,
				"waiting for PCI device driver to quiesce device at %s\n",
				node->sysfs_dev_path);
			sleep(1);
		}
	} while (rc == 0 &&
		 (++wait_time < PCI_REMOVE_TIMEOUT_MAX && !drmgr_timed_out()));

	if (rc == 0) {
		say(ERROR, "timeout while quiescing device at %s\n",
			node->sysfs_dev_path);
		rc = -EBUSY;
	} else if (rc == -ENOENT) {
		/* sysfs entries cleaned up as part of device removal */
		rc = 0;
	}

	return rc;
}
Example #3
0
/**
 * add_lmbs
 *
 * Attempt to acquire and online the given number of LMBs.
 * This function calls itself recursively to simplify recovery
 * actions in case of an error.  This is intended only for the case
 * where the user does not specify a drc-name.
 *
 * @param nr_lmbs number of lmbs to add
 * @param lmb_list list of lmbs on the partition
 * @returns 0 on success, !0 otherwise
 */
static int add_lmbs(struct lmb_list_head *lmb_list)
{
	int rc = 0;
	struct dr_node *lmb_head = lmb_list->lmbs;
	struct dr_node *lmb;

	lmb_list->lmbs_modified = 0;
	while (lmb_list->lmbs_modified < usr_drc_count) {
		if (drmgr_timed_out())
			break;

		lmb = get_available_lmb(lmb_head);
		if (lmb == NULL)
			return -1;

		/* Iterate only over the remaining LMBs */
		lmb_head = lmb->next;

		rc = acquire_drc(lmb->drc_index);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			lmb->unusable = 1;
			continue;
		}

		rc = add_device_tree_lmb(lmb, lmb_list);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			release_drc(lmb->drc_index, MEM_DEV);
			lmb->unusable = 1;
			continue;
		}

		rc = set_lmb_state(lmb, ONLINE);
		if (rc) {
			report_unknown_error(__FILE__, __LINE__);
			remove_device_tree_lmb(lmb, lmb_list);
			release_drc(lmb->drc_index, MEM_DEV);
			lmb->unusable = 1;
			continue;
		}

		lmb_list->lmbs_modified++;
	}

	return rc;
}
Example #4
0
/**
 * dr_lock
 * @brief Attempt to lock a token
 *
 * This will attempt to lock a token (either file or directory) and wait
 * a specified amount of time if the lock cannot be granted.
 *
 * @returns lock id if successful, -1 otherwise
 */
int dr_lock(void)
{
	struct flock    dr_lock_info;
	int             rc;
	mode_t          old_mode;
	int             first_try = 1;

	old_mode = umask(0);
	dr_lock_fd = open(DR_LOCK_FILE, O_RDWR | O_CREAT,
			  S_IRUSR | S_IRGRP | S_IROTH);
	if (dr_lock_fd < 0)
		return -1;

	umask(old_mode);
	dr_lock_info.l_type = F_WRLCK;
	dr_lock_info.l_whence = SEEK_SET;
	dr_lock_info.l_start = 0;
	dr_lock_info.l_len = 0;

	do {
		if (!first_try) {
			sleep(1);
			first_try = 0;
		}

		rc = fcntl(dr_lock_fd, F_SETLK, &dr_lock_info);
		if (rc != -1)
			return 0;

		if (drmgr_timed_out())
			break;

		if (rc == -1 && errno == EACCES)
			continue;

	} while (1);

	close(dr_lock_fd);
	dr_lock_fd = 0;
	perror(DR_LOCK_FILE);
	return -1;
}
/**
 * dlpar_io_kernel_op
 * @brief access kernel interface files
 *
 * @param interface_file
 * @param drc_name
 * @returns 0 on success, !0 otherwise
 */
static int dlpar_io_kernel_op(const char *interface_file, const char *drc_name)
{
	int rc = 0, len;
	FILE *file;

	len = strlen(drc_name);
	say(DEBUG, "performing kernel op for %s, file is %s\n", drc_name,
	    interface_file);

	do {
		errno = 0;

    		file = fopen(interface_file, "r+");
    		if (file == NULL) {
			say(ERROR, "failed to open %s: %s\n", interface_file,
			    strerror(errno));
			return -ENODEV;
    		}

    		rc = fwrite(drc_name, 1, len, file);
		fclose(file);

		sleep(1);
		if (drmgr_timed_out())
			return -1;
	} while (errno == EBUSY);

 	if (errno || (rc != len)) {
		say(ERROR, "kernel I/O op failed, rc = %d len = %d.\n%s\n",
		    rc, len, strerror(errno));

		return errno ? errno : rc;
	}

	return 0;
}