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

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (28 commits)
  ipheth: remove incorrect devtype to WWAN
  MAINTAINERS: Add CAIF
  sctp: fix test for end of loop
  KS8851: Correct RX packet allocation
  udp: add rehash on connect()
  net: blackhole route should always be recalculated
  ipv4: Suppress lockdep-RCU false positive in FIB trie (3)
  niu: Fix kernel buffer overflow for ETHTOOL_GRXCLSRLALL
  ipvs: fix active FTP
  gro: Re-fix different skb headrooms
  via-velocity: Turn scatter-gather support back off.
  ipv4: Fix reverse path filtering with multipath routing.
  UNIX: Do not loop forever at unix_autobind().
  PATCH: b44 Handle RX FIFO overflow better (simplified)
  irda: off by one
  3c59x: Fix deadlock in vortex_error()
  netfilter: discard overlapping IPv6 fragment
  ipv6: discard overlapping fragment
  net: fix tx queue selection for bridged devices implementing select_queue
  bonding: Fix jiffies overflow problems (again)
  ...

Fix up trivial conflicts due to the same cgroup API thinko fix going
through both Andrew and the networking tree.  However, there were small
differences between the two, with Andrew's version generally being the
nicer one, and the one I merged first. So pick that one.

Conflicts in: include/linux/cgroup.h and kernel/cgroup.c
This commit is contained in:
Linus Torvalds 2010-09-11 08:06:38 -07:00
commit 002e473d1c
37 changed files with 384 additions and 304 deletions

View file

@ -1445,6 +1445,16 @@ S: Maintained
F: Documentation/video4linux/cafe_ccic
F: drivers/media/video/cafe_ccic*
CAIF NETWORK LAYER
M: Sjur Braendeland <sjur.brandeland@stericsson.com>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/networking/caif/
F: drivers/net/caif/
F: include/linux/caif/
F: include/net/caif/
F: net/caif/
CALGARY x86-64 IOMMU
M: Muli Ben-Yehuda <muli@il.ibm.com>
M: "Jon D. Mason" <jdmason@kudzu.us>

View file

