Subject: Re: Sample splice(2) via kcont(9), work-in-progress towards
To: None <jonathan@dsg.stanford.edu>
From: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
List: tech-net
Date: 10/06/2005 19:12:56
hi,

> Before any thought of committing, I'd want to rework the API, to split
> the overloaded length/flags arguments into two separate arguments: an
> int for flags, and a u_long or off_t for the size to copy.  (though
> the length was, historically, for UDP/record traffic...)
> Oh, and the syscall numbers are for illustration only.

i don't think u_long is appropriate.

> +	/*
> +	 * XXX JRS: try instead
> +	 * (*from->so_recv)(from, &nam, &uio, &top, (struct mbuf**)0, &flags)
> +	 * as in sys/nfs/nfs_socket.c
> +	 */
> +	error = soreceive(from,  /* &paddr */ NULL,  &uio,
> +		  &top, /*controlp*/ NULL, &rcvflags);
> +#if defined(DEBUG)
> +	printf("asked for %ld got resid %ld\n", space, (long)uio.uio_resid);
> +#endif

i don't think it's safe to do soreceive from this context.

> +	if (error != 0 || top == NULL) {
> +		printf("splice: after recv, error = %d, top = %p\n",
> +		       error, top);
> +		soshutdown(from, SHUT_RDWR);
> +		soshutdown(to, SHUT_RDWR);
> +		goto done;
> +	}

why shutdown sockets here?  i don't think it's safe.

> +	/* send it ... */
> +#if 0
> +	error = (*to->so_send)(to, (struct mbuf*)NULL, (struct uio *)NULL,
> +			       top, NULL, 0, p);
> +#else
> +		s = splsoftnet();
> +		error = (*to->so_proto->pr_usrreq)(to, PRU_SEND, top, NULL, NULL, p);
> +	splx(s);
> +#endif

we should be already at splsoftnet.

> +	sblock(&so1->so_snd, M_WAITOK);
> +	sblock(&so2->so_snd, M_WAITOK);

you should unlock these later.

> +	/* wire up socket upcalls */
> +	s = splnet();

afaik splsoftnet() is enough.

> +	/* wait until both sockets are done */
> +	tsleep((caddr_t)knot, PSOCK, spliceio, 0);

it's racy.

YAMAMOTO Takashi