Ejemplo n.º 1
0
static int sg_io(struct request_queue *q, struct gendisk *bd_disk,
		struct sg_io_hdr *hdr, fmode_t mode)
{
	unsigned long start_time;
	ssize_t ret = 0;
	int writing = 0;
	int at_head = 0;
	struct request *rq;
	char sense[SCSI_SENSE_BUFFERSIZE];
	struct bio *bio;

	if (hdr->interface_id != 'S')
		return -EINVAL;

	if (hdr->dxfer_len > (queue_max_hw_sectors(q) << 9))
		return -EIO;

	if (hdr->dxfer_len)
		switch (hdr->dxfer_direction) {
		default:
			return -EINVAL;
		case SG_DXFER_TO_DEV:
			writing = 1;
			break;
		case SG_DXFER_TO_FROM_DEV:
		case SG_DXFER_FROM_DEV:
			break;
		}
	if (hdr->flags & SG_FLAG_Q_AT_HEAD)
		at_head = 1;

	ret = -ENOMEM;
	rq = blk_get_request(q, writing ? WRITE : READ, GFP_KERNEL);
	if (IS_ERR(rq))
		return PTR_ERR(rq);
	blk_rq_set_block_pc(rq);

	if (hdr->cmd_len > BLK_MAX_CDB) {
		rq->cmd = kzalloc(hdr->cmd_len, GFP_KERNEL);
		if (!rq->cmd)
			goto out_put_request;
	}

	ret = -EFAULT;
	if (blk_fill_sghdr_rq(q, rq, hdr, mode))
		goto out_free_cdb;

	ret = 0;
	if (hdr->iovec_count) {
		struct iov_iter i;
		struct iovec *iov = NULL;

		ret = rw_copy_check_uvector(-1, hdr->dxferp, hdr->iovec_count,
					    0, NULL, &iov);
		if (ret < 0) {
			kfree(iov);
			goto out_free_cdb;
		}

		/* SG_IO howto says that the shorter of the two wins */
		iov_iter_init(&i, rq_data_dir(rq), iov, hdr->iovec_count,
			      min_t(unsigned, ret, hdr->dxfer_len));

		ret = blk_rq_map_user_iov(q, rq, NULL, &i, GFP_KERNEL);
		kfree(iov);
	} else if (hdr->dxfer_len)
Ejemplo n.º 2
0
static ssize_t scribe_do_readv_writev(int type, struct file *file,
				      const struct iovec __user * uvector,
				      unsigned long nr_segs, loff_t *pos)
{
	struct scribe_ps *scribe = current->scribe;
	struct iovec iovstack[UIO_FASTIOV];
	struct iovec *iov = iovstack;
	int force_block = 0;
	ssize_t ret, len = 0;

	if (!is_scribed(scribe))
		return do_readv_writev(type, file, uvector, nr_segs, 0, pos,
				       force_block);

	if (is_kernel_copy())
		goto out;

	if (!should_scribe_data(scribe))
		goto out;

	scribe_need_syscall_ret(scribe);

	if (is_replaying(scribe)) {
		len = scribe->orig_ret;
		if (len <= 0) {
			rw_copy_check_uvector(type, uvector, nr_segs,
					      ARRAY_SIZE(iovstack), iovstack,
					      &iov);
			ret = len;
			goto free;
		}
		force_block = 1;
	}

	if (type == READ) {
		if (is_deterministic(file))
			goto out;

		scribe_data_non_det();

		if (is_recording(scribe))
			goto out;

		rw_copy_check_uvector(type, uvector, nr_segs,
				      ARRAY_SIZE(iovstack), iovstack, &iov);

		ret =  __do_loop_readv_writev(file, iov, nr_segs, len, pos,
					      io_scribe_emul_copy_to_user);
		goto free;
	}

out:
	scribe->in_read_write = true;
	ret = do_readv_writev(type, file, uvector, nr_segs, len, pos,
			      force_block);
	scribe->in_read_write = false;
free:
	if (iov != iovstack)
		kfree(iov);
	return ret;
}