提交 a14a8d93 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

1) Setting link attributes can modify the size of the attributes that
   would be reported on a subsequent getlink netlink operation,
   therefore min_ifinfo_dump_size needs to be adjusted.  From Stefan
   Gula.

2) Resegmentation of TSO frames while trimming can violate invariants
   expected by callers, namely that the number of segments can only stay
   the same or decrease, never increase.  If MSS changes, however, we
   can trim data but then end up with more segments.  Fix this by only
   segmenting to the MSS already recorded in the SKB.  That's the
   simplest fix for now and if we want to get more fancy in the future
   that's a more involved change.

   This probably explains some retransmit counter inaccuracies.

   From Neal Cardwell.

3) Fix too-many-wakeups in POLL with AF_UNIX sockets, from Eric Dumazet.

4) Fix CAIF crashes wrt.  namespace handling.  From Eric Dumazet and
   Eric W. Biederman.

5) TCP port selection fixes from Flavio Leitner.

6) More socket memory cgroup build fixes in certain randonfig
   situations.  From Glauber Costa.

7) Fix TCP memory sysctl regression reported by Ingo Molnar, also from
   Glauber Costa.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net:
  af_unix: fix EPOLLET regression for stream sockets
  tcp: fix tcp_trim_head() to adjust segment count with skb MSS
  net/tcp: Fix tcp memory limits initialization when !CONFIG_SYSCTL
  net caif: Register properly as a pernet subsystem.
  netns: Fail conspicously if someone uses net_generic at an inappropriate time.
  net: explicitly add jump_label.h header to sock.h
  net: RTNETLINK adjusting values of min_ifinfo_dump_size
  ipv6: Fix ip_gre lockless xmits.
  xen-netfront: correct MAX_TX_TARGET calculation.
  netns: fix net_alloc_generic()
  tcp: bind() optimize port allocation
  tcp: bind() fix autoselection to share ports
  l2tp: l2tp_ip - fix possible oops on packet receive
  iwlwifi: fix PCI-E transport "inta" race
  mac80211: set bss_conf.idle when vif is connected
  mac80211: update oper_channel on ibss join
