From: Willy Tarreau <w@1wt.eu>
To: Andi Kleen <andi@firstfloor.org>, linux-kernel@vger.kernel.org
Subject: Re: splice() on two pipes
Date: Thu, 30 Apr 2009 06:56:47 +0200 [thread overview]
Message-ID: <20090430045645.GF570@1wt.eu> (raw)
In-Reply-To: <20090429194254.GA7956@squirrel.roonstrasse.net>
[-- Attachment #1: Type: text/plain, Size: 1487 bytes --]
On Wed, Apr 29, 2009 at 09:42:55PM +0200, Max Kellermann wrote:
> On 2009/04/29 17:23, Andi Kleen <andi@firstfloor.org> wrote:
> > I don't think splice is about handling all possible cases,
> > but just cases where the kernel can do better than user space.
> > I don't think that's the case here.
>
> If splice() is about passing pointers of a pipe buffer, what's more
> trivial (and natural) than passing that pointer between two pipes?
>
> > > when I read about the splice() system call, I thought it was obvious
> > > that it could copy data between two pipes.
> >
> > It would be more efficient if you used fd passing to pass the fd
> > around to the other process and let it read directly.
>
> That's not so easy in my case. The header output of the one process
> has to be parsed before the rest of it (or part of the rest) is going
> to be forwarded to the second one. My master process would lose
> control over the transfer. splice() looks like the perfect solution.
indeed, that could make sense. From what I have seen in the splicing
code, I think tht implementing pipe to pipe should not be *that* hard,
starting from existing code (eg: net to pipe). Maybe you could try to
implement it since you have the code which makes use of it ? I think
it is the kind of feature which can only improve step by step based
on application needs.
BTW, I like your test program. Simple and easy. I have completed it to
test tcp and udp, you can find it attached.
Regards,
Willy
[-- Attachment #2: test_splice.c --]
[-- Type: text/plain, Size: 3240 bytes --]
/*
* Copyright (C) 2009 Max Kellermann <max@duempel.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*/
/*
* This tiny program prints a matrix: which file descriptor
* combinations are supported by splice()?
*/
#define _GNU_SOURCE
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
static struct {
const char *const name;
int in, out;
} fds[] = {
{ .name = "pipe", },
{ .name = "reg", },
{ .name = "chr", },
{ .name = "unix", },
{ .name = "tcp", },
{ .name = "udp", },
};
enum {
NUM_FDS = sizeof(fds) / sizeof(fds[0]),
};
int main(int argc, char **argv)
{
int f[2], ret;
unsigned x, y;
char template1[] = "/tmp/test_splice.XXXXXX";
char template2[] = "/tmp/test_splice.XXXXXX";
(void)argc;
(void)argv;
/* open two file descriptors of each kind */
fds[0].in = pipe(f) >= 0 ? f[0] : -1;
fds[0].out = pipe(f) >= 0 ? f[1] : -1;
fds[1].in = mkstemp(template1);
fds[1].out = mkstemp(template2);
fds[2].in = open("/dev/zero", O_RDONLY);
fds[2].out = open("/dev/null", O_WRONLY);
fds[3].in = socketpair(AF_UNIX, SOCK_STREAM, 0, f) >= 0 ? f[0] : -1;
fds[3].out = socketpair(AF_UNIX, SOCK_STREAM, 0, f) >= 0 ? f[0] : -1;
fds[4].in = socket(AF_INET, SOCK_STREAM, 0);
fds[4].out = socket(AF_INET, SOCK_STREAM, 0);
fds[5].in = socket(AF_INET, SOCK_DGRAM, 0);
fds[5].out = socket(AF_INET, SOCK_DGRAM, 0);
/* print table header */
printf("in\\out");
for (x = 0; x < NUM_FDS; ++x)
printf("\t%s", fds[x].name);
putchar('\n');
for (y = 0; y < NUM_FDS; ++y) {
fputs(fds[y].name, stdout);
for (x = 0; x < NUM_FDS; ++x) {
putchar('\t');
if (fds[x].out < 0 || fds[y].in < 0) {
fputs("n/a", stdout);
continue;
}
ret = splice(fds[y].in, NULL, fds[x].out, NULL, 1,
SPLICE_F_NONBLOCK);
if (ret >= 0 || errno == EAGAIN || errno == EWOULDBLOCK
|| errno == ENOTCONN)
/* EAGAIN or EWOULDBLOCK means that the kernel has
accepted this combination, but can't move pages
right now */
fputs("yes", stdout);
else if (errno == EINVAL)
/* the kernel doesn't support this combination */
fputs("no", stdout);
else if (errno == ENOSYS)
/* splice() isn't supported at all */
fputs("ENOSYS", stdout);
else
/* an unexpected error code */
fputs("err", stdout);
}
putchar('\n');
}
unlink(template1);
unlink(template2);
}
next prev parent reply other threads:[~2009-04-30 4:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-29 10:33 splice() on two pipes Max Kellermann
2009-04-29 15:23 ` Andi Kleen
2009-04-29 19:42 ` Max Kellermann
2009-04-30 4:56 ` Willy Tarreau [this message]
2009-04-30 14:26 ` Mark Hills
2009-04-30 6:21 ` Jens Axboe
2009-04-30 6:42 ` Max Kellermann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090430045645.GF570@1wt.eu \
--to=w@1wt.eu \
--cc=andi@firstfloor.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.