示例#1
0
int netfs_trans_send(struct netfs_trans *t, struct netfs_state *st)
{
	int err;
	struct msghdr msg;

	BUG_ON(!t->iovec.iov_len);
	BUG_ON(t->iovec.iov_len > 1024*1024*1024);

	netfs_state_lock_send(st);
	if (!st->socket) {
		err = netfs_state_init(st);
		if (err)
			goto err_out_unlock_return;
	}

	msg.msg_iov = &t->iovec;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = NULL;
	msg.msg_controllen = 0;
	msg.msg_flags = MSG_WAITALL;

	if (t->attached_pages)
		msg.msg_flags |= MSG_MORE;

	err = kernel_sendmsg(st->socket, &msg, (struct kvec *)msg.msg_iov, 1, t->iovec.iov_len);
	if (err <= 0) {
		printk("%s: failed to send contig transaction: t: %p, gen: %u, size: %zu, err: %d.\n",
				__func__, t, t->gen, t->iovec.iov_len, err);
		if (err == 0)
			err = -ECONNRESET;
		goto err_out_unlock_return;
	}

	dprintk("%s: sent %s transaction: t: %p, gen: %u, size: %zu, page_num: %u.\n",
			__func__, (t->page_num)?"partial":"full",
			t, t->gen, t->iovec.iov_len, t->page_num);

	err = 0;
	if (t->attached_pages)
		err = netfs_trans_send_pages(t, st);

err_out_unlock_return:

	if (st->need_reset)
		netfs_state_exit(st);

	netfs_state_unlock_send(st);

	dprintk("%s: t: %p, gen: %u, err: %d.\n",
		__func__, t, t->gen, err);

	t->result = err;
	return err;
}
示例#2
0
static int pohmelfs_data_recv(struct netfs_state *st, void *data, unsigned int size)
{
	unsigned int revents = 0;
	unsigned int err_mask = POLLERR | POLLHUP | POLLRDHUP;
	unsigned int mask = err_mask | POLLIN;
	int err = 0;

	while (size && !err) {
		revents = netfs_state_poll(st);

		if (!(revents & mask)) {
			DEFINE_WAIT(wait);

			for (;;) {
				prepare_to_wait(&st->thread_wait, &wait, TASK_INTERRUPTIBLE);
				if (kthread_should_stop())
					break;

				revents = netfs_state_poll(st);

				if (revents & mask)
					break;

				if (signal_pending(current))
					break;

				schedule();
				continue;
			}
			finish_wait(&st->thread_wait, &wait);
		}

		err = 0;
		netfs_state_lock(st);
		if (st->socket && (st->read_socket == st->socket) && (revents & POLLIN)) {
			err = netfs_data_recv(st, data, size);
			if (err > 0) {
				data += err;
				size -= err;
				err = 0;
			} else if (err == 0)
				err = -ECONNRESET;
		}

		if (revents & err_mask) {
			printk("%s: revents: %x, socket: %p, size: %u, err: %d.\n",
					__func__, revents, st->socket, size, err);
			err = -ECONNRESET;
		}
		netfs_state_unlock(st);

		if (err < 0) {
			if (netfs_state_trylock_send(st)) {
				netfs_state_exit(st);
				err = netfs_state_init(st);
				if (!err)
					err = -EAGAIN;
				netfs_state_unlock_send(st);
			} else {
				st->need_reset = 1;
			}
		}

		if (kthread_should_stop())
			err = -ENODEV;

		if (err)
			printk("%s: socket: %p, read_socket: %p, revents: %x, rev_error: %d, "
					"should_stop: %d, size: %u, err: %d.\n",
				__func__, st->socket, st->read_socket,
				revents, revents & err_mask, kthread_should_stop(), size, err);
	}

	return err;
}