Beispiel #1
0
static int
np_fdtrans_recv(Npfcall **fcp, u32 msize, void *a)
{
	Fdtrans *fdt = (Fdtrans *)a;
	Npfcall *fc = NULL;
	int n, size, len;

	if (fdt->fc) {
		assert (fdt->fc_msize >= msize);
		fc = fdt->fc;
		len = fdt->fc->size;
		fdt->fc = NULL;
		size = np_peek_size (fc->pkt, len);
	} else {
		if (!(fc = np_alloc_fcall (msize))) {
			np_uerror (ENOMEM);
			goto error;
		}
		len = 0;
		size = 0;
	}
	while (len < size || len < 4) {
		n = read(fdt->fdin, fc->pkt + len, msize - len);
		if (n < 0) {
			np_uerror (errno);
			goto error;
		}	
		if (n == 0) {	/* EOF */
			free (fc);
			fc = NULL;
			goto done;
		}
		len += n;
		if (size == 0)
			size = np_peek_size(fc->pkt, len);
		if (size > msize) {
			np_uerror(EPROTO);
			goto error;
		}
	}
	if (len > size) {
		if (!(fdt->fc = np_alloc_fcall (msize))) {
			np_uerror(ENOMEM);
			goto error;
		}
		fdt->fc_msize = msize;
		memcpy (fdt->fc->pkt, fc->pkt + size, len - size);
		fdt->fc->size = len - size;
	}
	fc->size = size;
done:
	*fcp = fc;
	return 0;
error:
	if (fc)
		free (fc);
	return -1;
}
Beispiel #2
0
static int
rdma_trans_recv(Npfcall **fcp, u32 msize, void *a)
{
	int n, ret, closing = 0;
	struct ibv_cq *cq;
	struct ibv_wc wc;
	void *context;
	Rdmatrans *rdma = (Rdmatrans *)a;
	Rdmactx *ctx;
	Npfcall *fc = NULL;

	if (!(fc = np_alloc_fcall (msize))) {
		np_uerror(ENOMEM);
		return -1;
	}
	pthread_mutex_lock(&rdma->lock);
again:
	if (rdma->rfirst) {
		ctx = rdma->rfirst;

		n = ctx->len - ctx->pos;
		if (n > msize)
			n = msize;

		memmove(fc->pkt, ctx->buf + ctx->pos, n);
		ctx->pos += n;
		if (ctx->pos == ctx->len) {
			rdma->rfirst = ctx->next;
			if (ctx == rdma->rlast)
				rdma->rlast = NULL;

			rdma_post_recv(rdma, ctx);
		}

		pthread_mutex_unlock(&rdma->lock);
		fc->size = n;
		*fcp = fc;
		return 0;
	}

	pthread_mutex_unlock(&rdma->lock);

poll:
	ret = ibv_get_cq_event(rdma->ch, &cq, &context);
	if (ret) {
		np_uerror(ret);
		//fprintf(stderr, "Error %d polling cq\n", ret);
		return -1;
	}
	ibv_ack_cq_events(rdma->cq, 1);

	ibv_req_notify_cq(cq, 0);
	while ((ret = ibv_poll_cq(rdma->cq, 1, &wc)) > 0) {
		/* Check if it's a flush */
		if (wc.status != IBV_WC_SUCCESS) {
			//fprintf(stderr, "cq fail: status %d opcode %d\n",
			//	wc.status, wc.opcode);
			closing = 1;
			continue;
		}

		if (wc.opcode == IBV_WC_RECV) {
			ctx = (Rdmactx *) wc.wr_id;
			pthread_mutex_lock(&rdma->lock);
			ctx->used = 0;
			ctx->len = wc.byte_len;
			ctx->pos = 0;
			if (rdma->rlast)
				rdma->rlast->next = ctx;
			else
				rdma->rfirst = ctx;

			rdma->rlast = ctx;
			ctx->next = NULL;
			goto again;
		} else if (wc.opcode == IBV_WC_SEND) {
			ctx = (Rdmactx *) wc.wr_id;
			pthread_mutex_lock(&rdma->lock);
			ctx->used = 0;
			pthread_cond_signal(&rdma->cond);
			pthread_mutex_unlock(&rdma->lock);
		}
	}

	if (!ret && !closing)
		goto poll;

	np_uerror(ret);
	return -1;
}