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