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 */
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++;
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;
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)
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;
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) &&
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) &&
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;