diff options
author | John W. Linville <linville@tuxdriver.com> | 2006-08-29 16:17:25 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2006-08-29 16:17:25 -0400 |
commit | e4ac2663ea27d5dda88d97d117080995fcfcd6d5 (patch) | |
tree | 74eac23956a86546ed93eac973b0bc4744b97ccc /net | |
parent | 4c2be501b7e8695f8bdf4f7d5f51595ed55eea44 (diff) | |
parent | d96299537e43681942ea272e00b0e529aa5b5fa4 (diff) |
Merge branch 'from-linus' into upstream
Diffstat (limited to 'net')
-rw-r--r-- | net/bridge/br_forward.c | 10 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.c | 153 | ||||
-rw-r--r-- | net/dccp/ccids/ccid3.h | 9 | ||||
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.c | 36 | ||||
-rw-r--r-- | net/dccp/ccids/lib/loss_interval.h | 9 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.c | 168 | ||||
-rw-r--r-- | net/dccp/ccids/lib/packet_history.h | 17 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc.h | 2 | ||||
-rw-r--r-- | net/dccp/ccids/lib/tfrc_equation.c | 2 | ||||
-rw-r--r-- | net/dccp/dccp.h | 10 | ||||
-rw-r--r-- | net/dccp/options.c | 2 | ||||
-rw-r--r-- | net/ipv4/netfilter/arp_tables.c | 3 | ||||
-rw-r--r-- | net/ipv4/tcp_output.c | 1 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 30 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 20 | ||||
-rw-r--r-- | net/sctp/socket.c | 10 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 3 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 30 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 55 |
20 files changed, 273 insertions, 299 deletions
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 6ccd32b30809..864fbbc7b24d 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -40,11 +40,15 @@ int br_dev_queue_push_xmit(struct sk_buff *skb) | |||
40 | else { | 40 | else { |
41 | #ifdef CONFIG_BRIDGE_NETFILTER | 41 | #ifdef CONFIG_BRIDGE_NETFILTER |
42 | /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ | 42 | /* ip_refrag calls ip_fragment, doesn't copy the MAC header. */ |
43 | nf_bridge_maybe_copy_header(skb); | 43 | if (nf_bridge_maybe_copy_header(skb)) |
44 | kfree_skb(skb); | ||
45 | else | ||
44 | #endif | 46 | #endif |
45 | skb_push(skb, ETH_HLEN); | 47 | { |
48 | skb_push(skb, ETH_HLEN); | ||
46 | 49 | ||
47 | dev_queue_xmit(skb); | 50 | dev_queue_xmit(skb); |
51 | } | ||
48 | } | 52 | } |
49 | 53 | ||
50 | return 0; | 54 | return 0; |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index c39bff706cfc..090bc39e8199 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/dccp/ccids/ccid3.c | 2 | * net/dccp/ccids/ccid3.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
5 | * Copyright (c) 2005-6 Ian McDonald <imcdnzl@gmail.com> | 5 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> |
6 | * | 6 | * |
7 | * An implementation of the DCCP protocol | 7 | * An implementation of the DCCP protocol |
8 | * | 8 | * |
@@ -342,6 +342,8 @@ static int ccid3_hc_tx_send_packet(struct sock *sk, | |||
342 | new_packet->dccphtx_ccval = | 342 | new_packet->dccphtx_ccval = |
343 | DCCP_SKB_CB(skb)->dccpd_ccval = | 343 | DCCP_SKB_CB(skb)->dccpd_ccval = |
344 | hctx->ccid3hctx_last_win_count; | 344 | hctx->ccid3hctx_last_win_count; |
345 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | ||
346 | hctx->ccid3hctx_t_ipi); | ||
345 | } | 347 | } |
346 | out: | 348 | out: |
347 | return rc; | 349 | return rc; |
@@ -413,7 +415,8 @@ static void ccid3_hc_tx_packet_sent(struct sock *sk, int more, int len) | |||
413 | case TFRC_SSTATE_NO_FBACK: | 415 | case TFRC_SSTATE_NO_FBACK: |
414 | case TFRC_SSTATE_FBACK: | 416 | case TFRC_SSTATE_FBACK: |
415 | if (len > 0) { | 417 | if (len > 0) { |
416 | hctx->ccid3hctx_t_nom = now; | 418 | timeval_sub_usecs(&hctx->ccid3hctx_t_nom, |
419 | hctx->ccid3hctx_t_ipi); | ||
417 | ccid3_calc_new_t_ipi(hctx); | 420 | ccid3_calc_new_t_ipi(hctx); |
418 | ccid3_calc_new_delta(hctx); | 421 | ccid3_calc_new_delta(hctx); |
419 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, | 422 | timeval_add_usecs(&hctx->ccid3hctx_t_nom, |
@@ -757,8 +760,7 @@ static void ccid3_hc_rx_send_feedback(struct sock *sk) | |||
757 | } | 760 | } |
758 | 761 | ||
759 | hcrx->ccid3hcrx_tstamp_last_feedback = now; | 762 | hcrx->ccid3hcrx_tstamp_last_feedback = now; |
760 | hcrx->ccid3hcrx_last_counter = packet->dccphrx_ccval; | 763 | hcrx->ccid3hcrx_ccval_last_counter = packet->dccphrx_ccval; |
761 | hcrx->ccid3hcrx_seqno_last_counter = packet->dccphrx_seqno; | ||
762 | hcrx->ccid3hcrx_bytes_recv = 0; | 764 | hcrx->ccid3hcrx_bytes_recv = 0; |
763 | 765 | ||
764 | /* Convert to multiples of 10us */ | 766 | /* Convert to multiples of 10us */ |
@@ -782,7 +784,7 @@ static int ccid3_hc_rx_insert_options(struct sock *sk, struct sk_buff *skb) | |||
782 | if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) | 784 | if (!(sk->sk_state == DCCP_OPEN || sk->sk_state == DCCP_PARTOPEN)) |
783 | return 0; | 785 | return 0; |
784 | 786 | ||
785 | DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_last_counter; | 787 | DCCP_SKB_CB(skb)->dccpd_ccval = hcrx->ccid3hcrx_ccval_last_counter; |
786 | 788 | ||
787 | if (dccp_packet_without_ack(skb)) | 789 | if (dccp_packet_without_ack(skb)) |
788 | return 0; | 790 | return 0; |
@@ -854,6 +856,11 @@ static u32 ccid3_hc_rx_calc_first_li(struct sock *sk) | |||
854 | interval = 1; | 856 | interval = 1; |
855 | } | 857 | } |
856 | found: | 858 | found: |
859 | if (!tail) { | ||
860 | LIMIT_NETDEBUG(KERN_WARNING "%s: tail is null\n", | ||
861 | __FUNCTION__); | ||
862 | return ~0; | ||
863 | } | ||
857 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; | 864 | rtt = timeval_delta(&tstamp, &tail->dccphrx_tstamp) * 4 / interval; |
858 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", | 865 | ccid3_pr_debug("%s, sk=%p, approximated RTT to %uus\n", |
859 | dccp_role(sk), sk, rtt); | 866 | dccp_role(sk), sk, rtt); |
@@ -864,9 +871,20 @@ found: | |||
864 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); | 871 | delta = timeval_delta(&tstamp, &hcrx->ccid3hcrx_tstamp_last_feedback); |
865 | x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); | 872 | x_recv = usecs_div(hcrx->ccid3hcrx_bytes_recv, delta); |
866 | 873 | ||
874 | if (x_recv == 0) | ||
875 | x_recv = hcrx->ccid3hcrx_x_recv; | ||
876 | |||
867 | tmp1 = (u64)x_recv * (u64)rtt; | 877 | tmp1 = (u64)x_recv * (u64)rtt; |
868 | do_div(tmp1,10000000); | 878 | do_div(tmp1,10000000); |
869 | tmp2 = (u32)tmp1; | 879 | tmp2 = (u32)tmp1; |
880 | |||
881 | if (!tmp2) { | ||
882 | LIMIT_NETDEBUG(KERN_WARNING "tmp2 = 0 " | ||
883 | "%s: x_recv = %u, rtt =%u\n", | ||
884 | __FUNCTION__, x_recv, rtt); | ||
885 | return ~0; | ||
886 | } | ||
887 | |||
870 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; | 888 | fval = (hcrx->ccid3hcrx_s * 100000) / tmp2; |
871 | /* do not alter order above or you will get overflow on 32 bit */ | 889 | /* do not alter order above or you will get overflow on 32 bit */ |
872 | p = tfrc_calc_x_reverse_lookup(fval); | 890 | p = tfrc_calc_x_reverse_lookup(fval); |
@@ -882,31 +900,101 @@ found: | |||
882 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) | 900 | static void ccid3_hc_rx_update_li(struct sock *sk, u64 seq_loss, u8 win_loss) |
883 | { | 901 | { |
884 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 902 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
903 | struct dccp_li_hist_entry *next, *head; | ||
904 | u64 seq_temp; | ||
885 | 905 | ||
886 | if (seq_loss != DCCP_MAX_SEQNO + 1 && | 906 | if (list_empty(&hcrx->ccid3hcrx_li_hist)) { |
887 | list_empty(&hcrx->ccid3hcrx_li_hist)) { | 907 | if (!dccp_li_hist_interval_new(ccid3_li_hist, |
888 | struct dccp_li_hist_entry *li_tail; | 908 | &hcrx->ccid3hcrx_li_hist, seq_loss, win_loss)) |
909 | return; | ||
889 | 910 | ||
890 | li_tail = dccp_li_hist_interval_new(ccid3_li_hist, | 911 | next = (struct dccp_li_hist_entry *) |
891 | &hcrx->ccid3hcrx_li_hist, | 912 | hcrx->ccid3hcrx_li_hist.next; |
892 | seq_loss, win_loss); | 913 | next->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); |
893 | if (li_tail == NULL) | 914 | } else { |
915 | struct dccp_li_hist_entry *entry; | ||
916 | struct list_head *tail; | ||
917 | |||
918 | head = (struct dccp_li_hist_entry *) | ||
919 | hcrx->ccid3hcrx_li_hist.next; | ||
920 | /* FIXME win count check removed as was wrong */ | ||
921 | /* should make this check with receive history */ | ||
922 | /* and compare there as per section 10.2 of RFC4342 */ | ||
923 | |||
924 | /* new loss event detected */ | ||
925 | /* calculate last interval length */ | ||
926 | seq_temp = dccp_delta_seqno(head->dccplih_seqno, seq_loss); | ||
927 | entry = dccp_li_hist_entry_new(ccid3_li_hist, SLAB_ATOMIC); | ||
928 | |||
929 | if (entry == NULL) { | ||
930 | printk(KERN_CRIT "%s: out of memory\n",__FUNCTION__); | ||
931 | dump_stack(); | ||
894 | return; | 932 | return; |
895 | li_tail->dccplih_interval = ccid3_hc_rx_calc_first_li(sk); | 933 | } |
896 | } else | 934 | |
897 | LIMIT_NETDEBUG(KERN_WARNING "%s: FIXME: find end of " | 935 | list_add(&entry->dccplih_node, &hcrx->ccid3hcrx_li_hist); |
898 | "interval\n", __FUNCTION__); | 936 | |
937 | tail = hcrx->ccid3hcrx_li_hist.prev; | ||
938 | list_del(tail); | ||
939 | kmem_cache_free(ccid3_li_hist->dccplih_slab, tail); | ||
940 | |||
941 | /* Create the newest interval */ | ||
942 | entry->dccplih_seqno = seq_loss; | ||
943 | entry->dccplih_interval = seq_temp; | ||
944 | entry->dccplih_win_count = win_loss; | ||
945 | } | ||
899 | } | 946 | } |
900 | 947 | ||
901 | static void ccid3_hc_rx_detect_loss(struct sock *sk) | 948 | static int ccid3_hc_rx_detect_loss(struct sock *sk, |
949 | struct dccp_rx_hist_entry *packet) | ||
902 | { | 950 | { |
903 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); | 951 | struct ccid3_hc_rx_sock *hcrx = ccid3_hc_rx_sk(sk); |
904 | u8 win_loss; | 952 | struct dccp_rx_hist_entry *rx_hist = dccp_rx_hist_head(&hcrx->ccid3hcrx_hist); |
905 | const u64 seq_loss = dccp_rx_hist_detect_loss(&hcrx->ccid3hcrx_hist, | 953 | u64 seqno = packet->dccphrx_seqno; |
906 | &hcrx->ccid3hcrx_li_hist, | 954 | u64 tmp_seqno; |
907 | &win_loss); | 955 | int loss = 0; |
956 | u8 ccval; | ||
957 | |||
958 | |||
959 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; | ||
960 | |||
961 | if (!rx_hist || | ||
962 | follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { | ||
963 | hcrx->ccid3hcrx_seqno_nonloss = seqno; | ||
964 | hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; | ||
965 | goto detect_out; | ||
966 | } | ||
967 | |||
908 | 968 | ||
909 | ccid3_hc_rx_update_li(sk, seq_loss, win_loss); | 969 | while (dccp_delta_seqno(hcrx->ccid3hcrx_seqno_nonloss, seqno) |
970 | > TFRC_RECV_NUM_LATE_LOSS) { | ||
971 | loss = 1; | ||
972 | ccid3_hc_rx_update_li(sk, hcrx->ccid3hcrx_seqno_nonloss, | ||
973 | hcrx->ccid3hcrx_ccval_nonloss); | ||
974 | tmp_seqno = hcrx->ccid3hcrx_seqno_nonloss; | ||
975 | dccp_inc_seqno(&tmp_seqno); | ||
976 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | ||
977 | dccp_inc_seqno(&tmp_seqno); | ||
978 | while (dccp_rx_hist_find_entry(&hcrx->ccid3hcrx_hist, | ||
979 | tmp_seqno, &ccval)) { | ||
980 | hcrx->ccid3hcrx_seqno_nonloss = tmp_seqno; | ||
981 | hcrx->ccid3hcrx_ccval_nonloss = ccval; | ||
982 | dccp_inc_seqno(&tmp_seqno); | ||
983 | } | ||
984 | } | ||
985 | |||
986 | /* FIXME - this code could be simplified with above while */ | ||
987 | /* but works at moment */ | ||
988 | if (follows48(packet->dccphrx_seqno, hcrx->ccid3hcrx_seqno_nonloss)) { | ||
989 | hcrx->ccid3hcrx_seqno_nonloss = seqno; | ||
990 | hcrx->ccid3hcrx_ccval_nonloss = packet->dccphrx_ccval; | ||
991 | } | ||
992 | |||
993 | detect_out: | ||
994 | dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, | ||
995 | &hcrx->ccid3hcrx_li_hist, packet, | ||
996 | hcrx->ccid3hcrx_seqno_nonloss); | ||
997 | return loss; | ||
910 | } | 998 | } |
911 | 999 | ||
912 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | 1000 | static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) |
@@ -916,8 +1004,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
916 | struct dccp_rx_hist_entry *packet; | 1004 | struct dccp_rx_hist_entry *packet; |
917 | struct timeval now; | 1005 | struct timeval now; |
918 | u8 win_count; | 1006 | u8 win_count; |
919 | u32 p_prev, r_sample, t_elapsed; | 1007 | u32 p_prev, rtt_prev, r_sample, t_elapsed; |
920 | int ins; | 1008 | int loss; |
921 | 1009 | ||
922 | BUG_ON(hcrx == NULL || | 1010 | BUG_ON(hcrx == NULL || |
923 | !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || | 1011 | !(hcrx->ccid3hcrx_state == TFRC_RSTATE_NO_DATA || |
@@ -932,7 +1020,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
932 | case DCCP_PKT_DATAACK: | 1020 | case DCCP_PKT_DATAACK: |
933 | if (opt_recv->dccpor_timestamp_echo == 0) | 1021 | if (opt_recv->dccpor_timestamp_echo == 0) |
934 | break; | 1022 | break; |
935 | p_prev = hcrx->ccid3hcrx_rtt; | 1023 | rtt_prev = hcrx->ccid3hcrx_rtt; |
936 | dccp_timestamp(sk, &now); | 1024 | dccp_timestamp(sk, &now); |
937 | timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); | 1025 | timeval_sub_usecs(&now, opt_recv->dccpor_timestamp_echo * 10); |
938 | r_sample = timeval_usecs(&now); | 1026 | r_sample = timeval_usecs(&now); |
@@ -951,8 +1039,8 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
951 | hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + | 1039 | hcrx->ccid3hcrx_rtt = (hcrx->ccid3hcrx_rtt * 9) / 10 + |
952 | r_sample / 10; | 1040 | r_sample / 10; |
953 | 1041 | ||
954 | if (p_prev != hcrx->ccid3hcrx_rtt) | 1042 | if (rtt_prev != hcrx->ccid3hcrx_rtt) |
955 | ccid3_pr_debug("%s, New RTT=%luus, elapsed time=%u\n", | 1043 | ccid3_pr_debug("%s, New RTT=%uus, elapsed time=%u\n", |
956 | dccp_role(sk), hcrx->ccid3hcrx_rtt, | 1044 | dccp_role(sk), hcrx->ccid3hcrx_rtt, |
957 | opt_recv->dccpor_elapsed_time); | 1045 | opt_recv->dccpor_elapsed_time); |
958 | break; | 1046 | break; |
@@ -973,8 +1061,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
973 | 1061 | ||
974 | win_count = packet->dccphrx_ccval; | 1062 | win_count = packet->dccphrx_ccval; |
975 | 1063 | ||
976 | ins = dccp_rx_hist_add_packet(ccid3_rx_hist, &hcrx->ccid3hcrx_hist, | 1064 | loss = ccid3_hc_rx_detect_loss(sk, packet); |
977 | &hcrx->ccid3hcrx_li_hist, packet); | ||
978 | 1065 | ||
979 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) | 1066 | if (DCCP_SKB_CB(skb)->dccpd_type == DCCP_PKT_ACK) |
980 | return; | 1067 | return; |
@@ -991,7 +1078,7 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
991 | case TFRC_RSTATE_DATA: | 1078 | case TFRC_RSTATE_DATA: |
992 | hcrx->ccid3hcrx_bytes_recv += skb->len - | 1079 | hcrx->ccid3hcrx_bytes_recv += skb->len - |
993 | dccp_hdr(skb)->dccph_doff * 4; | 1080 | dccp_hdr(skb)->dccph_doff * 4; |
994 | if (ins != 0) | 1081 | if (loss) |
995 | break; | 1082 | break; |
996 | 1083 | ||
997 | dccp_timestamp(sk, &now); | 1084 | dccp_timestamp(sk, &now); |
@@ -1012,7 +1099,6 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1012 | ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", | 1099 | ccid3_pr_debug("%s, sk=%p(%s), data loss! Reacting...\n", |
1013 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); | 1100 | dccp_role(sk), sk, dccp_state_name(sk->sk_state)); |
1014 | 1101 | ||
1015 | ccid3_hc_rx_detect_loss(sk); | ||
1016 | p_prev = hcrx->ccid3hcrx_p; | 1102 | p_prev = hcrx->ccid3hcrx_p; |
1017 | 1103 | ||
1018 | /* Calculate loss event rate */ | 1104 | /* Calculate loss event rate */ |
@@ -1022,6 +1108,9 @@ static void ccid3_hc_rx_packet_recv(struct sock *sk, struct sk_buff *skb) | |||
1022 | /* Scaling up by 1000000 as fixed decimal */ | 1108 | /* Scaling up by 1000000 as fixed decimal */ |
1023 | if (i_mean != 0) | 1109 | if (i_mean != 0) |
1024 | hcrx->ccid3hcrx_p = 1000000 / i_mean; | 1110 | hcrx->ccid3hcrx_p = 1000000 / i_mean; |
1111 | } else { | ||
1112 | printk(KERN_CRIT "%s: empty loss hist\n",__FUNCTION__); | ||
1113 | dump_stack(); | ||
1025 | } | 1114 | } |
1026 | 1115 | ||
1027 | if (hcrx->ccid3hcrx_p > p_prev) { | 1116 | if (hcrx->ccid3hcrx_p > p_prev) { |
@@ -1230,7 +1319,7 @@ static __exit void ccid3_module_exit(void) | |||
1230 | } | 1319 | } |
1231 | module_exit(ccid3_module_exit); | 1320 | module_exit(ccid3_module_exit); |
1232 | 1321 | ||
1233 | MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " | 1322 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
1234 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 1323 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
1235 | MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); | 1324 | MODULE_DESCRIPTION("DCCP TFRC CCID3 CCID"); |
1236 | MODULE_LICENSE("GPL"); | 1325 | MODULE_LICENSE("GPL"); |
diff --git a/net/dccp/ccids/ccid3.h b/net/dccp/ccids/ccid3.h index 5ade4f668b22..0a2cb7536d26 100644 --- a/net/dccp/ccids/ccid3.h +++ b/net/dccp/ccids/ccid3.h | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/ccids/ccid3.h | 2 | * net/dccp/ccids/ccid3.h |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. |
5 | * | 5 | * |
6 | * An implementation of the DCCP protocol | 6 | * An implementation of the DCCP protocol |
7 | * | 7 | * |
8 | * This code has been developed by the University of Waikato WAND | 8 | * This code has been developed by the University of Waikato WAND |
9 | * research group. For further information please see http://www.wand.net.nz/ | 9 | * research group. For further information please see http://www.wand.net.nz/ |
10 | * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz | 10 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz |
11 | * | 11 | * |
12 | * This code also uses code from Lulea University, rereleased as GPL by its | 12 | * This code also uses code from Lulea University, rereleased as GPL by its |
13 | * authors: | 13 | * authors: |
@@ -120,9 +120,10 @@ struct ccid3_hc_rx_sock { | |||
120 | #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv | 120 | #define ccid3hcrx_x_recv ccid3hcrx_tfrc.tfrcrx_x_recv |
121 | #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt | 121 | #define ccid3hcrx_rtt ccid3hcrx_tfrc.tfrcrx_rtt |
122 | #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p | 122 | #define ccid3hcrx_p ccid3hcrx_tfrc.tfrcrx_p |
123 | u64 ccid3hcrx_seqno_last_counter:48, | 123 | u64 ccid3hcrx_seqno_nonloss:48, |
124 | ccid3hcrx_ccval_nonloss:4, | ||
124 | ccid3hcrx_state:8, | 125 | ccid3hcrx_state:8, |
125 | ccid3hcrx_last_counter:4; | 126 | ccid3hcrx_ccval_last_counter:4; |
126 | u32 ccid3hcrx_bytes_recv; | 127 | u32 ccid3hcrx_bytes_recv; |
127 | struct timeval ccid3hcrx_tstamp_last_feedback; | 128 | struct timeval ccid3hcrx_tstamp_last_feedback; |
128 | struct timeval ccid3hcrx_tstamp_last_ack; | 129 | struct timeval ccid3hcrx_tstamp_last_ack; |
diff --git a/net/dccp/ccids/lib/loss_interval.c b/net/dccp/ccids/lib/loss_interval.c index 5d7b7d864385..906c81ab9d4f 100644 --- a/net/dccp/ccids/lib/loss_interval.c +++ b/net/dccp/ccids/lib/loss_interval.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/dccp/ccids/lib/loss_interval.c | 2 | * net/dccp/ccids/lib/loss_interval.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
5 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 5 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> |
6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
@@ -12,6 +12,7 @@ | |||
12 | */ | 12 | */ |
13 | 13 | ||
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <net/sock.h> | ||
15 | 16 | ||
16 | #include "loss_interval.h" | 17 | #include "loss_interval.h" |
17 | 18 | ||
@@ -90,13 +91,13 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) | |||
90 | u32 w_tot = 0; | 91 | u32 w_tot = 0; |
91 | 92 | ||
92 | list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { | 93 | list_for_each_entry_safe(li_entry, li_next, list, dccplih_node) { |
93 | if (i < DCCP_LI_HIST_IVAL_F_LENGTH) { | 94 | if (li_entry->dccplih_interval != ~0) { |
94 | i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; | 95 | i_tot0 += li_entry->dccplih_interval * dccp_li_hist_w[i]; |
95 | w_tot += dccp_li_hist_w[i]; | 96 | w_tot += dccp_li_hist_w[i]; |
97 | if (i != 0) | ||
98 | i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; | ||
96 | } | 99 | } |
97 | 100 | ||
98 | if (i != 0) | ||
99 | i_tot1 += li_entry->dccplih_interval * dccp_li_hist_w[i - 1]; | ||
100 | 101 | ||
101 | if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) | 102 | if (++i > DCCP_LI_HIST_IVAL_F_LENGTH) |
102 | break; | 103 | break; |
@@ -107,37 +108,36 @@ u32 dccp_li_hist_calc_i_mean(struct list_head *list) | |||
107 | 108 | ||
108 | i_tot = max(i_tot0, i_tot1); | 109 | i_tot = max(i_tot0, i_tot1); |
109 | 110 | ||
110 | /* FIXME: Why do we do this? -Ian McDonald */ | 111 | if (!w_tot) { |
111 | if (i_tot * 4 < w_tot) | 112 | LIMIT_NETDEBUG(KERN_WARNING "%s: w_tot = 0\n", __FUNCTION__); |
112 | i_tot = w_tot * 4; | 113 | return 1; |
114 | } | ||
113 | 115 | ||
114 | return i_tot * 4 / w_tot; | 116 | return i_tot / w_tot; |
115 | } | 117 | } |
116 | 118 | ||
117 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); | 119 | EXPORT_SYMBOL_GPL(dccp_li_hist_calc_i_mean); |
118 | 120 | ||
119 | struct dccp_li_hist_entry *dccp_li_hist_interval_new(struct dccp_li_hist *hist, | 121 | int dccp_li_hist_interval_new(struct dccp_li_hist *hist, |
120 | struct list_head *list, | 122 | struct list_head *list, const u64 seq_loss, const u8 win_loss) |
121 | const u64 seq_loss, | ||
122 | const u8 win_loss) | ||
123 | { | 123 | { |
124 | struct dccp_li_hist_entry *tail = NULL, *entry; | 124 | struct dccp_li_hist_entry *entry; |
125 | int i; | 125 | int i; |
126 | 126 | ||
127 | for (i = 0; i <= DCCP_LI_HIST_IVAL_F_LENGTH; ++i) { | 127 | for (i = 0; i < DCCP_LI_HIST_IVAL_F_LENGTH; i++) { |
128 | entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); | 128 | entry = dccp_li_hist_entry_new(hist, SLAB_ATOMIC); |
129 | if (entry == NULL) { | 129 | if (entry == NULL) { |
130 | dccp_li_hist_purge(hist, list); | 130 | dccp_li_hist_purge(hist, list); |
131 | return NULL; | 131 | dump_stack(); |
132 | return 0; | ||
132 | } | 133 | } |
133 | if (tail == NULL) | 134 | entry->dccplih_interval = ~0; |
134 | tail = entry; | ||
135 | list_add(&entry->dccplih_node, list); | 135 | list_add(&entry->dccplih_node, list); |
136 | } | 136 | } |
137 | 137 | ||
138 | entry->dccplih_seqno = seq_loss; | 138 | entry->dccplih_seqno = seq_loss; |
139 | entry->dccplih_win_count = win_loss; | 139 | entry->dccplih_win_count = win_loss; |
140 | return tail; | 140 | return 1; |
141 | } | 141 | } |
142 | 142 | ||
143 | EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); | 143 | EXPORT_SYMBOL_GPL(dccp_li_hist_interval_new); |
diff --git a/net/dccp/ccids/lib/loss_interval.h b/net/dccp/ccids/lib/loss_interval.h index 43bf78269d1d..0ae85f0340b2 100644 --- a/net/dccp/ccids/lib/loss_interval.h +++ b/net/dccp/ccids/lib/loss_interval.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * net/dccp/ccids/lib/loss_interval.h | 4 | * net/dccp/ccids/lib/loss_interval.h |
5 | * | 5 | * |
6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
7 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 7 | * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz> |
8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
@@ -52,9 +52,6 @@ extern void dccp_li_hist_purge(struct dccp_li_hist *hist, | |||
52 | 52 | ||
53 | extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); | 53 | extern u32 dccp_li_hist_calc_i_mean(struct list_head *list); |
54 | 54 | ||
55 | extern struct dccp_li_hist_entry * | 55 | extern int dccp_li_hist_interval_new(struct dccp_li_hist *hist, |
56 | dccp_li_hist_interval_new(struct dccp_li_hist *hist, | 56 | struct list_head *list, const u64 seq_loss, const u8 win_loss); |
57 | struct list_head *list, | ||
58 | const u64 seq_loss, | ||
59 | const u8 win_loss); | ||
60 | #endif /* _DCCP_LI_HIST_ */ | 57 | #endif /* _DCCP_LI_HIST_ */ |
diff --git a/net/dccp/ccids/lib/packet_history.c b/net/dccp/ccids/lib/packet_history.c index ad98d6a322eb..b876c9c81c65 100644 --- a/net/dccp/ccids/lib/packet_history.c +++ b/net/dccp/ccids/lib/packet_history.c | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/packet_history.h | 2 | * net/dccp/packet_history.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. |
5 | * | 5 | * |
6 | * An implementation of the DCCP protocol | 6 | * An implementation of the DCCP protocol |
7 | * | 7 | * |
8 | * This code has been developed by the University of Waikato WAND | 8 | * This code has been developed by the University of Waikato WAND |
9 | * research group. For further information please see http://www.wand.net.nz/ | 9 | * research group. For further information please see http://www.wand.net.nz/ |
10 | * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz | 10 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz |
11 | * | 11 | * |
12 | * This code also uses code from Lulea University, rereleased as GPL by its | 12 | * This code also uses code from Lulea University, rereleased as GPL by its |
13 | * authors: | 13 | * authors: |
@@ -112,64 +112,27 @@ struct dccp_rx_hist_entry * | |||
112 | 112 | ||
113 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); | 113 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_data_packet); |
114 | 114 | ||
115 | int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | 115 | void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, |
116 | struct list_head *rx_list, | 116 | struct list_head *rx_list, |
117 | struct list_head *li_list, | 117 | struct list_head *li_list, |
118 | struct dccp_rx_hist_entry *packet) | 118 | struct dccp_rx_hist_entry *packet, |
119 | u64 nonloss_seqno) | ||
119 | { | 120 | { |
120 | struct dccp_rx_hist_entry *entry, *next, *iter; | 121 | struct dccp_rx_hist_entry *entry, *next; |
121 | u8 num_later = 0; | 122 | u8 num_later = 0; |
122 | 123 | ||
123 | iter = dccp_rx_hist_head(rx_list); | 124 | list_add(&packet->dccphrx_node, rx_list); |
124 | if (iter == NULL) | ||
125 | dccp_rx_hist_add_entry(rx_list, packet); | ||
126 | else { | ||
127 | const u64 seqno = packet->dccphrx_seqno; | ||
128 | |||
129 | if (after48(seqno, iter->dccphrx_seqno)) | ||
130 | dccp_rx_hist_add_entry(rx_list, packet); | ||
131 | else { | ||
132 | if (dccp_rx_hist_entry_data_packet(iter)) | ||
133 | num_later = 1; | ||
134 | |||
135 | list_for_each_entry_continue(iter, rx_list, | ||
136 | dccphrx_node) { | ||
137 | if (after48(seqno, iter->dccphrx_seqno)) { | ||
138 | dccp_rx_hist_add_entry(&iter->dccphrx_node, | ||
139 | packet); | ||
140 | goto trim_history; | ||
141 | } | ||
142 | |||
143 | if (dccp_rx_hist_entry_data_packet(iter)) | ||
144 | num_later++; | ||
145 | 125 | ||
146 | if (num_later == TFRC_RECV_NUM_LATE_LOSS) { | ||
147 | dccp_rx_hist_entry_delete(hist, packet); | ||
148 | return 1; | ||
149 | } | ||
150 | } | ||
151 | |||
152 | if (num_later < TFRC_RECV_NUM_LATE_LOSS) | ||
153 | dccp_rx_hist_add_entry(rx_list, packet); | ||
154 | /* | ||
155 | * FIXME: else what? should we destroy the packet | ||
156 | * like above? | ||
157 | */ | ||
158 | } | ||
159 | } | ||
160 | |||
161 | trim_history: | ||
162 | /* | ||
163 | * Trim history (remove all packets after the NUM_LATE_LOSS + 1 | ||
164 | * data packets) | ||
165 | */ | ||
166 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; | 126 | num_later = TFRC_RECV_NUM_LATE_LOSS + 1; |
167 | 127 | ||
168 | if (!list_empty(li_list)) { | 128 | if (!list_empty(li_list)) { |
169 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { | 129 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { |
170 | if (num_later == 0) { | 130 | if (num_later == 0) { |
171 | list_del_init(&entry->dccphrx_node); | 131 | if (after48(nonloss_seqno, |
172 | dccp_rx_hist_entry_delete(hist, entry); | 132 | entry->dccphrx_seqno)) { |
133 | list_del_init(&entry->dccphrx_node); | ||
134 | dccp_rx_hist_entry_delete(hist, entry); | ||
135 | } | ||
173 | } else if (dccp_rx_hist_entry_data_packet(entry)) | 136 | } else if (dccp_rx_hist_entry_data_packet(entry)) |
174 | --num_later; | 137 | --num_later; |
175 | } | 138 | } |
@@ -217,94 +180,10 @@ trim_history: | |||
217 | --num_later; | 180 | --num_later; |
218 | } | 181 | } |
219 | } | 182 | } |
220 | |||
221 | return 0; | ||
222 | } | 183 | } |
223 | 184 | ||
224 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); | 185 | EXPORT_SYMBOL_GPL(dccp_rx_hist_add_packet); |
225 | 186 | ||
226 | u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, | ||
227 | struct list_head *li_list, u8 *win_loss) | ||
228 | { | ||
229 | struct dccp_rx_hist_entry *entry, *next, *packet; | ||
230 | struct dccp_rx_hist_entry *a_loss = NULL; | ||
231 | struct dccp_rx_hist_entry *b_loss = NULL; | ||
232 | u64 seq_loss = DCCP_MAX_SEQNO + 1; | ||
233 | u8 num_later = TFRC_RECV_NUM_LATE_LOSS; | ||
234 | |||
235 | list_for_each_entry_safe(entry, next, rx_list, dccphrx_node) { | ||
236 | if (num_later == 0) { | ||
237 | b_loss = entry; | ||
238 | break; | ||
239 | } else if (dccp_rx_hist_entry_data_packet(entry)) | ||
240 | --num_later; | ||
241 | } | ||
242 | |||
243 | if (b_loss == NULL) | ||
244 | goto out; | ||
245 | |||
246 | num_later = 1; | ||
247 | list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { | ||
248 | if (num_later == 0) { | ||
249 | a_loss = entry; | ||
250 | break; | ||
251 | } else if (dccp_rx_hist_entry_data_packet(entry)) | ||
252 | --num_later; | ||
253 | } | ||
254 | |||
255 | if (a_loss == NULL) { | ||
256 | if (list_empty(li_list)) { | ||
257 | /* no loss event have occured yet */ | ||
258 | LIMIT_NETDEBUG("%s: TODO: find a lost data packet by " | ||
259 | "comparing to initial seqno\n", | ||
260 | __FUNCTION__); | ||
261 | goto out; | ||
262 | } else { | ||
263 | LIMIT_NETDEBUG("%s: Less than 4 data pkts in history!", | ||
264 | __FUNCTION__); | ||
265 | goto out; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | /* Locate a lost data packet */ | ||
270 | entry = packet = b_loss; | ||
271 | list_for_each_entry_safe_continue(entry, next, rx_list, dccphrx_node) { | ||
272 | u64 delta = dccp_delta_seqno(entry->dccphrx_seqno, | ||
273 | packet->dccphrx_seqno); | ||
274 | |||
275 | if (delta != 0) { | ||
276 | if (dccp_rx_hist_entry_data_packet(packet)) | ||
277 | --delta; | ||
278 | /* | ||
279 | * FIXME: check this, probably this % usage is because | ||
280 | * in earlier drafts the ndp count was just 8 bits | ||
281 | * long, but now it cam be up to 24 bits long. | ||
282 | */ | ||
283 | #if 0 | ||
284 | if (delta % DCCP_NDP_LIMIT != | ||
285 | (packet->dccphrx_ndp - | ||
286 | entry->dccphrx_ndp) % DCCP_NDP_LIMIT) | ||
287 | #endif | ||
288 | if (delta != packet->dccphrx_ndp - entry->dccphrx_ndp) { | ||
289 | seq_loss = entry->dccphrx_seqno; | ||
290 | dccp_inc_seqno(&seq_loss); | ||
291 | } | ||
292 | } | ||
293 | packet = entry; | ||
294 | if (packet == a_loss) | ||
295 | break; | ||
296 | } | ||
297 | out: | ||
298 | if (seq_loss != DCCP_MAX_SEQNO + 1) | ||
299 | *win_loss = a_loss->dccphrx_ccval; | ||
300 | else | ||
301 | *win_loss = 0; /* Paranoia */ | ||
302 | |||
303 | return seq_loss; | ||
304 | } | ||
305 | |||
306 | EXPORT_SYMBOL_GPL(dccp_rx_hist_detect_loss); | ||
307 | |||
308 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) | 187 | struct dccp_tx_hist *dccp_tx_hist_new(const char *name) |
309 | { | 188 | { |
310 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); | 189 | struct dccp_tx_hist *hist = kmalloc(sizeof(*hist), GFP_ATOMIC); |
@@ -365,6 +244,25 @@ struct dccp_tx_hist_entry * | |||
365 | 244 | ||
366 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); | 245 | EXPORT_SYMBOL_GPL(dccp_tx_hist_find_entry); |
367 | 246 | ||
247 | int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
248 | u8 *ccval) | ||
249 | { | ||
250 | struct dccp_rx_hist_entry *packet = NULL, *entry; | ||
251 | |||
252 | list_for_each_entry(entry, list, dccphrx_node) | ||
253 | if (entry->dccphrx_seqno == seq) { | ||
254 | packet = entry; | ||
255 | break; | ||
256 | } | ||
257 | |||
258 | if (packet) | ||
259 | *ccval = packet->dccphrx_ccval; | ||
260 | |||
261 | return packet != NULL; | ||
262 | } | ||
263 | |||
264 | EXPORT_SYMBOL_GPL(dccp_rx_hist_find_entry); | ||
265 | |||
368 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, | 266 | void dccp_tx_hist_purge_older(struct dccp_tx_hist *hist, |
369 | struct list_head *list, | 267 | struct list_head *list, |
370 | struct dccp_tx_hist_entry *packet) | 268 | struct dccp_tx_hist_entry *packet) |
@@ -391,7 +289,7 @@ void dccp_tx_hist_purge(struct dccp_tx_hist *hist, struct list_head *list) | |||
391 | 289 | ||
392 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); | 290 | EXPORT_SYMBOL_GPL(dccp_tx_hist_purge); |
393 | 291 | ||
394 | MODULE_AUTHOR("Ian McDonald <iam4@cs.waikato.ac.nz>, " | 292 | MODULE_AUTHOR("Ian McDonald <ian.mcdonald@jandi.co.nz>, " |
395 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); | 293 | "Arnaldo Carvalho de Melo <acme@ghostprotocols.net>"); |
396 | MODULE_DESCRIPTION("DCCP TFRC library"); | 294 | MODULE_DESCRIPTION("DCCP TFRC library"); |
397 | MODULE_LICENSE("GPL"); | 295 | MODULE_LICENSE("GPL"); |
diff --git a/net/dccp/ccids/lib/packet_history.h b/net/dccp/ccids/lib/packet_history.h index 673c209e4e85..067cf1c85a37 100644 --- a/net/dccp/ccids/lib/packet_history.h +++ b/net/dccp/ccids/lib/packet_history.h | |||
@@ -1,13 +1,13 @@ | |||
1 | /* | 1 | /* |
2 | * net/dccp/packet_history.h | 2 | * net/dccp/packet_history.h |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005-6 The University of Waikato, Hamilton, New Zealand. |
5 | * | 5 | * |
6 | * An implementation of the DCCP protocol | 6 | * An implementation of the DCCP protocol |
7 | * | 7 | * |
8 | * This code has been developed by the University of Waikato WAND | 8 | * This code has been developed by the University of Waikato WAND |
9 | * research group. For further information please see http://www.wand.net.nz/ | 9 | * research group. For further information please see http://www.wand.net.nz/ |
10 | * or e-mail Ian McDonald - iam4@cs.waikato.ac.nz | 10 | * or e-mail Ian McDonald - ian.mcdonald@jandi.co.nz |
11 | * | 11 | * |
12 | * This code also uses code from Lulea University, rereleased as GPL by its | 12 | * This code also uses code from Lulea University, rereleased as GPL by its |
13 | * authors: | 13 | * authors: |
@@ -106,6 +106,8 @@ static inline void dccp_tx_hist_entry_delete(struct dccp_tx_hist *hist, | |||
106 | extern struct dccp_tx_hist_entry * | 106 | extern struct dccp_tx_hist_entry * |
107 | dccp_tx_hist_find_entry(const struct list_head *list, | 107 | dccp_tx_hist_find_entry(const struct list_head *list, |
108 | const u64 seq); | 108 | const u64 seq); |
109 | extern int dccp_rx_hist_find_entry(const struct list_head *list, const u64 seq, | ||
110 | u8 *ccval); | ||
109 | 111 | ||
110 | static inline void dccp_tx_hist_add_entry(struct list_head *list, | 112 | static inline void dccp_tx_hist_add_entry(struct list_head *list, |
111 | struct dccp_tx_hist_entry *entry) | 113 | struct dccp_tx_hist_entry *entry) |
@@ -164,12 +166,6 @@ static inline void dccp_rx_hist_entry_delete(struct dccp_rx_hist *hist, | |||
164 | extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, | 166 | extern void dccp_rx_hist_purge(struct dccp_rx_hist *hist, |
165 | struct list_head *list); | 167 | struct list_head *list); |
166 | 168 | ||
167 | static inline void dccp_rx_hist_add_entry(struct list_head *list, | ||
168 | struct dccp_rx_hist_entry *entry) | ||
169 | { | ||
170 | list_add(&entry->dccphrx_node, list); | ||
171 | } | ||
172 | |||
173 | static inline struct dccp_rx_hist_entry * | 169 | static inline struct dccp_rx_hist_entry * |
174 | dccp_rx_hist_head(struct list_head *list) | 170 | dccp_rx_hist_head(struct list_head *list) |
175 | { | 171 | { |
@@ -188,10 +184,11 @@ static inline int | |||
188 | entry->dccphrx_type == DCCP_PKT_DATAACK; | 184 | entry->dccphrx_type == DCCP_PKT_DATAACK; |
189 | } | 185 | } |
190 | 186 | ||
191 | extern int dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, | 187 | extern void dccp_rx_hist_add_packet(struct dccp_rx_hist *hist, |
192 | struct list_head *rx_list, | 188 | struct list_head *rx_list, |
193 | struct list_head *li_list, | 189 | struct list_head *li_list, |
194 | struct dccp_rx_hist_entry *packet); | 190 | struct dccp_rx_hist_entry *packet, |
191 | u64 nonloss_seqno); | ||
195 | 192 | ||
196 | extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, | 193 | extern u64 dccp_rx_hist_detect_loss(struct list_head *rx_list, |
197 | struct list_head *li_list, u8 *win_loss); | 194 | struct list_head *li_list, u8 *win_loss); |
diff --git a/net/dccp/ccids/lib/tfrc.h b/net/dccp/ccids/lib/tfrc.h index 130c4c40cfe3..45f30f59ea2a 100644 --- a/net/dccp/ccids/lib/tfrc.h +++ b/net/dccp/ccids/lib/tfrc.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * net/dccp/ccids/lib/tfrc.h | 4 | * net/dccp/ccids/lib/tfrc.h |
5 | * | 5 | * |
6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 6 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
7 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 7 | * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz> |
8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 8 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
9 | * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon | 9 | * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon |
10 | * | 10 | * |
diff --git a/net/dccp/ccids/lib/tfrc_equation.c b/net/dccp/ccids/lib/tfrc_equation.c index 4fd2ebebf5a0..44076e0c6591 100644 --- a/net/dccp/ccids/lib/tfrc_equation.c +++ b/net/dccp/ccids/lib/tfrc_equation.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/dccp/ccids/lib/tfrc_equation.c | 2 | * net/dccp/ccids/lib/tfrc_equation.c |
3 | * | 3 | * |
4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. | 4 | * Copyright (c) 2005 The University of Waikato, Hamilton, New Zealand. |
5 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 5 | * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz> |
6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
7 | * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon | 7 | * Copyright (c) 2003 Nils-Erik Mattsson, Joacim Haggmark, Magnus Erixzon |
8 | * | 8 | * |
diff --git a/net/dccp/dccp.h b/net/dccp/dccp.h index d00a2f4ee5dd..a5c5475724c0 100644 --- a/net/dccp/dccp.h +++ b/net/dccp/dccp.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * | 5 | * |
6 | * An implementation of the DCCP protocol | 6 | * An implementation of the DCCP protocol |
7 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> | 7 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@conectiva.com.br> |
8 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 8 | * Copyright (c) 2005-6 Ian McDonald <ian.mcdonald@jandi.co.nz> |
9 | * | 9 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 10 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License version 2 as | 11 | * under the terms of the GNU General Public License version 2 as |
@@ -81,6 +81,14 @@ static inline u64 max48(const u64 seq1, const u64 seq2) | |||
81 | return after48(seq1, seq2) ? seq1 : seq2; | 81 | return after48(seq1, seq2) ? seq1 : seq2; |
82 | } | 82 | } |
83 | 83 | ||
84 | /* is seq1 next seqno after seq2 */ | ||
85 | static inline int follows48(const u64 seq1, const u64 seq2) | ||
86 | { | ||
87 | int diff = (seq1 & 0xFFFF) - (seq2 & 0xFFFF); | ||
88 | |||
89 | return diff==1; | ||
90 | } | ||
91 | |||
84 | enum { | 92 | enum { |
85 | DCCP_MIB_NUM = 0, | 93 | DCCP_MIB_NUM = 0, |
86 | DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */ | 94 | DCCP_MIB_ACTIVEOPENS, /* ActiveOpens */ |
diff --git a/net/dccp/options.c b/net/dccp/options.c index daf72bb671f0..07a34696ac97 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * An implementation of the DCCP protocol | 4 | * An implementation of the DCCP protocol |
5 | * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> | 5 | * Copyright (c) 2005 Aristeu Sergio Rozanski Filho <aris@cathedrallabs.org> |
6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> | 6 | * Copyright (c) 2005 Arnaldo Carvalho de Melo <acme@ghostprotocols.net> |
7 | * Copyright (c) 2005 Ian McDonald <iam4@cs.waikato.ac.nz> | 7 | * Copyright (c) 2005 Ian McDonald <ian.mcdonald@jandi.co.nz> |
8 | * | 8 | * |
9 | * This program is free software; you can redistribute it and/or | 9 | * This program is free software; you can redistribute it and/or |
10 | * modify it under the terms of the GNU General Public License | 10 | * modify it under the terms of the GNU General Public License |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index df4854cf598b..8d1d7a6e72a5 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -236,7 +236,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
236 | struct arpt_entry *e, *back; | 236 | struct arpt_entry *e, *back; |
237 | const char *indev, *outdev; | 237 | const char *indev, *outdev; |
238 | void *table_base; | 238 | void *table_base; |
239 | struct xt_table_info *private = table->private; | 239 | struct xt_table_info *private; |
240 | 240 | ||
241 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ | 241 | /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ |
242 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + | 242 | if (!pskb_may_pull((*pskb), (sizeof(struct arphdr) + |
@@ -248,6 +248,7 @@ unsigned int arpt_do_table(struct sk_buff **pskb, | |||
248 | outdev = out ? out->name : nulldevname; | 248 | outdev = out ? out->name : nulldevname; |
249 | 249 | ||
250 | read_lock_bh(&table->lock); | 250 | read_lock_bh(&table->lock); |
251 | private = table->private; | ||
251 | table_base = (void *)private->entries[smp_processor_id()]; | 252 | table_base = (void *)private->entries[smp_processor_id()]; |
252 | e = get_entry(table_base, private->hook_entry[hook]); | 253 | e = get_entry(table_base, private->hook_entry[hook]); |
253 | back = get_entry(table_base, private->underflow[hook]); | 254 | back = get_entry(table_base, private->underflow[hook]); |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 507adefbc17c..b4f3ffe1b3b4 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -201,6 +201,7 @@ void tcp_select_initial_window(int __space, __u32 mss, | |||
201 | * See RFC1323 for an explanation of the limit to 14 | 201 | * See RFC1323 for an explanation of the limit to 14 |
202 | */ | 202 | */ |
203 | space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); | 203 | space = max_t(u32, sysctl_tcp_rmem[2], sysctl_rmem_max); |
204 | space = min_t(u32, space, *window_clamp); | ||
204 | while (space > 65535 && (*rcv_wscale) < 14) { | 205 | while (space > 65535 && (*rcv_wscale) < 14) { |
205 | space >>= 1; | 206 | space >>= 1; |
206 | (*rcv_wscale)++; | 207 | (*rcv_wscale)++; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b843a650be71..802a1a6b1037 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -944,7 +944,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
944 | * comment in that function for the gory details. -acme | 944 | * comment in that function for the gory details. -acme |
945 | */ | 945 | */ |
946 | 946 | ||
947 | sk->sk_gso_type = SKB_GSO_TCPV6; | 947 | newsk->sk_gso_type = SKB_GSO_TCPV6; |
948 | __ip6_dst_store(newsk, dst, NULL); | 948 | __ip6_dst_store(newsk, dst, NULL); |
949 | 949 | ||
950 | newtcp6sk = (struct tcp6_sock *)newsk; | 950 | newtcp6sk = (struct tcp6_sock *)newsk; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 4f11f5858209..17b509282cf2 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -806,38 +806,26 @@ no_mem: | |||
806 | 806 | ||
807 | /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ | 807 | /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ |
808 | struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, | 808 | struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, |
809 | const struct sctp_chunk *chunk, | 809 | const struct msghdr *msg, |
810 | const struct msghdr *msg) | 810 | size_t paylen) |
811 | { | 811 | { |
812 | struct sctp_chunk *retval; | 812 | struct sctp_chunk *retval; |
813 | void *payload = NULL, *payoff; | 813 | void *payload = NULL; |
814 | size_t paylen = 0; | 814 | int err; |
815 | struct iovec *iov = NULL; | ||
816 | int iovlen = 0; | ||
817 | |||
818 | if (msg) { | ||
819 | iov = msg->msg_iov; | ||
820 | iovlen = msg->msg_iovlen; | ||
821 | paylen = get_user_iov_size(iov, iovlen); | ||
822 | } | ||
823 | 815 | ||
824 | retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); | 816 | retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen); |
825 | if (!retval) | 817 | if (!retval) |
826 | goto err_chunk; | 818 | goto err_chunk; |
827 | 819 | ||
828 | if (paylen) { | 820 | if (paylen) { |
829 | /* Put the msg_iov together into payload. */ | 821 | /* Put the msg_iov together into payload. */ |
830 | payload = kmalloc(paylen, GFP_ATOMIC); | 822 | payload = kmalloc(paylen, GFP_KERNEL); |
831 | if (!payload) | 823 | if (!payload) |
832 | goto err_payload; | 824 | goto err_payload; |
833 | payoff = payload; | ||
834 | 825 | ||
835 | for (; iovlen > 0; --iovlen) { | 826 | err = memcpy_fromiovec(payload, msg->msg_iov, paylen); |
836 | if (copy_from_user(payoff, iov->iov_base,iov->iov_len)) | 827 | if (err < 0) |
837 | goto err_copy; | 828 | goto err_copy; |
838 | payoff += iov->iov_len; | ||
839 | iov++; | ||
840 | } | ||
841 | } | 829 | } |
842 | 830 | ||
843 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); | 831 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index ead3f1b0ea3d..5b5ae7958322 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -4031,18 +4031,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4031 | * from its upper layer, but retransmits data to the far end | 4031 | * from its upper layer, but retransmits data to the far end |
4032 | * if necessary to fill gaps. | 4032 | * if necessary to fill gaps. |
4033 | */ | 4033 | */ |
4034 | struct msghdr *msg = arg; | 4034 | struct sctp_chunk *abort = arg; |
4035 | struct sctp_chunk *abort; | ||
4036 | sctp_disposition_t retval; | 4035 | sctp_disposition_t retval; |
4037 | 4036 | ||
4038 | retval = SCTP_DISPOSITION_CONSUME; | 4037 | retval = SCTP_DISPOSITION_CONSUME; |
4039 | 4038 | ||
4040 | /* Generate ABORT chunk to send the peer. */ | 4039 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
4041 | abort = sctp_make_abort_user(asoc, NULL, msg); | ||
4042 | if (!abort) | ||
4043 | retval = SCTP_DISPOSITION_NOMEM; | ||
4044 | else | ||
4045 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4046 | 4040 | ||
4047 | /* Even if we can't send the ABORT due to low memory delete the | 4041 | /* Even if we can't send the ABORT due to low memory delete the |
4048 | * TCB. This is a departure from our typical NOMEM handling. | 4042 | * TCB. This is a departure from our typical NOMEM handling. |
@@ -4166,8 +4160,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4166 | void *arg, | 4160 | void *arg, |
4167 | sctp_cmd_seq_t *commands) | 4161 | sctp_cmd_seq_t *commands) |
4168 | { | 4162 | { |
4169 | struct msghdr *msg = arg; | 4163 | struct sctp_chunk *abort = arg; |
4170 | struct sctp_chunk *abort; | ||
4171 | sctp_disposition_t retval; | 4164 | sctp_disposition_t retval; |
4172 | 4165 | ||
4173 | /* Stop T1-init timer */ | 4166 | /* Stop T1-init timer */ |
@@ -4175,12 +4168,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4175 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 4168 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
4176 | retval = SCTP_DISPOSITION_CONSUME; | 4169 | retval = SCTP_DISPOSITION_CONSUME; |
4177 | 4170 | ||
4178 | /* Generate ABORT chunk to send the peer */ | 4171 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
4179 | abort = sctp_make_abort_user(asoc, NULL, msg); | ||
4180 | if (!abort) | ||
4181 | retval = SCTP_DISPOSITION_NOMEM; | ||
4182 | else | ||
4183 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
4184 | 4172 | ||
4185 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4173 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4186 | SCTP_STATE(SCTP_STATE_CLOSED)); | 4174 | SCTP_STATE(SCTP_STATE_CLOSED)); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 54722e622e6d..fde3f55bfd4b 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -1520,8 +1520,16 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1520 | goto out_unlock; | 1520 | goto out_unlock; |
1521 | } | 1521 | } |
1522 | if (sinfo_flags & SCTP_ABORT) { | 1522 | if (sinfo_flags & SCTP_ABORT) { |
1523 | struct sctp_chunk *chunk; | ||
1524 | |||
1525 | chunk = sctp_make_abort_user(asoc, msg, msg_len); | ||
1526 | if (!chunk) { | ||
1527 | err = -ENOMEM; | ||
1528 | goto out_unlock; | ||
1529 | } | ||
1530 | |||
1523 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); | 1531 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); |
1524 | sctp_primitive_ABORT(asoc, msg); | 1532 | sctp_primitive_ABORT(asoc, chunk); |
1525 | err = 0; | 1533 | err = 0; |
1526 | goto out_unlock; | 1534 | goto out_unlock; |
1527 | } | 1535 | } |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 4a9aa9393b97..ef1cf5b476c8 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -718,8 +718,7 @@ gss_destroy(struct rpc_auth *auth) | |||
718 | auth, auth->au_flavor); | 718 | auth, auth->au_flavor); |
719 | 719 | ||
720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
721 | rpc_unlink(gss_auth->path); | 721 | rpc_unlink(gss_auth->dentry); |
722 | dput(gss_auth->dentry); | ||
723 | gss_auth->dentry = NULL; | 722 | gss_auth->dentry = NULL; |
724 | gss_mech_put(gss_auth->mech); | 723 | gss_mech_put(gss_auth->mech); |
725 | 724 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d6409e757219..3e19d321067a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -183,8 +183,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
183 | 183 | ||
184 | out_no_auth: | 184 | out_no_auth: |
185 | if (!IS_ERR(clnt->cl_dentry)) { | 185 | if (!IS_ERR(clnt->cl_dentry)) { |
186 | rpc_rmdir(clnt->cl_pathname); | 186 | rpc_rmdir(clnt->cl_dentry); |
187 | dput(clnt->cl_dentry); | ||
188 | rpc_put_mount(); | 187 | rpc_put_mount(); |
189 | } | 188 | } |
190 | out_no_path: | 189 | out_no_path: |
@@ -251,10 +250,8 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
251 | new->cl_autobind = 0; | 250 | new->cl_autobind = 0; |
252 | new->cl_oneshot = 0; | 251 | new->cl_oneshot = 0; |
253 | new->cl_dead = 0; | 252 | new->cl_dead = 0; |
254 | if (!IS_ERR(new->cl_dentry)) { | 253 | if (!IS_ERR(new->cl_dentry)) |
255 | dget(new->cl_dentry); | 254 | dget(new->cl_dentry); |
256 | rpc_get_mount(); | ||
257 | } | ||
258 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 255 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
259 | if (new->cl_auth) | 256 | if (new->cl_auth) |
260 | atomic_inc(&new->cl_auth->au_count); | 257 | atomic_inc(&new->cl_auth->au_count); |
@@ -317,11 +314,15 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
317 | clnt->cl_auth = NULL; | 314 | clnt->cl_auth = NULL; |
318 | } | 315 | } |
319 | if (clnt->cl_parent != clnt) { | 316 | if (clnt->cl_parent != clnt) { |
317 | if (!IS_ERR(clnt->cl_dentry)) | ||
318 | dput(clnt->cl_dentry); | ||
320 | rpc_destroy_client(clnt->cl_parent); | 319 | rpc_destroy_client(clnt->cl_parent); |
321 | goto out_free; | 320 | goto out_free; |
322 | } | 321 | } |
323 | if (clnt->cl_pathname[0]) | 322 | if (!IS_ERR(clnt->cl_dentry)) { |
324 | rpc_rmdir(clnt->cl_pathname); | 323 | rpc_rmdir(clnt->cl_dentry); |
324 | rpc_put_mount(); | ||
325 | } | ||
325 | if (clnt->cl_xprt) { | 326 | if (clnt->cl_xprt) { |
326 | xprt_destroy(clnt->cl_xprt); | 327 | xprt_destroy(clnt->cl_xprt); |
327 | clnt->cl_xprt = NULL; | 328 | clnt->cl_xprt = NULL; |
@@ -331,10 +332,6 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
331 | out_free: | 332 | out_free: |
332 | rpc_free_iostats(clnt->cl_metrics); | 333 | rpc_free_iostats(clnt->cl_metrics); |
333 | clnt->cl_metrics = NULL; | 334 | clnt->cl_metrics = NULL; |
334 | if (!IS_ERR(clnt->cl_dentry)) { | ||
335 | dput(clnt->cl_dentry); | ||
336 | rpc_put_mount(); | ||
337 | } | ||
338 | kfree(clnt); | 335 | kfree(clnt); |
339 | return 0; | 336 | return 0; |
340 | } | 337 | } |
@@ -1184,6 +1181,17 @@ call_verify(struct rpc_task *task) | |||
1184 | u32 *p = iov->iov_base, n; | 1181 | u32 *p = iov->iov_base, n; |
1185 | int error = -EACCES; | 1182 | int error = -EACCES; |
1186 | 1183 | ||
1184 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | ||
1185 | /* RFC-1014 says that the representation of XDR data must be a | ||
1186 | * multiple of four bytes | ||
1187 | * - if it isn't pointer subtraction in the NFS client may give | ||
1188 | * undefined results | ||
1189 | */ | ||
1190 | printk(KERN_WARNING | ||
1191 | "call_verify: XDR representation not a multiple of" | ||
1192 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | ||
1193 | goto out_eio; | ||
1194 | } | ||
1187 | if ((len -= 3) < 0) | 1195 | if ((len -= 3) < 0) |
1188 | goto out_overflow; | 1196 | goto out_overflow; |
1189 | p += 1; /* skip XID */ | 1197 | p += 1; /* skip XID */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a3bd2db2e024..0b1a1ac8a4bc 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -539,6 +539,7 @@ repeat: | |||
539 | rpc_close_pipes(dentry->d_inode); | 539 | rpc_close_pipes(dentry->d_inode); |
540 | simple_unlink(dir, dentry); | 540 | simple_unlink(dir, dentry); |
541 | } | 541 | } |
542 | inode_dir_notify(dir, DN_DELETE); | ||
542 | dput(dentry); | 543 | dput(dentry); |
543 | } while (n); | 544 | } while (n); |
544 | goto repeat; | 545 | goto repeat; |
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
610 | int error; | 611 | int error; |
611 | 612 | ||
612 | shrink_dcache_parent(dentry); | 613 | shrink_dcache_parent(dentry); |
613 | if (dentry->d_inode) | 614 | if (d_unhashed(dentry)) |
614 | rpc_close_pipes(dentry->d_inode); | 615 | return 0; |
615 | if ((error = simple_rmdir(dir, dentry)) != 0) | 616 | if ((error = simple_rmdir(dir, dentry)) != 0) |
616 | return error; | 617 | return error; |
617 | if (!error) { | 618 | if (!error) { |
@@ -684,28 +685,20 @@ err_dput: | |||
684 | } | 685 | } |
685 | 686 | ||
686 | int | 687 | int |
687 | rpc_rmdir(char *path) | 688 | rpc_rmdir(struct dentry *dentry) |
688 | { | 689 | { |
689 | struct nameidata nd; | 690 | struct dentry *parent; |
690 | struct dentry *dentry; | ||
691 | struct inode *dir; | 691 | struct inode *dir; |
692 | int error; | 692 | int error; |
693 | 693 | ||
694 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | 694 | parent = dget_parent(dentry); |
695 | return error; | 695 | dir = parent->d_inode; |
696 | dir = nd.dentry->d_inode; | ||
697 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 696 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
698 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); | ||
699 | if (IS_ERR(dentry)) { | ||
700 | error = PTR_ERR(dentry); | ||
701 | goto out_release; | ||
702 | } | ||
703 | rpc_depopulate(dentry); | 697 | rpc_depopulate(dentry); |
704 | error = __rpc_rmdir(dir, dentry); | 698 | error = __rpc_rmdir(dir, dentry); |
705 | dput(dentry); | 699 | dput(dentry); |
706 | out_release: | ||
707 | mutex_unlock(&dir->i_mutex); | 700 | mutex_unlock(&dir->i_mutex); |
708 | rpc_release_path(&nd); | 701 | dput(parent); |
709 | return error; | 702 | return error; |
710 | } | 703 | } |
711 | 704 | ||
@@ -746,32 +739,26 @@ err_dput: | |||
746 | } | 739 | } |
747 | 740 | ||
748 | int | 741 | int |
749 | rpc_unlink(char *path) | 742 | rpc_unlink(struct dentry *dentry) |
750 | { | 743 | { |
751 | struct nameidata nd; | 744 | struct dentry *parent; |
752 | struct dentry *dentry; | ||
753 | struct inode *dir; | 745 | struct inode *dir; |
754 | int error; | 746 | int error = 0; |
755 | 747 | ||
756 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | 748 | parent = dget_parent(dentry); |
757 | return error; | 749 | dir = parent->d_inode; |
758 | dir = nd.dentry->d_inode; | ||
759 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 750 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
760 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); | 751 | if (!d_unhashed(dentry)) { |
761 | if (IS_ERR(dentry)) { | 752 | d_drop(dentry); |
762 | error = PTR_ERR(dentry); | 753 | if (dentry->d_inode) { |
763 | goto out_release; | 754 | rpc_close_pipes(dentry->d_inode); |
764 | } | 755 | error = simple_unlink(dir, dentry); |
765 | d_drop(dentry); | 756 | } |
766 | if (dentry->d_inode) { | 757 | inode_dir_notify(dir, DN_DELETE); |
767 | rpc_close_pipes(dentry->d_inode); | ||
768 | error = simple_unlink(dir, dentry); | ||
769 | } | 758 | } |
770 | dput(dentry); | 759 | dput(dentry); |
771 | inode_dir_notify(dir, DN_DELETE); | ||
772 | out_release: | ||
773 | mutex_unlock(&dir->i_mutex); | 760 | mutex_unlock(&dir->i_mutex); |
774 | rpc_release_path(&nd); | 761 | dput(parent); |
775 | return error; | 762 | return error; |
776 | } | 763 | } |
777 | 764 | ||