示例#1
0
/**
 * zfcp_sg_setup_table - init scatterlist and allocate, assign buffers
 * @sg: pointer to struct scatterlist
 * @count: number of scatterlists which should be assigned with buffers
 * of size page
 *
 * Returns: 0 on success, -ENOMEM otherwise
 */
int zfcp_sg_setup_table(struct scatterlist *sg, int count)
{
	void *addr;
	int i;

	sg_init_table(sg, count);
	for (i = 0; i < count; i++, sg++) {
		addr = (void *) get_zeroed_page(GFP_KERNEL);
		if (!addr) {
			zfcp_sg_free_table(sg, i);
			return -ENOMEM;
		}
		sg_set_buf(sg, addr, PAGE_SIZE);
	}
	return 0;
}
示例#2
0
static int zfcp_cfdc_sg_setup(int command, struct scatterlist *sg,
			      u8 __user *control_file)
{
	int retval;
	retval = zfcp_sg_setup_table(sg, ZFCP_CFDC_PAGES);
	if (retval)
		return retval;

	sg[ZFCP_CFDC_PAGES - 1].length = ZFCP_CFDC_MAX_SIZE % PAGE_SIZE;

	if (command & ZFCP_CFDC_WITH_CONTROL_FILE &&
	    command & ZFCP_CFDC_DOWNLOAD) {
		retval = zfcp_cfdc_copy_from_user(sg, control_file);
		if (retval) {
			zfcp_sg_free_table(sg, ZFCP_CFDC_PAGES);
			return -EFAULT;
		}
	}

	return 0;
}
示例#3
0
static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command,
				unsigned long arg)
{
	struct zfcp_cfdc_data *data;
	struct zfcp_cfdc_data __user *data_user;
	struct zfcp_adapter *adapter;
	struct zfcp_fsf_req *req;
	struct zfcp_fsf_cfdc *fsf_cfdc;
	int retval;

	if (command != ZFCP_CFDC_IOC)
		return -ENOTTY;

	if (is_compat_task())
		data_user = compat_ptr(arg);
	else
		data_user = (void __user *)arg;

	if (!data_user)
		return -EINVAL;

	fsf_cfdc = kmalloc(sizeof(struct zfcp_fsf_cfdc), GFP_KERNEL);
	if (!fsf_cfdc)
		return -ENOMEM;

	data = kmalloc(sizeof(struct zfcp_cfdc_data), GFP_KERNEL);
	if (!data) {
		retval = -ENOMEM;
		goto no_mem_sense;
	}

	retval = copy_from_user(data, data_user, sizeof(*data));
	if (retval) {
		retval = -EFAULT;
		goto free_buffer;
	}

	if (data->signature != 0xCFDCACDF) {
		retval = -EINVAL;
		goto free_buffer;
	}

	retval = zfcp_cfdc_set_fsf(fsf_cfdc, data->command);

	adapter = zfcp_cfdc_get_adapter(data->devno);
	if (!adapter) {
		retval = -ENXIO;
		goto free_buffer;
	}

	retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg,
				    data_user->control_file);
	if (retval)
		goto adapter_put;
	req = zfcp_fsf_control_file(adapter, fsf_cfdc);
	if (IS_ERR(req)) {
		retval = PTR_ERR(req);
		goto free_sg;
	}

	if (req->status & ZFCP_STATUS_FSFREQ_ERROR) {
		retval = -ENXIO;
		goto free_fsf;
	}

	zfcp_cfdc_req_to_sense(data, req);
	retval = copy_to_user(data_user, data, sizeof(*data_user));
	if (retval) {
		retval = -EFAULT;
		goto free_fsf;
	}

	if (data->command & ZFCP_CFDC_UPLOAD)
		retval = zfcp_cfdc_copy_to_user(&data_user->control_file,
						fsf_cfdc->sg);

 free_fsf:
	zfcp_fsf_req_free(req);
 free_sg:
	zfcp_sg_free_table(fsf_cfdc->sg, ZFCP_CFDC_PAGES);
 adapter_put:
	zfcp_ccw_adapter_put(adapter);
 free_buffer:
	kfree(data);
 no_mem_sense:
	kfree(fsf_cfdc);
	return retval;
}