static int process_writes()

in xenbus/xenbus_comms.c [330:403]


static int process_writes(void)
{
	static struct {
		struct xb_req_data *req;
		int idx;
		unsigned int written;
	} state;
	void *base;
	unsigned int len;
	int err = 0;

	if (!xb_data_to_write())
		return 0;

	mutex_lock(&xb_write_mutex);

	if (!state.req) {
		state.req = list_first_entry(&xb_write_list,
					     struct xb_req_data, list);
		state.idx = -1;
		state.written = 0;
	}

	if (state.req->state == xb_req_state_aborted)
		goto out_err;

	while (state.idx < state.req->num_vecs) {
		if (state.idx < 0) {
			base = &state.req->msg;
			len = sizeof(state.req->msg);
		} else {
			base = state.req->vec[state.idx].iov_base;
			len = state.req->vec[state.idx].iov_len;
		}
		err = xb_write(base + state.written, len - state.written);
		if (err < 0)
			goto out_err;
		state.written += err;
		if (state.written != len)
			goto out;

		state.idx++;
		state.written = 0;
	}

	list_del(&state.req->list);
	state.req->state = xb_req_state_wait_reply;
	list_add_tail(&state.req->list, &xs_reply_list);
	state.req = NULL;

 out:
	mutex_unlock(&xb_write_mutex);

	return 0;

 out_err:
	state.req->msg.type = XS_ERROR;
	state.req->err = err;
	list_del(&state.req->list);
	if (state.req->state == xb_req_state_aborted)
		kfree(state.req);
	else {
		/* write err, then update state */
		virt_wmb();
		state.req->state = xb_req_state_got_reply;
		wake_up(&state.req->wq);
	}

	mutex_unlock(&xb_write_mutex);

	state.req = NULL;

	return err;
}