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

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: (27 commits)
  af_unix: limit recursion level
  pch_gbe driver: The wrong of initializer entry
  pch_gbe dreiver: chang author
  ucc_geth: fix ucc halt problem in half duplex mode
  inet: Fix __inet_inherit_port() to correctly increment bsockets and num_owners
  ehea: Add some info messages and fix an issue
  hso: fix disable_net
  NET: wan/x25_asy, move lapb_unregister to x25_asy_close_tty
  cxgb4vf: fix setting unicast/multicast addresses ...
  net, ppp: Report correct error code if unit allocation failed
  DECnet: don't leak uninitialized stack byte
  au1000_eth: fix invalid address accessing the MAC enable register
  dccp: fix error in updating the GAR
  tcp: restrict net.ipv4.tcp_adv_win_scale (#20312)
  netns: Don't leak others' openreq-s in proc
  Net: ceph: Makefile: Remove unnessary code
  vhost/net: fix rcu check usage
  econet: fix CVE-2010-3848
  econet: fix CVE-2010-3850
  econet: disallow NULL remote addr for sendmsg(), fixes CVE-2010-3849
  ...
......@@ -144,6 +144,7 @@ tcp_adv_win_scale - INTEGER
Count buffering overhead as bytes/2^tcp_adv_win_scale
(if tcp_adv_win_scale > 0) or bytes-bytes/2^(-tcp_adv_win_scale),
if it is <= 0.
Possible values are [-31, 31], inclusive.
Default: 2
tcp_allowed_congestion_control - STRING
......
......@@ -1627,7 +1627,7 @@ __setup("icn=", icn_setup);
static int __init icn_init(void)
{
char *p;
char rev[10];
char rev[20];
memset(&dev, 0, sizeof(icn_dev));
dev.memaddr = (membase & 0x0ffc000);
......@@ -1637,9 +1637,10 @@ static int __init icn_init(void)
spin_lock_init(&dev.devlock);
if ((p = strchr(revision, ':'))) {
strcpy(rev, p + 1);
strncpy(rev, p + 1, 20);
p = strchr(rev, '$');
*p = 0;
if (p)
*p = 0;
} else
strcpy(rev, " ??? ");
printk(KERN_NOTICE "ICN-ISDN-driver Rev%smem=0x%08lx\n", rev,
......
......@@ -2543,10 +2543,10 @@ config PCH_GBE
depends on PCI
select MII
---help---
This is a gigabit ethernet driver for Topcliff PCH.
Topcliff PCH is the platform controller hub that is used in Intel's
This is a gigabit ethernet driver for EG20T PCH.
EG20T PCH is the platform controller hub that is used in Intel's
general embedded platform.
Topcliff PCH has Gigabit Ethernet interface.
EG20T PCH has Gigabit Ethernet interface.
Using this interface, it is able to access system devices connected
to Gigabit Ethernet.
This driver enables Gigabit Ethernet function.
......
......@@ -155,10 +155,10 @@ static void au1000_enable_mac(struct net_device *dev, int force_reset)
spin_lock_irqsave(&aup->lock, flags);
if (force_reset || (!aup->mac_enabled)) {
writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
au_sync_delay(2);
writel((MAC_EN_RESET0 | MAC_EN_RESET1 | MAC_EN_RESET2
| MAC_EN_CLOCK_ENABLE), &aup->enable);
| MAC_EN_CLOCK_ENABLE), aup->enable);
au_sync_delay(2);
aup->mac_enabled = 1;
......@@ -503,9 +503,9 @@ static void au1000_reset_mac_unlocked(struct net_device *dev)
au1000_hard_stop(dev);
writel(MAC_EN_CLOCK_ENABLE, &aup->enable);
writel(MAC_EN_CLOCK_ENABLE, aup->enable);
au_sync_delay(2);
writel(0, &aup->enable);
writel(0, aup->enable);
au_sync_delay(2);
aup->tx_full = 0;
......@@ -1119,7 +1119,7 @@ static int __devinit au1000_probe(struct platform_device *pdev)
/* set a random MAC now in case platform_data doesn't provide one */
random_ether_addr(dev->dev_addr);
writel(0, &aup->enable);
writel(0, aup->enable);
aup->mac_enabled = 0;
pd = pdev->dev.platform_data;
......
......@@ -816,40 +816,48 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev)
}
/*
* Collect up to maxaddrs worth of a netdevice's unicast addresses into an
* array of addrss pointers and return the number collected.
* Collect up to maxaddrs worth of a netdevice's unicast addresses, starting
* at a specified offset within the list, into an array of addrss pointers and
* return the number collected.
*/
static inline int collect_netdev_uc_list_addrs(const struct net_device *dev,
const u8 **addr,
unsigned int maxaddrs)
static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev,
const u8 **addr,
unsigned int offset,
unsigned int maxaddrs)
{
unsigned int index = 0;
unsigned int naddr = 0;
const struct netdev_hw_addr *ha;
for_each_dev_addr(dev, ha) {
addr[naddr++] = ha->addr;
if (naddr >= maxaddrs)
break;
}
for_each_dev_addr(dev, ha)
if (index++ >= offset) {
addr[naddr++] = ha->addr;
if (naddr >= maxaddrs)
break;
}
return naddr;
}
/*
* Collect up to maxaddrs worth of a netdevice's multicast addresses into an
* array of addrss pointers and return the number collected.
* Collect up to maxaddrs worth of a netdevice's multicast addresses, starting
* at a specified offset within the list, into an array of addrss pointers and
* return the number collected.
*/
static inline int collect_netdev_mc_list_addrs(const struct net_device *dev,
const u8 **addr,
unsigned int maxaddrs)
static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev,
const u8 **addr,
unsigned int offset,
unsigned int maxaddrs)
{
unsigned int index = 0;
unsigned int naddr = 0;
const struct netdev_hw_addr *ha;
netdev_for_each_mc_addr(ha, dev) {
addr[naddr++] = ha->addr;
if (naddr >= maxaddrs)
break;
}
netdev_for_each_mc_addr(ha, dev)
if (index++ >= offset) {
addr[naddr++] = ha->addr;
if (naddr >= maxaddrs)
break;
}
return naddr;
}
......@@ -862,16 +870,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
u64 mhash = 0;
u64 uhash = 0;
bool free = true;
u16 filt_idx[7];
unsigned int offset, naddr;
const u8 *addr[7];
int ret, naddr = 0;
int ret;
const struct port_info *pi = netdev_priv(dev);
/* first do the secondary unicast addresses */
naddr = collect_netdev_uc_list_addrs(dev, addr, ARRAY_SIZE(addr));
if (naddr > 0) {
for (offset = 0; ; offset += naddr) {
naddr = collect_netdev_uc_list_addrs(dev, addr, offset,
ARRAY_SIZE(addr));
if (naddr == 0)
break;
ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
naddr, addr, filt_idx, &uhash, sleep);
naddr, addr, NULL, &uhash, sleep);
if (ret < 0)
return ret;
......@@ -879,12 +891,17 @@ static int set_addr_filters(const struct net_device *dev, bool sleep)
}
/* next set up the multicast addresses */
naddr = collect_netdev_mc_list_addrs(dev, addr, ARRAY_SIZE(addr));
if (naddr > 0) {
for (offset = 0; ; offset += naddr) {
naddr = collect_netdev_mc_list_addrs(dev, addr, offset,
ARRAY_SIZE(addr));
if (naddr == 0)
break;
ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free,
naddr, addr, filt_idx, &mhash, sleep);
naddr, addr, NULL, &mhash, sleep);
if (ret < 0)
return ret;
free = false;
}
return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0,
......
......@@ -1014,48 +1014,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
unsigned int naddr, const u8 **addr, u16 *idx,
u64 *hash, bool sleep_ok)
{
int i, ret;
int offset, ret = 0;
unsigned nfilters = 0;
unsigned int rem = naddr;
struct fw_vi_mac_cmd cmd, rpl;
struct fw_vi_mac_exact *p;
size_t len16;
if (naddr > ARRAY_SIZE(cmd.u.exact))
if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
return -EINVAL;
len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
u.exact[naddr]), 16);
memset(&cmd, 0, sizeof(cmd));
cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
FW_CMD_REQUEST |
FW_CMD_WRITE |
(free ? FW_CMD_EXEC : 0) |
FW_VI_MAC_CMD_VIID(viid));
cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
FW_CMD_LEN16(len16));
for (offset = 0; offset < naddr; /**/) {
unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
? rem
: ARRAY_SIZE(cmd.u.exact));
size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
u.exact[fw_naddr]), 16);
struct fw_vi_mac_exact *p;
int i;
for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) {
p->valid_to_idx =
cpu_to_be16(FW_VI_MAC_CMD_VALID |
FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
memcpy(p->macaddr, addr[i], sizeof(p->macaddr));
}
memset(&cmd, 0, sizeof(cmd));
cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
FW_CMD_REQUEST |
FW_CMD_WRITE |
(free ? FW_CMD_EXEC : 0) |
FW_VI_MAC_CMD_VIID(viid));
cmd.freemacs_to_len16 =
cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
FW_CMD_LEN16(len16));
for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
p->valid_to_idx = cpu_to_be16(
FW_VI_MAC_CMD_VALID |
FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
}
ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
sleep_ok);
if (ret && ret != -ENOMEM)
break;
ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok);
if (ret)
return ret;
for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) {
u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx));
if (idx)
idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES
? 0xffff
: index);
if (index < FW_CLS_TCAM_NUM_ENTRIES)
ret++;
else if (hash)
*hash |= (1 << hash_mac_addr(addr[i]));
for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
u16 index = FW_VI_MAC_CMD_IDX_GET(
be16_to_cpu(p->valid_to_idx));
if (idx)
idx[offset+i] =
(index >= FW_CLS_TCAM_NUM_ENTRIES
? 0xffff
: index);
if (index < FW_CLS_TCAM_NUM_ENTRIES)
nfilters++;
else if (hash)
*hash |= (1ULL << hash_mac_addr(addr[offset+i]));
}
free = false;
offset += fw_naddr;
rem -= fw_naddr;
}
/*
* If there were no errors or we merely ran out of room in our MAC
* address arena, return the number of filters actually written.
*/
if (ret == 0 || ret == -ENOMEM)
ret = nfilters;
return ret;
}
......
......@@ -400,6 +400,7 @@ static void ehea_refill_rq1(struct ehea_port_res *pr, int index, int nr_of_wqes)
skb_arr_rq1[index] = netdev_alloc_skb(dev,
EHEA_L_PKT_SIZE);
if (!skb_arr_rq1[index]) {
ehea_info("Unable to allocate enough skb in the array\n");
pr->rq1_skba.os_skbs = fill_wqes - i;
break;
}
......@@ -422,13 +423,20 @@ static void ehea_init_fill_rq1(struct ehea_port_res *pr, int nr_rq1a)
struct net_device *dev = pr->port->netdev;
int i;
for (i = 0; i < pr->rq1_skba.len; i++) {
if (nr_rq1a > pr->rq1_skba.len) {
ehea_error("NR_RQ1A bigger than skb array len\n");
return;
}
for (i = 0; i < nr_rq1a; i++) {
skb_arr_rq1[i] = netdev_alloc_skb(dev, EHEA_L_PKT_SIZE);
if (!skb_arr_rq1[i])
if (!skb_arr_rq1[i]) {
ehea_info("No enough memory to allocate skb array\n");
break;
}
}
/* Ring doorbell */
ehea_update_rq1a(pr->qp, nr_rq1a);
ehea_update_rq1a(pr->qp, i);
}
static int ehea_refill_rq_def(struct ehea_port_res *pr,
......@@ -735,8 +743,10 @@ static int ehea_proc_rwqes(struct net_device *dev,
skb = netdev_alloc_skb(dev,
EHEA_L_PKT_SIZE);
if (!skb)
if (!skb) {
ehea_info("Not enough memory to allocate skb\n");
break;
}
}
skb_copy_to_linear_data(skb, ((char *)cqe) + 64,
cqe->num_bytes_transfered - 4);
......
/*
* Copyright (C) 1999 - 2010 Intel Corporation.
* Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
* Copyright (C) 2010 OKI SEMICONDUCTOR CO., LTD.
*
* This code was derived from the Intel e1000e Linux driver.
*
......@@ -2464,8 +2464,8 @@ static void __exit pch_gbe_exit_module(void)
module_init(pch_gbe_init_module);
module_exit(pch_gbe_exit_module);
MODULE_DESCRIPTION("OKI semiconductor PCH Gigabit ethernet Driver");
MODULE_AUTHOR("OKI semiconductor, <masa-korg@dsn.okisemi.com>");
MODULE_DESCRIPTION("EG20T PCH Gigabit ethernet Driver");
MODULE_AUTHOR("OKI SEMICONDUCTOR, <toshiharu-linux@dsn.okisemi.com>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
MODULE_DEVICE_TABLE(pci, pch_gbe_pcidev_id);
......
......@@ -434,8 +434,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
.err = "using default of "
__MODULE_STRING(PCH_GBE_DEFAULT_TXD),
.def = PCH_GBE_DEFAULT_TXD,
.arg = { .r = { .min = PCH_GBE_MIN_TXD } },
.arg = { .r = { .max = PCH_GBE_MAX_TXD } }
.arg = { .r = { .min = PCH_GBE_MIN_TXD,
.max = PCH_GBE_MAX_TXD } }
};
struct pch_gbe_tx_ring *tx_ring = adapter->tx_ring;
tx_ring->count = TxDescriptors;
......@@ -450,8 +450,8 @@ void pch_gbe_check_options(struct pch_gbe_adapter *adapter)
.err = "using default of "
__MODULE_STRING(PCH_GBE_DEFAULT_RXD),
.def = PCH_GBE_DEFAULT_RXD,
.arg = { .r = { .min = PCH_GBE_MIN_RXD } },
.arg = { .r = { .max = PCH_GBE_MAX_RXD } }
.arg = { .r = { .min = PCH_GBE_MIN_RXD,
.max = PCH_GBE_MAX_RXD } }
};
struct pch_gbe_rx_ring *rx_ring = adapter->rx_ring;
rx_ring->count = RxDescriptors;
......
......@@ -2584,16 +2584,16 @@ ppp_create_interface(struct net *net, int unit, int *retp)
*/
dev_net_set(dev, net);
ret = -EEXIST;
mutex_lock(&pn->all_ppp_mutex);
if (unit < 0) {
unit = unit_get(&pn->units_idr, ppp);
if (unit < 0) {
*retp = unit;
ret = unit;
goto out2;
}
} else {
ret = -EEXIST;
if (unit_find(&pn->units_idr, unit))
goto out2; /* unit already exists */
/*
......@@ -2668,10 +2668,10 @@ static void ppp_shutdown_interface(struct ppp *ppp)
ppp->closing = 1;
ppp_unlock(ppp);
unregister_netdev(ppp->dev);
unit_put(&pn->units_idr, ppp->file.index);
} else
ppp_unlock(ppp);
unit_put(&pn->units_idr, ppp->file.index);
ppp->file.dead = 1;
ppp->owner = NULL;
wake_up_interruptible(&ppp->file.rwait);
......@@ -2859,8 +2859,7 @@ static void __exit ppp_cleanup(void)
* by holding all_ppp_mutex
*/
/* associate pointer with specified number */
static int unit_set(struct idr *p, void *ptr, int n)
static int __unit_alloc(struct idr *p, void *ptr, int n)
{
int unit, err;
......@@ -2871,10 +2870,24 @@ static int unit_set(struct idr *p, void *ptr, int n)
}
err = idr_get_new_above(p, ptr, n, &unit);
if (err == -EAGAIN)
goto again;
if (err < 0) {
if (err == -EAGAIN)
goto again;
return err;
}
return unit;
}
/* associate pointer with specified number */
static int unit_set(struct idr *p, void *ptr, int n)
{
int unit;
if (unit != n) {
unit = __unit_alloc(p, ptr, n);
if (unit < 0)
return unit;
else if (unit != n) {
idr_remove(p, unit);
return -EINVAL;
}
......@@ -2885,19 +2898,7 @@ static int unit_set(struct idr *p, void *ptr, int n)
/* get new free unit number and associate pointer with it */
static int unit_get(struct idr *p, void *ptr)
{
int unit, err;
again:
if (!idr_pre_get(p, GFP_KERNEL)) {
printk(KERN_ERR "PPP: No free memory for idr\n");
return -ENOMEM;
}
err = idr_get_new_above(p, ptr, 0, &unit);
if (err == -EAGAIN)
goto again;
return unit;
return __unit_alloc(p, ptr, 0);
}
/* put unit number back to a pool */
......
......@@ -899,7 +899,8 @@ struct ucc_geth_hardware_statistics {
#define UCC_GETH_UTFS_INIT 512 /* Tx virtual FIFO size
*/
#define UCC_GETH_UTFET_INIT 256 /* 1/2 utfs */
#define UCC_GETH_UTFTT_INIT 512
#define UCC_GETH_UTFTT_INIT 256 /* 1/2 utfs
due to errata */
/* Gigabit Ethernet (1000 Mbps) */
#define UCC_GETH_URFS_GIGA_INIT 4096/*2048*/ /* Rx virtual
FIFO size */
......
......@@ -2994,12 +2994,14 @@ static int hso_probe(struct usb_interface *interface,
case HSO_INTF_BULK:
/* It's a regular bulk interface */
if (((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) &&
!disable_net)
hso_dev = hso_create_net_device(interface, port_spec);
else
if ((port_spec & HSO_PORT_MASK) == HSO_PORT_NETWORK) {
if (!disable_net)
hso_dev =
hso_create_net_device(interface, port_spec);
} else {
hso_dev =
hso_create_bulk_serial_device(interface, port_spec);
}
if (!hso_dev)
goto exit;
break;
......
......@@ -498,7 +498,6 @@ static int x25_asy_open(struct net_device *dev)
static int x25_asy_close(struct net_device *dev)
{
struct x25_asy *sl = netdev_priv(dev);
int err;
spin_lock(&sl->lock);
if (sl->tty)
......@@ -507,10 +506,6 @@ static int x25_asy_close(struct net_device *dev)
netif_stop_queue(dev);
sl->rcount = 0;
sl->xleft = 0;
err = lapb_unregister(dev);
if (err != LAPB_OK)
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
err);
spin_unlock(&sl->lock);
return 0;
}
......@@ -595,6 +590,7 @@ static int x25_asy_open_tty(struct tty_struct *tty)
static void x25_asy_close_tty(struct tty_struct *tty)
{
struct x25_asy *sl = tty->disc_data;
int err;
/* First make sure we're connected. */
if (!sl || sl->magic != X25_ASY_MAGIC)
......@@ -605,6 +601,11 @@ static void x25_asy_close_tty(struct tty_struct *tty)
dev_close(sl->dev);
rtnl_unlock();
err = lapb_unregister(sl->dev);
if (err != LAPB_OK)
printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
err);
tty->disc_data = NULL;
sl->tty = NULL;
x25_asy_free(sl);
......
......@@ -518,7 +518,7 @@ bool ath_stoprecv(struct ath_softc *sc)
bool stopped;
spin_lock_bh(&sc->rx.rxbuflock);
ath9k_hw_stoppcurecv(ah);
ath9k_hw_abortpcurecv(ah);
ath9k_hw_setrxfilter(ah, 0);
stopped = ath9k_hw_stopdmarecv(ah);
......
......@@ -647,7 +647,7 @@ static int carl9170_op_add_interface(struct ieee80211_hw *hw,
}
unlock:
if (err && (vif_id != -1)) {
if (err && (vif_id >= 0)) {
vif_priv->active = false;
bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
ar->vifs--;
......
......@@ -163,6 +163,7 @@ static int b43_sdio_probe(struct sdio_func *func,
err_free_ssb:
kfree(sdio);
err_disable_func:
sdio_claim_host(func);
sdio_disable_func(func);
err_release_host:
sdio_release_host(func);
......
......@@ -24,6 +24,7 @@ static const struct pci_device_id b43_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4312) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4315) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4318) },
{ PCI_DEVICE(PCI_VENDOR_ID_BCM_GVC, 0x4318) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4319) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4320) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4321) },
......
......@@ -129,8 +129,9 @@ static void handle_tx(struct vhost_net *net)
size_t hdr_size;
struct socket *sock;
sock = rcu_dereference_check(vq->private_data,
lockdep_is_held(&vq->mutex));
/* TODO: check that we are running from vhost_worker?
* Not sure it's worth it, it's straight-forward enough. */
sock = rcu_dereference_check(vq->private_data, 1);
if (!sock)
return;
......
......@@ -2047,6 +2047,7 @@
#define PCI_DEVICE_ID_AFAVLAB_P030 0x2182
#define PCI_SUBDEVICE_ID_AFAVLAB_P061 0x2150
#define PCI_VENDOR_ID_BCM_GVC 0x14a4
#define PCI_VENDOR_ID_BROADCOM 0x14e4
#define PCI_DEVICE_ID_TIGON3_5752 0x1600
#define PCI_DEVICE_ID_TIGON3_5752M 0x1601
......
......@@ -10,6 +10,7 @@ extern void unix_inflight(struct file *fp);
extern void unix_notinflight(struct file *fp);
extern void unix_gc(void);
extern void wait_for_unix_gc(void);
extern struct sock *unix_get_socket(struct file *filp);
#define UNIX_HASH_SIZE 256
......@@ -56,6 +57,7 @@ struct unix_sock {
spinlock_t lock;
unsigned int gc_candidate : 1;
unsigned int gc_maybe_cycle : 1;
unsigned char recursion_level;
struct socket_wq peer_wq;
};
#define unix_sk(__sk) ((struct unix_sock *)__sk)
......
#
# Makefile for CEPH filesystem.
#
ifneq ($(KERNELRELEASE),)
obj-$(CONFIG_CEPH_LIB) += libceph.o
libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
......@@ -16,22 +13,3 @@ libceph-objs := ceph_common.o messenger.o msgpool.o buffer.o pagelist.o \
ceph_fs.o ceph_strings.o ceph_hash.o \
pagevec.o
else
#Otherwise we were called directly from the command
# line; invoke the kernel build system.
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default: all
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules
modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) CONFIG_CEPH_LIB=m modules_install
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif
......@@ -239,7 +239,8 @@ static int dccp_check_seqno(struct sock *sk, struct sk_buff *skb)
dccp_update_gsr(sk, seqno);
if (dh->dccph_type != DCCP_PKT_SYNC &&
(ackno != DCCP_PKT_WITHOUT_ACK_SEQ))
ackno != DCCP_PKT_WITHOUT_ACK_SEQ &&
after48(ackno, dp->dccps_gar))
dp->dccps_gar = ackno;
} else {
unsigned long now = jiffies;
......
......@@ -1556,6 +1556,8 @@ static int __dn_getsockopt(struct socket *sock, int level,int optname, char __us
if (r_len > sizeof(struct linkinfo_dn))
r_len = sizeof(struct linkinfo_dn);
memset(&link, 0, sizeof(link));
switch(sock->state) {
case SS_CONNECTING:
link.idn_linkstate = LL_CONNECTING;
......
......@@ -31,6 +31,7 @@
#include <linux/skbuff.h>
#include <linux/udp.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <net/sock.h>
#include <net/inet_common.h>
#include <linux/stat.h>
......@@ -276,12 +277,12 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
#endif
#ifdef CONFIG_ECONET_AUNUDP
struct msghdr udpmsg;
struct iovec iov[msg->msg_iovlen+1];
struct iovec iov[2];
struct aunhdr ah;
struct sockaddr_in udpdest;
__kernel_size_t size;
int i;
mm_segment_t oldfs;
char *userbuf;
#endif
/*
......@@ -297,23 +298,14 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
mutex_lock(&econet_mutex);
if (saddr == NULL) {
struct econet_sock *eo = ec_sk(sk);
addr.station = eo->station;
addr.net = eo->net;
port = eo->port;
cb = eo->cb;
} else {
if (msg->msg_namelen < sizeof(struct sockaddr_ec)) {
mutex_unlock(&econet_mutex);
return -EINVAL;
}
addr.station = saddr->addr.station;
addr.net = saddr->addr.net;
port = saddr->port;
cb = saddr->cb;
}
if (saddr == NULL || msg->msg_namelen < sizeof(struct sockaddr_ec)) {
mutex_unlock(&econet_mutex);
return -EINVAL;
}
addr.station = saddr->addr.station;
addr.net = saddr->addr.net;
port = saddr->port;
cb = saddr->cb;
/* Look for a device with the right network number. */
dev = net2dev_map[addr.net];
......@@ -328,17 +320,17 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
}
}
if (len + 15 > dev->mtu) {
mutex_unlock(&econet_mutex);
return -EMSGSIZE;
}
if (dev->type == ARPHRD_ECONET) {
/* Real hardware Econet. We're not worthy etc. */
#ifdef CONFIG_ECONET_NATIVE
unsigned short proto = 0;
int res;
if (len + 15 > dev->mtu) {
mutex_unlock(&econet_mutex);
return -EMSGSIZE;
}
dev_hold(dev);
skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev),
......@@ -351,7 +343,6 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
eb = (struct ec_cb *)&skb->cb;
/* BUG: saddr may be NULL */
eb->cookie = saddr->cookie;
eb->sec = *saddr;
eb->sent = ec_tx_done;
......@@ -415,6 +406,11 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
return -ENETDOWN; /* No socket - can't send */
}
if (len > 32768) {
err = -E2BIG;
goto error;
}
/* Make up a UDP datagram and hand it off to some higher intellect. */
memset(&udpdest, 0, sizeof(udpdest));
......@@ -446,36 +442,26 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
/* tack our header on the front of the iovec */
size = sizeof(struct aunhdr);
/*
* XXX: that is b0rken. We can't mix userland and kernel pointers
* in iovec, since on a lot of platforms copy_from_user() will
* *not* work with the kernel and userland ones at the same time,
* regardless of what we do with set_fs(). And we are talking about
* econet-over-ethernet here, so "it's only ARM anyway" doesn't
* apply. Any suggestions on fixing that code? -- AV
*/
iov[0].iov_base = (void *)&ah;
iov[0].iov_len = size;
for (i = 0; i < msg->msg_iovlen; i++) {
void __user *base = msg->msg_iov[i].iov_base;
size_t iov_len = msg->msg_iov[i].iov_len;
/* Check it now since we switch to KERNEL_DS later. */
if (!access_ok(VERIFY_READ, base, iov_len)) {
mutex_unlock(&econet_mutex);
return -EFAULT;
}
iov[i+1].iov_base = base;
iov[i+1].iov_len = iov_len;
size += iov_len;
userbuf = vmalloc(len);
if (userbuf == NULL) {
err = -ENOMEM;
goto error;
}
iov[1].iov_base = userbuf;
iov[1].iov_len = len;
err = memcpy_fromiovec(userbuf, msg->msg_iov, len);
if (err)
goto error_free_buf;
/* Get a skbuff (no data, just holds our cb information) */
if ((skb = sock_alloc_send_skb(sk, 0,
msg->msg_flags & MSG_DONTWAIT,
&err)) == NULL) {
mutex_unlock(&econet_mutex);
return err;
}
&err)) == NULL)
goto error_free_buf;
eb = (struct ec_cb *)&skb->cb;
......@@ -491,7 +477,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
udpmsg.msg_name = (void *)&udpdest;
udpmsg.msg_namelen = sizeof(udpdest);
udpmsg.msg_iov = &iov[0];
udpmsg.msg_iovlen = msg->msg_iovlen + 1;
udpmsg.msg_iovlen = 2;
udpmsg.msg_control = NULL;
udpmsg.msg_controllen = 0;
udpmsg.msg_flags=0;
......@@ -499,9 +485,13 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock,
oldfs = get_fs(); set_fs(KERNEL_DS); /* More privs :-) */
err = sock_sendmsg(udpsock, &udpmsg, size);
set_fs(oldfs);
error_free_buf:
vfree(userbuf);
#else
err = -EPROTOTYPE;
#endif
error:
mutex_unlock(&econet_mutex);
return err;
......@@ -671,6 +661,9 @@ static int ec_dev_ioctl(struct socket *sock, unsigned int cmd, void __user *arg)
err = 0;
switch (cmd) {
case SIOCSIFADDR:
if (!capable(CAP_NET_ADMIN))
return -EPERM;
edev = dev->ec_ptr;
if (edev == NULL) {
/* Magic up a new one. */
......
......@@ -133,8 +133,7 @@ int __inet_inherit_port(struct sock *sk, struct sock *child)
}
}
}
sk_add_bind_node(child, &tb->owners);
inet_csk(child)->icsk_bind_hash = tb;
inet_bind_hash(child, tb, port);
spin_unlock(&head->lock);
return 0;
......
......@@ -26,6 +26,8 @@ static int zero;
static int tcp_retr1_max = 255;
static int ip_local_port_range_min[] = { 1, 1 };
static int ip_local_port_range_max[] = { 65535, 65535 };
static int tcp_adv_win_scale_min = -31;
static int tcp_adv_win_scale_max = 31;
/* Update system visible IP port range */
static void set_local_port_range(int range[2])
......@@ -426,7 +428,9 @@ static struct ctl_table ipv4_table[] = {
.data = &sysctl_tcp_adv_win_scale,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = proc_dointvec
.proc_handler = proc_dointvec_minmax,
.extra1 = &tcp_adv_win_scale_min,
.extra2 = &tcp_adv_win_scale_max,
},
{
.procname = "tcp_tw_reuse",
......
......@@ -2246,7 +2246,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
/* Values greater than interface MTU won't take effect. However
* at the point when this call is done we typically don't yet
* know which interface is going to be used */
if (val < 64 || val > MAX_TCP_WINDOW) {
if (val < TCP_MIN_MSS || val > MAX_TCP_WINDOW) {
err = -EINVAL;
break;
}
......
......@@ -2043,7 +2043,9 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
}
get_sk:
sk_nulls_for_each_from(sk, node) {
if (sk->sk_family == st->family && net_eq(sock_net(sk), net)) {
if (!net_eq(sock_net(sk), net))
continue;
if (sk->sk_family == st->family) {
cur = sk;
goto out;
}
......
......@@ -1343,9 +1343,25 @@ static void unix_destruct_scm(struct sk_buff *skb)
sock_wfree(skb);
}
#define MAX_RECURSION_LEVEL 4
static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
{
int i;
unsigned char max_level = 0;
int unix_sock_count = 0;
for (i = scm->fp->count - 1; i >= 0; i--) {
struct sock *sk = unix_get_socket(scm->fp->fp[i]);
if (sk) {
unix_sock_count++;
max_level = max(max_level,
unix_sk(sk)->recursion_level);
}
}
if (unlikely(max_level > MAX_RECURSION_LEVEL))
return -ETOOMANYREFS;
/*
* Need to duplicate file references for the sake of garbage
......@@ -1356,9 +1372,11 @@ static int unix_attach_fds(struct scm_cookie *scm, struct sk_buff *skb)
if (!UNIXCB(skb).fp)
return -ENOMEM;
for (i = scm->fp->count-1; i >= 0; i--)
unix_inflight(scm->fp->fp[i]);
return 0;
if (unix_sock_count) {
for (i = scm->fp->count - 1; i >= 0; i--)
unix_inflight(scm->fp->fp[i]);
}
return max_level;
}
static int unix_scm_to_skb(struct scm_cookie *scm, struct sk_buff *skb, bool send_fds)
......@@ -1393,6 +1411,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sk_buff *skb;
long timeo;
struct scm_cookie tmp_scm;
int max_level;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
......@@ -1431,8 +1450,9 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto out;
err = unix_scm_to_skb(siocb->scm, skb, true);
if (err)
if (err < 0)
goto out_free;
max_level = err + 1;
unix_get_secdata(siocb->scm, skb);
skb_reset_transport_header(skb);
......@@ -1514,6 +1534,8 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock,
if (sock_flag(other, SOCK_RCVTSTAMP))
__net_timestamp(skb);
skb_queue_tail(&other->sk_receive_queue, skb);
if (max_level > unix_sk(other)->recursion_level)
unix_sk(other)->recursion_level = max_level;
unix_state_unlock(other);
other->sk_data_ready(other, len);
sock_put(other);
......@@ -1544,6 +1566,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
int sent = 0;
struct scm_cookie tmp_scm;
bool fds_sent = false;
int max_level;
if (NULL == siocb->scm)
siocb->scm = &tmp_scm;
......@@ -1607,10 +1630,11 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
/* Only send the fds in the first buffer */
err = unix_scm_to_skb(siocb->scm, skb, !fds_sent);
if (err) {
if (err < 0) {
kfree_skb(skb);
goto out_err;
}
max_level = err + 1;
fds_sent = true;
err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
......@@ -1626,6 +1650,8 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock,
goto pipe_err_free;
skb_queue_tail(&other->sk_receive_queue, skb);
if (max_level > unix_sk(other)->recursion_level)
unix_sk(other)->recursion_level = max_level;
unix_state_unlock(other);
other->sk_data_ready(other, size);
sent += size;
......@@ -1845,6 +1871,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
unix_state_lock(sk);
skb = skb_dequeue(&sk->sk_receive_queue);
if (skb == NULL) {
unix_sk(sk)->recursion_level = 0;
if (copied >= target)
goto unlock;
......
......@@ -96,7 +96,7 @@ static DECLARE_WAIT_QUEUE_HEAD(unix_gc_wait);
unsigned int unix_tot_inflight;
static struct sock *unix_get_socket(struct file *filp)
struct sock *unix_get_socket(struct file *filp)
{
struct sock *u_sock = NULL;
struct inode *inode = filp->f_path.dentry->d_inode;
......@@ -259,9 +259,16 @@ static void inc_inflight_move_tail(struct unix_sock *u)
}
static bool gc_in_progress = false;
#define UNIX_INFLIGHT_TRIGGER_GC 16000
void wait_for_unix_gc(void)
{
/*
* If number of inflight sockets is insane,
* force a garbage collect right now.
*/
if (unix_tot_inflight > UNIX_INFLIGHT_TRIGGER_GC && !gc_in_progress)
unix_gc();
wait_event(unix_gc_wait, gc_in_progress == false);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册