From: Willy Tarreau Date: Wed, 6 Jun 2018 04:53:15 +0000 (+0200) Subject: MINOR: channel/buffer: replace buffer_slow_realign() with channel_slow_realign()... X-Git-Tag: v1.9-dev1~157 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4cf1300e6a0127d73bf5fc57df40d8103cc58f82;p=thirdparty%2Fhaproxy.git MINOR: channel/buffer: replace buffer_slow_realign() with channel_slow_realign() and b_slow_realign() Where relevant, the channel version is used instead. The buffer version was ported to be more generic and now takes a swap buffer and the output byte count to know where to set the alignment point. The H2 mux still uses buffer_slow_realign() with buf->o but it will change later. --- diff --git a/include/common/buf.h b/include/common/buf.h index 564e0ebad3..fccad45b2f 100644 --- a/include/common/buf.h +++ b/include/common/buf.h @@ -329,6 +329,47 @@ static inline void b_realign_if_empty(struct buffer *b) b->p = b->data; } +/* b_slow_realign() : this function realigns a possibly wrapping buffer so that + * the part remaining to be parsed is contiguous and starts at the beginning of + * the buffer and the already parsed output part ends at the end of the buffer. + * This provides the best conditions since it allows the largest inputs to be + * processed at once and ensures that once the output data leaves, the whole + * buffer is available at once. The number of output bytes supposedly present + * at the beginning of the buffer and which need to be moved to the end must be + * passed in . A temporary swap area at least as large as b->size must + * be provided in . It's up to the caller to ensure is no larger + * than the difference between the whole buffer's length and its input. + */ +static inline void b_slow_realign(struct buffer *b, char *swap, size_t output) +{ + size_t block1 = output; + size_t block2 = 0; + + /* process output data in two steps to cover wrapping */ + if (block1 > b_size(b) - b_head_ofs(b)) { + block2 = b_size(b) - b_head_ofs(b); + block1 -= block2; + } + memcpy(swap + b_size(b) - output, b_head(b), block1); + memcpy(swap + b_size(b) - block2, b_orig(b), block2); + + /* process input data in two steps to cover wrapping */ + block1 = b_data(b) - output; + block2 = 0; + + if (block1 > b_tail_ofs(b)) { + block2 = b_tail_ofs(b); + block1 = block1 - block2; + } + memcpy(swap, b_peek(b, output), block1); + memcpy(swap + block1, b_orig(b), block2); + + /* reinject changes into the buffer */ + memcpy(b_orig(b), swap, b_data(b) - output); + memcpy(b_wrap(b) - output, swap + b_size(b) - output, output); + + b->p = b->data; +} #endif /* _COMMON_BUF_H */ diff --git a/include/common/buffer.h b/include/common/buffer.h index 0218afa693..3b34267b0c 100644 --- a/include/common/buffer.h +++ b/include/common/buffer.h @@ -52,7 +52,7 @@ void deinit_buffer(); int buffer_replace2(struct buffer *b, char *pos, char *end, const char *str, int len); int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len); void buffer_dump(FILE *o, struct buffer *b, int from, int to); -void buffer_slow_realign(struct buffer *buf); +void buffer_slow_realign(struct buffer *buf, size_t output); /*****************************************************************/ /* These functions are used to compute various buffer area sizes */ diff --git a/include/proto/channel.h b/include/proto/channel.h index 3f30cc0f9c..c7135de010 100644 --- a/include/proto/channel.h +++ b/include/proto/channel.h @@ -701,6 +701,17 @@ static inline void channel_truncate(struct channel *chn) chn->buf->i = 0; } +/* This function realigns a possibly wrapping channel buffer so that the input + * part is contiguous and starts at the beginning of the buffer and the output + * part ends at the end of the buffer. This provides the best conditions since + * it allows the largest inputs to be processed at once and ensures that once + * the output data leaves, the whole buffer is available at once. + */ +static inline void channel_slow_realign(struct channel *chn) +{ + return buffer_slow_realign(chn->buf, co_data(chn)); +} + /* * Advance the channel buffer's read pointer by bytes. This is useful * when data have been read directly from the buffer. It is illegal to call diff --git a/src/buffer.c b/src/buffer.c index b6ece4ba67..becaa1066e 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -172,37 +172,15 @@ int buffer_insert_line2(struct buffer *b, char *pos, const char *str, int len) * contiguous and starts at the beginning of the buffer and the output part * ends at the end of the buffer. This provides the best conditions since it * allows the largest inputs to be processed at once and ensures that once the - * output data leaves, the whole buffer is available at once. + * output data leaves, the whole buffer is available at once. The number of + * output bytes supposedly present at the beginning of the buffer and which + * need to be moved to the end must be passed in . It's up to the + * caller to ensure is no larger than the difference between the + * while buffer's length and its input. */ -void buffer_slow_realign(struct buffer *buf) +void buffer_slow_realign(struct buffer *buf, size_t output) { - int block1 = buf->o; - int block2 = 0; - - /* process output data in two steps to cover wrapping */ - if (block1 > buf->p - buf->data) { - block2 = buf->p - buf->data; - block1 -= block2; - } - memcpy(swap_buffer + buf->size - buf->o, bo_ptr(buf), block1); - memcpy(swap_buffer + buf->size - block2, buf->data, block2); - - /* process input data in two steps to cover wrapping */ - block1 = buf->i; - block2 = 0; - - if (block1 > buf->data + buf->size - buf->p) { - block1 = buf->data + buf->size - buf->p; - block2 = buf->i - block1; - } - memcpy(swap_buffer, bi_ptr(buf), block1); - memcpy(swap_buffer + block1, buf->data, block2); - - /* reinject changes into the buffer */ - memcpy(buf->data, swap_buffer, buf->i); - memcpy(buf->data + buf->size - buf->o, swap_buffer + buf->size - buf->o, buf->o); - - buf->p = buf->data; + return b_slow_realign(buf, swap_buffer, output); } /* diff --git a/src/hlua.c b/src/hlua.c index 4715639a16..cdb5ff69c6 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -3041,7 +3041,7 @@ __LJMP static int hlua_channel_send_yield(lua_State *L, int status, lua_KContext * detects a non contiguous buffer and realign it. */ if (bi_space_for_replace(chn->buf) < max) - buffer_slow_realign(chn->buf); + channel_slow_realign(chn); /* Copy input data in the buffer. */ max = buffer_replace2(chn->buf, chn->buf->p, chn->buf->p, str + l, max); diff --git a/src/mux_h2.c b/src/mux_h2.c index 1eba104b3d..3210302613 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -2688,7 +2688,7 @@ static int h2_frt_decode_headers(struct h2s *h2s, struct buffer *buf, int count) /* it doesn't fit and the buffer is fragmented, * so let's defragment it and try again. */ - buffer_slow_realign(buf); + buffer_slow_realign(buf, 0); } /* first check if we have some room after p+i */ @@ -2995,7 +2995,7 @@ static int h2s_frt_make_resp_headers(struct h2s *h2s, struct buffer *buf) if (outbuf.size >= 9 || !buffer_space_wraps(h2c->mbuf)) break; realign_again: - buffer_slow_realign(h2c->mbuf); + buffer_slow_realign(h2c->mbuf, h2c->mbuf->o); } if (outbuf.size < 9) { @@ -3153,7 +3153,7 @@ static int h2s_frt_make_resp_data(struct h2s *h2s, struct buffer *buf) if (outbuf.size >= 9 || !buffer_space_wraps(h2c->mbuf)) break; realign_again: - buffer_slow_realign(h2c->mbuf); + buffer_slow_realign(h2c->mbuf, h2c->mbuf->o); } if (outbuf.size < 9) { diff --git a/src/proto_http.c b/src/proto_http.c index c447929c85..a4db33a48e 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -1652,7 +1652,7 @@ int http_wait_for_request(struct stream *s, struct channel *req, int an_bit) } if (unlikely(bi_end(req->buf) < b_ptr(req->buf, msg->next) || bi_end(req->buf) > req->buf->data + req->buf->size - global.tune.maxrewrite)) - buffer_slow_realign(req->buf); + channel_slow_realign(req); } if (likely(msg->next < req->buf->i)) /* some unparsed data are available */ @@ -5139,7 +5139,7 @@ int http_wait_for_response(struct stream *s, struct channel *rep, int an_bit) if (unlikely(bi_end(rep->buf) < b_ptr(rep->buf, msg->next) || bi_end(rep->buf) > rep->buf->data + rep->buf->size - global.tune.maxrewrite)) - buffer_slow_realign(rep->buf); + channel_slow_realign(rep); if (likely(msg->next < rep->buf->i)) http_msg_analyzer(msg, &txn->hdr_idx); @@ -9517,7 +9517,7 @@ int smp_prefetch_http(struct proxy *px, struct stream *s, unsigned int opt, */ if (s->req.buf->p > s->req.buf->data && s->req.buf->i + s->req.buf->p > s->req.buf->data + s->req.buf->size - global.tune.maxrewrite) - buffer_slow_realign(s->req.buf); + channel_slow_realign(&s->req); if (unlikely(txn->req.msg_state < HTTP_MSG_BODY)) { if (msg->msg_state == HTTP_MSG_ERROR)