...@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans) ...@@ -972,11 +972,11 @@ void iwl_irq_tasklet(struct iwl_trans *trans)
} }
#endif #endif
spin_unlock_irqrestore(&trans->shrd->lock, flags);
/* saved interrupt in inta variable now we can reset trans_pcie->inta */ /* saved interrupt in inta variable now we can reset trans_pcie->inta */
trans_pcie->inta = 0; trans_pcie->inta = 0;
spin_unlock_irqrestore(&trans->shrd->lock, flags);
/* Now service all interrupt bits discovered above. */ /* Now service all interrupt bits discovered above. */
if (inta & CSR_INT_BIT_HW_ERR) { if (inta & CSR_INT_BIT_HW_ERR) {
IWL_ERR(trans, "Hardware error detected. Restarting.\n"); IWL_ERR(trans, "Hardware error detected. Restarting.\n");
......
...@@ -68,7 +68,7 @@ struct netfront_cb { ...@@ -68,7 +68,7 @@ struct netfront_cb {
#define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE) #define NET_TX_RING_SIZE __CONST_RING_SIZE(xen_netif_tx, PAGE_SIZE)
#define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE) #define NET_RX_RING_SIZE __CONST_RING_SIZE(xen_netif_rx, PAGE_SIZE)
#define TX_MAX_TARGET min_t(int, NET_RX_RING_SIZE, 256) #define TX_MAX_TARGET min_t(int, NET_TX_RING_SIZE, 256)
struct netfront_stats { struct netfront_stats {
u64 rx_packets; u64 rx_packets;
......
...@@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id) ...@@ -41,6 +41,7 @@ static inline void *net_generic(const struct net *net, int id)
ptr = ng->ptr[id - 1]; ptr = ng->ptr[id - 1];
rcu_read_unlock(); rcu_read_unlock();
BUG_ON(!ptr);
return ptr; return ptr;
} }
#endif #endif
...@@ -55,6 +55,7 @@ ...@@ -55,6 +55,7 @@
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <linux/memcontrol.h> #include <linux/memcontrol.h>
#include <linux/res_counter.h> #include <linux/res_counter.h>
#include <linux/jump_label.h>
#include <linux/filter.h> #include <linux/filter.h>
#include <linux/rculist_nulls.h> #include <linux/rculist_nulls.h>
......
...@@ -311,6 +311,8 @@ extern struct proto tcp_prot; ...@@ -311,6 +311,8 @@ extern struct proto tcp_prot;
#define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS_USER(net, field, val) SNMP_ADD_STATS_USER((net)->mib.tcp_statistics, field, val)
#define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val) #define TCP_ADD_STATS(net, field, val) SNMP_ADD_STATS((net)->mib.tcp_statistics, field, val)
extern void tcp_init_mem(struct net *net);
extern void tcp_v4_err(struct sk_buff *skb, u32); extern void tcp_v4_err(struct sk_buff *skb, u32);
extern void tcp_shutdown (struct sock *sk, int how); extern void tcp_shutdown (struct sock *sk, int how);
......
...@@ -59,8 +59,6 @@ struct cfcnfg *get_cfcnfg(struct net *net) ...@@ -59,8 +59,6 @@ struct cfcnfg *get_cfcnfg(struct net *net)
{ {
struct caif_net *caifn; struct caif_net *caifn;
caifn = net_generic(net, caif_net_id); caifn = net_generic(net, caif_net_id);
if (!caifn)
return NULL;
return caifn->cfg; return caifn->cfg;
} }
EXPORT_SYMBOL(get_cfcnfg); EXPORT_SYMBOL(get_cfcnfg);
...@@ -69,8 +67,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net) ...@@ -69,8 +67,6 @@ static struct caif_device_entry_list *caif_device_list(struct net *net)
{ {
struct caif_net *caifn; struct caif_net *caifn;
caifn = net_generic(net, caif_net_id); caifn = net_generic(net, caif_net_id);
if (!caifn)
return NULL;
return &caifn->caifdevs; return &caifn->caifdevs;
} }
...@@ -99,8 +95,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev) ...@@ -99,8 +95,6 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
struct caif_device_entry *caifd; struct caif_device_entry *caifd;
caifdevs = caif_device_list(dev_net(dev)); caifdevs = caif_device_list(dev_net(dev));
if (!caifdevs)
return NULL;
caifd = kzalloc(sizeof(*caifd), GFP_KERNEL); caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
if (!caifd) if (!caifd)
...@@ -120,8 +114,6 @@ static struct caif_device_entry *caif_get(struct net_device *dev) ...@@ -120,8 +114,6 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
struct caif_device_entry_list *caifdevs = struct caif_device_entry_list *caifdevs =
caif_device_list(dev_net(dev)); caif_device_list(dev_net(dev));
struct caif_device_entry *caifd; struct caif_device_entry *caifd;
if (!caifdevs)
return NULL;
list_for_each_entry_rcu(caifd, &caifdevs->list, list) { list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
if (caifd->netdev == dev) if (caifd->netdev == dev)
...@@ -321,8 +313,6 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev, ...@@ -321,8 +313,6 @@ void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
struct caif_device_entry_list *caifdevs; struct caif_device_entry_list *caifdevs;
caifdevs = caif_device_list(dev_net(dev)); caifdevs = caif_device_list(dev_net(dev));
if (!cfg || !caifdevs)
return;
caifd = caif_device_alloc(dev); caifd = caif_device_alloc(dev);
if (!caifd) if (!caifd)
return; return;
...@@ -374,8 +364,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, ...@@ -374,8 +364,6 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
cfg = get_cfcnfg(dev_net(dev)); cfg = get_cfcnfg(dev_net(dev));
caifdevs = caif_device_list(dev_net(dev)); caifdevs = caif_device_list(dev_net(dev));
if (!cfg || !caifdevs)
return 0;
caifd = caif_get(dev); caifd = caif_get(dev);
if (caifd == NULL && dev->type != ARPHRD_CAIF) if (caifd == NULL && dev->type != ARPHRD_CAIF)
...@@ -507,9 +495,6 @@ static struct notifier_block caif_device_notifier = { ...@@ -507,9 +495,6 @@ static struct notifier_block caif_device_notifier = {
static int caif_init_net(struct net *net) static int caif_init_net(struct net *net)
{ {
struct caif_net *caifn = net_generic(net, caif_net_id); struct caif_net *caifn = net_generic(net, caif_net_id);
if (WARN_ON(!caifn))
return -EINVAL;
INIT_LIST_HEAD(&caifn->caifdevs.list); INIT_LIST_HEAD(&caifn->caifdevs.list);
mutex_init(&caifn->caifdevs.lock); mutex_init(&caifn->caifdevs.lock);
...@@ -527,9 +512,6 @@ static void caif_exit_net(struct net *net) ...@@ -527,9 +512,6 @@ static void caif_exit_net(struct net *net)
caif_device_list(net); caif_device_list(net);
struct cfcnfg *cfg = get_cfcnfg(net); struct cfcnfg *cfg = get_cfcnfg(net);
if (!cfg || !caifdevs)
return;
rtnl_lock(); rtnl_lock();
mutex_lock(&caifdevs->lock); mutex_lock(&caifdevs->lock);
...@@ -569,7 +551,7 @@ static int __init caif_device_init(void) ...@@ -569,7 +551,7 @@ static int __init caif_device_init(void)
{ {
int result; int result;
result = register_pernet_device(&caif_net_ops); result = register_pernet_subsys(&caif_net_ops);
if (result) if (result)
return result; return result;
...@@ -582,7 +564,7 @@ static int __init caif_device_init(void) ...@@ -582,7 +564,7 @@ static int __init caif_device_init(void)
static void __exit caif_device_exit(void) static void __exit caif_device_exit(void)
{ {
unregister_pernet_device(&caif_net_ops); unregister_pernet_subsys(&caif_net_ops);
unregister_netdevice_notifier(&caif_device_notifier); unregister_netdevice_notifier(&caif_device_notifier);
dev_remove_pack(&caif_packet_type); dev_remove_pack(&caif_packet_type);
} }
......
...@@ -309,7 +309,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, ...@@ -309,7 +309,6 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
int err; int err;
struct cfctrl_link_param param; struct cfctrl_link_param param;
struct cfcnfg *cfg = get_cfcnfg(net); struct cfcnfg *cfg = get_cfcnfg(net);
caif_assert(cfg != NULL);
rcu_read_lock(); rcu_read_lock();
err = caif_connect_req_to_link_param(cfg, conn_req, &param); err = caif_connect_req_to_link_param(cfg, conn_req, &param);
......
...@@ -30,6 +30,20 @@ EXPORT_SYMBOL(init_net); ...@@ -30,6 +30,20 @@ EXPORT_SYMBOL(init_net);
#define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */ #define INITIAL_NET_GEN_PTRS 13 /* +1 for len +2 for rcu_head */
static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
static struct net_generic *net_alloc_generic(void)
{
struct net_generic *ng;
size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
ng = kzalloc(generic_size, GFP_KERNEL);
if (ng)
ng->len = max_gen_ptrs;
return ng;
}
static int net_assign_generic(struct net *net, int id, void *data) static int net_assign_generic(struct net *net, int id, void *data)
{ {
struct net_generic *ng, *old_ng; struct net_generic *ng, *old_ng;
...@@ -43,8 +57,7 @@ static int net_assign_generic(struct net *net, int id, void *data) ...@@ -43,8 +57,7 @@ static int net_assign_generic(struct net *net, int id, void *data)
if (old_ng->len >= id) if (old_ng->len >= id)
goto assign; goto assign;
ng = kzalloc(sizeof(struct net_generic) + ng = net_alloc_generic();
id * sizeof(void *), GFP_KERNEL);
if (ng == NULL) if (ng == NULL)
return -ENOMEM; return -ENOMEM;
...@@ -59,7 +72,6 @@ static int net_assign_generic(struct net *net, int id, void *data) ...@@ -59,7 +72,6 @@ static int net_assign_generic(struct net *net, int id, void *data)
* the old copy for kfree after a grace period. * the old copy for kfree after a grace period.
*/ */
ng->len = id;
memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*)); memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
rcu_assign_pointer(net->gen, ng); rcu_assign_pointer(net->gen, ng);
...@@ -161,18 +173,6 @@ static __net_init int setup_net(struct net *net) ...@@ -161,18 +173,6 @@ static __net_init int setup_net(struct net *net)
goto out; goto out;
} }
static struct net_generic *net_alloc_generic(void)
{
struct net_generic *ng;
size_t generic_size = sizeof(struct net_generic) +
INITIAL_NET_GEN_PTRS * sizeof(void *);
ng = kzalloc(generic_size, GFP_KERNEL);
if (ng)
ng->len = INITIAL_NET_GEN_PTRS;
return ng;
}
#ifdef CONFIG_NET_NS #ifdef CONFIG_NET_NS
static struct kmem_cache *net_cachep; static struct kmem_cache *net_cachep;
...@@ -483,6 +483,7 @@ static int register_pernet_operations(struct list_head *list, ...@@ -483,6 +483,7 @@ static int register_pernet_operations(struct list_head *list,
} }
return error; return error;
} }
max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
} }
error = __register_pernet_operations(list, ops); error = __register_pernet_operations(list, ops);
if (error) { if (error) {
......
...@@ -1509,6 +1509,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, ...@@ -1509,6 +1509,9 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
if (send_addr_notify) if (send_addr_notify)
call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); call_netdevice_notifiers(NETDEV_CHANGEADDR, dev);
min_ifinfo_dump_size = max_t(u16, if_nlmsg_size(dev),
min_ifinfo_dump_size);
return err; return err;
} }
......
...@@ -123,11 +123,14 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum) ...@@ -123,11 +123,14 @@ int inet_csk_get_port(struct sock *sk, unsigned short snum)
smallest_size = tb->num_owners; smallest_size = tb->num_owners;
smallest_rover = rover; smallest_rover = rover;
if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) {
spin_unlock(&head->lock);
snum = smallest_rover; snum = smallest_rover;
goto have_snum; goto tb_found;
} }
} }
if (!inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) {
snum = rover;
goto tb_found;
}
goto next; goto next;
} }
break; break;
......
...@@ -422,6 +422,10 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net, ...@@ -422,6 +422,10 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net,
if (register_netdevice(dev) < 0) if (register_netdevice(dev) < 0)
goto failed_free; goto failed_free;
/* Can use a lockless transmit, unless we generate output sequences */
if (!(nt->parms.o_flags & GRE_SEQ))
dev->features |= NETIF_F_LLTX;
dev_hold(dev); dev_hold(dev);
ipgre_tunnel_link(ign, nt); ipgre_tunnel_link(ign, nt);
return nt; return nt;
......
...@@ -814,6 +814,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) ...@@ -814,6 +814,7 @@ static __net_init int ipv4_sysctl_init_net(struct net *net)
net->ipv4.sysctl_rt_cache_rebuild_count = 4; net->ipv4.sysctl_rt_cache_rebuild_count = 4;
tcp_init_mem(net);
limit = nr_free_buffer_pages() / 8; limit = nr_free_buffer_pages() / 8;
limit = max(limit, 128UL); limit = max(limit, 128UL);
net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3; net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
......
...@@ -3216,6 +3216,16 @@ static int __init set_thash_entries(char *str) ...@@ -3216,6 +3216,16 @@ static int __init set_thash_entries(char *str)
} }
__setup("thash_entries=", set_thash_entries); __setup("thash_entries=", set_thash_entries);
void tcp_init_mem(struct net *net)
{
/* Set per-socket limits to no more than 1/128 the pressure threshold */
unsigned long limit = nr_free_buffer_pages() / 8;
limit = max(limit, 128UL);
net->ipv4.sysctl_tcp_mem[0] = limit / 4 * 3;
net->ipv4.sysctl_tcp_mem[1] = limit;
net->ipv4.sysctl_tcp_mem[2] = net->ipv4.sysctl_tcp_mem[0] * 2;
}
void __init tcp_init(void) void __init tcp_init(void)
{ {
struct sk_buff *skb = NULL; struct sk_buff *skb = NULL;
...@@ -3276,9 +3286,9 @@ void __init tcp_init(void) ...@@ -3276,9 +3286,9 @@ void __init tcp_init(void)
sysctl_tcp_max_orphans = cnt / 2; sysctl_tcp_max_orphans = cnt / 2;
sysctl_max_syn_backlog = max(128, cnt / 256); sysctl_max_syn_backlog = max(128, cnt / 256);
/* Set per-socket limits to no more than 1/128 the pressure threshold */ tcp_init_mem(&init_net);
limit = ((unsigned long)init_net.ipv4.sysctl_tcp_mem[1]) limit = nr_free_buffer_pages() / 8;
<< (PAGE_SHIFT - 7); limit = max(limit, 128UL);
max_share = min(4UL*1024*1024, limit); max_share = min(4UL*1024*1024, limit);
sysctl_tcp_wmem[0] = SK_MEM_QUANTUM; sysctl_tcp_wmem[0] = SK_MEM_QUANTUM;
......
...@@ -1141,11 +1141,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len) ...@@ -1141,11 +1141,9 @@ int tcp_trim_head(struct sock *sk, struct sk_buff *skb, u32 len)
sk_mem_uncharge(sk, len); sk_mem_uncharge(sk, len);
sock_set_flag(sk, SOCK_QUEUE_SHRUNK); sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
/* Any change of skb->len requires recalculation of tso /* Any change of skb->len requires recalculation of tso factor. */
* factor and mss.
*/
if (tcp_skb_pcount(skb) > 1) if (tcp_skb_pcount(skb) > 1)
tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk)); tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
return 0; return 0;
} }
......
...@@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb) ...@@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct sock *sk, struct sk_buff *skb)
{ {
int rc; int rc;
if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
goto drop;
nf_reset(skb);
/* Charge it to the socket, dropping if the queue is full. */ /* Charge it to the socket, dropping if the queue is full. */
rc = sock_queue_rcv_skb(sk, skb); rc = sock_queue_rcv_skb(sk, skb);
if (rc < 0) if (rc < 0)
......
...@@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, ...@@ -106,6 +106,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
local->oper_channel = chan;
channel_type = ifibss->channel_type; channel_type = ifibss->channel_type;
if (channel_type > NL80211_CHAN_HT20 && if (channel_type > NL80211_CHAN_HT20 &&
!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
......
...@@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local) ...@@ -1314,6 +1314,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
continue; continue;
} }
/* count everything else */ /* count everything else */
sdata->vif.bss_conf.idle = false;
count++; count++;
} }
......
...@@ -1918,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1918,7 +1918,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
struct sk_buff *skb; struct sk_buff *skb;
unix_state_lock(sk); unix_state_lock(sk);
skb = skb_dequeue(&sk->sk_receive_queue); skb = skb_peek(&sk->sk_receive_queue);
if (skb == NULL) { if (skb == NULL) {
unix_sk(sk)->recursion_level = 0; unix_sk(sk)->recursion_level = 0;
if (copied >= target) if (copied >= target)
...@@ -1958,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1958,11 +1958,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
if (check_creds) { if (check_creds) {
/* Never glue messages from different writers */ /* Never glue messages from different writers */
if ((UNIXCB(skb).pid != siocb->scm->pid) || if ((UNIXCB(skb).pid != siocb->scm->pid) ||
(UNIXCB(skb).cred != siocb->scm->cred)) { (UNIXCB(skb).cred != siocb->scm->cred))
skb_queue_head(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
break; break;
}
} else { } else {
/* Copy credentials */ /* Copy credentials */
scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
...@@ -1977,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1977,8 +1974,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
chunk = min_t(unsigned int, skb->len, size); chunk = min_t(unsigned int, skb->len, size);
if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) { if (memcpy_toiovec(msg->msg_iov, skb->data, chunk)) {
skb_queue_head(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
if (copied == 0) if (copied == 0)
copied = -EFAULT; copied = -EFAULT;
break; break;
...@@ -1993,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -1993,13 +1988,10 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
unix_detach_fds(siocb->scm, skb); unix_detach_fds(siocb->scm, skb);
/* put the skb back if we didn't use it up.. */ if (skb->len)
if (skb->len) {
skb_queue_head(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
break; break;
}
skb_unlink(skb, &sk->sk_receive_queue);
consume_skb(skb); consume_skb(skb);
if (siocb->scm->fp) if (siocb->scm->fp)
...@@ -2010,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, ...@@ -2010,9 +2002,6 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
if (UNIXCB(skb).fp) if (UNIXCB(skb).fp)
siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp); siocb->scm->fp = scm_fp_dup(UNIXCB(skb).fp);
/* put message back and return */
skb_queue_head(&sk->sk_receive_queue, skb);
sk->sk_data_ready(sk, skb->len);
break; break;
} }
} while (size); } while (size);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册