mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-02-19 20:27:01 +00:00
[MEDIUM] splice: set the capability on each stream_interface
The splice code did not consider compatibility between both ends of the connection. Now we set different capabilities on each stream interface, depending on what the protocol can splice to/from. Right now, only TCP is supported. Thanks to this, we're now able to automatically detect when splice() is not implemented and automatically disable it on one end instead of reporting errors to the upper layer.
This commit is contained in:
parent
1a52dbda59
commit
dc340a900d
@ -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 */
|
||||
|
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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) &&
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user