diff options
author | Gerrit Renker <gerrit@erg.abdn.ac.uk> | 2006-12-09 21:09:21 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-11 17:34:54 -0500 |
commit | c5a1ae9a4cc4aef1505fa0aba079f834c3ee1af1 (patch) | |
tree | ce26c29076ae01f762fd5b09becca79ac602a63b /net/dccp | |
parent | e312d100f19fdfe1019512b07a9d15653f254abf (diff) |
[DCCP] ccid3: Perform history operations only after packet has been sent
This migrates all packet history operations into the routine
ccid3_hc_tx_packet_sent, thereby removing synchronization problems
that occur when, as before, the operations are spread over multiple
routines.
The following minor simplifications are also applied:
* several simplifications now follow from this change - several tests
are now no longer required
* removal of one unnecessary variable (dp)
Justification:
Currently packet history operations span two different routines,
one of which is likely to pass through several iterations of sleeping
and awakening.
The first routine, ccid3_hc_tx_send_packet, allocates an entry and
sets a few fields. The remaining fields are filled in when the second
routine (which is not within a sleeping context), ccid3_hc_tx_packet_sent,
is called. This has several strong drawbacks:
* it is not necessary to split history operations - all fields can be
filled in by the second routine
* the first routine is called multiple times, until a packet can be sent,
and sleeps meanwhile - this causes a lot of difficulties with regard to
keeping the list consistent
* since both routines do not have a producer-consumer like synchronization,
it is very difficult to maintain data across calls to these routines
* the fact that the routines are called in different contexts (sleeping, not
sleeping) adds further problems
Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Acked-by: Ian McDonald <ian.mcdonald@jandi.co.nz>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
Diffstat (limited to 'net/dccp')
-rw-r--r-- | net/dccp/ccids/ccid3.c | 38 |
1 files changed, 9 insertions, 29 deletions
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index 6bb3f8352dad..ef68c35183ed 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -296,7 +296,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
296 | { | 296 | { |
297 | struct dccp_sock *dp = dccp_sk(sk); | 297 | struct dccp_sock *dp = dccp_sk(sk); |
298 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 298 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
299 | struct dccp_tx_hist_entry *new_packet; | ||
300 | struct timeval now; | 299 | struct timeval now; |
301 | suseconds_t delay; | 300 | suseconds_t delay; |
302 | 301 | ||
@@ -310,21 +309,6 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
310 | if (unlikely(skb->len == 0)) | 309 | if (unlikely(skb->len == 0)) |
311 | return -EBADMSG; | 310 | return -EBADMSG; |
312 | 311 | ||
313 | /* See if last packet allocated was not sent */ | ||
314 | new_packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | ||
315 | if (new_packet == NULL || new_packet->dccphtx_sent) { | ||
316 | new_packet = dccp_tx_hist_entry_new(ccid3_tx_hist, | ||
317 | GFP_ATOMIC); | ||
318 | |||
319 | if (unlikely(new_packet == NULL)) { | ||
320 | DCCP_WARN("%s, sk=%p, not enough mem to add to history," | ||
321 | "send refused\n", dccp_role(sk), sk); | ||
322 | return -ENOBUFS; | ||
323 | } | ||
324 | |||
325 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, new_packet); | ||
326 | } | ||
327 | |||
328 | dccp_timestamp(sk, &now); | 312 | dccp_timestamp(sk, &now); |
329 | 313 | ||
330 | switch (hctx->ccid3hctx_state) { | 314 | switch (hctx->ccid3hctx_state) { |
@@ -380,31 +364,27 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, struct sk_buff *skb) | |||
380 | 364 | ||
381 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) | 365 | static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, unsigned int len) |
382 | { | 366 | { |
383 | const struct dccp_sock *dp = dccp_sk(sk); | ||
384 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); | 367 | struct ccid3_hc_tx_sock *hctx = ccid3_hc_tx_sk(sk); |
385 | struct timeval now; | 368 | struct timeval now; |
386 | struct dccp_tx_hist_entry *packet; | 369 | struct dccp_tx_hist_entry *packet; |
387 | 370 | ||
388 | BUG_ON(hctx == NULL); | 371 | BUG_ON(hctx == NULL); |
389 | 372 | ||
390 | dccp_timestamp(sk, &now); | ||
391 | |||
392 | ccid3_hc_tx_update_s(hctx, len); | 373 | ccid3_hc_tx_update_s(hctx, len); |
393 | 374 | ||
394 | packet = dccp_tx_hist_head(&hctx->ccid3hctx_hist); | 375 | packet = dccp_tx_hist_entry_new(ccid3_tx_hist, GFP_ATOMIC); |
395 | if (unlikely(packet == NULL)) { | 376 | if (unlikely(packet == NULL)) { |
396 | DCCP_WARN("packet doesn't exist in history!\n"); | 377 | DCCP_CRIT("packet history - out of memory!"); |
397 | return; | ||
398 | } | ||
399 | if (unlikely(packet->dccphtx_sent)) { | ||
400 | DCCP_WARN("no unsent packet in history!\n"); | ||
401 | return; | 378 | return; |
402 | } | 379 | } |
380 | dccp_tx_hist_add_entry(&hctx->ccid3hctx_hist, packet); | ||
381 | |||
382 | dccp_timestamp(sk, &now); | ||
403 | packet->dccphtx_tstamp = now; | 383 | packet->dccphtx_tstamp = now; |
404 | packet->dccphtx_seqno = dp->dccps_gss; | 384 | packet->dccphtx_seqno = dccp_sk(sk)->dccps_gss; |
405 | hctx->ccid3hctx_idle = 0; | 385 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; |
406 | packet->dccphtx_rtt = hctx->ccid3hctx_rtt; | 386 | packet->dccphtx_sent = 1; |
407 | packet->dccphtx_sent = 1; | 387 | hctx->ccid3hctx_idle = 0; |
408 | } | 388 | } |
409 | 389 | ||
410 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) | 390 | static void ccid3_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) |