[TFRC]: History allocation / deallocation routines

Within the set, this patch is concerned with allocation/de-allocation of list 
entries:
  * adding information is transparent to the calling module;
  * de-allocation will be transparent, hence dccp_tx_hist_purge_older removed 
here;
  * allocation and cleanup are taken care of internally.
        
Note on locking:
----------------
  Since the CCID3 module functions can be called both from user context (e.g. 
dccp_sendmsg)
  and from softirq context (receive handler, dccp_write_xmit_timer), all 
read/write locks will
  disable software interrupts as well. Time-intensive operations (e.g. full 
list traversal)
  are therefore avoided when under lock.
  All `dangerous' (i.e. not protected by lock) functions have the usual prefix 
of `__'.  

Signed-off-by: Gerrit Renker <[EMAIL PROTECTED]>
---
 net/dccp/ccids/ccid3.c              |   16 ++---------
 net/dccp/ccids/lib/packet_history.c |   51 ++++++++++++++++++++++++------------
 net/dccp/ccids/lib/packet_history.h |   41 ++++------------------------
 3 files changed, 44 insertions(+), 64 deletions(-)

--- a/net/dccp/ccids/lib/packet_history.h
+++ b/net/dccp/ccids/lib/packet_history.h
@@ -79,47 +79,18 @@ struct tfrc_tx_hist_head {
        struct kmem_cache       *cache;
 };
 
-static inline struct dccp_tx_hist_entry *
-                       dccp_tx_hist_entry_new(struct dccp_tx_hist *hist,
-                                              const gfp_t prio)
+static inline void tfrc_tx_hist_init(struct tfrc_tx_hist_head *head,
+                                    struct kmem_cache *cache)
 {
-       return kmem_cache_alloc(hist->dccptxh_slab, prio);
-}
-
-static inline struct dccp_tx_hist_entry *
-                       dccp_tx_hist_head(struct list_head *list)
-{
-       struct dccp_tx_hist_entry *head = NULL;
-
-       if (!list_empty(list))
-               head = list_entry(list->next, struct dccp_tx_hist_entry,
-                                 dccphtx_node);
-       return head;
+       head->first = NULL;
+       head->cache = cache;
 }
 
 extern struct dccp_tx_hist_entry *
                        dccp_tx_hist_find_entry(const struct list_head *list,
                                                const u64 seq);
