mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-11 13:27:06 +09:00
Merge tag 'v4.9.8' of git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable into odroidxu3-4.9.y
This is the 4.9.8 stable release
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,6 +1,6 @@
|
||||
VERSION = 4
|
||||
PATCHLEVEL = 9
|
||||
SUBLEVEL = 7
|
||||
SUBLEVEL = 8
|
||||
EXTRAVERSION =
|
||||
NAME = Roaring Lionus
|
||||
|
||||
|
||||
@@ -710,11 +710,8 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||
unsigned int c_index, last_c_index, last_tx_cn, num_tx_cbs;
|
||||
unsigned int pkts_compl = 0, bytes_compl = 0;
|
||||
struct bcm_sysport_cb *cb;
|
||||
struct netdev_queue *txq;
|
||||
u32 hw_ind;
|
||||
|
||||
txq = netdev_get_tx_queue(ndev, ring->index);
|
||||
|
||||
/* Compute how many descriptors have been processed since last call */
|
||||
hw_ind = tdma_readl(priv, TDMA_DESC_RING_PROD_CONS_INDEX(ring->index));
|
||||
c_index = (hw_ind >> RING_CONS_INDEX_SHIFT) & RING_CONS_INDEX_MASK;
|
||||
@@ -745,9 +742,6 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||
|
||||
ring->c_index = c_index;
|
||||
|
||||
if (netif_tx_queue_stopped(txq) && pkts_compl)
|
||||
netif_tx_wake_queue(txq);
|
||||
|
||||
netif_dbg(priv, tx_done, ndev,
|
||||
"ring=%d c_index=%d pkts_compl=%d, bytes_compl=%d\n",
|
||||
ring->index, ring->c_index, pkts_compl, bytes_compl);
|
||||
@@ -759,16 +753,33 @@ static unsigned int __bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||
static unsigned int bcm_sysport_tx_reclaim(struct bcm_sysport_priv *priv,
|
||||
struct bcm_sysport_tx_ring *ring)
|
||||
{
|
||||
struct netdev_queue *txq;
|
||||
unsigned int released;
|
||||
unsigned long flags;
|
||||
|
||||
txq = netdev_get_tx_queue(priv->netdev, ring->index);
|
||||
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
released = __bcm_sysport_tx_reclaim(priv, ring);
|
||||
if (released)
|
||||
netif_tx_wake_queue(txq);
|
||||
|
||||
spin_unlock_irqrestore(&ring->lock, flags);
|
||||
|
||||
return released;
|
||||
}
|
||||
|
||||
/* Locked version of the per-ring TX reclaim, but does not wake the queue */
|
||||
static void bcm_sysport_tx_clean(struct bcm_sysport_priv *priv,
|
||||
struct bcm_sysport_tx_ring *ring)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&ring->lock, flags);
|
||||
__bcm_sysport_tx_reclaim(priv, ring);
|
||||
spin_unlock_irqrestore(&ring->lock, flags);
|
||||
}
|
||||
|
||||
static int bcm_sysport_tx_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct bcm_sysport_tx_ring *ring =
|
||||
@@ -1253,7 +1264,7 @@ static void bcm_sysport_fini_tx_ring(struct bcm_sysport_priv *priv,
|
||||
napi_disable(&ring->napi);
|
||||
netif_napi_del(&ring->napi);
|
||||
|
||||
bcm_sysport_tx_reclaim(priv, ring);
|
||||
bcm_sysport_tx_clean(priv, ring);
|
||||
|
||||
kfree(ring->cbs);
|
||||
ring->cbs = NULL;
|
||||
|
||||
@@ -1740,8 +1740,11 @@ int mlx4_en_start_port(struct net_device *dev)
|
||||
/* Process all completions if exist to prevent
|
||||
* the queues freezing if they are full
|
||||
*/
|
||||
for (i = 0; i < priv->rx_ring_num; i++)
|
||||
for (i = 0; i < priv->rx_ring_num; i++) {
|
||||
local_bh_disable();
|
||||
napi_schedule(&priv->rx_cq[i]->napi);
|
||||
local_bh_enable();
|
||||
}
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
netif_device_attach(dev);
|
||||
|
||||
@@ -193,6 +193,9 @@ static inline bool mlx5e_rx_cache_put(struct mlx5e_rq *rq,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely(page_is_pfmemalloc(dma_info->page)))
|
||||
return false;
|
||||
|
||||
cache->page_cache[cache->tail] = *dma_info;
|
||||
cache->tail = tail_next;
|
||||
return true;
|
||||
|
||||
@@ -211,21 +211,21 @@ MLXSW_ITEM32(pci, eqe, owner, 0x0C, 0, 1);
|
||||
/* pci_eqe_cmd_token
|
||||
* Command completion event - token
|
||||
*/
|
||||
MLXSW_ITEM32(pci, eqe, cmd_token, 0x08, 16, 16);
|
||||
MLXSW_ITEM32(pci, eqe, cmd_token, 0x00, 16, 16);
|
||||
|
||||
/* pci_eqe_cmd_status
|
||||
* Command completion event - status
|
||||
*/
|
||||
MLXSW_ITEM32(pci, eqe, cmd_status, 0x08, 0, 8);
|
||||
MLXSW_ITEM32(pci, eqe, cmd_status, 0x00, 0, 8);
|
||||
|
||||
/* pci_eqe_cmd_out_param_h
|
||||
* Command completion event - output parameter - higher part
|
||||
*/
|
||||
MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x0C, 0, 32);
|
||||
MLXSW_ITEM32(pci, eqe, cmd_out_param_h, 0x04, 0, 32);
|
||||
|
||||
/* pci_eqe_cmd_out_param_l
|
||||
* Command completion event - output parameter - lower part
|
||||
*/
|
||||
MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x10, 0, 32);
|
||||
MLXSW_ITEM32(pci, eqe, cmd_out_param_l, 0x08, 0, 32);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -684,6 +684,7 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
|
||||
dev_kfree_skb_any(skb_orig);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
dev_consume_skb_any(skb_orig);
|
||||
}
|
||||
|
||||
if (eth_skb_pad(skb)) {
|
||||
|
||||
@@ -314,6 +314,7 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
|
||||
dev_kfree_skb_any(skb_orig);
|
||||
return NETDEV_TX_OK;
|
||||
}
|
||||
dev_consume_skb_any(skb_orig);
|
||||
}
|
||||
mlxsw_sx_txhdr_construct(skb, &tx_info);
|
||||
/* TX header is consumed by HW on the way so we shouldn't count its
|
||||
|
||||
@@ -1508,6 +1508,19 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
|
||||
buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
|
||||
entry / NUM_TX_DESC * DPTR_ALIGN;
|
||||
len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
|
||||
/* Zero length DMA descriptors are problematic as they seem to
|
||||
* terminate DMA transfers. Avoid them by simply using a length of
|
||||
* DPTR_ALIGN (4) when skb data is aligned to DPTR_ALIGN.
|
||||
*
|
||||
* As skb is guaranteed to have at least ETH_ZLEN (60) bytes of
|
||||
* data by the call to skb_put_padto() above this is safe with
|
||||
* respect to both the length of the first DMA descriptor (len)
|
||||
* overflowing the available data and the length of the second DMA
|
||||
* descriptor (skb->len - len) being negative.
|
||||
*/
|
||||
if (len == 0)
|
||||
len = DPTR_ALIGN;
|
||||
|
||||
memcpy(buffer, skb->data, len);
|
||||
dma_addr = dma_map_single(ndev->dev.parent, buffer, len, DMA_TO_DEVICE);
|
||||
if (dma_mapping_error(ndev->dev.parent, dma_addr))
|
||||
|
||||
@@ -659,6 +659,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
* policy filters on the host). Deliver these via the VF
|
||||
* interface in the guest.
|
||||
*/
|
||||
rcu_read_lock();
|
||||
vf_netdev = rcu_dereference(net_device_ctx->vf_netdev);
|
||||
if (vf_netdev && (vf_netdev->flags & IFF_UP))
|
||||
net = vf_netdev;
|
||||
@@ -667,6 +668,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
skb = netvsc_alloc_recv_skb(net, packet, csum_info, *data, vlan_tci);
|
||||
if (unlikely(!skb)) {
|
||||
++net->stats.rx_dropped;
|
||||
rcu_read_unlock();
|
||||
return NVSP_STAT_FAIL;
|
||||
}
|
||||
|
||||
@@ -696,6 +698,7 @@ int netvsc_recv_callback(struct hv_device *device_obj,
|
||||
* TODO - use NAPI?
|
||||
*/
|
||||
netif_rx(skb);
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -827,7 +827,7 @@ static ssize_t macvtap_put_user(struct macvtap_queue *q,
|
||||
return -EINVAL;
|
||||
|
||||
ret = virtio_net_hdr_from_skb(skb, &vnet_hdr,
|
||||
macvtap_is_little_endian(q));
|
||||
macvtap_is_little_endian(q), true);
|
||||
if (ret)
|
||||
BUG();
|
||||
|
||||
|
||||
@@ -21,6 +21,23 @@ MODULE_DESCRIPTION("Broadcom 63xx internal PHY driver");
|
||||
MODULE_AUTHOR("Maxime Bizon <mbizon@freebox.fr>");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
static int bcm63xx_config_intr(struct phy_device *phydev)
|
||||
{
|
||||
int reg, err;
|
||||
|
||||
reg = phy_read(phydev, MII_BCM63XX_IR);
|
||||
if (reg < 0)
|
||||
return reg;
|
||||
|
||||
if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
|
||||
reg &= ~MII_BCM63XX_IR_GMASK;
|
||||
else
|
||||
reg |= MII_BCM63XX_IR_GMASK;
|
||||
|
||||
err = phy_write(phydev, MII_BCM63XX_IR, reg);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int bcm63xx_config_init(struct phy_device *phydev)
|
||||
{
|
||||
int reg, err;
|
||||
@@ -55,7 +72,7 @@ static struct phy_driver bcm63xx_driver[] = {
|
||||
.config_aneg = genphy_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
.ack_interrupt = bcm_phy_ack_intr,
|
||||
.config_intr = bcm_phy_config_intr,
|
||||
.config_intr = bcm63xx_config_intr,
|
||||
}, {
|
||||
/* same phy as above, with just a different OUI */
|
||||
.phy_id = 0x002bdc00,
|
||||
@@ -67,7 +84,7 @@ static struct phy_driver bcm63xx_driver[] = {
|
||||
.config_aneg = genphy_config_aneg,
|
||||
.read_status = genphy_read_status,
|
||||
.ack_interrupt = bcm_phy_ack_intr,
|
||||
.config_intr = bcm_phy_config_intr,
|
||||
.config_intr = bcm63xx_config_intr,
|
||||
} };
|
||||
|
||||
module_phy_driver(bcm63xx_driver);
|
||||
|
||||
@@ -1374,7 +1374,7 @@ static ssize_t tun_put_user(struct tun_struct *tun,
|
||||
return -EINVAL;
|
||||
|
||||
ret = virtio_net_hdr_from_skb(skb, &gso,
|
||||
tun_is_little_endian(tun));
|
||||
tun_is_little_endian(tun), true);
|
||||
if (ret) {
|
||||
struct skb_shared_info *sinfo = skb_shinfo(skb);
|
||||
pr_err("unexpected GSO type: "
|
||||
|
||||
@@ -531,6 +531,7 @@ static const struct driver_info wwan_info = {
|
||||
#define SAMSUNG_VENDOR_ID 0x04e8
|
||||
#define LENOVO_VENDOR_ID 0x17ef
|
||||
#define NVIDIA_VENDOR_ID 0x0955
|
||||
#define HP_VENDOR_ID 0x03f0
|
||||
|
||||
static const struct usb_device_id products[] = {
|
||||
/* BLACKLIST !!
|
||||
@@ -677,6 +678,13 @@ static const struct usb_device_id products[] = {
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
/* HP lt2523 (Novatel E371) - handled by qmi_wwan */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(HP_VENDOR_ID, 0x421d, USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
|
||||
.driver_info = 0,
|
||||
},
|
||||
|
||||
/* AnyDATA ADU960S - handled by qmi_wwan */
|
||||
{
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x16d5, 0x650a, USB_CLASS_COMM,
|
||||
|
||||
@@ -654,6 +654,13 @@ static const struct usb_device_id products[] = {
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
},
|
||||
{ /* HP lt2523 (Novatel E371) */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x421d,
|
||||
USB_CLASS_COMM,
|
||||
USB_CDC_SUBCLASS_ETHERNET,
|
||||
USB_CDC_PROTO_NONE),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
},
|
||||
{ /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
|
||||
USB_DEVICE_AND_INTERFACE_INFO(0x03f0, 0x581d, USB_CLASS_VENDOR_SPEC, 1, 7),
|
||||
.driver_info = (unsigned long)&qmi_wwan_info,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define NETNEXT_VERSION "08"
|
||||
|
||||
/* Information for net */
|
||||
#define NET_VERSION "6"
|
||||
#define NET_VERSION "7"
|
||||
|
||||
#define DRIVER_VERSION "v1." NETNEXT_VERSION "." NET_VERSION
|
||||
#define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>"
|
||||
@@ -1730,7 +1730,7 @@ static u8 r8152_rx_csum(struct r8152 *tp, struct rx_desc *rx_desc)
|
||||
u8 checksum = CHECKSUM_NONE;
|
||||
u32 opts2, opts3;
|
||||
|
||||
if (tp->version == RTL_VER_01 || tp->version == RTL_VER_02)
|
||||
if (!(tp->netdev->features & NETIF_F_RXCSUM))
|
||||
goto return_result;
|
||||
|
||||
opts2 = le32_to_cpu(rx_desc->opts2);
|
||||
@@ -3572,6 +3572,8 @@ static bool delay_autosuspend(struct r8152 *tp)
|
||||
*/
|
||||
if (!sw_linking && tp->rtl_ops.in_nway(tp))
|
||||
return true;
|
||||
else if (!skb_queue_empty(&tp->tx_queue))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -4358,6 +4360,11 @@ static int rtl8152_probe(struct usb_interface *intf,
|
||||
NETIF_F_HIGHDMA | NETIF_F_FRAGLIST |
|
||||
NETIF_F_IPV6_CSUM | NETIF_F_TSO6;
|
||||
|
||||
if (tp->version == RTL_VER_01) {
|
||||
netdev->features &= ~NETIF_F_RXCSUM;
|
||||
netdev->hw_features &= ~NETIF_F_RXCSUM;
|
||||
}
|
||||
|
||||
netdev->ethtool_ops = &ops;
|
||||
netif_set_gso_max_size(netdev, RTL_LIMITED_TSO_SIZE);
|
||||
|
||||
|
||||
@@ -840,7 +840,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb)
|
||||
hdr = skb_vnet_hdr(skb);
|
||||
|
||||
if (virtio_net_hdr_from_skb(skb, &hdr->hdr,
|
||||
virtio_is_little_endian(vi->vdev)))
|
||||
virtio_is_little_endian(vi->vdev), false))
|
||||
BUG();
|
||||
|
||||
if (vi->mergeable_rx_bufs)
|
||||
|
||||
@@ -2887,7 +2887,7 @@ static int vxlan_dev_configure(struct net *src_net, struct net_device *dev,
|
||||
memcpy(&vxlan->cfg, conf, sizeof(*conf));
|
||||
if (!vxlan->cfg.dst_port) {
|
||||
if (conf->flags & VXLAN_F_GPE)
|
||||
vxlan->cfg.dst_port = 4790; /* IANA assigned VXLAN-GPE port */
|
||||
vxlan->cfg.dst_port = htons(4790); /* IANA VXLAN-GPE port */
|
||||
else
|
||||
vxlan->cfg.dst_port = default_port;
|
||||
}
|
||||
|
||||
@@ -95,10 +95,7 @@ unsigned int
|
||||
xfs_alloc_set_aside(
|
||||
struct xfs_mount *mp)
|
||||
{
|
||||
unsigned int blocks;
|
||||
|
||||
blocks = 4 + (mp->m_sb.sb_agcount * XFS_ALLOC_AGFL_RESERVE);
|
||||
return blocks;
|
||||
return mp->m_sb.sb_agcount * (XFS_ALLOC_AGFL_RESERVE + 4);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -365,35 +362,11 @@ xfs_alloc_fix_len(
|
||||
return;
|
||||
ASSERT(rlen >= args->minlen && rlen <= args->maxlen);
|
||||
ASSERT(rlen % args->prod == args->mod);
|
||||
ASSERT(args->pag->pagf_freeblks + args->pag->pagf_flcount >=
|
||||
rlen + args->minleft);
|
||||
args->len = rlen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix up length if there is too little space left in the a.g.
|
||||
* Return 1 if ok, 0 if too little, should give up.
|
||||
*/
|
||||
STATIC int
|
||||
xfs_alloc_fix_minleft(
|
||||
xfs_alloc_arg_t *args) /* allocation argument structure */
|
||||
{
|
||||
xfs_agf_t *agf; /* a.g. freelist header */
|
||||
int diff; /* free space difference */
|
||||
|
||||
if (args->minleft == 0)
|
||||
return 1;
|
||||
agf = XFS_BUF_TO_AGF(args->agbp);
|
||||
diff = be32_to_cpu(agf->agf_freeblks)
|
||||
- args->len - args->minleft;
|
||||
if (diff >= 0)
|
||||
return 1;
|
||||
args->len += diff; /* shrink the allocated space */
|
||||
/* casts to (int) catch length underflows */
|
||||
if ((int)args->len >= (int)args->minlen)
|
||||
return 1;
|
||||
args->agbno = NULLAGBLOCK;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update the two btrees, logically removing from freespace the extent
|
||||
* starting at rbno, rlen blocks. The extent is contained within the
|
||||
@@ -689,8 +662,6 @@ xfs_alloc_ag_vextent(
|
||||
xfs_alloc_arg_t *args) /* argument structure for allocation */
|
||||
{
|
||||
int error=0;
|
||||
xfs_extlen_t reservation;
|
||||
xfs_extlen_t oldmax;
|
||||
|
||||
ASSERT(args->minlen > 0);
|
||||
ASSERT(args->maxlen > 0);
|
||||
@@ -698,20 +669,6 @@ xfs_alloc_ag_vextent(
|
||||
ASSERT(args->mod < args->prod);
|
||||
ASSERT(args->alignment > 0);
|
||||
|
||||
/*
|
||||
* Clamp maxlen to the amount of free space minus any reservations
|
||||
* that have been made.
|
||||
*/
|
||||
oldmax = args->maxlen;
|
||||
reservation = xfs_ag_resv_needed(args->pag, args->resv);
|
||||
if (args->maxlen > args->pag->pagf_freeblks - reservation)
|
||||
args->maxlen = args->pag->pagf_freeblks - reservation;
|
||||
if (args->maxlen == 0) {
|
||||
args->agbno = NULLAGBLOCK;
|
||||
args->maxlen = oldmax;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Branch to correct routine based on the type.
|
||||
*/
|
||||
@@ -731,8 +688,6 @@ xfs_alloc_ag_vextent(
|
||||
/* NOTREACHED */
|
||||
}
|
||||
|
||||
args->maxlen = oldmax;
|
||||
|
||||
if (error || args->agbno == NULLAGBLOCK)
|
||||
return error;
|
||||
|
||||
@@ -841,9 +796,6 @@ xfs_alloc_ag_vextent_exact(
|
||||
args->len = XFS_AGBLOCK_MIN(tend, args->agbno + args->maxlen)
|
||||
- args->agbno;
|
||||
xfs_alloc_fix_len(args);
|
||||
if (!xfs_alloc_fix_minleft(args))
|
||||
goto not_found;
|
||||
|
||||
ASSERT(args->agbno + args->len <= tend);
|
||||
|
||||
/*
|
||||
@@ -1149,12 +1101,7 @@ restart:
|
||||
XFS_WANT_CORRUPTED_GOTO(args->mp, i == 1, error0);
|
||||
ASSERT(ltbno + ltlen <= be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
|
||||
args->len = blen;
|
||||
if (!xfs_alloc_fix_minleft(args)) {
|
||||
xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
|
||||
trace_xfs_alloc_near_nominleft(args);
|
||||
return 0;
|
||||
}
|
||||
blen = args->len;
|
||||
|
||||
/*
|
||||
* We are allocating starting at bnew for blen blocks.
|
||||
*/
|
||||
@@ -1346,12 +1293,6 @@ restart:
|
||||
*/
|
||||
args->len = XFS_EXTLEN_MIN(ltlena, args->maxlen);
|
||||
xfs_alloc_fix_len(args);
|
||||
if (!xfs_alloc_fix_minleft(args)) {
|
||||
trace_xfs_alloc_near_nominleft(args);
|
||||
xfs_btree_del_cursor(bno_cur_lt, XFS_BTREE_NOERROR);
|
||||
xfs_btree_del_cursor(cnt_cur, XFS_BTREE_NOERROR);
|
||||
return 0;
|
||||
}
|
||||
rlen = args->len;
|
||||
(void)xfs_alloc_compute_diff(args->agbno, rlen, args->alignment,
|
||||
args->datatype, ltbnoa, ltlena, <new);
|
||||
@@ -1553,8 +1494,6 @@ restart:
|
||||
}
|
||||
xfs_alloc_fix_len(args);
|
||||
|
||||
if (!xfs_alloc_fix_minleft(args))
|
||||
goto out_nominleft;
|
||||
rlen = args->len;
|
||||
XFS_WANT_CORRUPTED_GOTO(args->mp, rlen <= flen, error0);
|
||||
/*
|
||||
@@ -2056,7 +1995,7 @@ xfs_alloc_space_available(
|
||||
int flags)
|
||||
{
|
||||
struct xfs_perag *pag = args->pag;
|
||||
xfs_extlen_t longest;
|
||||
xfs_extlen_t alloc_len, longest;
|
||||
xfs_extlen_t reservation; /* blocks that are still reserved */
|
||||
int available;
|
||||
|
||||
@@ -2066,17 +2005,28 @@ xfs_alloc_space_available(
|
||||
reservation = xfs_ag_resv_needed(pag, args->resv);
|
||||
|
||||
/* do we have enough contiguous free space for the allocation? */
|
||||
alloc_len = args->minlen + (args->alignment - 1) + args->minalignslop;
|
||||
longest = xfs_alloc_longest_free_extent(args->mp, pag, min_free,
|
||||
reservation);
|
||||
if ((args->minlen + args->alignment + args->minalignslop - 1) > longest)
|
||||
if (longest < alloc_len)
|
||||
return false;
|
||||
|
||||
/* do we have enough free space remaining for the allocation? */
|
||||
available = (int)(pag->pagf_freeblks + pag->pagf_flcount -
|
||||
reservation - min_free - args->total);
|
||||
if (available < (int)args->minleft || available <= 0)
|
||||
reservation - min_free - args->minleft);
|
||||
if (available < (int)max(args->total, alloc_len))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Clamp maxlen to the amount of free space available for the actual
|
||||
* extent allocation.
|
||||
*/
|
||||
if (available < (int)args->maxlen && !(flags & XFS_ALLOC_FLAG_CHECK)) {
|
||||
args->maxlen = available;
|
||||
ASSERT(args->maxlen > 0);
|
||||
ASSERT(args->maxlen >= args->minlen);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2122,7 +2072,8 @@ xfs_alloc_fix_freelist(
|
||||
}
|
||||
|
||||
need = xfs_alloc_min_freelist(mp, pag);
|
||||
if (!xfs_alloc_space_available(args, need, flags))
|
||||
if (!xfs_alloc_space_available(args, need, flags |
|
||||
XFS_ALLOC_FLAG_CHECK))
|
||||
goto out_agbp_relse;
|
||||
|
||||
/*
|
||||
@@ -2638,12 +2589,10 @@ xfs_alloc_vextent(
|
||||
xfs_agblock_t agsize; /* allocation group size */
|
||||
int error;
|
||||
int flags; /* XFS_ALLOC_FLAG_... locking flags */
|
||||
xfs_extlen_t minleft;/* minimum left value, temp copy */
|
||||
xfs_mount_t *mp; /* mount structure pointer */
|
||||
xfs_agnumber_t sagno; /* starting allocation group number */
|
||||
xfs_alloctype_t type; /* input allocation type */
|
||||
int bump_rotor = 0;
|
||||
int no_min = 0;
|
||||
xfs_agnumber_t rotorstep = xfs_rotorstep; /* inode32 agf stepper */
|
||||
|
||||
mp = args->mp;
|
||||
@@ -2672,7 +2621,6 @@ xfs_alloc_vextent(
|
||||
trace_xfs_alloc_vextent_badargs(args);
|
||||
return 0;
|
||||
}
|
||||
minleft = args->minleft;
|
||||
|
||||
switch (type) {
|
||||
case XFS_ALLOCTYPE_THIS_AG:
|
||||
@@ -2683,9 +2631,7 @@ xfs_alloc_vextent(
|
||||
*/
|
||||
args->agno = XFS_FSB_TO_AGNO(mp, args->fsbno);
|
||||
args->pag = xfs_perag_get(mp, args->agno);
|
||||
args->minleft = 0;
|
||||
error = xfs_alloc_fix_freelist(args, 0);
|
||||
args->minleft = minleft;
|
||||
if (error) {
|
||||
trace_xfs_alloc_vextent_nofix(args);
|
||||
goto error0;
|
||||
@@ -2750,9 +2696,7 @@ xfs_alloc_vextent(
|
||||
*/
|
||||
for (;;) {
|
||||
args->pag = xfs_perag_get(mp, args->agno);
|
||||
if (no_min) args->minleft = 0;
|
||||
error = xfs_alloc_fix_freelist(args, flags);
|
||||
args->minleft = minleft;
|
||||
if (error) {
|
||||
trace_xfs_alloc_vextent_nofix(args);
|
||||
goto error0;
|
||||
@@ -2792,20 +2736,17 @@ xfs_alloc_vextent(
|
||||
* or switch to non-trylock mode.
|
||||
*/
|
||||
if (args->agno == sagno) {
|
||||
if (no_min == 1) {
|
||||
if (flags == 0) {
|
||||
args->agbno = NULLAGBLOCK;
|
||||
trace_xfs_alloc_vextent_allfailed(args);
|
||||
break;
|
||||
}
|
||||
if (flags == 0) {
|
||||
no_min = 1;
|
||||
} else {
|
||||
flags = 0;
|
||||
if (type == XFS_ALLOCTYPE_START_BNO) {
|
||||
args->agbno = XFS_FSB_TO_AGBNO(mp,
|
||||
args->fsbno);
|
||||
args->type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
}
|
||||
|
||||
flags = 0;
|
||||
if (type == XFS_ALLOCTYPE_START_BNO) {
|
||||
args->agbno = XFS_FSB_TO_AGBNO(mp,
|
||||
args->fsbno);
|
||||
args->type = XFS_ALLOCTYPE_NEAR_BNO;
|
||||
}
|
||||
}
|
||||
xfs_perag_put(args->pag);
|
||||
|
||||
@@ -56,7 +56,7 @@ typedef unsigned int xfs_alloctype_t;
|
||||
#define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/
|
||||
#define XFS_ALLOC_FLAG_NORMAP 0x00000004 /* don't modify the rmapbt */
|
||||
#define XFS_ALLOC_FLAG_NOSHRINK 0x00000008 /* don't shrink the freelist */
|
||||
|
||||
#define XFS_ALLOC_FLAG_CHECK 0x00000010 /* test only, don't modify args */
|
||||
|
||||
/*
|
||||
* Argument structure for xfs_alloc routines.
|
||||
|
||||
@@ -131,9 +131,6 @@ xfs_attr_get(
|
||||
if (XFS_FORCED_SHUTDOWN(ip->i_mount))
|
||||
return -EIO;
|
||||
|
||||
if (!xfs_inode_hasattr(ip))
|
||||
return -ENOATTR;
|
||||
|
||||
error = xfs_attr_args_init(&args, ip, name, flags);
|
||||
if (error)
|
||||
return error;
|
||||
@@ -392,9 +389,6 @@ xfs_attr_remove(
|
||||
if (XFS_FORCED_SHUTDOWN(dp->i_mount))
|
||||
return -EIO;
|
||||
|
||||
if (!xfs_inode_hasattr(dp))
|
||||
return -ENOATTR;
|
||||
|
||||
error = xfs_attr_args_init(&args, dp, name, flags);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@@ -3720,7 +3720,7 @@ xfs_bmap_btalloc(
|
||||
align = xfs_get_cowextsz_hint(ap->ip);
|
||||
else if (xfs_alloc_is_userdata(ap->datatype))
|
||||
align = xfs_get_extsz_hint(ap->ip);
|
||||
if (unlikely(align)) {
|
||||
if (align) {
|
||||
error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
|
||||
align, 0, ap->eof, 0, ap->conv,
|
||||
&ap->offset, &ap->length);
|
||||
@@ -3792,7 +3792,7 @@ xfs_bmap_btalloc(
|
||||
args.minlen = ap->minlen;
|
||||
}
|
||||
/* apply extent size hints if obtained earlier */
|
||||
if (unlikely(align)) {
|
||||
if (align) {
|
||||
args.prod = align;
|
||||
if ((args.mod = (xfs_extlen_t)do_mod(ap->offset, args.prod)))
|
||||
args.mod = (xfs_extlen_t)(args.prod - args.mod);
|
||||
@@ -3903,7 +3903,6 @@ xfs_bmap_btalloc(
|
||||
args.fsbno = 0;
|
||||
args.type = XFS_ALLOCTYPE_FIRST_AG;
|
||||
args.total = ap->minlen;
|
||||
args.minleft = 0;
|
||||
if ((error = xfs_alloc_vextent(&args)))
|
||||
return error;
|
||||
ap->dfops->dop_low = true;
|
||||
@@ -4437,8 +4436,6 @@ xfs_bmapi_allocate(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (bma->dfops->dop_low)
|
||||
bma->minleft = 0;
|
||||
if (bma->cur)
|
||||
bma->cur->bc_private.b.firstblock = *bma->firstblock;
|
||||
if (bma->blkno == NULLFSBLOCK)
|
||||
@@ -4610,8 +4607,6 @@ xfs_bmapi_write(
|
||||
int n; /* current extent index */
|
||||
xfs_fileoff_t obno; /* old block number (offset) */
|
||||
int whichfork; /* data or attr fork */
|
||||
char inhole; /* current location is hole in file */
|
||||
char wasdelay; /* old extent was delayed */
|
||||
|
||||
#ifdef DEBUG
|
||||
xfs_fileoff_t orig_bno; /* original block number value */
|
||||
@@ -4697,22 +4692,44 @@ xfs_bmapi_write(
|
||||
bma.firstblock = firstblock;
|
||||
|
||||
while (bno < end && n < *nmap) {
|
||||
inhole = eof || bma.got.br_startoff > bno;
|
||||
wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
|
||||
bool need_alloc = false, wasdelay = false;
|
||||
|
||||
/*
|
||||
* Make sure we only reflink into a hole.
|
||||
*/
|
||||
if (flags & XFS_BMAPI_REMAP)
|
||||
ASSERT(inhole);
|
||||
if (flags & XFS_BMAPI_COWFORK)
|
||||
ASSERT(!inhole);
|
||||
/* in hole or beyoned EOF? */
|
||||
if (eof || bma.got.br_startoff > bno) {
|
||||
if (flags & XFS_BMAPI_DELALLOC) {
|
||||
/*
|
||||
* For the COW fork we can reasonably get a
|
||||
* request for converting an extent that races
|
||||
* with other threads already having converted
|
||||
* part of it, as there converting COW to
|
||||
* regular blocks is not protected using the
|
||||
* IOLOCK.
|
||||
*/
|
||||
ASSERT(flags & XFS_BMAPI_COWFORK);
|
||||
if (!(flags & XFS_BMAPI_COWFORK)) {
|
||||
error = -EIO;
|
||||
goto error0;
|
||||
}
|
||||
|
||||
if (eof || bno >= end)
|
||||
break;
|
||||
} else {
|
||||
need_alloc = true;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Make sure we only reflink into a hole.
|
||||
*/
|
||||
ASSERT(!(flags & XFS_BMAPI_REMAP));
|
||||
if (isnullstartblock(bma.got.br_startblock))
|
||||
wasdelay = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* First, deal with the hole before the allocated space
|
||||
* that we found, if any.
|
||||
*/
|
||||
if (inhole || wasdelay) {
|
||||
if (need_alloc || wasdelay) {
|
||||
bma.eof = eof;
|
||||
bma.conv = !!(flags & XFS_BMAPI_CONVERT);
|
||||
bma.wasdel = wasdelay;
|
||||
|
||||
@@ -110,6 +110,9 @@ struct xfs_extent_free_item
|
||||
/* Map something in the CoW fork. */
|
||||
#define XFS_BMAPI_COWFORK 0x200
|
||||
|
||||
/* Only convert delalloc space, don't allocate entirely new extents */
|
||||
#define XFS_BMAPI_DELALLOC 0x400
|
||||
|
||||
#define XFS_BMAPI_FLAGS \
|
||||
{ XFS_BMAPI_ENTIRE, "ENTIRE" }, \
|
||||
{ XFS_BMAPI_METADATA, "METADATA" }, \
|
||||
@@ -120,7 +123,8 @@ struct xfs_extent_free_item
|
||||
{ XFS_BMAPI_CONVERT, "CONVERT" }, \
|
||||
{ XFS_BMAPI_ZERO, "ZERO" }, \
|
||||
{ XFS_BMAPI_REMAP, "REMAP" }, \
|
||||
{ XFS_BMAPI_COWFORK, "COWFORK" }
|
||||
{ XFS_BMAPI_COWFORK, "COWFORK" }, \
|
||||
{ XFS_BMAPI_DELALLOC, "DELALLOC" }
|
||||
|
||||
|
||||
static inline int xfs_bmapi_aflag(int w)
|
||||
|
||||
@@ -502,12 +502,11 @@ try_another_ag:
|
||||
if (args.fsbno == NULLFSBLOCK && args.minleft) {
|
||||
/*
|
||||
* Could not find an AG with enough free space to satisfy
|
||||
* a full btree split. Try again without minleft and if
|
||||
* a full btree split. Try again and if
|
||||
* successful activate the lowspace algorithm.
|
||||
*/
|
||||
args.fsbno = 0;
|
||||
args.type = XFS_ALLOCTYPE_FIRST_AG;
|
||||
args.minleft = 0;
|
||||
error = xfs_alloc_vextent(&args);
|
||||
if (error)
|
||||
goto error0;
|
||||
|
||||
@@ -36,21 +36,29 @@
|
||||
struct xfs_name xfs_name_dotdot = { (unsigned char *)"..", 2, XFS_DIR3_FT_DIR };
|
||||
|
||||
/*
|
||||
* @mode, if set, indicates that the type field needs to be set up.
|
||||
* This uses the transformation from file mode to DT_* as defined in linux/fs.h
|
||||
* for file type specification. This will be propagated into the directory
|
||||
* structure if appropriate for the given operation and filesystem config.
|
||||
* Convert inode mode to directory entry filetype
|
||||
*/
|
||||
const unsigned char xfs_mode_to_ftype[S_IFMT >> S_SHIFT] = {
|
||||
[0] = XFS_DIR3_FT_UNKNOWN,
|
||||
[S_IFREG >> S_SHIFT] = XFS_DIR3_FT_REG_FILE,
|
||||
[S_IFDIR >> S_SHIFT] = XFS_DIR3_FT_DIR,
|
||||
[S_IFCHR >> S_SHIFT] = XFS_DIR3_FT_CHRDEV,
|
||||
[S_IFBLK >> S_SHIFT] = XFS_DIR3_FT_BLKDEV,
|
||||
[S_IFIFO >> S_SHIFT] = XFS_DIR3_FT_FIFO,
|
||||
[S_IFSOCK >> S_SHIFT] = XFS_DIR3_FT_SOCK,
|
||||
[S_IFLNK >> S_SHIFT] = XFS_DIR3_FT_SYMLINK,
|
||||
};
|
||||
unsigned char xfs_mode_to_ftype(int mode)
|
||||
{
|
||||
switch (mode & S_IFMT) {
|
||||
case S_IFREG:
|
||||
return XFS_DIR3_FT_REG_FILE;
|
||||
case S_IFDIR:
|
||||
return XFS_DIR3_FT_DIR;
|
||||
case S_IFCHR:
|
||||
return XFS_DIR3_FT_CHRDEV;
|
||||
case S_IFBLK:
|
||||
return XFS_DIR3_FT_BLKDEV;
|
||||
case S_IFIFO:
|
||||
return XFS_DIR3_FT_FIFO;
|
||||
case S_IFSOCK:
|
||||
return XFS_DIR3_FT_SOCK;
|
||||
case S_IFLNK:
|
||||
return XFS_DIR3_FT_SYMLINK;
|
||||
default:
|
||||
return XFS_DIR3_FT_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ASCII case-insensitive (ie. A-Z) support for directories that was
|
||||
@@ -631,7 +639,8 @@ xfs_dir2_isblock(
|
||||
if ((rval = xfs_bmap_last_offset(args->dp, &last, XFS_DATA_FORK)))
|
||||
return rval;
|
||||
rval = XFS_FSB_TO_B(args->dp->i_mount, last) == args->geo->blksize;
|
||||
ASSERT(rval == 0 || args->dp->i_d.di_size == args->geo->blksize);
|
||||
if (rval != 0 && args->dp->i_d.di_size != args->geo->blksize)
|
||||
return -EFSCORRUPTED;
|
||||
*vp = rval;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#ifndef __XFS_DIR2_H__
|
||||
#define __XFS_DIR2_H__
|
||||
|
||||
#include "xfs_da_format.h"
|
||||
#include "xfs_da_btree.h"
|
||||
|
||||
struct xfs_defer_ops;
|
||||
struct xfs_da_args;
|
||||
struct xfs_inode;
|
||||
@@ -32,10 +35,9 @@ struct xfs_dir2_data_unused;
|
||||
extern struct xfs_name xfs_name_dotdot;
|
||||
|
||||
/*
|
||||
* directory filetype conversion tables.
|
||||
* Convert inode mode to directory entry filetype
|
||||
*/
|
||||
#define S_SHIFT 12
|
||||
extern const unsigned char xfs_mode_to_ftype[];
|
||||
extern unsigned char xfs_mode_to_ftype(int mode);
|
||||
|
||||
/*
|
||||
* directory operations vector for encode/decode routines
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "xfs_icache.h"
|
||||
#include "xfs_trans.h"
|
||||
#include "xfs_ialloc.h"
|
||||
#include "xfs_dir2.h"
|
||||
|
||||
/*
|
||||
* Check that none of the inode's in the buffer have a next
|
||||
@@ -386,6 +387,7 @@ xfs_dinode_verify(
|
||||
struct xfs_inode *ip,
|
||||
struct xfs_dinode *dip)
|
||||
{
|
||||
uint16_t mode;
|
||||
uint16_t flags;
|
||||
uint64_t flags2;
|
||||
|
||||
@@ -396,8 +398,12 @@ xfs_dinode_verify(
|
||||
if (be64_to_cpu(dip->di_size) & (1ULL << 63))
|
||||
return false;
|
||||
|
||||
/* No zero-length symlinks. */
|
||||
if (S_ISLNK(be16_to_cpu(dip->di_mode)) && dip->di_size == 0)
|
||||
mode = be16_to_cpu(dip->di_mode);
|
||||
if (mode && xfs_mode_to_ftype(mode) == XFS_DIR3_FT_UNKNOWN)
|
||||
return false;
|
||||
|
||||
/* No zero-length symlinks/dirs. */
|
||||
if ((S_ISLNK(mode) || S_ISDIR(mode)) && dip->di_size == 0)
|
||||
return false;
|
||||
|
||||
/* only version 3 or greater inodes are extensively verified here */
|
||||
|
||||
@@ -242,7 +242,7 @@ xfs_mount_validate_sb(
|
||||
sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
|
||||
sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
|
||||
sbp->sb_blocksize != (1 << sbp->sb_blocklog) ||
|
||||
sbp->sb_dirblklog > XFS_MAX_BLOCKSIZE_LOG ||
|
||||
sbp->sb_dirblklog + sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
|
||||
sbp->sb_inodesize < XFS_DINODE_MIN_SIZE ||
|
||||
sbp->sb_inodesize > XFS_DINODE_MAX_SIZE ||
|
||||
sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
|
||||
|
||||
@@ -528,7 +528,6 @@ xfs_getbmap(
|
||||
xfs_bmbt_irec_t *map; /* buffer for user's data */
|
||||
xfs_mount_t *mp; /* file system mount point */
|
||||
int nex; /* # of user extents can do */
|
||||
int nexleft; /* # of user extents left */
|
||||
int subnex; /* # of bmapi's can do */
|
||||
int nmap; /* number of map entries */
|
||||
struct getbmapx *out; /* output structure */
|
||||
@@ -686,10 +685,8 @@ xfs_getbmap(
|
||||
goto out_free_map;
|
||||
}
|
||||
|
||||
nexleft = nex;
|
||||
|
||||
do {
|
||||
nmap = (nexleft > subnex) ? subnex : nexleft;
|
||||
nmap = (nex> subnex) ? subnex : nex;
|
||||
error = xfs_bmapi_read(ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset),
|
||||
XFS_BB_TO_FSB(mp, bmv->bmv_length),
|
||||
map, &nmap, bmapi_flags);
|
||||
@@ -697,8 +694,8 @@ xfs_getbmap(
|
||||
goto out_free_map;
|
||||
ASSERT(nmap <= subnex);
|
||||
|
||||
for (i = 0; i < nmap && nexleft && bmv->bmv_length &&
|
||||
cur_ext < bmv->bmv_count; i++) {
|
||||
for (i = 0; i < nmap && bmv->bmv_length &&
|
||||
cur_ext < bmv->bmv_count - 1; i++) {
|
||||
out[cur_ext].bmv_oflags = 0;
|
||||
if (map[i].br_state == XFS_EXT_UNWRITTEN)
|
||||
out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
|
||||
@@ -760,16 +757,27 @@ xfs_getbmap(
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* In order to report shared extents accurately,
|
||||
* we report each distinct shared/unshared part
|
||||
* of a single bmbt record using multiple bmap
|
||||
* extents. To make that happen, we iterate the
|
||||
* same map array item multiple times, each
|
||||
* time trimming out the subextent that we just
|
||||
* reported.
|
||||
*
|
||||
* Because of this, we must check the out array
|
||||
* index (cur_ext) directly against bmv_count-1
|
||||
* to avoid overflows.
|
||||
*/
|
||||
if (inject_map.br_startblock != NULLFSBLOCK) {
|
||||
map[i] = inject_map;
|
||||
i--;
|
||||
} else
|
||||
nexleft--;
|
||||
}
|
||||
bmv->bmv_entries++;
|
||||
cur_ext++;
|
||||
}
|
||||
} while (nmap && nexleft && bmv->bmv_length &&
|
||||
cur_ext < bmv->bmv_count);
|
||||
} while (nmap && bmv->bmv_length && cur_ext < bmv->bmv_count - 1);
|
||||
|
||||
out_free_map:
|
||||
kmem_free(map);
|
||||
|
||||
@@ -423,6 +423,7 @@ retry:
|
||||
out_free_pages:
|
||||
for (i = 0; i < bp->b_page_count; i++)
|
||||
__free_page(bp->b_pages[i]);
|
||||
bp->b_flags &= ~_XBF_PAGES;
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@@ -710,6 +710,10 @@ xfs_dq_get_next_id(
|
||||
/* Simple advance */
|
||||
next_id = *id + 1;
|
||||
|
||||
/* If we'd wrap past the max ID, stop */
|
||||
if (next_id < *id)
|
||||
return -ENOENT;
|
||||
|
||||
/* If new ID is within the current chunk, advancing it sufficed */
|
||||
if (next_id % mp->m_quotainfo->qi_dqperchunk) {
|
||||
*id = next_id;
|
||||
|
||||
@@ -681,7 +681,7 @@ xfs_iomap_write_allocate(
|
||||
xfs_trans_t *tp;
|
||||
int nimaps;
|
||||
int error = 0;
|
||||
int flags = 0;
|
||||
int flags = XFS_BMAPI_DELALLOC;
|
||||
int nres;
|
||||
|
||||
if (whichfork == XFS_COW_FORK)
|
||||
|
||||
@@ -97,13 +97,28 @@ xfs_init_security(
|
||||
|
||||
static void
|
||||
xfs_dentry_to_name(
|
||||
struct xfs_name *namep,
|
||||
struct dentry *dentry)
|
||||
{
|
||||
namep->name = dentry->d_name.name;
|
||||
namep->len = dentry->d_name.len;
|
||||
namep->type = XFS_DIR3_FT_UNKNOWN;
|
||||
}
|
||||
|
||||
static int
|
||||
xfs_dentry_mode_to_name(
|
||||
struct xfs_name *namep,
|
||||
struct dentry *dentry,
|
||||
int mode)
|
||||
{
|
||||
namep->name = dentry->d_name.name;
|
||||
namep->len = dentry->d_name.len;
|
||||
namep->type = xfs_mode_to_ftype[(mode & S_IFMT) >> S_SHIFT];
|
||||
namep->type = xfs_mode_to_ftype(mode);
|
||||
|
||||
if (unlikely(namep->type == XFS_DIR3_FT_UNKNOWN))
|
||||
return -EFSCORRUPTED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
STATIC void
|
||||
@@ -119,7 +134,7 @@ xfs_cleanup_inode(
|
||||
* xfs_init_security we must back out.
|
||||
* ENOSPC can hit here, among other things.
|
||||
*/
|
||||
xfs_dentry_to_name(&teardown, dentry, 0);
|
||||
xfs_dentry_to_name(&teardown, dentry);
|
||||
|
||||
xfs_remove(XFS_I(dir), &teardown, XFS_I(inode));
|
||||
}
|
||||
@@ -154,8 +169,12 @@ xfs_generic_create(
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Verify mode is valid also for tmpfile case */
|
||||
error = xfs_dentry_mode_to_name(&name, dentry, mode);
|
||||
if (unlikely(error))
|
||||
goto out_free_acl;
|
||||
|
||||
if (!tmpfile) {
|
||||
xfs_dentry_to_name(&name, dentry, mode);
|
||||
error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip);
|
||||
} else {
|
||||
error = xfs_create_tmpfile(XFS_I(dir), dentry, mode, &ip);
|
||||
@@ -248,7 +267,7 @@ xfs_vn_lookup(
|
||||
if (dentry->d_name.len >= MAXNAMELEN)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
|
||||
xfs_dentry_to_name(&name, dentry, 0);
|
||||
xfs_dentry_to_name(&name, dentry);
|
||||
error = xfs_lookup(XFS_I(dir), &name, &cip, NULL);
|
||||
if (unlikely(error)) {
|
||||
if (unlikely(error != -ENOENT))
|
||||
@@ -275,7 +294,7 @@ xfs_vn_ci_lookup(
|
||||
if (dentry->d_name.len >= MAXNAMELEN)
|
||||
return ERR_PTR(-ENAMETOOLONG);
|
||||
|
||||
xfs_dentry_to_name(&xname, dentry, 0);
|
||||
xfs_dentry_to_name(&xname, dentry);
|
||||
error = xfs_lookup(XFS_I(dir), &xname, &ip, &ci_name);
|
||||
if (unlikely(error)) {
|
||||
if (unlikely(error != -ENOENT))
|
||||
@@ -310,7 +329,9 @@ xfs_vn_link(
|
||||
struct xfs_name name;
|
||||
int error;
|
||||
|
||||
xfs_dentry_to_name(&name, dentry, inode->i_mode);
|
||||
error = xfs_dentry_mode_to_name(&name, dentry, inode->i_mode);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
||||
error = xfs_link(XFS_I(dir), XFS_I(inode), &name);
|
||||
if (unlikely(error))
|
||||
@@ -329,7 +350,7 @@ xfs_vn_unlink(
|
||||
struct xfs_name name;
|
||||
int error;
|
||||
|
||||
xfs_dentry_to_name(&name, dentry, 0);
|
||||
xfs_dentry_to_name(&name, dentry);
|
||||
|
||||
error = xfs_remove(XFS_I(dir), &name, XFS_I(d_inode(dentry)));
|
||||
if (error)
|
||||
@@ -359,7 +380,9 @@ xfs_vn_symlink(
|
||||
|
||||
mode = S_IFLNK |
|
||||
(irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO);
|
||||
xfs_dentry_to_name(&name, dentry, mode);
|
||||
error = xfs_dentry_mode_to_name(&name, dentry, mode);
|
||||
if (unlikely(error))
|
||||
goto out;
|
||||
|
||||
error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip);
|
||||
if (unlikely(error))
|
||||
@@ -395,6 +418,7 @@ xfs_vn_rename(
|
||||
{
|
||||
struct inode *new_inode = d_inode(ndentry);
|
||||
int omode = 0;
|
||||
int error;
|
||||
struct xfs_name oname;
|
||||
struct xfs_name nname;
|
||||
|
||||
@@ -405,8 +429,14 @@ xfs_vn_rename(
|
||||
if (flags & RENAME_EXCHANGE)
|
||||
omode = d_inode(ndentry)->i_mode;
|
||||
|
||||
xfs_dentry_to_name(&oname, odentry, omode);
|
||||
xfs_dentry_to_name(&nname, ndentry, d_inode(odentry)->i_mode);
|
||||
error = xfs_dentry_mode_to_name(&oname, odentry, omode);
|
||||
if (omode && unlikely(error))
|
||||
return error;
|
||||
|
||||
error = xfs_dentry_mode_to_name(&nname, ndentry,
|
||||
d_inode(odentry)->i_mode);
|
||||
if (unlikely(error))
|
||||
return error;
|
||||
|
||||
return xfs_rename(XFS_I(odir), &oname, XFS_I(d_inode(odentry)),
|
||||
XFS_I(ndir), &nname,
|
||||
|
||||
@@ -330,11 +330,11 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
|
||||
}
|
||||
|
||||
#define ASSERT_ALWAYS(expr) \
|
||||
(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
|
||||
(likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSERT(expr) \
|
||||
(unlikely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
|
||||
(likely(expr) ? (void)0 : assfail(#expr, __FILE__, __LINE__))
|
||||
|
||||
#ifndef STATIC
|
||||
# define STATIC noinline
|
||||
@@ -345,7 +345,7 @@ static inline __uint64_t howmany_64(__uint64_t x, __uint32_t y)
|
||||
#ifdef XFS_WARN
|
||||
|
||||
#define ASSERT(expr) \
|
||||
(unlikely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__))
|
||||
(likely(expr) ? (void)0 : asswarn(#expr, __FILE__, __LINE__))
|
||||
|
||||
#ifndef STATIC
|
||||
# define STATIC static noinline
|
||||
|
||||
@@ -3324,12 +3324,8 @@ xfs_log_force(
|
||||
xfs_mount_t *mp,
|
||||
uint flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
trace_xfs_log_force(mp, 0, _RET_IP_);
|
||||
error = _xfs_log_force(mp, flags, NULL);
|
||||
if (error)
|
||||
xfs_warn(mp, "%s: error %d returned.", __func__, error);
|
||||
_xfs_log_force(mp, flags, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3473,12 +3469,8 @@ xfs_log_force_lsn(
|
||||
xfs_lsn_t lsn,
|
||||
uint flags)
|
||||
{
|
||||
int error;
|
||||
|
||||
trace_xfs_log_force(mp, lsn, _RET_IP_);
|
||||
error = _xfs_log_force_lsn(mp, lsn, flags, NULL);
|
||||
if (error)
|
||||
xfs_warn(mp, "%s: error %d returned.", __func__, error);
|
||||
_xfs_log_force_lsn(mp, lsn, flags, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -62,8 +62,13 @@ static inline unsigned int tcp_optlen(const struct sk_buff *skb)
|
||||
|
||||
/* TCP Fast Open Cookie as stored in memory */
|
||||
struct tcp_fastopen_cookie {
|
||||
union {
|
||||
u8 val[TCP_FASTOPEN_COOKIE_MAX];
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
struct in6_addr addr;
|
||||
#endif
|
||||
};
|
||||
s8 len;
|
||||
u8 val[TCP_FASTOPEN_COOKIE_MAX];
|
||||
bool exp; /* In RFC6994 experimental option format */
|
||||
};
|
||||
|
||||
|
||||
@@ -56,7 +56,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
|
||||
|
||||
static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
|
||||
struct virtio_net_hdr *hdr,
|
||||
bool little_endian)
|
||||
bool little_endian,
|
||||
bool has_data_valid)
|
||||
{
|
||||
memset(hdr, 0, sizeof(*hdr));
|
||||
|
||||
@@ -91,7 +92,8 @@ static inline int virtio_net_hdr_from_skb(const struct sk_buff *skb,
|
||||
skb_checksum_start_offset(skb));
|
||||
hdr->csum_offset = __cpu_to_virtio16(little_endian,
|
||||
skb->csum_offset);
|
||||
} else if (skb->ip_summed == CHECKSUM_UNNECESSARY) {
|
||||
} else if (has_data_valid &&
|
||||
skb->ip_summed == CHECKSUM_UNNECESSARY) {
|
||||
hdr->flags = VIRTIO_NET_HDR_F_DATA_VALID;
|
||||
} /* else everything is zero */
|
||||
|
||||
|
||||
@@ -43,13 +43,12 @@ struct lwtunnel_encap_ops {
|
||||
int (*get_encap_size)(struct lwtunnel_state *lwtstate);
|
||||
int (*cmp_encap)(struct lwtunnel_state *a, struct lwtunnel_state *b);
|
||||
int (*xmit)(struct sk_buff *skb);
|
||||
|
||||
struct module *owner;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_LWTUNNEL
|
||||
static inline void lwtstate_free(struct lwtunnel_state *lws)
|
||||
{
|
||||
kfree(lws);
|
||||
}
|
||||
void lwtstate_free(struct lwtunnel_state *lws);
|
||||
|
||||
static inline struct lwtunnel_state *
|
||||
lwtstate_get(struct lwtunnel_state *lws)
|
||||
@@ -106,6 +105,8 @@ int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *op,
|
||||
unsigned int num);
|
||||
int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
|
||||
unsigned int num);
|
||||
int lwtunnel_valid_encap_type(u16 encap_type);
|
||||
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len);
|
||||
int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
|
||||
struct nlattr *encap,
|
||||
unsigned int family, const void *cfg,
|
||||
@@ -169,6 +170,15 @@ static inline int lwtunnel_encap_del_ops(const struct lwtunnel_encap_ops *op,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int lwtunnel_valid_encap_type(u16 encap_type)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
static inline int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int len)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
|
||||
struct nlattr *encap,
|
||||
unsigned int family, const void *cfg,
|
||||
|
||||
@@ -264,7 +264,7 @@ void ax25_disconnect(ax25_cb *ax25, int reason)
|
||||
{
|
||||
ax25_clear_queues(ax25);
|
||||
|
||||
if (!sock_flag(ax25->sk, SOCK_DESTROY))
|
||||
if (!ax25->sk || !sock_flag(ax25->sk, SOCK_DESTROY))
|
||||
ax25_stop_heartbeat(ax25);
|
||||
ax25_stop_t1timer(ax25);
|
||||
ax25_stop_t2timer(ax25);
|
||||
|
||||
@@ -781,20 +781,6 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_dev_newlink(struct net *src_net, struct net_device *dev,
|
||||
struct nlattr *tb[], struct nlattr *data[])
|
||||
{
|
||||
struct net_bridge *br = netdev_priv(dev);
|
||||
|
||||
if (tb[IFLA_ADDRESS]) {
|
||||
spin_lock_bh(&br->lock);
|
||||
br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
|
||||
return register_netdevice(dev);
|
||||
}
|
||||
|
||||
static int br_port_slave_changelink(struct net_device *brdev,
|
||||
struct net_device *dev,
|
||||
struct nlattr *tb[],
|
||||
@@ -1093,6 +1079,25 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int br_dev_newlink(struct net *src_net, struct net_device *dev,
|
||||
struct nlattr *tb[], struct nlattr *data[])
|
||||
{
|
||||
struct net_bridge *br = netdev_priv(dev);
|
||||
int err;
|
||||
|
||||
if (tb[IFLA_ADDRESS]) {
|
||||
spin_lock_bh(&br->lock);
|
||||
br_stp_change_bridge_id(br, nla_data(tb[IFLA_ADDRESS]));
|
||||
spin_unlock_bh(&br->lock);
|
||||
}
|
||||
|
||||
err = br_changelink(dev, tb, data);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return register_netdevice(dev);
|
||||
}
|
||||
|
||||
static size_t br_get_size(const struct net_device *brdev)
|
||||
{
|
||||
return nla_total_size(sizeof(u32)) + /* IFLA_BR_FORWARD_DELAY */
|
||||
|
||||
@@ -2815,9 +2815,9 @@ static netdev_features_t harmonize_features(struct sk_buff *skb,
|
||||
if (skb->ip_summed != CHECKSUM_NONE &&
|
||||
!can_checksum_protocol(features, type)) {
|
||||
features &= ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
|
||||
} else if (illegal_highdma(skb->dev, skb)) {
|
||||
features &= ~NETIF_F_SG;
|
||||
}
|
||||
if (illegal_highdma(skb->dev, skb))
|
||||
features &= ~NETIF_F_SG;
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <net/lwtunnel.h>
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/ip6_fib.h>
|
||||
#include <net/nexthop.h>
|
||||
|
||||
#ifdef CONFIG_MODULES
|
||||
|
||||
@@ -65,6 +66,15 @@ EXPORT_SYMBOL(lwtunnel_state_alloc);
|
||||
static const struct lwtunnel_encap_ops __rcu *
|
||||
lwtun_encaps[LWTUNNEL_ENCAP_MAX + 1] __read_mostly;
|
||||
|
||||
void lwtstate_free(struct lwtunnel_state *lws)
|
||||
{
|
||||
const struct lwtunnel_encap_ops *ops = lwtun_encaps[lws->type];
|
||||
|
||||
kfree(lws);
|
||||
module_put(ops->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(lwtstate_free);
|
||||
|
||||
int lwtunnel_encap_add_ops(const struct lwtunnel_encap_ops *ops,
|
||||
unsigned int num)
|
||||
{
|
||||
@@ -110,26 +120,78 @@ int lwtunnel_build_state(struct net_device *dev, u16 encap_type,
|
||||
ret = -EOPNOTSUPP;
|
||||
rcu_read_lock();
|
||||
ops = rcu_dereference(lwtun_encaps[encap_type]);
|
||||
#ifdef CONFIG_MODULES
|
||||
if (!ops) {
|
||||
const char *encap_type_str = lwtunnel_encap_str(encap_type);
|
||||
|
||||
if (encap_type_str) {
|
||||
rcu_read_unlock();
|
||||
request_module("rtnl-lwt-%s", encap_type_str);
|
||||
rcu_read_lock();
|
||||
ops = rcu_dereference(lwtun_encaps[encap_type]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (likely(ops && ops->build_state))
|
||||
if (likely(ops && ops->build_state && try_module_get(ops->owner))) {
|
||||
ret = ops->build_state(dev, encap, family, cfg, lws);
|
||||
if (ret)
|
||||
module_put(ops->owner);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_build_state);
|
||||
|
||||
int lwtunnel_valid_encap_type(u16 encap_type)
|
||||
{
|
||||
const struct lwtunnel_encap_ops *ops;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (encap_type == LWTUNNEL_ENCAP_NONE ||
|
||||
encap_type > LWTUNNEL_ENCAP_MAX)
|
||||
return ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ops = rcu_dereference(lwtun_encaps[encap_type]);
|
||||
rcu_read_unlock();
|
||||
#ifdef CONFIG_MODULES
|
||||
if (!ops) {
|
||||
const char *encap_type_str = lwtunnel_encap_str(encap_type);
|
||||
|
||||
if (encap_type_str) {
|
||||
__rtnl_unlock();
|
||||
request_module("rtnl-lwt-%s", encap_type_str);
|
||||
rtnl_lock();
|
||||
|
||||
rcu_read_lock();
|
||||
ops = rcu_dereference(lwtun_encaps[encap_type]);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ops ? 0 : -EOPNOTSUPP;
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_valid_encap_type);
|
||||
|
||||
int lwtunnel_valid_encap_type_attr(struct nlattr *attr, int remaining)
|
||||
{
|
||||
struct rtnexthop *rtnh = (struct rtnexthop *)attr;
|
||||
struct nlattr *nla_entype;
|
||||
struct nlattr *attrs;
|
||||
struct nlattr *nla;
|
||||
u16 encap_type;
|
||||
int attrlen;
|
||||
|
||||
while (rtnh_ok(rtnh, remaining)) {
|
||||
attrlen = rtnh_attrlen(rtnh);
|
||||
if (attrlen > 0) {
|
||||
attrs = rtnh_attrs(rtnh);
|
||||
nla = nla_find(attrs, attrlen, RTA_ENCAP);
|
||||
nla_entype = nla_find(attrs, attrlen, RTA_ENCAP_TYPE);
|
||||
|
||||
if (nla_entype) {
|
||||
encap_type = nla_get_u16(nla_entype);
|
||||
|
||||
if (lwtunnel_valid_encap_type(encap_type) != 0)
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
}
|
||||
rtnh = rtnh_next(rtnh, &remaining);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(lwtunnel_valid_encap_type_attr);
|
||||
|
||||
int lwtunnel_fill_encap(struct sk_buff *skb, struct lwtunnel_state *lwtstate)
|
||||
{
|
||||
const struct lwtunnel_encap_ops *ops;
|
||||
|
||||
@@ -1201,6 +1201,8 @@ int dsa_slave_suspend(struct net_device *slave_dev)
|
||||
{
|
||||
struct dsa_slave_priv *p = netdev_priv(slave_dev);
|
||||
|
||||
netif_device_detach(slave_dev);
|
||||
|
||||
if (p->phy) {
|
||||
phy_stop(p->phy);
|
||||
p->old_pause = -1;
|
||||
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <net/rtnetlink.h>
|
||||
#include <net/xfrm.h>
|
||||
#include <net/l3mdev.h>
|
||||
#include <net/lwtunnel.h>
|
||||
#include <trace/events/fib.h>
|
||||
|
||||
#ifndef CONFIG_IP_MULTIPLE_TABLES
|
||||
@@ -676,6 +677,10 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
|
||||
cfg->fc_mx_len = nla_len(attr);
|
||||
break;
|
||||
case RTA_MULTIPATH:
|
||||
err = lwtunnel_valid_encap_type_attr(nla_data(attr),
|
||||
nla_len(attr));
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
cfg->fc_mp = nla_data(attr);
|
||||
cfg->fc_mp_len = nla_len(attr);
|
||||
break;
|
||||
@@ -690,6 +695,9 @@ static int rtm_to_fib_config(struct net *net, struct sk_buff *skb,
|
||||
break;
|
||||
case RTA_ENCAP_TYPE:
|
||||
cfg->fc_encap_type = nla_get_u16(attr);
|
||||
err = lwtunnel_valid_encap_type(cfg->fc_encap_type);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1278,8 +1278,9 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
|
||||
nla_put_u32(skb, RTA_FLOW, fi->fib_nh[0].nh_tclassid))
|
||||
goto nla_put_failure;
|
||||
#endif
|
||||
if (fi->fib_nh->nh_lwtstate)
|
||||
lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate);
|
||||
if (fi->fib_nh->nh_lwtstate &&
|
||||
lwtunnel_fill_encap(skb, fi->fib_nh->nh_lwtstate) < 0)
|
||||
goto nla_put_failure;
|
||||
}
|
||||
#ifdef CONFIG_IP_ROUTE_MULTIPATH
|
||||
if (fi->fib_nhs > 1) {
|
||||
@@ -1315,8 +1316,10 @@ int fib_dump_info(struct sk_buff *skb, u32 portid, u32 seq, int event,
|
||||
nla_put_u32(skb, RTA_FLOW, nh->nh_tclassid))
|
||||
goto nla_put_failure;
|
||||
#endif
|
||||
if (nh->nh_lwtstate)
|
||||
lwtunnel_fill_encap(skb, nh->nh_lwtstate);
|
||||
if (nh->nh_lwtstate &&
|
||||
lwtunnel_fill_encap(skb, nh->nh_lwtstate) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
/* length of rtnetlink header + attributes */
|
||||
rtnh->rtnh_len = nlmsg_get_pos(skb) - (void *) rtnh;
|
||||
} endfor_nexthops(fi);
|
||||
|
||||
@@ -313,6 +313,7 @@ static const struct lwtunnel_encap_ops ip_tun_lwt_ops = {
|
||||
.fill_encap = ip_tun_fill_encap_info,
|
||||
.get_encap_size = ip_tun_encap_nlsize,
|
||||
.cmp_encap = ip_tun_cmp_encap,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static const struct nla_policy ip6_tun_policy[LWTUNNEL_IP6_MAX + 1] = {
|
||||
@@ -403,6 +404,7 @@ static const struct lwtunnel_encap_ops ip6_tun_lwt_ops = {
|
||||
.fill_encap = ip6_tun_fill_encap_info,
|
||||
.get_encap_size = ip6_tun_encap_nlsize,
|
||||
.cmp_encap = ip_tun_cmp_encap,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
void __init ip_tunnel_core_init(void)
|
||||
|
||||
@@ -2440,7 +2440,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, u32 table_id,
|
||||
r->rtm_dst_len = 32;
|
||||
r->rtm_src_len = 0;
|
||||
r->rtm_tos = fl4->flowi4_tos;
|
||||
r->rtm_table = table_id;
|
||||
r->rtm_table = table_id < 256 ? table_id : RT_TABLE_COMPAT;
|
||||
if (nla_put_u32(skb, RTA_TABLE, table_id))
|
||||
goto nla_put_failure;
|
||||
r->rtm_type = rt->rt_type;
|
||||
|
||||
@@ -113,7 +113,7 @@ static bool tcp_fastopen_cookie_gen(struct request_sock *req,
|
||||
struct tcp_fastopen_cookie tmp;
|
||||
|
||||
if (__tcp_fastopen_cookie_gen(&ip6h->saddr, &tmp)) {
|
||||
struct in6_addr *buf = (struct in6_addr *) tmp.val;
|
||||
struct in6_addr *buf = &tmp.addr;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
@@ -205,6 +205,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
|
||||
* scaled. So correct it appropriately.
|
||||
*/
|
||||
tp->snd_wnd = ntohs(tcp_hdr(skb)->window);
|
||||
tp->max_window = tp->snd_wnd;
|
||||
|
||||
/* Activate the retrans timer so that SYNACK can be retransmitted.
|
||||
* The request socket is not added to the ehash
|
||||
|
||||
@@ -5515,8 +5515,7 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
|
||||
struct net_device *dev;
|
||||
struct inet6_dev *idev;
|
||||
|
||||
rcu_read_lock();
|
||||
for_each_netdev_rcu(net, dev) {
|
||||
for_each_netdev(net, dev) {
|
||||
idev = __in6_dev_get(dev);
|
||||
if (idev) {
|
||||
int changed = (!idev->cnf.disable_ipv6) ^ (!newf);
|
||||
@@ -5525,7 +5524,6 @@ static void addrconf_disable_change(struct net *net, __s32 newf)
|
||||
dev_disable_change(idev);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static int addrconf_disable_ipv6(struct ctl_table *table, int *p, int newf)
|
||||
|
||||
@@ -164,6 +164,7 @@ static const struct lwtunnel_encap_ops ila_encap_ops = {
|
||||
.fill_encap = ila_fill_encap_info,
|
||||
.get_encap_size = ila_encap_nlsize,
|
||||
.cmp_encap = ila_encap_cmp,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
int ila_lwt_init(void)
|
||||
|
||||
@@ -1108,7 +1108,7 @@ route_lookup:
|
||||
t->parms.name);
|
||||
goto tx_err_dst_release;
|
||||
}
|
||||
mtu = dst_mtu(dst) - psh_hlen;
|
||||
mtu = dst_mtu(dst) - psh_hlen - t->tun_hlen;
|
||||
if (encap_limit >= 0) {
|
||||
max_headroom += 8;
|
||||
mtu -= 8;
|
||||
@@ -1117,7 +1117,7 @@ route_lookup:
|
||||
mtu = IPV6_MIN_MTU;
|
||||
if (skb_dst(skb) && !t->parms.collect_md)
|
||||
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
|
||||
if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
if (skb->len - t->tun_hlen > mtu && !skb_is_gso(skb)) {
|
||||
*pmtu = mtu;
|
||||
err = -EMSGSIZE;
|
||||
goto tx_err_dst_release;
|
||||
|
||||
@@ -2885,6 +2885,11 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (tb[RTA_MULTIPATH]) {
|
||||
cfg->fc_mp = nla_data(tb[RTA_MULTIPATH]);
|
||||
cfg->fc_mp_len = nla_len(tb[RTA_MULTIPATH]);
|
||||
|
||||
err = lwtunnel_valid_encap_type_attr(cfg->fc_mp,
|
||||
cfg->fc_mp_len);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[RTA_PREF]) {
|
||||
@@ -2898,9 +2903,14 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
if (tb[RTA_ENCAP])
|
||||
cfg->fc_encap = tb[RTA_ENCAP];
|
||||
|
||||
if (tb[RTA_ENCAP_TYPE])
|
||||
if (tb[RTA_ENCAP_TYPE]) {
|
||||
cfg->fc_encap_type = nla_get_u16(tb[RTA_ENCAP_TYPE]);
|
||||
|
||||
err = lwtunnel_valid_encap_type(cfg->fc_encap_type);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[RTA_EXPIRES]) {
|
||||
unsigned long timeout = addrconf_timeout_fixup(nla_get_u32(tb[RTA_EXPIRES]), HZ);
|
||||
|
||||
@@ -3306,7 +3316,8 @@ static int rt6_fill_node(struct net *net,
|
||||
if (nla_put_u8(skb, RTA_PREF, IPV6_EXTRACT_PREF(rt->rt6i_flags)))
|
||||
goto nla_put_failure;
|
||||
|
||||
lwtunnel_fill_encap(skb, rt->dst.lwtstate);
|
||||
if (lwtunnel_fill_encap(skb, rt->dst.lwtstate) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
nlmsg_end(skb, nlh);
|
||||
return 0;
|
||||
|
||||
@@ -98,18 +98,19 @@ bool mpls_pkt_too_big(const struct sk_buff *skb, unsigned int mtu)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mpls_pkt_too_big);
|
||||
|
||||
static u32 mpls_multipath_hash(struct mpls_route *rt,
|
||||
struct sk_buff *skb, bool bos)
|
||||
static u32 mpls_multipath_hash(struct mpls_route *rt, struct sk_buff *skb)
|
||||
{
|
||||
struct mpls_entry_decoded dec;
|
||||
unsigned int mpls_hdr_len = 0;
|
||||
struct mpls_shim_hdr *hdr;
|
||||
bool eli_seen = false;
|
||||
int label_index;
|
||||
u32 hash = 0;
|
||||
|
||||
for (label_index = 0; label_index < MAX_MP_SELECT_LABELS && !bos;
|
||||
for (label_index = 0; label_index < MAX_MP_SELECT_LABELS;
|
||||
label_index++) {
|
||||
if (!pskb_may_pull(skb, sizeof(*hdr) * label_index))
|
||||
mpls_hdr_len += sizeof(*hdr);
|
||||
if (!pskb_may_pull(skb, mpls_hdr_len))
|
||||
break;
|
||||
|
||||
/* Read and decode the current label */
|
||||
@@ -134,37 +135,38 @@ static u32 mpls_multipath_hash(struct mpls_route *rt,
|
||||
eli_seen = true;
|
||||
}
|
||||
|
||||
bos = dec.bos;
|
||||
if (bos && pskb_may_pull(skb, sizeof(*hdr) * label_index +
|
||||
sizeof(struct iphdr))) {
|
||||
if (!dec.bos)
|
||||
continue;
|
||||
|
||||
/* found bottom label; does skb have room for a header? */
|
||||
if (pskb_may_pull(skb, mpls_hdr_len + sizeof(struct iphdr))) {
|
||||
const struct iphdr *v4hdr;
|
||||
|
||||
v4hdr = (const struct iphdr *)(mpls_hdr(skb) +
|
||||
label_index);
|
||||
v4hdr = (const struct iphdr *)(hdr + 1);
|
||||
if (v4hdr->version == 4) {
|
||||
hash = jhash_3words(ntohl(v4hdr->saddr),
|
||||
ntohl(v4hdr->daddr),
|
||||
v4hdr->protocol, hash);
|
||||
} else if (v4hdr->version == 6 &&
|
||||
pskb_may_pull(skb, sizeof(*hdr) * label_index +
|
||||
sizeof(struct ipv6hdr))) {
|
||||
pskb_may_pull(skb, mpls_hdr_len +
|
||||
sizeof(struct ipv6hdr))) {
|
||||
const struct ipv6hdr *v6hdr;
|
||||
|
||||
v6hdr = (const struct ipv6hdr *)(mpls_hdr(skb) +
|
||||
label_index);
|
||||
|
||||
v6hdr = (const struct ipv6hdr *)(hdr + 1);
|
||||
hash = __ipv6_addr_jhash(&v6hdr->saddr, hash);
|
||||
hash = __ipv6_addr_jhash(&v6hdr->daddr, hash);
|
||||
hash = jhash_1word(v6hdr->nexthdr, hash);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
|
||||
struct sk_buff *skb, bool bos)
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
int alive = ACCESS_ONCE(rt->rt_nhn_alive);
|
||||
u32 hash = 0;
|
||||
@@ -180,7 +182,7 @@ static struct mpls_nh *mpls_select_multipath(struct mpls_route *rt,
|
||||
if (alive <= 0)
|
||||
return NULL;
|
||||
|
||||
hash = mpls_multipath_hash(rt, skb, bos);
|
||||
hash = mpls_multipath_hash(rt, skb);
|
||||
nh_index = hash % alive;
|
||||
if (alive == rt->rt_nhn)
|
||||
goto out;
|
||||
@@ -278,17 +280,11 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
|
||||
hdr = mpls_hdr(skb);
|
||||
dec = mpls_entry_decode(hdr);
|
||||
|
||||
/* Pop the label */
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
rt = mpls_route_input_rcu(net, dec.label);
|
||||
if (!rt)
|
||||
goto drop;
|
||||
|
||||
nh = mpls_select_multipath(rt, skb, dec.bos);
|
||||
nh = mpls_select_multipath(rt, skb);
|
||||
if (!nh)
|
||||
goto drop;
|
||||
|
||||
@@ -297,6 +293,12 @@ static int mpls_forward(struct sk_buff *skb, struct net_device *dev,
|
||||
if (!mpls_output_possible(out_dev))
|
||||
goto drop;
|
||||
|
||||
/* Pop the label */
|
||||
skb_pull(skb, sizeof(*hdr));
|
||||
skb_reset_network_header(skb);
|
||||
|
||||
skb_orphan(skb);
|
||||
|
||||
if (skb_warn_if_lro(skb))
|
||||
goto drop;
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ static const struct lwtunnel_encap_ops mpls_iptun_ops = {
|
||||
.fill_encap = mpls_fill_encap_info,
|
||||
.get_encap_size = mpls_encap_nlsize,
|
||||
.cmp_encap = mpls_encap_cmp,
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init mpls_iptunnel_init(void)
|
||||
|
||||
@@ -514,7 +514,7 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
|
||||
int hooknum, nh_off, err = NF_ACCEPT;
|
||||
|
||||
nh_off = skb_network_offset(skb);
|
||||
skb_pull(skb, nh_off);
|
||||
skb_pull_rcsum(skb, nh_off);
|
||||
|
||||
/* See HOOK2MANIP(). */
|
||||
if (maniptype == NF_NAT_MANIP_SRC)
|
||||
@@ -579,6 +579,7 @@ static int ovs_ct_nat_execute(struct sk_buff *skb, struct nf_conn *ct,
|
||||
err = nf_nat_packet(ct, ctinfo, hooknum, skb);
|
||||
push:
|
||||
skb_push(skb, nh_off);
|
||||
skb_postpush_rcsum(skb, skb->data, nh_off);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -890,7 +891,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
|
||||
|
||||
/* The conntrack module expects to be working at L3. */
|
||||
nh_ofs = skb_network_offset(skb);
|
||||
skb_pull(skb, nh_ofs);
|
||||
skb_pull_rcsum(skb, nh_ofs);
|
||||
|
||||
if (key->ip.frag != OVS_FRAG_TYPE_NONE) {
|
||||
err = handle_fragments(net, key, info->zone.id, skb);
|
||||
@@ -904,6 +905,7 @@ int ovs_ct_execute(struct net *net, struct sk_buff *skb,
|
||||
err = ovs_ct_lookup(net, key, info, skb);
|
||||
|
||||
skb_push(skb, nh_ofs);
|
||||
skb_postpush_rcsum(skb, skb->data, nh_ofs);
|
||||
if (err)
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
|
||||
@@ -1972,7 +1972,7 @@ static int __packet_rcv_vnet(const struct sk_buff *skb,
|
||||
{
|
||||
*vnet_hdr = (const struct virtio_net_hdr) { 0 };
|
||||
|
||||
if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le()))
|
||||
if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le(), true))
|
||||
BUG();
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -903,8 +903,6 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
|
||||
goto err;
|
||||
}
|
||||
act->order = i;
|
||||
if (event == RTM_GETACTION)
|
||||
act->tcfa_refcnt++;
|
||||
list_add_tail(&act->list, &actions);
|
||||
}
|
||||
|
||||
@@ -917,7 +915,8 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
|
||||
return ret;
|
||||
}
|
||||
err:
|
||||
tcf_action_destroy(&actions, 0);
|
||||
if (event != RTM_GETACTION)
|
||||
tcf_action_destroy(&actions, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -995,6 +995,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
unsigned int hash;
|
||||
struct unix_address *addr;
|
||||
struct hlist_head *list;
|
||||
struct path path = { NULL, NULL };
|
||||
|
||||
err = -EINVAL;
|
||||
if (sunaddr->sun_family != AF_UNIX)
|
||||
@@ -1010,9 +1011,20 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
goto out;
|
||||
addr_len = err;
|
||||
|
||||
if (sun_path[0]) {
|
||||
umode_t mode = S_IFSOCK |
|
||||
(SOCK_INODE(sock)->i_mode & ~current_umask());
|
||||
err = unix_mknod(sun_path, mode, &path);
|
||||
if (err) {
|
||||
if (err == -EEXIST)
|
||||
err = -EADDRINUSE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
err = mutex_lock_interruptible(&u->bindlock);
|
||||
if (err)
|
||||
goto out;
|
||||
goto out_put;
|
||||
|
||||
err = -EINVAL;
|
||||
if (u->addr)
|
||||
@@ -1029,16 +1041,6 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
|
||||
atomic_set(&addr->refcnt, 1);
|
||||
|
||||
if (sun_path[0]) {
|
||||
struct path path;
|
||||
umode_t mode = S_IFSOCK |
|
||||
(SOCK_INODE(sock)->i_mode & ~current_umask());
|
||||
err = unix_mknod(sun_path, mode, &path);
|
||||
if (err) {
|
||||
if (err == -EEXIST)
|
||||
err = -EADDRINUSE;
|
||||
unix_release_addr(addr);
|
||||
goto out_up;
|
||||
}
|
||||
addr->hash = UNIX_HASH_SIZE;
|
||||
hash = d_real_inode(path.dentry)->i_ino & (UNIX_HASH_SIZE - 1);
|
||||
spin_lock(&unix_table_lock);
|
||||
@@ -1065,6 +1067,9 @@ out_unlock:
|
||||
spin_unlock(&unix_table_lock);
|
||||
out_up:
|
||||
mutex_unlock(&u->bindlock);
|
||||
out_put:
|
||||
if (err)
|
||||
path_put(&path);
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user