[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