-
-static inline void dccp_tx_hist_add_entry(struct list_head *list,
-                                         struct dccp_tx_hist_entry *entry)
-{
-       list_add(&entry->dccphtx_node, list);
-}
-
-static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist,
-                                            struct dccp_tx_hist_entry *entry)
-{
-       if (entry != NULL)
-               kmem_cache_free(hist->dccptxh_slab, entry);
-}
-
-extern void dccp_tx_hist_purge(struct dccp_tx_hist *hist,
-                              struct list_head *list);
-
-extern void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
-                                    struct list_head *list,
-                                    struct dccp_tx_hist_entry *next);
+extern int  tfrc_tx_hist_add(struct tfrc_tx_hist_head *head, u64 seqno);
+extern void tfrc_tx_hist_cleanup(struct tfrc_tx_hist_head *head);
 
 /*
  *     Receiver History data structures and declarations
--- a/net/dccp/ccids/lib/packet_history.c
+++ b/net/dccp/ccids/lib/packet_history.c
@@ -90,31 +90,50 @@ struct dccp_tx_hist_entry *
 
 EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry);
 
-void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list)
+int tfrc_tx_hist_add(struct tfrc_tx_hist_head *head, u64 seqno)
 {
-       struct dccp_tx_hist_entry *entry, *next;
+       struct tfrc_tx_hist *new = kmem_cache_alloc(head->cache, gfp_any());
 
-       list_for_each_entry_safe(entry, next, list, dccphtx_node) {
-               list_del_init(&entry->dccphtx_node);
-               dccp_tx_hist_entry_delete(hist, entry);
-       }
+       if (new == NULL)
+               return -ENOBUFS;
+
+       new->seqno = seqno;
+       new->stamp = ktime_get_real();
+
+       write_lock_bh(&tfrc_tx_hist_lock);
+       new->next = head->first;
+       head->first = new;
+       write_unlock_bh(&tfrc_tx_hist_lock);
+
+       return 0;
 }
+EXPORT_SYMBOL_GPL(tfrc_tx_hist_add);
 
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge);
+static void __tfrc_tx_hist_remove_tail(struct tfrc_tx_hist *ptr,
+                                      struct kmem_cache *cache)
+ {
+       struct tfrc_tx_hist *old;
 
-void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist,
-                             struct list_head *list,
-                             struct dccp_tx_hist_entry *packet)
+       while (ptr != NULL) {
+               old = ptr;
+               ptr = ptr->next;
+               kmem_cache_free(cache, old);
+       }
+}
+
+void tfrc_tx_hist_cleanup(struct tfrc_tx_hist_head *head)
 {
-       struct dccp_tx_hist_entry *next;
+       struct tfrc_tx_hist *free_this;
 
-       list_for_each_entry_safe_continue(packet, next, list, dccphtx_node) {
-               list_del_init(&packet->dccphtx_node);
-               dccp_tx_hist_entry_delete(hist, packet);
-       }
+       write_lock_bh(&tfrc_tx_hist_lock);
+       free_this = head->first;
+       head->first = NULL;
+       write_unlock_bh(&tfrc_tx_hist_lock);
+
+       __tfrc_tx_hist_remove_tail(free_this, head->cache);
 }
+EXPORT_SYMBOL_GPL(tfrc_tx_hist_cleanup);
 
-EXPORT_SYMBOL_GPL(dccp_tx_hist_purge_older);
 
 /*
  *     Receiver History Routines
--- a/net/dccp/ccids/ccid3.c
+++ b/net/dccp/ccids/ccid3.c
@@ -394,23 +394,13 @@ static void ccid3_hc_tx_packet_sent(stru
                                    unsigned int len)
 {
        struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk);
-       struct timeval now;
-       struct dccp_tx_hist_entry *packet;
 
        BUG_ON(hctx == NULL);
 
        ccid3_hc_tx_update_s(hctx, len);
 
-       packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC);
-       if (unlikely(packet == NULL)) {
+       if (tfrc_tx_hist_add(&hctx->ccid3hctx_hist, dccp_sk(sk)->dccps_gss))
                DCCP_CRIT("packet history - out of memory!");
-               return;
-       }
-
-       dccp_timestamp(sk, &now);
-       packet->dccphtx_tstamp = now;
-       packet->dccphtx_seqno  = dccp_sk(sk)->dccps_gss;
-       dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet);
 }
 
 static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb)
@@ -611,7 +601,7 @@ static int ccid3_hc_tx_init(struct ccid 
        hctx->ccid3hctx_s     = 0;
        hctx->ccid3hctx_rtt   = 0;
        hctx->ccid3hctx_state = TFRC_SSTATE_NO_SENT;
-       INIT_LIST_HEAD(&hctx->ccid3hctx_hist);
+       tfrc_tx_hist_init(&hctx->ccid3hctx_hist, ccid3_tx_hist);
 
        hctx->ccid3hctx_no_feedback_timer.function =
                                ccid3_hc_tx_no_feedback_timer;
@@ -631,7 +621,7 @@ static void ccid3_hc_tx_exit(struct sock
        sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer);
 
        /* Empty packet history */
-       dccp_tx_hist_purge(ccid3_tx_hist, &hctx->ccid3hctx_hist);
+       tfrc_tx_hist_cleanup(&hctx->ccid3hctx_hist);
 }
 
 static void ccid3_hc_tx_get_info(struct sock *sk, struct tcp_info *info)
-
To unsubscribe from this list: send the line "unsubscribe dccp" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to