From: Christopher Faulet Date: Tue, 11 Jun 2019 14:32:24 +0000 (+0200) Subject: MINOR: htx: Deduce the number of used blocks from tail and head values X-Git-Tag: v2.1-dev2~380 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=192c6a23d48a0b4393885207221aebca82ff7609;p=thirdparty%2Fhaproxy.git MINOR: htx: Deduce the number of used blocks from tail and head values and fields are now signed 32-bits integers. For an empty HTX message, these fields are set to -1. So the field is now useless and can safely be removed. To know if an HTX message is empty or not, we just compare against -1 (it also works with ). The function htx_nbblks() has been added to get the number of used blocks. --- diff --git a/include/common/htx.h b/include/common/htx.h index ba6604b27b..3c9aa68ad2 100644 --- a/include/common/htx.h +++ b/include/common/htx.h @@ -202,21 +202,21 @@ struct htx { * blocks (blocks and their contents), you need to add size used by blocks, * i.e. [ used * sizeof(struct htx_blk *) ] */ - uint32_t used; /* number of blocks in use */ - uint32_t tail; /* newest inserted block. -1 if the HTX message is empty */ - uint32_t head; /* oldest inserted block. -1 if the HTX message is empty */ + int32_t tail; /* newest inserted block. -1 if the HTX message is empty */ + int32_t head; /* oldest inserted block. -1 if the HTX message is empty */ + int32_t first; /* position of the first block to (re)start the analyse. -1 if unset. */ uint32_t tail_addr; /* start address of the free space in front of the the blocks table */ uint32_t head_addr; /* start address of the free space at the beginning */ uint32_t end_addr; /* end address of the free space at the beginning */ - uint64_t extra; /* known bytes amount remaining to receive */ uint32_t flags; /* HTX_FL_* */ - int32_t first; /* position of the first block to (re)start the analyse. -1 if unset. */ + /* XXX 4 bytes unused */ - struct htx_blk blocks[0]; /* Blocks representing the HTTP message itself */ + /* Blocks representing the HTTP message itself */ + struct htx_blk blocks[0] __attribute__((aligned(8))); }; @@ -370,15 +370,12 @@ static inline uint32_t htx_get_blksz(const struct htx_blk *blk) } } -/* Returns the position of the oldest entry (head). - * - * An signed 32-bits integer is returned to handle -1 case. Blocks position are - * store on unsigned 32-bits integer, but it is impossible to have so much - * blocks to overflow a 32-bits signed integer ! +/* Returns the position of the oldest entry (head). It returns a signed 32-bits + * integer, -1 means the HTX message is empty. */ static inline int32_t htx_get_head(const struct htx *htx) { - return (htx->used ? htx->head : -1); + return htx->head; } /* Returns the oldest HTX block (head) if the HTX message is not @@ -401,15 +398,12 @@ static inline enum htx_blk_type htx_get_head_type(const struct htx *htx) return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED); } -/* Returns the position of the newest entry (tail). - * - * An signed 32-bits integer is returned to handle -1 case. Blocks position are - * store on unsigned 32-bits integer, but it is impossible to have so much - * blocks to overflow a 32-bits signed integer ! +/* Returns the position of the newest entry (tail). It returns a signed 32-bits + * integer, -1 means the HTX message is empty. */ static inline int32_t htx_get_tail(const struct htx *htx) { - return (htx->used ? htx->tail : -1); + return htx->tail; } /* Returns the newest HTX block (tail) if the HTX message is not @@ -432,17 +426,11 @@ static inline enum htx_blk_type htx_get_tail_type(const struct htx *htx) return (blk ? htx_get_blk_type(blk) : HTX_BLK_UNUSED); } -/* Returns the position of the first block in the HTX message . If unset, - * or if is empty, -1 is returned. - * - * An signed 32-bits integer is returned to handle -1 case. Blocks position are - * store on unsigned 32-bits integer, but it is impossible to have so much - * blocks to overflow a 32-bits signed integer ! +/* Returns the position of the first block in the HTX message . -1 means + * the first block is unset or the HTS is empty. */ static inline int32_t htx_get_first(const struct htx *htx) { - if (!htx->used) - return -1; return htx->first; } @@ -469,17 +457,10 @@ static inline enum htx_blk_type htx_get_first_type(const struct htx *htx) /* Returns the position of block immediately before the one pointed by . If * the message is empty or if is the position of the head, -1 returned. - * - * An signed 32-bits integer is returned to handle -1 case. Blocks position are - * store on unsigned 32-bits integer, but it is impossible to have so much - * blocks to overflow a 32-bits signed integer ! */ static inline int32_t htx_get_prev(const struct htx *htx, uint32_t pos) { - int32_t head; - - head = htx_get_head(htx); - if (head == -1 || pos == head) + if (htx->head == -1 || pos == htx->head) return -1; return (pos - 1); } @@ -498,14 +479,10 @@ static inline struct htx_blk *htx_get_prev_blk(const struct htx *htx, /* Returns the position of block immediately after the one pointed by . If * the message is empty or if is the position of the tail, -1 returned. - * - * An signed 32-bits integer is returned to handle -1 case. Blocks position are - * store on unsigned 32-bits integer, but it is impossible to have so much - * blocks to overflow a 32-bits signed integer ! */ static inline int32_t htx_get_next(const struct htx *htx, uint32_t pos) { - if (!htx->used || pos == htx->tail) + if (htx->tail == -1 || pos == htx->tail) return -1; return (pos + 1); @@ -655,7 +632,10 @@ static inline void htx_cut_data_blk(struct htx *htx, struct htx_blk *blk, uint32 /* Returns the space used by metadata in . */ static inline uint32_t htx_meta_space(const struct htx *htx) { - return (htx->used * sizeof(htx->blocks[0])); + if (htx->tail == -1) + return 0; + + return ((htx->tail + 1 - htx->head) * sizeof(htx->blocks[0])); } /* Returns the space used (payload + metadata) in */ @@ -707,11 +687,11 @@ static inline int htx_almost_full(const struct htx *htx) /* Resets an HTX message */ static inline void htx_reset(struct htx *htx) { - htx->data = htx->used = htx->tail = htx->head = 0; + htx->tail = htx->head = htx->first = -1; + htx->data = 0; htx->tail_addr = htx->head_addr = htx->end_addr = 0; htx->extra = 0; htx->flags = HTX_FL_NONE; - htx->first = -1; } /* Returns the available room for raw data in buffer once HTX overhead is @@ -773,7 +753,7 @@ static inline struct htx *htx_from_buf(struct buffer *buf) /* Update accordingly to the HTX message */ static inline void htx_to_buf(struct htx *htx, struct buffer *buf) { - if (!htx->used && !(htx->flags & (HTX_FL_PARSING_ERROR|HTX_FL_UPGRADE))) { + if ((htx->head == -1) && !(htx->flags & (HTX_FL_PARSING_ERROR|HTX_FL_UPGRADE))) { htx_reset(htx); b_set_data(buf, 0); } @@ -786,7 +766,7 @@ static inline void htx_to_buf(struct htx *htx, struct buffer *buf) */ static inline int htx_is_empty(const struct htx *htx) { - return !htx->used; + return (htx->head == -1); } /* Returns 1 if the message is not empty, otherwise it returns 0. Note that it @@ -794,9 +774,17 @@ static inline int htx_is_empty(const struct htx *htx) */ static inline int htx_is_not_empty(const struct htx *htx) { - return htx->used; + return (htx->head != -1); } +/* Returns the number of used blocks in the HTX message . Note that it is + * illegal to call this function with htx == NULL. Note also blocks of type + * HTX_BLK_UNUSED are part of used blocks. + */ +static inline int htx_nbblks(const struct htx *htx) +{ + return ((htx->head != -1) ? (htx->tail + 1 - htx->head) : 0); +} /* For debugging purpose */ static inline const char *htx_blk_type_str(enum htx_blk_type type) { @@ -820,7 +808,8 @@ static inline void htx_dump(struct htx *htx) int32_t pos; fprintf(stderr, "htx:%p [ size=%u - data=%u - used=%u - wrap=%s - extra=%llu]\n", - htx, htx->size, htx->data, htx->used, (!htx->head_addr) ? "NO" : "YES", + htx, htx->size, htx->data, htx_nbblks(htx), + (!htx->head_addr) ? "NO" : "YES", (unsigned long long)htx->extra); fprintf(stderr, "\tfirst=%d - head=%u, tail=%u\n", htx->first, htx->head, htx->tail); diff --git a/src/http_htx.c b/src/http_htx.c index 0e788c1d87..13c1453a55 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -77,7 +77,7 @@ int http_find_header(const struct htx *htx, const struct ist name, goto return_hdr; } - if (!htx->used) + if (htx_is_empty(htx)) return 0; for (blk = htx_get_first_blk(htx); blk; blk = htx_get_next_blk(htx, blk)) { @@ -431,7 +431,7 @@ int http_remove_header(struct htx *htx, struct http_hdr_ctx *ctx) v = htx_get_blk_value(htx, blk); if (len == v.len) { blk = htx_remove_blk(htx, blk); - if (blk || !htx->used) { + if (blk || htx_is_empty(htx)) { ctx->blk = blk; ctx->value = ist2(NULL, 0); ctx->lws_before = ctx->lws_after = 0; diff --git a/src/htx.c b/src/htx.c index bdd10bad87..bbf1f8fc1d 100644 --- a/src/htx.c +++ b/src/htx.c @@ -13,7 +13,7 @@ #include #include -struct htx htx_empty = { .size = 0, .data = 0, .used = 0 }; +struct htx htx_empty = { .size = 0, .data = 0, .head = -1, .tail = -1, .first = -1 }; /* Defragments an HTX message. It removes unused blocks and unwraps the payloads * part. A temporary buffer is used to do so. This function never fails. if @@ -30,7 +30,7 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk) uint32_t addr, blksz; int32_t first = -1; - if (!htx->used) + if (htx->head == -1) return NULL; blkpos = -1; @@ -64,7 +64,6 @@ struct htx_blk *htx_defrag(struct htx *htx, struct htx_blk *blk) } - htx->used = new; htx->first = first; htx->head = 0; htx->tail = new - 1; @@ -116,16 +115,14 @@ static void htx_defrag_blks(struct htx *htx) static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) { struct htx_blk *blk; - uint32_t used, tail; - uint32_t headroom, tailroom; + uint32_t tail, headroom, tailroom; if (blksz > htx_free_data_space(htx)) return NULL; /* full */ - if (!htx->used) { + if (htx->head == -1) { /* Empty message */ htx->head = htx->tail = htx->first = 0; - htx->used = 1; blk = htx_get_blk(htx, htx->tail); blk->addr = 0; htx->data = blksz; @@ -141,11 +138,10 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) */ tail = htx->tail + 1; if (sizeof(htx->blocks[0]) * htx_pos_to_idx(htx, tail) >= htx->tail_addr) - used = htx->used + 1; - else if (tail > htx->used) { + ; + else if (htx->head > 0) { htx_defrag_blks(htx); tail = htx->tail + 1; - used = htx->used + 1; BUG_ON(sizeof(htx->blocks[0]) * htx_pos_to_idx(htx, tail) < htx->tail_addr); } else @@ -182,14 +178,12 @@ static struct htx_blk *htx_reserve_nxblk(struct htx *htx, uint32_t blksz) /* need to defragment the message before inserting upfront */ htx_defrag(htx, NULL); tail = htx->tail + 1; - used = htx->used + 1; blk = htx_get_blk(htx, tail); blk->addr = htx->tail_addr; htx->tail_addr += blksz; } htx->tail = tail; - htx->used = used; htx->data += blksz; /* Set first position if not already set */ if (htx->first == -1) @@ -226,6 +220,8 @@ static int htx_prepare_blk_expansion(struct htx *htx, struct htx_blk *blk, int32 uint32_t sz, tailroom, headroom; int ret = 3; + BUG_ON(htx->head == -1); + headroom = (htx->end_addr - htx->head_addr); tailroom = sizeof(htx->blocks[0]) * htx_pos_to_idx(htx, htx->tail) - htx->tail_addr; BUG_ON((int32_t)headroom < 0); @@ -328,8 +324,10 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) enum htx_blk_type type; uint32_t pos, addr, sz; + BUG_ON(htx->head == -1); + /* This is the last block in use */ - if (htx->used == 1) { + if (htx->head == htx->tail) { htx_reset(htx); return NULL; } @@ -347,14 +345,12 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) /* There is at least 2 blocks, so tail is always > 0 */ if (pos == htx->head) { /* move the head forward */ - htx->used--; htx->head++; } else if (pos == htx->tail) { /* remove the tail. this was the last inserted block so * return NULL. */ htx->tail--; - htx->used--; blk = NULL; goto end; } @@ -364,7 +360,7 @@ struct htx_blk *htx_remove_blk(struct htx *htx, struct htx_blk *blk) if (pos == htx->first) htx->first = (blk ? htx_get_blk_pos(htx, blk) : -1); - if (htx->used == 1) { + if (htx->head == htx->tail) { /* If there is just one block in the HTX message, free space can * be ajusted. This operation could save some defrags. */ struct htx_blk *lastblk = htx_get_blk(htx, htx->tail); @@ -474,7 +470,7 @@ struct htx_blk *htx_add_data_atonce(struct htx *htx, struct ist data) void *ptr; uint32_t len, sz, tailroom, headroom; - if (!htx->used) + if (htx->head == -1) goto add_new_block; /* Not enough space to store data */ @@ -929,7 +925,7 @@ size_t htx_add_data(struct htx *htx, const struct ist data) uint32_t sz, room; int32_t len = data.len; - if (!htx->used) + if (htx->head == -1) goto add_new_block; /* Not enough space to store data */ diff --git a/src/mux_h1.c b/src/mux_h1.c index 365c5ea025..009afb09a1 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -1543,7 +1543,7 @@ static size_t h1_process_output(struct h1c *h1c, struct buffer *buf, size_t coun * the HTX blocks. */ if (!b_data(&h1c->obuf)) { - if (chn_htx->used == 1 && + if (htx_nbblks(chn_htx) == 1 && htx_get_blk_type(blk) == HTX_BLK_DATA && htx_get_blk_value(chn_htx, blk).len == count) { void *old_area = h1c->obuf.area; diff --git a/src/mux_h2.c b/src/mux_h2.c index ab781ddebb..7866c7883e 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -4936,7 +4936,7 @@ static size_t h2s_htx_frt_make_resp_data(struct h2s *h2s, struct buffer *buf, si * from the HTX blocks. */ if (unlikely(fsize == count && - htx->used == 1 && type == HTX_BLK_DATA && + htx_nbblks(htx) == 1 && type == HTX_BLK_DATA && fsize <= h2s->mws && fsize <= h2c->mws && fsize <= h2c->mfs)) { void *old_area = mbuf->area; diff --git a/src/stream.c b/src/stream.c index a5c5f45c77..78c228823e 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3344,7 +3344,7 @@ static int stats_dump_full_strm_to_buffer(struct stream_interface *si, struct st chunk_appendf(&trash, " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", - htx, htx->flags, htx->size, htx->data, htx->used, + htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), (htx->tail >= htx->head) ? "NO" : "YES", (unsigned long long)htx->extra); } @@ -3383,7 +3383,7 @@ static int stats_dump_full_strm_to_buffer(struct stream_interface *si, struct st chunk_appendf(&trash, " htx=%p flags=0x%x size=%u data=%u used=%u wrap=%s extra=%llu\n", - htx, htx->flags, htx->size, htx->data, htx->used, + htx, htx->flags, htx->size, htx->data, htx_nbblks(htx), (htx->tail >= htx->head) ? "NO" : "YES", (unsigned long long)htx->extra); }