diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h index bb4a9e3b5..f97aa624d 100644 --- a/include/types/stream_interface.h +++ b/include/types/stream_interface.h @@ -67,14 +67,17 @@ enum { SI_FL_ERR = 0x0002, /* a non-recoverable error has occurred */ SI_FL_WAIT_ROOM = 0x0004, /* waiting for space to store incoming data */ SI_FL_WAIT_DATA = 0x0008, /* waiting for more data to send */ + SI_FL_CAP_SPLTCP = 0x0010, /* splicing possible from/to TCP */ }; +#define SI_FL_CAP_SPLICE (SI_FL_CAP_SPLTCP) + struct stream_interface { unsigned int state; /* SI_ST* */ unsigned int prev_state;/* SI_ST*, copy of previous state */ void *owner; /* generally a (struct task*) */ int fd; /* file descriptor for a stream driver when known */ - unsigned int flags; /* SI_FL_*, must be cleared before I/O */ + unsigned int flags; unsigned int exp; /* wake up time for connect, queue, turn-around, ... */ void (*shutr)(struct stream_interface *); /* shutr function */ void (*shutw)(struct stream_interface *); /* shutw function */ diff --git a/src/backend.c b/src/backend.c index 5cea8089b..bf9f78922 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1985,6 +1985,7 @@ int connect_server(struct session *s) EV_FD_SET(fd, DIR_WR); /* for connect status */ s->req->cons->state = SI_ST_CON; + s->req->cons->flags |= SI_FL_CAP_SPLTCP; /* TCP supports splicing */ if (s->srv) { s->flags |= SN_CURR_SESS; s->srv->cur_sess++; diff --git a/src/client.c b/src/client.c index 45c576dd6..3e2099eed 100644 --- a/src/client.c +++ b/src/client.c @@ -190,7 +190,7 @@ int event_accept(int fd) { s->si[0].chk_rcv = stream_sock_chk_rcv; s->si[0].chk_snd = stream_sock_chk_snd; s->si[0].fd = cfd; - s->si[0].flags = SI_FL_NONE; + s->si[0].flags = SI_FL_NONE | SI_FL_CAP_SPLTCP; /* TCP splicing capable */ s->si[0].exp = TICK_ETERNITY; s->si[1].state = s->si[1].prev_state = SI_ST_INI; diff --git a/src/session.c b/src/session.c index 9ea45e1ba..d3f3710c9 100644 --- a/src/session.c +++ b/src/session.c @@ -184,6 +184,7 @@ int sess_update_st_con_tcp(struct session *s, struct stream_interface *si) if (unlikely(si->flags & (SI_FL_EXP|SI_FL_ERR))) { si->exp = TICK_ETERNITY; si->state = SI_ST_CER; + si->flags &= ~SI_FL_CAP_SPLICE; fd_delete(si->fd); if (si->err_type) @@ -207,6 +208,7 @@ int sess_update_st_con_tcp(struct session *s, struct stream_interface *si) si->shutw(si); si->err_type |= SI_ET_CONN_ABRT; si->err_loc = s->srv; + si->flags &= ~SI_FL_CAP_SPLICE; if (s->srv_error) s->srv_error(s, si); return 1; @@ -859,6 +861,7 @@ resync_stream_interface: if (!(s->req->flags & (BF_KERN_SPLICING|BF_SHUTR)) && s->req->to_forward && (global.tune.options & GTUNE_USE_SPLICE) && + (s->si[0].flags & s->si[1].flags & SI_FL_CAP_SPLICE) && (pipes_used < global.maxpipes) && (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_REQ) || (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) && @@ -966,6 +969,7 @@ resync_stream_interface: if (!(s->rep->flags & (BF_KERN_SPLICING|BF_SHUTR)) && s->rep->to_forward && (global.tune.options & GTUNE_USE_SPLICE) && + (s->si[0].flags & s->si[1].flags & SI_FL_CAP_SPLICE) && (pipes_used < global.maxpipes) && (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_RTR) || (((s->fe->options2|s->be->options2) & PR_O2_SPLIC_AUT) && diff --git a/src/stream_sock.c b/src/stream_sock.c index 52305c5e3..438ff0a5e 100644 --- a/src/stream_sock.c +++ b/src/stream_sock.c @@ -186,6 +186,16 @@ static int stream_sock_splice_in(struct buffer *b, struct stream_interface *si) retval = -1; break; } + + if (errno == ENOSYS) { + /* splice not supported on this end, disable it */ + b->flags &= ~BF_KERN_SPLICING; + si->flags &= ~SI_FL_CAP_SPLICE; + put_pipe(b->pipe); + b->pipe = NULL; + return -1; + } + /* here we have another error */ si->flags |= SI_FL_ERR; retval = 1;