This patch prepares adding TX history locking by changing all functions which return a reference to a TX history object: 1) removal of dccp_tx_hist_head - nowhere used in the code; 2) change dccp_tx_hist_find_entry - the sole use is to look up a timestamp for an Ack-ed packet; and then do garbage-collection. The latter function is changed to return the desired timestamp instead of a history object reference. Not returning object references is necessary, since otherwise lists could not be garbage-collected (or would have to use atomic reference counts). Furthermore, the garbage-collection is now integrated into (2), since it requires first a read access and then a write access at the same place in the list: giving up the lock here would permit race condition. Signed-off-by: Gerrit Renker <gerrit@xxxxxxxxxxxxxx> Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxxxxxxxxxx> --- net/dccp/ccids/ccid3.c | 18 +++++++----------- net/dccp/ccids/lib/packet_history.c | 27 +++++++++++++++++++++------ net/dccp/ccids/lib/packet_history.h | 16 ++-------------- 3 files changed, 30 insertions(+), 31 deletions(-) diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 131001b..0029979 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c @@ -421,10 +421,9 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) { struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); struct ccid3_options_received *opt_recv; - struct dccp_tx_hist_entry *packet; - struct timeval now; + struct timeval now, t_send; unsigned long t_nfb; - u32 pinv, r_sample; + u32 pinv, r_sample, rc; BUG_ON(hctx == NULL); @@ -440,10 +439,10 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) default: return; } - /* get packet from history to look up t_recvdata */ - packet = dccp_tx_hist_find_entry(&hctx->ccid3hctx_hist, - DCCP_SKB_CB(skb)->dccpd_ack_seq); - if (unlikely(packet == NULL)) { + /* look up t_recvdata in packet history */ + rc = dccp_tx_hist_get_send_time(ccid3_tx_hist, &hctx->ccid3hctx_hist, + DCCP_SKB_CB(skb)->dccpd_ack_seq, &t_send); + if (unlikely(!rc)) { DCCP_WARN("%s(%p), seqno %llu(%s) doesn't exist in history!\n", dccp_role(sk), sk, (unsigned long long)DCCP_SKB_CB(skb)->dccpd_ack_seq, @@ -466,7 +465,7 @@ static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) * R_sample = (t_now - t_recvdata) - t_elapsed */ skb_get_timestamp(skb, &now); - r_sample = dccp_sample_rtt(sk, &now, &packet->dccphtx_tstamp); + r_sample = dccp_sample_rtt(sk, &now, &t_send); /* * Update RTT estimate (honours RTT from SYN exchange): @@ -523,9 +522,6 @@ done_computing_x: /* unschedule no feedback timer */ sk_stop_timer(sk, &hctx->ccid3hctx_no_feedback_timer); - /* remove all packets older than the one acked from history */ - dccp_tx_hist_purge_older(ccid3_tx_hist, - &hctx->ccid3hctx_hist, packet); /* * As we have calculated new ipi, delta, t_nom it is possible * that we now can send a packet, so wake up dccp_wait_for_ccid diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index 2e8ef42..d149b19 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c @@ -85,21 +85,36 @@ void dccp_tx_hist_delete(struct dccp_tx_hist *hist) EXPORT_SYMBOL_GPL(dccp_tx_hist_delete); -struct dccp_tx_hist_entry * - dccp_tx_hist_find_entry(const struct list_head *list, const u64 seq) +/** + * dccp_tx_hist_get_send_time - Retrieve timestamp of sent packet + * + * @hist: history slab associated with TX history + * @list: TX history list head + * @seq: 48-bit sequence number of packet in question + * @t_send: timestamp to be returned + * Returns 1 on success and then garbage-collects all older entries. + */ +int dccp_tx_hist_get_send_time(struct dccp_tx_hist *hist, + struct list_head *list, u64 seq, + struct timeval *t_send) { - struct dccp_tx_hist_entry *packet = NULL, *entry; + struct dccp_tx_hist_entry *entry; + int found = 0; list_for_each_entry(entry, list, dccphtx_node) if (entry->dccphtx_seqno == seq) { - packet = entry; + found = 1; + *t_send = entry->dccphtx_tstamp; break; } - return packet; + if (found) + dccp_tx_hist_purge_older(hist, list, entry); + + return found; } -EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); +EXPORT_SYMBOL_GPL(dccp_tx_hist_get_send_time); void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) { diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 330b58f..da81709 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h @@ -80,20 +80,8 @@ static inline struct dccp_tx_hist_entry * return entry; } -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; -} - -extern struct dccp_tx_hist_entry * - dccp_tx_hist_find_entry(const struct list_head *list, - const u64 seq); +extern int dccp_tx_hist_get_send_time(struct dccp_tx_hist *, struct list_head *, + u64 seq, struct timeval *t_send); static inline void dccp_tx_hist_add_entry(struct list_head *list, struct dccp_tx_hist_entry *entry) -- 1.5.0.6 - To unsubscribe from this list: send the line "unsubscribe dccp" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html