@ -1994,10 +1994,9 @@ vortex_error(struct net_device *dev, int status)
}
}
if (status & RxEarly) { /* Rx early is unused. */
vortex_rx(dev);
if (status & RxEarly) /* Rx early is unused. */
iowrite16(AckIntr | RxEarly, ioaddr + EL3_CMD);
}
if (status & StatsFull) { /* Empty statistics. */
static int DoneDidThat;
if (vortex_debug > 4)
@ -2298,7 +2297,12 @@ vortex_interrupt(int irq, void *dev_id)
if (status & (HostError | RxEarly | StatsFull | TxComplete | IntReq)) {
if (status == 0xffff)
break;
if (status & RxEarly)
vortex_rx(dev);
spin_unlock(&vp->window_lock);
vortex_error(dev, status);
spin_lock(&vp->window_lock);
window_set(vp, 7);
}
if (--work_done < 0) {

View file

@ -848,6 +848,15 @@ static int b44_poll(struct napi_struct *napi, int budget)
b44_tx(bp);
/* spin_unlock(&bp->tx_lock); */
}
if (bp->istat & ISTAT_RFO) { /* fast recovery, in ~20msec */
bp->istat &= ~ISTAT_RFO;
b44_disable_ints(bp);
ssb_device_enable(bp->sdev, 0); /* resets ISTAT_RFO */
b44_init_rings(bp);
b44_init_hw(bp, B44_FULL_RESET_SKIP_PHY);
netif_wake_queue(bp->dev);
}
spin_unlock_irqrestore(&bp->lock, flags);
work_done = 0;

View file

@ -181,6 +181,7 @@ struct be_drvr_stats {
u64 be_rx_bytes_prev;
u64 be_rx_pkts;
u32 be_rx_rate;
u32 be_rx_mcast_pkt;
/* number of non ether type II frames dropped where
* frame len > length field of Mac Hdr */
u32 be_802_3_dropped_frames;

View file

@ -140,10 +140,8 @@ int be_process_mcc(struct be_adapter *adapter, int *status)
while ((compl = be_mcc_compl_get(adapter))) {
if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
/* Interpret flags as an async trailer */
BUG_ON(!is_link_state_evt(compl->flags));
/* Interpret compl as a async link evt */
be_async_link_state_process(adapter,
if (is_link_state_evt(compl->flags))
be_async_link_state_process(adapter,
(struct be_async_event_link_state *) compl);
} else if (compl->flags & CQE_FLAGS_COMPLETED_MASK) {
*status = be_mcc_compl_process(adapter, compl);
@ -207,7 +205,7 @@ static int be_mbox_db_ready_wait(struct be_adapter *adapter, void __iomem *db)
if (msecs > 4000) {
dev_err(&adapter->pdev->dev, "mbox poll timed out\n");
be_dump_ue(adapter);
be_detect_dump_ue(adapter);
return -1;
}

View file

@ -992,5 +992,5 @@ extern int be_cmd_set_loopback(struct be_adapter *adapter, u8 port_num,
extern int be_cmd_get_phy_info(struct be_adapter *adapter,
struct be_dma_mem *cmd);
extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
extern void be_dump_ue(struct be_adapter *adapter);
extern void be_detect_dump_ue(struct be_adapter *adapter);

View file

@ -60,6 +60,7 @@ static const struct be_ethtool_stat et_stats[] = {
{DRVSTAT_INFO(be_rx_events)},
{DRVSTAT_INFO(be_tx_compl)},
{DRVSTAT_INFO(be_rx_compl)},
{DRVSTAT_INFO(be_rx_mcast_pkt)},
{DRVSTAT_INFO(be_ethrx_post_fail)},
{DRVSTAT_INFO(be_802_3_dropped_frames)},
{DRVSTAT_INFO(be_802_3_malformed_frames)},

View file

@ -167,8 +167,11 @@
#define FLASH_FCoE_BIOS_START_g3 (13631488)
#define FLASH_REDBOOT_START_g3 (262144)
/************* Rx Packet Type Encoding **************/
#define BE_UNICAST_PACKET 0
#define BE_MULTICAST_PACKET 1
#define BE_BROADCAST_PACKET 2
#define BE_RSVD_PACKET 3
/*
* BE descriptors: host memory data structures whose formats

View file

@ -247,6 +247,7 @@ void netdev_stats_update(struct be_adapter *adapter)
dev_stats->tx_packets = drvr_stats(adapter)->be_tx_pkts;
dev_stats->rx_bytes = drvr_stats(adapter)->be_rx_bytes;
dev_stats->tx_bytes = drvr_stats(adapter)->be_tx_bytes;
dev_stats->multicast = drvr_stats(adapter)->be_rx_mcast_pkt;
/* bad pkts received */
dev_stats->rx_errors = port_stats->rx_crc_errors +
@ -294,7 +295,6 @@ void netdev_stats_update(struct be_adapter *adapter)
/* no space available in linux */
dev_stats->tx_dropped = 0;
dev_stats->multicast = port_stats->rx_multicast_frames;
dev_stats->collisions = 0;
/* detailed tx_errors */
@ -848,7 +848,7 @@ static void be_rx_rate_update(struct be_adapter *adapter)
}
static void be_rx_stats_update(struct be_adapter *adapter,
u32 pktsize, u16 numfrags)
u32 pktsize, u16 numfrags, u8 pkt_type)
{
struct be_drvr_stats *stats = drvr_stats(adapter);
@ -856,6 +856,9 @@ static void be_rx_stats_update(struct be_adapter *adapter,
stats->be_rx_frags += numfrags;
stats->be_rx_bytes += pktsize;
stats->be_rx_pkts++;
if (pkt_type == BE_MULTICAST_PACKET)
stats->be_rx_mcast_pkt++;
}
static inline bool do_pkt_csum(struct be_eth_rx_compl *rxcp, bool cso)
@ -925,9 +928,11 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
u16 rxq_idx, i, j;
u32 pktsize, hdr_len, curr_frag_len, size;
u8 *start;
u8 pkt_type;
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
page_info = get_rx_page_info(adapter, rxq_idx);
@ -993,7 +998,7 @@ static void skb_fill_rx_data(struct be_adapter *adapter,
BUG_ON(j > MAX_SKB_FRAGS);
done:
be_rx_stats_update(adapter, pktsize, num_rcvd);
be_rx_stats_update(adapter, pktsize, num_rcvd, pkt_type);
}
/* Process the RX completion indicated by rxcp when GRO is disabled */
@ -1060,6 +1065,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
u16 i, rxq_idx = 0, vid, j;
u8 vtm;
u8 pkt_type;
num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
/* Is it a flush compl that has no data */
@ -1070,6 +1076,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
/* vlanf could be wrongly set in some cards.
* ignore if vtm is not set */
@ -1125,7 +1132,7 @@ static void be_rx_compl_process_gro(struct be_adapter *adapter,
vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
}
be_rx_stats_update(adapter, pkt_size, num_rcvd);
be_rx_stats_update(adapter, pkt_size, num_rcvd, pkt_type);
}
static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter)
@ -1743,26 +1750,7 @@ static int be_poll_tx_mcc(struct napi_struct *napi, int budget)
return 1;
}
static inline bool be_detect_ue(struct be_adapter *adapter)
{
u32 online0 = 0, online1 = 0;
pci_read_config_dword(adapter->pdev, PCICFG_ONLINE0, &online0);
pci_read_config_dword(adapter->pdev, PCICFG_ONLINE1, &online1);
if (!online0 || !online1) {
adapter->ue_detected = true;
dev_err(&adapter->pdev->dev,
"UE Detected!! online0=%d online1=%d\n",
online0, online1);
return true;
}
return false;
}
void be_dump_ue(struct be_adapter *adapter)
void be_detect_dump_ue(struct be_adapter *adapter)
{
u32 ue_status_lo, ue_status_hi, ue_status_lo_mask, ue_status_hi_mask;
u32 i;
@ -1779,6 +1767,11 @@ void be_dump_ue(struct be_adapter *adapter)
ue_status_lo = (ue_status_lo & (~ue_status_lo_mask));
ue_status_hi = (ue_status_hi & (~ue_status_hi_mask));
if (ue_status_lo || ue_status_hi) {
adapter->ue_detected = true;
dev_err(&adapter->pdev->dev, "UE Detected!!\n");
}
if (ue_status_lo) {
for (i = 0; ue_status_lo; ue_status_lo >>= 1, i++) {
if (ue_status_lo & 1)
@ -1814,10 +1807,8 @@ static void be_worker(struct work_struct *work)
adapter->rx_post_starved = false;
be_post_rx_frags(adapter);
}
if (!adapter->ue_detected) {
if (be_detect_ue(adapter))
be_dump_ue(adapter);
}
if (!adapter->ue_detected)
be_detect_dump_ue(adapter);
schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
}

View file

@ -2797,9 +2797,15 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
* so it can wait
*/
bond_for_each_slave(bond, slave, i) {
unsigned long trans_start = dev_trans_start(slave->dev);
if (slave->link != BOND_LINK_UP) {
if (time_before_eq(jiffies, dev_trans_start(slave->dev) + delta_in_ticks) &&
time_before_eq(jiffies, slave->dev->last_rx + delta_in_ticks)) {
if (time_in_range(jiffies,
trans_start - delta_in_ticks,
trans_start + delta_in_ticks) &&
time_in_range(jiffies,
slave->dev->last_rx - delta_in_ticks,
slave->dev->last_rx + delta_in_ticks)) {
slave->link = BOND_LINK_UP;
slave->state = BOND_STATE_ACTIVE;
@ -2827,8 +2833,12 @@ void bond_loadbalance_arp_mon(struct work_struct *work)
* when the source ip is 0, so don't take the link down
* if we don't know our ip yet
*/
if (time_after_eq(jiffies, dev_trans_start(slave->dev) + 2*delta_in_ticks) ||
(time_after_eq(jiffies, slave->dev->last_rx + 2*delta_in_ticks))) {
if (!time_in_range(jiffies,
trans_start - delta_in_ticks,
trans_start + 2 * delta_in_ticks) ||
!time_in_range(jiffies,
slave->dev->last_rx - delta_in_ticks,
slave->dev->last_rx + 2 * delta_in_ticks)) {
slave->link = BOND_LINK_DOWN;
slave->state = BOND_STATE_BACKUP;
@ -2883,13 +2893,16 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
{
struct slave *slave;
int i, commit = 0;
unsigned long trans_start;
bond_for_each_slave(bond, slave, i) {
slave->new_link = BOND_LINK_NOCHANGE;
if (slave->link != BOND_LINK_UP) {
if (time_before_eq(jiffies, slave_last_rx(bond, slave) +
delta_in_ticks)) {
if (time_in_range(jiffies,
slave_last_rx(bond, slave) - delta_in_ticks,
slave_last_rx(bond, slave) + delta_in_ticks)) {
slave->new_link = BOND_LINK_UP;
commit++;
}
@ -2902,8 +2915,9 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
* active. This avoids bouncing, as the last receive
* times need a full ARP monitor cycle to be updated.
*/
if (!time_after_eq(jiffies, slave->jiffies +
2 * delta_in_ticks))
if (time_in_range(jiffies,
slave->jiffies - delta_in_ticks,
slave->jiffies + 2 * delta_in_ticks))
continue;
/*
@ -2921,8 +2935,10 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
*/
if (slave->state == BOND_STATE_BACKUP &&
!bond->current_arp_slave &&
time_after(jiffies, slave_last_rx(bond, slave) +
3 * delta_in_ticks)) {
!time_in_range(jiffies,
slave_last_rx(bond, slave) - delta_in_ticks,
slave_last_rx(bond, slave) + 3 * delta_in_ticks)) {
slave->new_link = BOND_LINK_DOWN;
commit++;
}
@ -2933,11 +2949,15 @@ static int bond_ab_arp_inspect(struct bonding *bond, int delta_in_ticks)
* - (more than 2*delta since receive AND
* the bond has an IP address)
*/
trans_start = dev_trans_start(slave->dev);
if ((slave->state == BOND_STATE_ACTIVE) &&
(time_after_eq(jiffies, dev_trans_start(slave->dev) +
2 * delta_in_ticks) ||
(time_after_eq(jiffies, slave_last_rx(bond, slave)
+ 2 * delta_in_ticks)))) {
(!time_in_range(jiffies,
trans_start - delta_in_ticks,
trans_start + 2 * delta_in_ticks) ||
!time_in_range(jiffies,
slave_last_rx(bond, slave) - delta_in_ticks,
slave_last_rx(bond, slave) + 2 * delta_in_ticks))) {
slave->new_link = BOND_LINK_DOWN;
commit++;
}
@ -2956,6 +2976,7 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
{
struct slave *slave;
int i;
unsigned long trans_start;
bond_for_each_slave(bond, slave, i) {
switch (slave->new_link) {
@ -2963,10 +2984,11 @@ static void bond_ab_arp_commit(struct bonding *bond, int delta_in_ticks)
continue;
case BOND_LINK_UP:
trans_start = dev_trans_start(slave->dev);
if ((!bond->curr_active_slave &&
time_before_eq(jiffies,
dev_trans_start(slave->dev) +
delta_in_ticks)) ||
time_in_range(jiffies,
trans_start - delta_in_ticks,
trans_start + delta_in_ticks)) ||
bond->curr_active_slave != slave) {
slave->link = BOND_LINK_UP;
bond->current_arp_slave = NULL;

View file

@ -503,30 +503,33 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
ks8851_wrreg16(ks, KS_RXQCR,
ks->rc_rxqcr | RXQCR_SDA | RXQCR_ADRFE);
if (rxlen > 0) {
skb = netdev_alloc_skb(ks->netdev, rxlen + 2 + 8);
if (!skb) {
/* todo - dump frame and move on */
if (rxlen > 4) {
unsigned int rxalign;
rxlen -= 4;
rxalign = ALIGN(rxlen, 4);
skb = netdev_alloc_skb_ip_align(ks->netdev, rxalign);
if (skb) {
/* 4 bytes of status header + 4 bytes of
* garbage: we put them before ethernet
* header, so that they are copied,
* but ignored.
*/
rxpkt = skb_put(skb, rxlen) - 8;
ks8851_rdfifo(ks, rxpkt, rxalign + 8);
if (netif_msg_pktdata(ks))
ks8851_dbg_dumpkkt(ks, rxpkt);
skb->protocol = eth_type_trans(skb, ks->netdev);
netif_rx(skb);
ks->netdev->stats.rx_packets++;
ks->netdev->stats.rx_bytes += rxlen;
}
/* two bytes to ensure ip is aligned, and four bytes
* for the status header and 4 bytes of garbage */
skb_reserve(skb, 2 + 4 + 4);
rxpkt = skb_put(skb, rxlen - 4) - 8;
/* align the packet length to 4 bytes, and add 4 bytes
* as we're getting the rx status header as well */
ks8851_rdfifo(ks, rxpkt, ALIGN(rxlen, 4) + 8);
if (netif_msg_pktdata(ks))
ks8851_dbg_dumpkkt(ks, rxpkt);
skb->protocol = eth_type_trans(skb, ks->netdev);
netif_rx(skb);
ks->netdev->stats.rx_packets++;
ks->netdev->stats.rx_bytes += rxlen - 4;
}
ks8851_wrreg16(ks, KS_RXQCR, ks->rc_rxqcr);

View file

@ -7269,32 +7269,28 @@ static int niu_get_ethtool_tcam_all(struct niu *np,
struct niu_parent *parent = np->parent;
struct niu_tcam_entry *tp;
int i, idx, cnt;
u16 n_entries;
unsigned long flags;
int ret = 0;
/* put the tcam size here */
nfc->data = tcam_get_size(np);
niu_lock_parent(np, flags);
n_entries = nfc->rule_cnt;
for (cnt = 0, i = 0; i < nfc->data; i++) {
idx = tcam_get_index(np, i);
tp = &parent->tcam[idx];
if (!tp->valid)
continue;
if (cnt == nfc->rule_cnt) {
ret = -EMSGSIZE;
break;
}
rule_locs[cnt] = i;
cnt++;
}
niu_unlock_parent(np, flags);
if (n_entries != cnt) {
/* print warning, this should not happen */
netdev_info(np->dev, "niu%d: In %s(): n_entries[%d] != cnt[%d]!!!\n",
np->parent->index, __func__, n_entries, cnt);
}
return 0;
return ret;
}
static int niu_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,

View file

@ -1865,15 +1865,15 @@ static int stmmac_resume(struct platform_device *pdev)
if (!netif_running(dev))
return 0;
spin_lock(&priv->lock);
if (priv->shutdown) {
/* Re-open the interface and re-init the MAC/DMA
and the rings. */
and the rings (i.e. on hibernation stage) */
stmmac_open(dev);
goto out_resume;
return 0;
}
spin_lock(&priv->lock);
/* Power Down bit, into the PM register, is cleared
* automatically as soon as a magic packet or a Wake-up frame
* is received. Anyway, it's better to manually clear
@ -1901,7 +1901,6 @@ static int stmmac_resume(struct platform_device *pdev)
netif_start_queue(dev);
out_resume:
spin_unlock(&priv->lock);
return 0;
}

View file

@ -429,10 +429,6 @@ static const struct net_device_ops ipheth_netdev_ops = {
.ndo_get_stats = &ipheth_stats,
};
static struct device_type ipheth_type = {
.name = "wwan",
};
static int ipheth_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@ -450,7 +446,7 @@ static int ipheth_probe(struct usb_interface *intf,
netdev->netdev_ops = &ipheth_netdev_ops;
netdev->watchdog_timeo = IPHETH_TX_TIMEOUT;
strcpy(netdev->name, "wwan%d");
strcpy(netdev->name, "eth%d");
dev = netdev_priv(netdev);
dev->udev = udev;
@ -500,7 +496,6 @@ static int ipheth_probe(struct usb_interface *intf,
SET_NETDEV_DEV(netdev, &intf->dev);
SET_ETHTOOL_OPS(netdev, &ops);
SET_NETDEV_DEVTYPE(netdev, &ipheth_type);
retval = register_netdev(netdev);
if (retval) {

View file

@ -2824,7 +2824,7 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi
netif_napi_add(dev, &vptr->napi, velocity_poll, VELOCITY_NAPI_WEIGHT);
dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER |
NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM | NETIF_F_SG;
NETIF_F_HW_VLAN_RX | NETIF_F_IP_CSUM;
ret = register_netdev(dev);
if (ret < 0)

View file

@ -60,17 +60,8 @@ static int vhost_poll_wakeup(wait_queue_t *wait, unsigned mode, int sync,
return 0;
}
/* Init poll structure */
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
unsigned long mask, struct vhost_dev *dev)
static void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn)
{
struct vhost_work *work = &poll->work;
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
init_poll_funcptr(&poll->table, vhost_poll_func);
poll->mask = mask;
poll->dev = dev;
INIT_LIST_HEAD(&work->node);
work->fn = fn;
init_waitqueue_head(&work->done);
@ -78,6 +69,18 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
work->queue_seq = work->done_seq = 0;
}
/* Init poll structure */
void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn,
unsigned long mask, struct vhost_dev *dev)
{
init_waitqueue_func_entry(&poll->wait, vhost_poll_wakeup);
init_poll_funcptr(&poll->table, vhost_poll_func);
poll->mask = mask;
poll->dev = dev;
vhost_work_init(&poll->work, fn);
}
/* Start polling a file. We add ourselves to file's wait queue. The caller must
* keep a reference to a file until after vhost_poll_stop is called. */
void vhost_poll_start(struct vhost_poll *poll, struct file *file)
@ -95,35 +98,38 @@ void vhost_poll_stop(struct vhost_poll *poll)
remove_wait_queue(poll->wqh, &poll->wait);
}
/* Flush any work that has been scheduled. When calling this, don't hold any
* locks that are also used by the callback. */
void vhost_poll_flush(struct vhost_poll *poll)
static void vhost_work_flush(struct vhost_dev *dev, struct vhost_work *work)
{
struct vhost_work *work = &poll->work;
unsigned seq;
int left;
int flushing;
spin_lock_irq(&poll->dev->work_lock);
spin_lock_irq(&dev->work_lock);
seq = work->queue_seq;
work->flushing++;
spin_unlock_irq(&poll->dev->work_lock);
spin_unlock_irq(&dev->work_lock);
wait_event(work->done, ({
spin_lock_irq(&poll->dev->work_lock);
spin_lock_irq(&dev->work_lock);
left = seq - work->done_seq <= 0;
spin_unlock_irq(&poll->dev->work_lock);
spin_unlock_irq(&dev->work_lock);
left;
}));
spin_lock_irq(&poll->dev->work_lock);
spin_lock_irq(&dev->work_lock);
flushing = --work->flushing;
spin_unlock_irq(&poll->dev->work_lock);
spin_unlock_irq(&dev->work_lock);
BUG_ON(flushing < 0);
}
void vhost_poll_queue(struct vhost_poll *poll)
/* Flush any work that has been scheduled. When calling this, don't hold any
* locks that are also used by the callback. */
void vhost_poll_flush(struct vhost_poll *poll)
{
vhost_work_flush(poll->dev, &poll->work);
}
static inline void vhost_work_queue(struct vhost_dev *dev,
struct vhost_work *work)
{
struct vhost_dev *dev = poll->dev;
struct vhost_work *work = &poll->work;
unsigned long flags;
spin_lock_irqsave(&dev->work_lock, flags);
@ -135,6 +141,11 @@ void vhost_poll_queue(struct vhost_poll *poll)
spin_unlock_irqrestore(&dev->work_lock, flags);
}
void vhost_poll_queue(struct vhost_poll *poll)
{
vhost_work_queue(poll->dev, &poll->work);
}
static void vhost_vq_reset(struct vhost_dev *dev,
struct vhost_virtqueue *vq)
{
@ -236,6 +247,29 @@ long vhost_dev_check_owner(struct vhost_dev *dev)
return dev->mm == current->mm ? 0 : -EPERM;
}
struct vhost_attach_cgroups_struct {
struct vhost_work work;
struct task_struct *owner;
int ret;
};
static void vhost_attach_cgroups_work(struct vhost_work *work)
{
struct vhost_attach_cgroups_struct *s;
s = container_of(work, struct vhost_attach_cgroups_struct, work);
s->ret = cgroup_attach_task_all(s->owner, current);
}
static int vhost_attach_cgroups(struct vhost_dev *dev)
{
struct vhost_attach_cgroups_struct attach;
attach.owner = current;
vhost_work_init(&attach.work, vhost_attach_cgroups_work);
vhost_work_queue(dev, &attach.work);
vhost_work_flush(dev, &attach.work);
return attach.ret;
}
/* Caller should have device mutex */
static long vhost_dev_set_owner(struct vhost_dev *dev)
{
@ -255,14 +289,16 @@ static long vhost_dev_set_owner(struct vhost_dev *dev)
}
dev->worker = worker;
err = cgroup_attach_task_current_cg(worker);
wake_up_process(worker); /* avoid contributing to loadavg */
err = vhost_attach_cgroups(dev);
if (err)
goto err_cgroup;
wake_up_process(worker); /* avoid contributing to loadavg */
return 0;
err_cgroup:
kthread_stop(worker);
dev->worker = NULL;
err_worker:
if (dev->mm)
mmput(dev->mm);

View file

@ -27,11 +27,17 @@ struct cgroup_cls_state
#ifdef CONFIG_NET_CLS_CGROUP
static inline u32 task_cls_classid(struct task_struct *p)
{
int classid;
if (in_interrupt())
return 0;
return container_of(task_subsys_state(p, net_cls_subsys_id),
struct cgroup_cls_state, css)->classid;
rcu_read_lock();
classid = container_of(task_subsys_state(p, net_cls_subsys_id),
struct cgroup_cls_state, css)->classid;
rcu_read_unlock();
return classid;
}
#else
extern int net_cls_subsys_id;

View file

@ -955,6 +955,9 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)
return csum_partial(diff, sizeof(diff), oldsum);
}
extern void ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp,
int outin);
#endif /* __KERNEL__ */
#endif /* _NET_IP_VS_H */

View file

@ -752,6 +752,7 @@ struct proto {
/* Keeping track of sk's, looking them up, and port selection methods. */
void (*hash)(struct sock *sk);
void (*unhash)(struct sock *sk);
void (*rehash)(struct sock *sk);
int (*get_port)(struct sock *sk, unsigned short snum);
/* Keeping track of sockets in use */

View file

@ -151,6 +151,7 @@ static inline void udp_lib_hash(struct sock *sk)
}
extern void udp_lib_unhash(struct sock *sk);
extern void udp_lib_rehash(struct sock *sk, u16 new_hash);
static inline void udp_lib_close(struct sock *sk, long timeout)
{

View file

@ -2058,16 +2058,16 @@ static struct netdev_queue *dev_pick_tx(struct net_device *dev,
struct sk_buff *skb)
{
int queue_index;
struct sock *sk = skb->sk;
const struct net_device_ops *ops = dev->netdev_ops;
queue_index = sk_tx_queue_get(sk);
if (queue_index < 0) {
const struct net_device_ops *ops = dev->netdev_ops;
if (ops->ndo_select_queue) {
queue_index = ops->ndo_select_queue(dev, skb);
queue_index = dev_cap_txqueue(dev, queue_index);
} else {
struct sock *sk = skb->sk;
queue_index = sk_tx_queue_get(sk);
if (queue_index < 0) {
if (ops->ndo_select_queue) {
queue_index = ops->ndo_select_queue(dev, skb);
queue_index = dev_cap_txqueue(dev, queue_index);
} else {
queue_index = 0;
if (dev->real_num_tx_queues > 1)
queue_index = skb_tx_hash(dev, skb);

View file

@ -2706,7 +2706,7 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
} else if (skb_gro_len(p) != pinfo->gso_size)
return -E2BIG;
headroom = NET_SKB_PAD + NET_IP_ALIGN;
headroom = skb_headroom(p);
nskb = alloc_skb(headroom + skb_gro_offset(p), GFP_ATOMIC);
if (unlikely(!nskb))
return -ENOMEM;

View file

@ -62,8 +62,11 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
}
if (!inet->inet_saddr)
inet->inet_saddr = rt->rt_src; /* Update source address */
if (!inet->inet_rcv_saddr)
if (!inet->inet_rcv_saddr) {
inet->inet_rcv_saddr = rt->rt_src;
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
}
inet->inet_daddr = rt->rt_dst;
inet->inet_dport = usin->sin_port;
sk->sk_state = TCP_ESTABLISHED;

View file

@ -246,6 +246,7 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
struct fib_result res;
int no_addr, rpf, accept_local;
bool dev_match;
int ret;
struct net *net;
@ -273,12 +274,22 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif,
}
*spec_dst = FIB_RES_PREFSRC(res);
fib_combine_itag(itag, &res);
dev_match = false;
#ifdef CONFIG_IP_ROUTE_MULTIPATH
if (FIB_RES_DEV(res) == dev || res.fi->fib_nhs > 1)
for (ret = 0; ret < res.fi->fib_nhs; ret++) {
struct fib_nh *nh = &res.fi->fib_nh[ret];
if (nh->nh_dev == dev) {
dev_match = true;
break;
}
}
#else
if (FIB_RES_DEV(res) == dev)
dev_match = true;
#endif
{
if (dev_match) {
ret = FIB_RES_NH(res).nh_scope >= RT_SCOPE_HOST;
fib_res_put(&res);
return ret;

View file

@ -186,7 +186,9 @@ static inline struct tnode *node_parent_rcu(struct node *node)
{
struct tnode *ret = node_parent(node);
return rcu_dereference(ret);
return rcu_dereference_check(ret,
rcu_read_lock_held() ||
lockdep_rtnl_is_held());
}
/* Same as rcu_assign_pointer
@ -1753,7 +1755,9 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct node *c)
static struct leaf *trie_firstleaf(struct trie *t)
{
struct tnode *n = (struct tnode *) rcu_dereference(t->trie);
struct tnode *n = (struct tnode *) rcu_dereference_check(t->trie,
rcu_read_lock_held() ||
lockdep_rtnl_is_held());
if (!n)
return NULL;

View file

@ -2738,6 +2738,11 @@ int __ip_route_output_key(struct net *net, struct rtable **rp,
}
EXPORT_SYMBOL_GPL(__ip_route_output_key);
static struct dst_entry *ipv4_blackhole_dst_check(struct dst_entry *dst, u32 cookie)
{
return NULL;
}
static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu)
{
}
@ -2746,7 +2751,7 @@ static struct dst_ops ipv4_dst_blackhole_ops = {
.family = AF_INET,
.protocol = cpu_to_be16(ETH_P_IP),
.destroy = ipv4_dst_destroy,
.check = ipv4_dst_check,
.check = ipv4_blackhole_dst_check,
.update_pmtu = ipv4_rt_blackhole_update_pmtu,
.entries = ATOMIC_INIT(0),
};

View file

@ -1260,6 +1260,49 @@ void udp_lib_unhash(struct sock *sk)
}
EXPORT_SYMBOL(udp_lib_unhash);
/*
* inet_rcv_saddr was changed, we must rehash secondary hash
*/
void udp_lib_rehash(struct sock *sk, u16 newhash)
{
if (sk_hashed(sk)) {
struct udp_table *udptable = sk->sk_prot->h.udp_table;
struct udp_hslot *hslot, *hslot2, *nhslot2;
hslot2 = udp_hashslot2(udptable, udp_sk(sk)->udp_portaddr_hash);
nhslot2 = udp_hashslot2(udptable, newhash);
udp_sk(sk)->udp_portaddr_hash = newhash;
if (hslot2 != nhslot2) {
hslot = udp_hashslot(udptable, sock_net(sk),
udp_sk(sk)->udp_port_hash);
/* we must lock primary chain too */
spin_lock_bh(&hslot->lock);
spin_lock(&hslot2->lock);
hlist_nulls_del_init_rcu(&udp_sk(sk)->udp_portaddr_node);
hslot2->count--;
spin_unlock(&hslot2->lock);
spin_lock(&nhslot2->lock);
hlist_nulls_add_head_rcu(&udp_sk(sk)->udp_portaddr_node,
&nhslot2->head);
nhslot2->count++;
spin_unlock(&nhslot2->lock);
spin_unlock_bh(&hslot->lock);
}
}
}
EXPORT_SYMBOL(udp_lib_rehash);
static void udp_v4_rehash(struct sock *sk)
{
u16 new_hash = udp4_portaddr_hash(sock_net(sk),
inet_sk(sk)->inet_rcv_saddr,
inet_sk(sk)->inet_num);
udp_lib_rehash(sk, new_hash);
}
static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
{
int rc;
@ -1843,6 +1886,7 @@ struct proto udp_prot = {
.backlog_rcv = __udp_queue_rcv_skb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
.rehash = udp_v4_rehash,
.get_port = udp_v4_get_port,
.memory_allocated = &udp_memory_allocated,
.sysctl_mem = sysctl_udp_mem,

View file

@ -105,9 +105,12 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (ipv6_addr_any(&np->saddr))
ipv6_addr_set_v4mapped(inet->inet_saddr, &np->saddr);
if (ipv6_addr_any(&np->rcv_saddr))
if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_set_v4mapped(inet->inet_rcv_saddr,
&np->rcv_saddr);
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
}
goto out;
}
@ -181,6 +184,8 @@ int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
if (ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &fl.fl6_src);
inet->inet_rcv_saddr = LOOPBACK4_IPV6;
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
}
ip6_dst_store(sk, dst,

View file

@ -113,14 +113,6 @@ static void nf_skb_free(struct sk_buff *skb)
kfree_skb(NFCT_FRAG6_CB(skb)->orig);
}
/* Memory Tracking Functions. */
static void frag_kfree_skb(struct sk_buff *skb)
{
atomic_sub(skb->truesize, &nf_init_frags.mem);
nf_skb_free(skb);
kfree_skb(skb);
}
/* Destruction primitives. */
static __inline__ void fq_put(struct nf_ct_frag6_queue *fq)
@ -282,66 +274,22 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
}
found:
/* We found where to put this one. Check for overlap with
* preceding fragment, and, if needed, align things so that
* any overlaps are eliminated.
/* RFC5722, Section 4:
* When reassembling an IPv6 datagram, if
* one or more its constituent fragments is determined to be an
* overlapping fragment, the entire datagram (and any constituent
* fragments, including those not yet received) MUST be silently
* discarded.
*/
if (prev) {
int i = (NFCT_FRAG6_CB(prev)->offset + prev->len) - offset;
if (i > 0) {
offset += i;
if (end <= offset) {
pr_debug("overlap\n");
goto err;
}
if (!pskb_pull(skb, i)) {
pr_debug("Can't pull\n");
goto err;
}
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
skb->ip_summed = CHECKSUM_NONE;
}
}
/* Check for overlap with preceding fragment. */
if (prev &&
(NFCT_FRAG6_CB(prev)->offset + prev->len) - offset > 0)
goto discard_fq;
/* Look for overlap with succeeding segments.
* If we can merge fragments, do it.
*/
while (next && NFCT_FRAG6_CB(next)->offset < end) {
/* overlap is 'i' bytes */
int i = end - NFCT_FRAG6_CB(next)->offset;
if (i < next->len) {
/* Eat head of the next overlapped fragment
* and leave the loop. The next ones cannot overlap.
*/
pr_debug("Eat head of the overlapped parts.: %d", i);
if (!pskb_pull(next, i))
goto err;
/* next fragment */
NFCT_FRAG6_CB(next)->offset += i;
fq->q.meat -= i;
if (next->ip_summed != CHECKSUM_UNNECESSARY)
next->ip_summed = CHECKSUM_NONE;
break;
} else {
struct sk_buff *free_it = next;
/* Old fragmnet is completely overridden with
* new one drop it.
*/
next = next->next;
if (prev)
prev->next = next;
else
fq->q.fragments = next;
fq->q.meat -= free_it->len;
frag_kfree_skb(free_it);
}
}
/* Look for overlap with succeeding segment. */
if (next && NFCT_FRAG6_CB(next)->offset < end)
goto discard_fq;
NFCT_FRAG6_CB(skb)->offset = offset;
@ -371,6 +319,8 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
write_unlock(&nf_frags.lock);
return 0;
discard_fq:
fq_kill(fq);
err:
return -1;
}

View file

@ -149,13 +149,6 @@ int ip6_frag_match(struct inet_frag_queue *q, void *a)
}
EXPORT_SYMBOL(ip6_frag_match);
/* Memory Tracking Functions. */
static void frag_kfree_skb(struct netns_frags *nf, struct sk_buff *skb)
{
atomic_sub(skb->truesize, &nf->mem);
kfree_skb(skb);
}
void ip6_frag_init(struct inet_frag_queue *q, void *a)
{
struct frag_queue *fq = container_of(q, struct frag_queue, q);
@ -346,58 +339,22 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
}
found:
/* We found where to put this one. Check for overlap with
* preceding fragment, and, if needed, align things so that
* any overlaps are eliminated.
/* RFC5722, Section 4:
* When reassembling an IPv6 datagram, if
* one or more its constituent fragments is determined to be an
* overlapping fragment, the entire datagram (and any constituent
* fragments, including those not yet received) MUST be silently
* discarded.
*/
if (prev) {
int i = (FRAG6_CB(prev)->offset + prev->len) - offset;
if (i > 0) {
offset += i;
if (end <= offset)
goto err;
if (!pskb_pull(skb, i))
goto err;
if (skb->ip_summed != CHECKSUM_UNNECESSARY)
skb->ip_summed = CHECKSUM_NONE;
}
}
/* Check for overlap with preceding fragment. */
if (prev &&
(FRAG6_CB(prev)->offset + prev->len) - offset > 0)
goto discard_fq;
/* Look for overlap with succeeding segments.
* If we can merge fragments, do it.
*/
while (next && FRAG6_CB(next)->offset < end) {
int i = end - FRAG6_CB(next)->offset; /* overlap is 'i' bytes */
if (i < next->len) {
/* Eat head of the next overlapped fragment
* and leave the loop. The next ones cannot overlap.
*/
if (!pskb_pull(next, i))
goto err;
FRAG6_CB(next)->offset += i; /* next fragment */
fq->q.meat -= i;
if (next->ip_summed != CHECKSUM_UNNECESSARY)
next->ip_summed = CHECKSUM_NONE;
break;
} else {
struct sk_buff *free_it = next;
/* Old fragment is completely overridden with
* new one drop it.
*/
next = next->next;
if (prev)
prev->next = next;
else
fq->q.fragments = next;
fq->q.meat -= free_it->len;
frag_kfree_skb(fq->q.net, free_it);
}
}
/* Look for overlap with succeeding segment. */
if (next && FRAG6_CB(next)->offset < end)
goto discard_fq;
FRAG6_CB(skb)->offset = offset;
@ -436,6 +393,8 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb,
write_unlock(&ip6_frags.lock);
return -1;
discard_fq:
fq_kill(fq);
err:
IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
IPSTATS_MIB_REASMFAILS);

View file

@ -111,6 +111,15 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
return udp_lib_get_port(sk, snum, ipv6_rcv_saddr_equal, hash2_nulladdr);
}
static void udp_v6_rehash(struct sock *sk)
{
u16 new_hash = udp6_portaddr_hash(sock_net(sk),
&inet6_sk(sk)->rcv_saddr,
inet_sk(sk)->inet_num);
udp_lib_rehash(sk, new_hash);
}
static inline int compute_score(struct sock *sk, struct net *net,
unsigned short hnum,
struct in6_addr *saddr, __be16 sport,
@ -1447,6 +1456,7 @@ struct proto udpv6_prot = {
.backlog_rcv = udpv6_queue_rcv_skb,
.hash = udp_lib_hash,
.unhash = udp_lib_unhash,
.rehash = udp_v6_rehash,
.get_port = udp_v6_get_port,
.memory_allocated = &udp_memory_allocated,
.sysctl_mem = sysctl_udp_mem,

View file

@ -1102,7 +1102,7 @@ int irlan_extract_param(__u8 *buf, char *name, char *value, __u16 *len)
memcpy(&val_len, buf+n, 2); /* To avoid alignment problems */
le16_to_cpus(&val_len); n+=2;
if (val_len > 1016) {
if (val_len >= 1016) {
IRDA_DEBUG(2, "%s(), parameter length to long\n", __func__ );
return -RSP_INVALID_COMMAND_FORMAT;
}

View file

@ -924,6 +924,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
ip_vs_out_stats(cp, skb);
ip_vs_set_state(cp, IP_VS_DIR_OUTPUT, skb, pp);
ip_vs_update_conntrack(skb, cp, 0);
ip_vs_conn_put(cp);
skb->ipvs_property = 1;

View file

@ -410,7 +410,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
union nf_inet_addr to;
__be16 port;
struct ip_vs_conn *n_cp;
struct nf_conn *ct;
#ifdef CONFIG_IP_VS_IPV6
/* This application helper doesn't work with IPv6 yet,
@ -497,11 +496,6 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
ip_vs_control_add(n_cp, cp);
}
ct = (struct nf_conn *)skb->nfct;
if (ct && ct != &nf_conntrack_untracked)
ip_vs_expect_related(skb, ct, n_cp,
IPPROTO_TCP, &n_cp->dport, 1);
/*
* Move tunnel to listen state
*/

View file

@ -349,8 +349,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
}
#endif
static void
ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
void
ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp, int outin)
{
struct nf_conn *ct = (struct nf_conn *)skb->nfct;
struct nf_conntrack_tuple new_tuple;
@ -365,11 +365,17 @@ ip_vs_update_conntrack(struct sk_buff *skb, struct ip_vs_conn *cp)
* real-server we will see RIP->DIP.
*/
new_tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
new_tuple.src.u3 = cp->daddr;
if (outin)
new_tuple.src.u3 = cp->daddr;
else
new_tuple.dst.u3 = cp->vaddr;
/*
* This will also take care of UDP and other protocols.
*/
new_tuple.src.u.tcp.port = cp->dport;
if (outin)
new_tuple.src.u.tcp.port = cp->dport;
else
new_tuple.dst.u.tcp.port = cp->vport;
nf_conntrack_alter_reply(ct, &new_tuple);
}
@ -428,7 +434,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
ip_vs_update_conntrack(skb, cp);
ip_vs_update_conntrack(skb, cp, 1);
/* FIXME: when application helper enlarges the packet and the length
is larger than the MTU of outgoing device, there will be still
@ -506,7 +512,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
IP_VS_DBG_PKT(10, pp, skb, 0, "After DNAT");
ip_vs_update_conntrack(skb, cp);
ip_vs_update_conntrack(skb, cp, 1);
/* FIXME: when application helper enlarges the packet and the length
is larger than the MTU of outgoing device, there will be still

View file

@ -1232,6 +1232,18 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa,
return 0;
}
static bool list_has_sctp_addr(const struct list_head *list,
union sctp_addr *ipaddr)
{
struct sctp_transport *addr;
list_for_each_entry(addr, list, transports) {
if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr))
return true;
}
return false;
}
/* A restart is occurring, check to make sure no new addresses
* are being added as we may be under a takeover attack.
*/
@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
struct sctp_chunk *init,
sctp_cmd_seq_t *commands)
{
struct sctp_transport *new_addr, *addr;
int found;
struct sctp_transport *new_addr;
int ret = 1;
/* Implementor's Guide - Sectin 5.2.2
/* Implementor's Guide - Section 5.2.2
* ...
* Before responding the endpoint MUST check to see if the
* unexpected INIT adds new addresses to the association. If new
@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc,
/* Search through all current addresses and make sure
* we aren't adding any new ones.
*/
new_addr = NULL;
found = 0;
list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list,
transports) {
found = 0;
list_for_each_entry(addr, &asoc->peer.transport_addr_list,
transports) {
if (sctp_cmp_addr_exact(&new_addr->ipaddr,
&addr->ipaddr)) {
found = 1;
break;
}
}
if (!found)
transports) {
if (!list_has_sctp_addr(&asoc->peer.transport_addr_list,
&new_addr->ipaddr)) {
sctp_sf_send_restart_abort(&new_addr->ipaddr, init,
commands);
ret = 0;
break;
}
/* If a new address was added, ABORT the sender. */
if (!found && new_addr) {
sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands);
}
}
/* Return success if all addresses were found. */
return found;
return ret;
}
/* Populate the verification/tie tags based on overlapping INIT

View file

@ -692,6 +692,7 @@ static int unix_autobind(struct socket *sock)
static u32 ordernum = 1;
struct unix_address *addr;
int err;
unsigned int retries = 0;
mutex_lock(&u->readlock);
@ -717,9 +718,17 @@ static int unix_autobind(struct socket *sock)
if (__unix_find_socket_byname(net, addr->name, addr->len, sock->type,
addr->hash)) {
spin_unlock(&unix_table_lock);
/* Sanity yield. It is unusual case, but yet... */
if (!(ordernum&0xFF))
yield();
/*
* __unix_find_socket_byname() may take long time if many names
* are already in use.
*/
cond_resched();
/* Give up if all names seems to be in use. */
if (retries++ == 0xFFFFF) {
err = -ENOSPC;
kfree(addr);
goto out;
}
goto retry;
}
addr->hash ^= sk->sk_type;