@@ -192,28 +192,135 @@ tfw_h2_apply_new_settings(TfwH2Ctx *ctx)
192192 clear_bit (HTTP2_SETTINGS_NEED_TO_APPLY , ctx -> settings_to_apply );
193193}
194194
195- int
196- tfw_h2_init (void )
195+ #define TFW_H2_PAGE_ORDER 1
196+ #define TFW_H2_BOUNDARY (base ) \
197+ (char *)base + PAGE_SIZE * (1 << TFW_H2_PAGE_ORDER);
198+ #define TFW_H2_NEXT_BLOCK (boundary ) \
199+ (unsigned long *)(boundary - sizeof(unsigned long));
200+
201+ TfwH2Ctx *
202+ tfw_h2_context_alloc (void )
197203{
198- return tfw_h2_stream_cache_create ();
204+ struct page * pg ;
205+
206+ pg = alloc_pages (GFP_ATOMIC , TFW_H2_PAGE_ORDER );
207+ if (!pg )
208+ return NULL ;
209+ return (TfwH2Ctx * )page_address (pg );
199210}
200211
201212void
202- tfw_h2_cleanup ( void )
213+ tfw_h2_context_free ( TfwH2Ctx * ctx )
203214{
204- tfw_h2_stream_cache_destroy ( );
215+ free_pages (( unsigned long ) ctx , TFW_H2_PAGE_ORDER );
205216}
206217
207- TfwH2Ctx *
208- tfw_h2_context_alloc (void )
218+ static inline void
219+ tfw_h2_context_init_stream_storage_impl (TfwH2Ctx * ctx , void * base ,
220+ unsigned long * next_block )
209221{
210- return (TfwH2Ctx * )kzalloc (sizeof (TfwH2Ctx ), GFP_ATOMIC );
222+ TfwStream * stream = (TfwStream * )base ;
223+
224+ while ((char * )stream <= (char * )next_block - sizeof (TfwStream )) {
225+ stream -> next = ctx -> empty_list ;
226+ ctx -> empty_list = stream ;
227+ stream ++ ;
228+ }
229+ }
230+
231+ static inline int
232+ tfw_h2_conext_alloc_stream_storage_new_block (TfwH2Ctx * ctx )
233+ {
234+ char * boundary ;
235+ unsigned long * next_block ;
236+ unsigned long * new_block , * next_new_block ;
237+ struct page * pg ;
238+
239+ boundary = TFW_H2_BOUNDARY (ctx );
240+ next_block = TFW_H2_NEXT_BLOCK (boundary );
241+
242+ pg = alloc_pages (GFP_ATOMIC , TFW_H2_PAGE_ORDER );
243+ if (!unlikely (pg ))
244+ return - ENOMEM ;
245+
246+ new_block = (unsigned long * )page_address (pg );
247+ boundary = TFW_H2_BOUNDARY (new_block );
248+ next_new_block = TFW_H2_NEXT_BLOCK (boundary );
249+
250+ * next_new_block = * next_block ;
251+ * next_block = (unsigned long )new_block ;
252+
253+ tfw_h2_context_init_stream_storage_impl (ctx , new_block ,
254+ next_new_block );
255+
256+ return 0 ;
257+ }
258+
259+ static inline void
260+ tfw_h2_context_clear_stream_storage (TfwH2Ctx * ctx )
261+ {
262+ char * boundary ;
263+ unsigned long * next_block ;
264+
265+ boundary = TFW_H2_BOUNDARY (ctx );
266+ next_block = TFW_H2_NEXT_BLOCK (boundary );
267+
268+ while (* next_block ) {
269+ unsigned long to_free ;
270+
271+ to_free = * next_block ;
272+ boundary = TFW_H2_BOUNDARY (* next_block );
273+ next_block = TFW_H2_NEXT_BLOCK (boundary );
274+ free_pages (to_free , TFW_H2_PAGE_ORDER );
275+ }
276+ }
277+
278+ static inline void
279+ tfw_h2_context_init_stream_storage (TfwH2Ctx * ctx )
280+ {
281+ char * boundary ;
282+ unsigned long * new_block ;
283+ unsigned long * next_block ;
284+
285+ boundary = TFW_H2_BOUNDARY (ctx );
286+ new_block = (unsigned long * )ctx + sizeof (TfwH2Ctx );
287+ next_block = TFW_H2_NEXT_BLOCK (boundary );
288+
289+ /*
290+ * Pointer to the next page block for empty streams, will be allocated,
291+ * if count of preallocated streams exceeded.
292+ */
293+ * next_block = 0 ;
294+ tfw_h2_context_init_stream_storage_impl (ctx , new_block , next_block );
295+ }
296+
297+ #undef TFW_H2_NEXT_BLOCK
298+ #undef TFW_H2_BOUNDARY
299+ #undef TFW_H2_PAGE_ORDER
300+
301+ TfwStream *
302+ tfw_h2_conext_alloc_stream (TfwH2Ctx * ctx )
303+ {
304+ TfwStream * stream ;
305+
306+ if (!ctx -> empty_list ) {
307+ if (tfw_h2_conext_alloc_stream_storage_new_block (ctx ))
308+ return NULL ;
309+ }
310+
311+ stream = ctx -> empty_list ;
312+ ctx -> empty_list = ctx -> empty_list -> next ;
313+ memset (stream , 0 , sizeof (TfwStream ));
314+
315+ return stream ;
211316}
212317
213318void
214- tfw_h2_context_free (TfwH2Ctx * ctx )
319+ tfw_h2_conext_free_stream (TfwH2Ctx * ctx , TfwStream * stream )
215320{
216- kfree (ctx );
321+ BUG_ON (stream -> xmit .resp || stream -> xmit .skb_head );
322+ stream -> next = ctx -> empty_list ;
323+ ctx -> empty_list = stream ;
217324}
218325
219326int
@@ -236,6 +343,7 @@ tfw_h2_context_init(TfwH2Ctx *ctx, TfwH2Conn *conn)
236343 INIT_LIST_HEAD (& idle_streams -> list );
237344
238345 tfw_h2_init_stream_sched (& ctx -> sched );
346+ tfw_h2_context_init_stream_storage (ctx );
239347
240348 lset -> hdr_tbl_sz = rset -> hdr_tbl_sz = HPACK_TABLE_DEF_SIZE ;
241349 lset -> push = rset -> push = 1 ;
@@ -262,6 +370,7 @@ tfw_h2_context_clear(TfwH2Ctx *ctx)
262370 * postponed frames and connection closing initiated.
263371 */
264372 ss_skb_queue_purge (& ctx -> skb_head );
373+ tfw_h2_context_clear_stream_storage (ctx );
265374 tfw_hpack_clean (& ctx -> hpack );
266375}
267376
@@ -321,7 +430,7 @@ tfw_h2_conn_streams_cleanup(TfwH2Ctx *ctx)
321430 * No further actions regarding streams dependencies/prio
322431 * is required at this stage.
323432 */
324- tfw_h2_delete_stream ( cur );
433+ tfw_h2_conext_free_stream ( ctx , cur );
325434 -- ctx -> streams_num ;
326435 }
327436 sched -> streams = RB_ROOT ;
0 commit comments