projects
/
firefly-linux-kernel-4.4.55.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[firefly-linux-kernel-4.4.55.git]
/
net
/
ipv4
/
tcp.c
diff --git
a/net/ipv4/tcp.c
b/net/ipv4/tcp.c
index e457c7ab2e28daf5607e93ef0c31e667f1cec216..2aa69c8ae60c1990c76e69fe5aef46b990b6da6e 100644
(file)
--- a/
net/ipv4/tcp.c
+++ b/
net/ipv4/tcp.c
@@
-536,13
+536,14
@@
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
{
struct tcp_sock *tp = tcp_sk(sk);
int answ;
{
struct tcp_sock *tp = tcp_sk(sk);
int answ;
+ bool slow;
switch (cmd) {
case SIOCINQ:
if (sk->sk_state == TCP_LISTEN)
return -EINVAL;
switch (cmd) {
case SIOCINQ:
if (sk->sk_state == TCP_LISTEN)
return -EINVAL;
-
lock_sock
(sk);
+
slow = lock_sock_fast
(sk);
if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
answ = 0;
else if (sock_flag(sk, SOCK_URGINLINE) ||
if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV))
answ = 0;
else if (sock_flag(sk, SOCK_URGINLINE) ||
@@
-557,7
+558,7
@@
int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg)
answ--;
} else
answ = tp->urg_seq - tp->copied_seq;
answ--;
} else
answ = tp->urg_seq - tp->copied_seq;
-
release_sock(sk
);
+
unlock_sock_fast(sk, slow
);
break;
case SIOCATMARK:
answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
break;
case SIOCATMARK:
answ = tp->urg_data && tp->urg_seq == tp->copied_seq;
@@
-1427,12
+1428,12
@@
static void tcp_service_net_dma(struct sock *sk, bool wait)
}
#endif
}
#endif
-static
inline
struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
+static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
{
struct sk_buff *skb;
u32 offset;
{
struct sk_buff *skb;
u32 offset;
-
skb_queue_walk(&sk->sk_receive_queue, skb
) {
+
while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL
) {
offset = seq - TCP_SKB_CB(skb)->seq;
if (tcp_hdr(skb)->syn)
offset--;
offset = seq - TCP_SKB_CB(skb)->seq;
if (tcp_hdr(skb)->syn)
offset--;
@@
-1440,6
+1441,11
@@
static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
*off = offset;
return skb;
}
*off = offset;
return skb;
}
+ /* This looks weird, but this can happen if TCP collapsing
+ * splitted a fat GRO packet, while we released socket lock
+ * in skb_splice_bits()
+ */
+ sk_eat_skb(sk, skb, false);
}
return NULL;
}
}
return NULL;
}
@@
-1481,7
+1487,7
@@
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
break;
}
used = recv_actor(desc, skb, offset, len);
break;
}
used = recv_actor(desc, skb, offset, len);
- if (used < 0) {
+ if (used <
=
0) {
if (!copied)
copied = used;
break;
if (!copied)
copied = used;
break;
@@
-1490,15
+1496,19
@@
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
copied += used;
offset += used;
}
copied += used;
offset += used;
}
- /*
- * If recv_actor drops the lock (e.g. TCP splice
+ /* If recv_actor drops the lock (e.g. TCP splice
* receive) the skb pointer might be invalid when
* getting here: tcp_collapse might have deleted it
* while aggregating skbs from the socket queue.
*/
* receive) the skb pointer might be invalid when
* getting here: tcp_collapse might have deleted it
* while aggregating skbs from the socket queue.
*/
- skb = tcp_recv_skb(sk, seq
-
1, &offset);
- if (!skb
|| (offset+1 != skb->len)
)
+ skb = tcp_recv_skb(sk, seq
-
1, &offset);
+ if (!skb)
break;
break;
+ /* TCP coalescing might have appended data to the skb.
+ * Try to splice more frags
+ */
+ if (offset + 1 != skb->len)
+ continue;
}
if (tcp_hdr(skb)->fin) {
sk_eat_skb(sk, skb, false);
}
if (tcp_hdr(skb)->fin) {
sk_eat_skb(sk, skb, false);
@@
-1515,8
+1525,10
@@
int tcp_read_sock(struct sock *sk, read_descriptor_t *desc,
tcp_rcv_space_adjust(sk);
/* Clean up data we have read: This will do ACK frames. */
tcp_rcv_space_adjust(sk);
/* Clean up data we have read: This will do ACK frames. */
- if (copied > 0)
+ if (copied > 0) {
+ tcp_recv_skb(sk, seq, &offset);
tcp_cleanup_rbuf(sk, copied);
tcp_cleanup_rbuf(sk, copied);
+ }
return copied;
}
EXPORT_SYMBOL(tcp_read_sock);
return copied;
}
EXPORT_SYMBOL(tcp_read_sock);
@@
-2300,7
+2312,7
@@
void tcp_sock_destruct(struct sock *sk)
static inline bool tcp_can_repair_sock(const struct sock *sk)
{
static inline bool tcp_can_repair_sock(const struct sock *sk)
{
- return
capable(
CAP_NET_ADMIN) &&
+ return
ns_capable(sock_net(sk)->user_ns,
CAP_NET_ADMIN) &&
((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
}
((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_ESTABLISHED));
}
@@
-3586,8
+3598,7
@@
void __init tcp_init(void)
alloc_large_system_hash("TCP established",
sizeof(struct inet_ehash_bucket),
thash_entries,
alloc_large_system_hash("TCP established",
sizeof(struct inet_ehash_bucket),
thash_entries,
- (totalram_pages >= 128 * 1024) ?
- 13 : 15,
+ 17, /* one slot per 128 KB of memory */
0,
NULL,
&tcp_hashinfo.ehash_mask,
0,
NULL,
&tcp_hashinfo.ehash_mask,
@@
-3603,8
+3614,7
@@
void __init tcp_init(void)
alloc_large_system_hash("TCP bind",
sizeof(struct inet_bind_hashbucket),
tcp_hashinfo.ehash_mask + 1,
alloc_large_system_hash("TCP bind",
sizeof(struct inet_bind_hashbucket),
tcp_hashinfo.ehash_mask + 1,
- (totalram_pages >= 128 * 1024) ?
- 13 : 15,
+ 17, /* one slot per 128 KB of memory */
0,
&tcp_hashinfo.bhash_size,
NULL,
0,
&tcp_hashinfo.bhash_size,
NULL,