* Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Daniel Mack @ 2012-11-03 14:16 UTC (permalink / raw)
To: Christof Meerwald
Cc: Artem S. Tashkinov, pavel, linux-kernel, netdev, security,
linux-media, linux-usb
In-Reply-To: <20121103141049.GA24238@edge.cmeerw.net>
On 03.11.2012 15:10, Christof Meerwald wrote:
> On Sat, 20 Oct 2012 23:15:17 +0000 (GMT), Artem S. Tashkinov wrote:
>> It's almost definitely either a USB driver bug or video4linux driver bug:
>>
>> I'm CC'ing linux-media and linux-usb mailing lists, the problem is described here:
>> https://lkml.org/lkml/2012/10/20/35
>> https://lkml.org/lkml/2012/10/20/148
>
> Not sure if it's related, but I am seeing a kernel freeze with a
> usb-audio headset (connected via an external USB hub) on Linux 3.5.0
> (Ubuntu 12.10) - see
Does Ubuntu 12.10 really ship with 3.5.0? Not any more recent
> http://comments.gmane.org/gmane.comp.voip.twinkle/3052 and
> http://pastebin.com/aHGe1S1X for a self-contained C test.
Some questions:
- Are you seeing the same issue with 3.6.x?
- If you can reproduce this issue, could you paste the messages in
dmesg when this happens? Do they resemble to the list corruption that
was reported?
- Do you see the same problem with 3.4?
- Are you able to apply the patch Alan Stern posted in this thread earlier?
We should really sort this out, but I unfortunately lack a system or
setup that shows the bug.
Thanks,
Daniel
^ permalink raw reply
* Re: [PATCH 10/16] drivers/net/ethernet/ibm/emac/mal.c: use WARN
From: Julia Lawall @ 2012-11-03 14:14 UTC (permalink / raw)
To: walter harms; +Cc: Julia Lawall, netdev, kernel-janitors, linux-kernel
In-Reply-To: <50950055.8040307@bfs.de>
On Sat, 3 Nov 2012, walter harms wrote:
>
>
> Am 03.11.2012 11:58, schrieb Julia Lawall:
>> From: Julia Lawall <Julia.Lawall@lip6.fr>
>>
>> Use WARN rather than printk followed by WARN_ON(1), for conciseness.
>>
>> A simplified version of the semantic patch that makes this transformation
>> is as follows: (http://coccinelle.lip6.fr/)
>>
>> // <smpl>
>> @@
>> expression list es;
>> @@
>>
>> -printk(
>> +WARN(1,
>> es);
>> -WARN_ON(1);
>> // </smpl>
>>
>> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>>
>> ---
>> drivers/net/ethernet/ibm/emac/mal.c | 6 ++----
>> 1 file changed, 2 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
>> index 479e43e..84c6b6c 100644
>> --- a/drivers/net/ethernet/ibm/emac/mal.c
>> +++ b/drivers/net/ethernet/ibm/emac/mal.c
>> @@ -738,13 +738,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
>> /* Synchronize with scheduled polling */
>> napi_disable(&mal->napi);
>>
>> - if (!list_empty(&mal->list)) {
>> + if (!list_empty(&mal->list))
>> /* This is *very* bad */
>> - printk(KERN_EMERG
>> + WARN(1, KERN_EMERG
>> "mal%d: commac list is not empty on remove!\n",
>> mal->index);
>> - WARN_ON(1);
>> - }
>>
>> dev_set_drvdata(&ofdev->dev, NULL);
>>
>>
>
> Hi Julia,
> you are removing the {} behin the if. I prefer to be a bit conservative
> about {}. There is suggest to keep them because WARN may be expanded in
> future (with a second line) and that will cause subtle changes that do
> no break the code. (Yes i know it is possible to write macros that
> contain savely more than one line.)
WARN is already multi-line, surrounded by ({ }). It seems to be set up to
be used as an expression. Is it necessary to assume that it might someday
be changed from safe to unsafe?
julia
^ permalink raw reply
* Re: A reliable kernel panic (3.6.2) and system crash when visiting a particular website
From: Christof Meerwald @ 2012-11-03 14:10 UTC (permalink / raw)
To: Artem S. Tashkinov
Cc: pavel, linux-kernel, netdev, security, linux-media, linux-usb
In-Reply-To: <1781795634.31179.1350774917965.JavaMail.mail@webmail04>
On Sat, 20 Oct 2012 23:15:17 +0000 (GMT), Artem S. Tashkinov wrote:
> It's almost definitely either a USB driver bug or video4linux driver bug:
>
> I'm CC'ing linux-media and linux-usb mailing lists, the problem is described here:
> https://lkml.org/lkml/2012/10/20/35
> https://lkml.org/lkml/2012/10/20/148
Not sure if it's related, but I am seeing a kernel freeze with a
usb-audio headset (connected via an external USB hub) on Linux 3.5.0
(Ubuntu 12.10) - see
http://comments.gmane.org/gmane.comp.voip.twinkle/3052 and
http://pastebin.com/aHGe1S1X for a self-contained C test.
Christof
--
http://cmeerw.org sip:cmeerw at cmeerw.org
mailto:cmeerw at cmeerw.org xmpp:cmeerw at cmeerw.org
^ permalink raw reply
* Re: Query regarding pushing a patch series against net-next tree
From: Francois Romieu @ 2012-11-03 11:54 UTC (permalink / raw)
To: Vipul Pandya
Cc: netdev@vger.kernel.org, David Miller, Steve Wise, kumar Sanghvi,
Divy Le Ray, Dimitrios Michailidis
In-Reply-To: <5094CC60.20907@chelsio.com>
Vipul Pandya <vipul@chelsio.com> :
[...]
> Can you please suggest how should we proceed for submitting this patch
> series?
- Answer #1
You rework the fix against -net so that it can be fed into -stable asap
(your customers use -stable or derivative kernels, don't they ?). You
rework the feature part against your modified -net vs -net-next merge
and you carry it until -net gets merged.
- Answer #2
You wait until David merges -net into -net-next again.
If you don't read netdev regularly (!), you should read
http://marc.info/?l=linux-netdev&m=135170163622882&w=2
--
Ueimor
^ permalink raw reply
* Re: [PATCH v4] Network driver for the Armada 370 and Armada XP ARM Marvell SoCs
From: Francois Romieu @ 2012-11-03 11:53 UTC (permalink / raw)
To: Thomas Petazzoni
Cc: Eric Dumazet, David S. Miller, Lennert Buytenhek, netdev,
linux-arm-kernel, Jason Cooper, Andrew Lunn, Gregory Clement,
Lior Amsalem, Maen Suleiman
In-Reply-To: <20121102232137.3c9da5e4@skate>
Thomas Petazzoni <thomas.petazzoni@free-electrons.com> :
[...]
> Any comments on this patch set? What should I do to make it progress
> towards integration?
Nits review above. I'll search more substantial things this evening.
It looks quite good.
Thomas Petazzoni <thomas.petazzoni@free-electrons.com> :
[...]
> +mvneta_rxq_next_desc_get(struct mvneta_rx_queue *rxq)
> +{
> + int rx_desc = rxq->next_desc_to_proc;
> + rxq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(rxq, rx_desc);
Insert an empty line after local variables declaration.
[...]
> +static struct mvneta_tx_desc *
> +mvneta_txq_next_desc_get(struct mvneta_tx_queue *txq)
> +{
> + int tx_desc = txq->next_desc_to_proc;
> + txq->next_desc_to_proc = MVNETA_QUEUE_NEXT_DESC(txq, tx_desc);
Insert an empty line after local variables declaration.
[...]
> +static struct mvneta_tx_queue *mvneta_tx_done_policy(struct mvneta_port *pp,
> + u32 cause)
> +{
> + int queue;
> + queue = fls(cause) - 1;
Insert an empty line after local variables declaration.
You may set this variable when you declare it.
> + if (queue < 0 || queue >= txq_number)
> + return NULL;
> + return &pp->txqs[queue];
return (queue < 0 || queue >= txq_number) ? NULL : &pp->txqs[queue];
[...]
> +static int mvneta_rx_refill(struct mvneta_port *pp,
> + struct mvneta_rx_desc *rx_desc)
> +
> +{
> + dma_addr_t phys_addr;
> + struct sk_buff *skb;
> +
> + skb = netdev_alloc_skb(pp->dev, pp->pkt_size);
> + if (!skb)
> + return 1;
> +
> + phys_addr = dma_map_single(pp->dev->dev.parent, skb->head,
> + MVNETA_RX_BUF_SIZE(pp->pkt_size),
> + DMA_FROM_DEVICE);
> + if (unlikely(dma_mapping_error(pp->dev->dev.parent,
> + phys_addr))) {
if (unlikely(dma_mapping_error(pp->dev->dev.parent, phys_addr))) {
> + dev_kfree_skb(skb);
> + return 1;
> + }
> +
> + mvneta_rx_desc_fill(rx_desc, phys_addr, (u32)skb);
> +
> + return 0;
> +}
This is a bool returning function in disguise.
Were it supposed to be an error returning function, it should return <= 0
[...]
> +static struct mvneta_rx_queue *mvneta_rx_policy(struct mvneta_port *pp,
> + u32 cause)
> +{
> + int queue = fls(cause >> 8) - 1;
Insert an empty line after local variables declaration.
> + if (queue < 0 || queue >= rxq_number)
> + return NULL;
> + return &pp->rxqs[queue];
See mvneta_tx_done_policy above.
[...]
> +static void mvneta_rxq_drop_pkts(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq)
> +{
> + int rx_done, i;
> +
> + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
> + for (i = 0; i < rxq->size; i++) {
> + struct mvneta_rx_desc *rx_desc = rxq->descs + i;
> + struct sk_buff *skb = (struct sk_buff *)rx_desc->buf_cookie;
> + dev_kfree_skb_any(skb);
Insert an empty line after local variables declaration.
[...]
> +static int mvneta_rx(struct mvneta_port *pp, int rx_todo,
> + struct mvneta_rx_queue *rxq)
> +{
> + struct net_device *dev = pp->dev;
> + int rx_done, rx_filled;
> +
> + /* Get number of received packets */
> + rx_done = mvneta_rxq_busy_desc_num_get(pp, rxq);
> +
> + if (rx_todo > rx_done)
> + rx_todo = rx_done;
> +
> + rx_done = 0;
> + rx_filled = 0;
> +
> + /* Fairness NAPI loop */
> + while (rx_done < rx_todo) {
> + struct mvneta_rx_desc *rx_desc = mvneta_rxq_next_desc_get(rxq);
> + struct sk_buff *skb;
> + u32 rx_status;
> + int rx_bytes, err;
> +
> + prefetch(rx_desc);
> + rx_done++;
> + rx_filled++;
> + rx_status = rx_desc->status;
> + skb = (struct sk_buff *)rx_desc->buf_cookie;
> +
> + if (((rx_status & MVNETA_RXD_FIRST_LAST_DESC)
> + != MVNETA_RXD_FIRST_LAST_DESC)
> + || (rx_status & MVNETA_RXD_ERR_SUMMARY)) {
Operators appear at the end.
A dedicated (inline) function will help.
[...]
> +static int mvneta_tx_frag_process(struct mvneta_port *pp, struct sk_buff *skb,
[...]
> + if (i == (skb_shinfo(skb)->nr_frags - 1)) {
> + /* Last descriptor */
> + tx_desc->command = (MVNETA_TXD_L_DESC |
> + MVNETA_TXD_Z_PAD);
tx_desc->command = MVNETA_TXD_L_DESC | MVNETA_TXD_Z_PAD;
[...]
> +error:
> + /* Release all descriptors that were used to map fragments of
> + * this packet, as well as the corresponding DMA mappings */
> + for (j = i - 1; j >= 0; j--) {
j isn't needed. Recycle i.
[...]
> +static int mvneta_tx(struct sk_buff *skb, struct net_device *dev)
> +{
> + struct mvneta_port *pp = netdev_priv(dev);
> + struct mvneta_tx_queue *txq = &pp->txqs[txq_def];
> + struct netdev_queue *nq;
> + struct mvneta_tx_desc *tx_desc;
> + int frags = 0;
> + u32 tx_cmd;
Long lines first when possible.
[...]
> + /* Continue with other skb fragments */
> + if (mvneta_tx_frag_process(pp, skb, txq)) {
got out_unmap;
> + dma_unmap_single(dev->dev.parent,
> + tx_desc->buf_phys_addr,
> + tx_desc->data_size,
> + DMA_TO_DEVICE);
> + mvneta_txq_desc_put(txq);
> + frags = 0;
> + goto out;
> + }
[...]
> +static void mvneta_txq_done_force(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq)
> +
> +{
> + int tx_done = txq->count;
> + mvneta_txq_bufs_free(pp, txq, tx_done);
Insert an empty line after local variables declaration.
[...]
> +static int mvneta_rxq_fill(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
> + int num)
> +{
> + int i;
> + struct net_device *dev = pp->dev;
Long lines first when possible.
[...]
> +static int mvneta_rxq_init(struct mvneta_port *pp,
> + struct mvneta_rx_queue *rxq)
> +
> +{
> + rxq->size = pp->rx_ring_size;
> +
> + /* Allocate memory for RX descriptors */
> + rxq->descs = dma_alloc_coherent(pp->dev->dev.parent,
> + rxq->size * MVNETA_DESC_ALIGNED_SIZE,
> + &rxq->descs_phys,
> + GFP_KERNEL);
&rxq->descs_phys, GFP_KERNEL);
> + if (rxq->descs == NULL) {
> + netdev_err(pp->dev,
> + "rxQ=%d: Can't allocate %d bytes for %d RX descr\n",
> + rxq->id, rxq->size * MVNETA_DESC_ALIGNED_SIZE,
> + rxq->size);
> + return -ENOMEM;
> + }
> +
> + BUG_ON(rxq->descs !=
> + PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE));
There is no reason to crash.
(...]
> +static int mvneta_txq_init(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq)
> +{
> + txq->size = pp->tx_ring_size;
> +
> + /* Allocate memory for TX descriptors */
> + txq->descs = dma_alloc_coherent(pp->dev->dev.parent,
> + txq->size * MVNETA_DESC_ALIGNED_SIZE,
> + &txq->descs_phys,
> + DMA_BIDIRECTIONAL);
&txq->descs_phys, DMA_BIDIRECTIONAL);
> + if (txq->descs == NULL) {
> + netdev_err(pp->dev,
> + "txQ=%d: Can't allocate %d bytes for %d TX descr\n",
> + txq->id, txq->size * MVNETA_DESC_ALIGNED_SIZE,
> + txq->size);
> + return -ENOMEM;
> + }
> +
> + /* Make sure descriptor address is cache line size aligned */
> + BUG_ON(txq->descs !=
> + PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE));
There is no reason to crash.
[...]
> + txq->tx_skb = kmalloc(txq->size * sizeof(*txq->tx_skb),
> + GFP_KERNEL);
txq->tx_skb = kmalloc(txq->size * sizeof(*txq->tx_skb), GFP_KERNEL);
[...]
> +static void mvneta_txq_deinit(struct mvneta_port *pp,
> + struct mvneta_tx_queue *txq)
> +{
> + kfree(txq->tx_skb);
> +
> + if (txq->descs)
> + dma_free_coherent(pp->dev->dev.parent,
> + txq->size * MVNETA_DESC_ALIGNED_SIZE,
> + txq->descs,
> + txq->descs_phys);
txq->descs, txq->descs_phys);
[...]
> +static void mvneta_cleanup_txqs(struct mvneta_port *pp)
> +{
> + int queue;
> + for (queue = 0; queue < txq_number; queue++)
> + mvneta_txq_deinit(pp, &pp->txqs[queue]);
Insert an empty line after local variables declaration.
[...]
> +static void mvneta_cleanup_rxqs(struct mvneta_port *pp)
> +{
> + int queue;
> + for (queue = 0; queue < rxq_number; queue++)
> + mvneta_rxq_deinit(pp, &pp->rxqs[queue]);
Insert an empty line after local variables declaration.
[...]
> +static int mvneta_setup_rxqs(struct mvneta_port *pp)
> +{
> + int queue;
> +
> + for (queue = 0; queue < rxq_number; queue++) {
> + int err = mvneta_rxq_init(pp, &pp->rxqs[queue]);
> + if (err) {
> + netdev_err(pp->dev,
> + "%s: can't create RxQ rxq=%d\n",
netdev_err(pp->dev, "%s: can't create RxQ rxq=%d\n",
> + __func__, queue);
> + mvneta_cleanup_rxqs(pp);
> + return -ENODEV;
mvneta_rxq_init should return a proper error code and it should be
propagated (option: break instead of return and mvneta_setup_rxqs scoped
err variable)
[...]
> +static int mvneta_setup_txqs(struct mvneta_port *pp)
> +{
> + int queue;
> +
> + for (queue = 0; queue < txq_number; queue++) {
> + int err = mvneta_txq_init(pp, &pp->txqs[queue]);
> + if (err) {
> + netdev_err(pp->dev,
> + "%s: can't create TxQ txq=%d\n",
> + __func__, queue);
> + mvneta_cleanup_txqs(pp);
> + return err;
> + }
> + }
See mvneta_setup_rxqs above.
[...]
> +static void mvneta_start_dev(struct mvneta_port *pp)
> +{
> + mvneta_max_rx_size_set(pp, pp->pkt_size);
> + mvneta_txq_max_tx_size_set(pp, pp->pkt_size);
> +
> + /* start the Rx/Tx activity */
> + mvneta_port_enable(pp);
> +
> + /* Enable polling on the port */
> + napi_enable(&pp->napi);
> +
> + /* Unmask interrupts */
> + mvneta_interrupts_unmask(pp);
> + smp_call_function_many(cpu_online_mask,
> + mvneta_interrupts_unmask,
> + pp, 1);
smp_call_function_many(cpu_online_mask, mvneta_interrupts_unmask,
(as done in mvneta_stop_dev)
> +
> + phy_start(pp->phy_dev);
> + netif_tx_start_all_queues(pp->dev);
> +}
> +
> +static void mvneta_stop_dev(struct mvneta_port *pp)
> +{
> + phy_stop(pp->phy_dev);
> +
> + napi_disable(&pp->napi);
> +
> + /* Stop upper layer */
> + netif_carrier_off(pp->dev);
Useless comment.
> +
> + mvneta_port_down(pp);
> + netif_tx_stop_all_queues(pp->dev);
> +
> + /* Stop the port activity */
> + mvneta_port_disable(pp);
> +
> + /* Clear all ethernet port interrupts */
> + mvreg_write(pp, MVNETA_INTR_MISC_CAUSE, 0);
> + mvreg_write(pp, MVNETA_INTR_OLD_CAUSE, 0);
> +
> + /* Mask all interrupts */
> + mvneta_interrupts_mask(pp);
Useless comment.
> + smp_call_function_many(cpu_online_mask, mvneta_interrupts_mask,
> + pp, 1);
> +
> + /* Reset TX port here. */
> + mvneta_tx_reset(pp);
> + mvneta_rx_reset(pp);
Useless comment.
> +}
> +
> +/* tx timeout callback - display a message and stop/start the network device */
> +static void mvneta_tx_timeout(struct net_device *dev)
> +{
> + struct mvneta_port *pp = netdev_priv(dev);
> + netdev_info(dev, "tx timeout\n");
Insert an empty line after local variables declaration.
[...]
> +static int mvneta_check_mtu_valid(struct net_device *dev, int mtu)
> +{
> + if (mtu < 68) {
> + netdev_err(dev, "cannot change mtu to less than 68\n");
> + return -EINVAL;
> + }
> +
> + if (mtu > 9676 /* 9700 - 20 and rounding to 8 */) {
Please use a different comment style, say on a proper line, or a define with
a comment above it.
[...]
> +static int mvneta_ethtool_set_coalesce(struct net_device *dev,
> + struct ethtool_coalesce *c)
> +{
> + int queue;
> + struct mvneta_port *pp = netdev_priv(dev);
Long lines first when possible.
[...]
> +static const struct net_device_ops mvneta_netdev_ops = {
> + .ndo_open = mvneta_open,
> + .ndo_stop = mvneta_stop,
> + .ndo_start_xmit = mvneta_tx,
> + .ndo_set_rx_mode = mvneta_set_rx_mode,
> + .ndo_set_mac_address = mvneta_set_mac_addr,
> + .ndo_change_mtu = mvneta_change_mtu,
> + .ndo_tx_timeout = mvneta_tx_timeout,
> + .ndo_get_stats64 = mvneta_get_stats64,
Please use tabs before '=' and line things up.
> +};
> +
> +const struct ethtool_ops mvneta_eth_tool_ops = {
> + .get_link = ethtool_op_get_link,
> + .get_settings = mvneta_ethtool_get_settings,
> + .set_settings = mvneta_ethtool_set_settings,
> + .set_coalesce = mvneta_ethtool_set_coalesce,
> + .get_coalesce = mvneta_ethtool_get_coalesce,
> + .get_drvinfo = mvneta_ethtool_get_drvinfo,
> + .get_ringparam = mvneta_ethtool_get_ringparam,
> + .set_ringparam = mvneta_ethtool_set_ringparam,
Please use tabs before '=' and line things up.
[...]
> +static int __devinit mvneta_init(struct mvneta_port *pp, int phy_addr)
> +{
> + int queue, i, ret = 0;
> +
> + /* Disable port */
> + mvneta_port_disable(pp);
> +
> + /* Set port default values */
> + mvneta_defaults_set(pp);
> +
> + pp->txqs = kzalloc(txq_number * sizeof(struct mvneta_tx_queue),
> + GFP_KERNEL);
> + if (!pp->txqs) {
> + netdev_err(pp->dev, "out of memory in allocating tx queue\n");
I doubt a message is really needed when a GFP_KERNEL oom triggers.
(...]
> +static void __devinit mvneta_conf_mbus_windows(struct mvneta_port *pp,
> + const struct mbus_dram_target_info *dram)
> +{
[...]
> + for (i = 0; i < dram->num_cs; i++) {
> + const struct mbus_dram_window *cs = dram->cs + i;
> + mvreg_write(pp, MVNETA_WIN_BASE(i),
> + (cs->base & 0xffff0000) |
> + (cs->mbus_attr << 8) |
> + dram->mbus_dram_target_id);
mvreg_write(pp, MVNETA_WIN_BASE(i), (cs->base & 0xffff0000) |
(cs->mbus_attr << 8) | dram->mbus_dram_target_id);
[...]
> +static int __devinit mvneta_probe(struct platform_device *pdev)
> +{
> + int err = -EINVAL;
> + struct mvneta_port *pp;
> + struct net_device *dev;
> + u32 phy_addr, clk_rate_hz;
> + int phy_mode;
> + const char *mac_addr;
> + const struct mbus_dram_target_info *dram_target_info;
> + struct device_node *dn = pdev->dev.of_node;
Long lines first when possible.
--
Ueimor
^ permalink raw reply
* Re: iptables/tc: page allocation failures question
From: Eric Dumazet @ 2012-11-03 11:34 UTC (permalink / raw)
To: Miroslav Kratochvil; +Cc: netdev
In-Reply-To: <CAO0uZ+_AZG2cT4NvvLKrbkKjMm09vi_Dqd6d49h0hE5Lh9+pmA@mail.gmail.com>
On Sat, 2012-11-03 at 11:27 +0100, Miroslav Kratochvil wrote:
> Hello everyone,
>
> I've got several linux boxes that do mostly routing and traffic
> shaping stuff. The load isn't any dramatic - it's around 100Mbit of
> traffic shaping over a HFSC qdisc with ~10k classes/filters.
>
> Recently I started seeing messages like this in dmesg:
>
> iptables: page allocation failure: order:9, mode:0xc0d0
>
> tc: page allocation failure (....)
>
> (full messages are attached below)
>
> I understood that it means the kernel couldn't allocate memory for
> execution of given command - it is usually triggered by stuff like 'tc
> class add' or 'iptables -A something'.
>
> The boxes, on the other hand, still have pretty much free memory
> (alloc+buffers+cache fill around 400MB of 2 gigs available, swap is
> empty). I guess the problem is caused by the fact that the allocation
> is constrained by something (like GFP_ATOMIC, or that they can only
> allocate lower memory). Is this true? If so, is there some possibility
> to avoid such constraint?
>
> What also worries me is that when the box at some point starts to do
> memory allocation failures, I've been unable to make it stop, even if
> I delete all qdiscs/iptable entries, clear every cache I know about
> and restart most of userspace, which should hopefully free a good
> amount of memory, nothing can be added back.
>
> I'm attaching the dmesg of the failure below. Could anyone provide a
> comment on this, or possibly point me to what can cause this behavior?
> Is there any better debug output that could clarify this?
>
> Thanks in advance,
> Mirek Kratochvil
You apparently load xt_recent module with a big ip_list_tot value
(default is 100), and kzalloc() wants an order-9 page (contiguous 2MB of
ram), and it fails.
I guess following patch should solve your problem
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index 4635c9b..ceebd8b 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -29,6 +29,7 @@
#include <linux/skbuff.h>
#include <linux/inet.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
#include <net/net_namespace.h>
#include <net/netns/generic.h>
@@ -310,6 +311,14 @@ out:
return ret;
}
+static void recent_table_free(void *addr)
+{
+ if (is_vmalloc_addr(addr))
+ vfree(addr);
+ else
+ kfree(addr);
+}
+
static int recent_mt_check(const struct xt_mtchk_param *par,
const struct xt_recent_mtinfo_v1 *info)
{
@@ -322,6 +331,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
#endif
unsigned int i;
int ret = -EINVAL;
+ size_t sz;
if (unlikely(!hash_rnd_inited)) {
get_random_bytes(&hash_rnd, sizeof(hash_rnd));
@@ -360,8 +370,11 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
goto out;
}
- t = kzalloc(sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size,
- GFP_KERNEL);
+ sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size;
+ if (sz <= PAGE_SIZE)
+ t = kzalloc(sz, GFP_KERNEL);
+ else
+ t = vzalloc(sz);
if (t == NULL) {
ret = -ENOMEM;
goto out;
@@ -377,14 +390,14 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
uid = make_kuid(&init_user_ns, ip_list_uid);
gid = make_kgid(&init_user_ns, ip_list_gid);
if (!uid_valid(uid) || !gid_valid(gid)) {
- kfree(t);
+ recent_table_free(t);
ret = -EINVAL;
goto out;
}
pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
&recent_mt_fops, t);
if (pde == NULL) {
- kfree(t);
+ recent_table_free(t);
ret = -ENOMEM;
goto out;
}
@@ -434,7 +447,7 @@ static void recent_mt_destroy(const struct xt_mtdtor_param *par)
remove_proc_entry(t->name, recent_net->xt_recent);
#endif
recent_table_flush(t);
- kfree(t);
+ recent_table_free(t);
}
mutex_unlock(&recent_mutex);
}
^ permalink raw reply related
* Re: [PATCH 10/16] drivers/net/ethernet/ibm/emac/mal.c: use WARN
From: walter harms @ 2012-11-03 11:30 UTC (permalink / raw)
To: Julia Lawall; +Cc: netdev, kernel-janitors, linux-kernel
In-Reply-To: <1351940317-14812-11-git-send-email-Julia.Lawall@lip6.fr>
Am 03.11.2012 11:58, schrieb Julia Lawall:
> From: Julia Lawall <Julia.Lawall@lip6.fr>
>
> Use WARN rather than printk followed by WARN_ON(1), for conciseness.
>
> A simplified version of the semantic patch that makes this transformation
> is as follows: (http://coccinelle.lip6.fr/)
>
> // <smpl>
> @@
> expression list es;
> @@
>
> -printk(
> +WARN(1,
> es);
> -WARN_ON(1);
> // </smpl>
>
> Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
>
> ---
> drivers/net/ethernet/ibm/emac/mal.c | 6 ++----
> 1 file changed, 2 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
> index 479e43e..84c6b6c 100644
> --- a/drivers/net/ethernet/ibm/emac/mal.c
> +++ b/drivers/net/ethernet/ibm/emac/mal.c
> @@ -738,13 +738,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
> /* Synchronize with scheduled polling */
> napi_disable(&mal->napi);
>
> - if (!list_empty(&mal->list)) {
> + if (!list_empty(&mal->list))
> /* This is *very* bad */
> - printk(KERN_EMERG
> + WARN(1, KERN_EMERG
> "mal%d: commac list is not empty on remove!\n",
> mal->index);
> - WARN_ON(1);
> - }
>
> dev_set_drvdata(&ofdev->dev, NULL);
>
>
Hi Julia,
you are removing the {} behin the if. I prefer to be a bit conservative
about {}. There is suggest to keep them because WARN may be expanded in
future (with a second line) and that will cause subtle changes that do
no break the code. (Yes i know it is possible to write macros that
contain savely more than one line.)
re,
wh
^ permalink raw reply
* [PATCH 14/16] drivers/ssb/main.c: use WARN
From: Julia Lawall @ 2012-11-03 10:58 UTC (permalink / raw)
To: Michael Buesch; +Cc: kernel-janitors, netdev, linux-kernel
In-Reply-To: <1351940317-14812-1-git-send-email-Julia.Lawall@lip6.fr>
From: Julia Lawall <Julia.Lawall@lip6.fr>
Use WARN rather than printk followed by WARN_ON(1), for conciseness.
A simplified version of the semantic patch that makes this transformation
is as follows: (http://coccinelle.lip6.fr/)
// <smpl>
@@
expression list es;
@@
-printk(
+WARN(1,
es);
-WARN_ON(1);
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/ssb/main.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c
index df0f145..519688d 100644
--- a/drivers/ssb/main.c
+++ b/drivers/ssb/main.c
@@ -1118,8 +1118,7 @@ static u32 ssb_tmslow_reject_bitmask(struct ssb_device *dev)
case SSB_IDLOW_SSBREV_27: /* same here */
return SSB_TMSLOW_REJECT; /* this is a guess */
default:
- printk(KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
- WARN_ON(1);
+ WARN(1, KERN_INFO "ssb: Backplane Revision 0x%.8X\n", rev);
}
return (SSB_TMSLOW_REJECT | SSB_TMSLOW_REJECT_23);
}
^ permalink raw reply related
* [PATCH 10/16] drivers/net/ethernet/ibm/emac/mal.c: use WARN
From: Julia Lawall @ 2012-11-03 10:58 UTC (permalink / raw)
To: netdev; +Cc: kernel-janitors, linux-kernel
In-Reply-To: <1351940317-14812-1-git-send-email-Julia.Lawall@lip6.fr>
From: Julia Lawall <Julia.Lawall@lip6.fr>
Use WARN rather than printk followed by WARN_ON(1), for conciseness.
A simplified version of the semantic patch that makes this transformation
is as follows: (http://coccinelle.lip6.fr/)
// <smpl>
@@
expression list es;
@@
-printk(
+WARN(1,
es);
-WARN_ON(1);
// </smpl>
Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>
---
drivers/net/ethernet/ibm/emac/mal.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/ethernet/ibm/emac/mal.c b/drivers/net/ethernet/ibm/emac/mal.c
index 479e43e..84c6b6c 100644
--- a/drivers/net/ethernet/ibm/emac/mal.c
+++ b/drivers/net/ethernet/ibm/emac/mal.c
@@ -738,13 +738,11 @@ static int __devexit mal_remove(struct platform_device *ofdev)
/* Synchronize with scheduled polling */
napi_disable(&mal->napi);
- if (!list_empty(&mal->list)) {
+ if (!list_empty(&mal->list))
/* This is *very* bad */
- printk(KERN_EMERG
+ WARN(1, KERN_EMERG
"mal%d: commac list is not empty on remove!\n",
mal->index);
- WARN_ON(1);
- }
dev_set_drvdata(&ofdev->dev, NULL);
^ permalink raw reply related
* iptables/tc: page allocation failures question
From: Miroslav Kratochvil @ 2012-11-03 10:27 UTC (permalink / raw)
To: netdev
Hello everyone,
I've got several linux boxes that do mostly routing and traffic
shaping stuff. The load isn't any dramatic - it's around 100Mbit of
traffic shaping over a HFSC qdisc with ~10k classes/filters.
Recently I started seeing messages like this in dmesg:
iptables: page allocation failure: order:9, mode:0xc0d0
tc: page allocation failure (....)
(full messages are attached below)
I understood that it means the kernel couldn't allocate memory for
execution of given command - it is usually triggered by stuff like 'tc
class add' or 'iptables -A something'.
The boxes, on the other hand, still have pretty much free memory
(alloc+buffers+cache fill around 400MB of 2 gigs available, swap is
empty). I guess the problem is caused by the fact that the allocation
is constrained by something (like GFP_ATOMIC, or that they can only
allocate lower memory). Is this true? If so, is there some possibility
to avoid such constraint?
What also worries me is that when the box at some point starts to do
memory allocation failures, I've been unable to make it stop, even if
I delete all qdiscs/iptable entries, clear every cache I know about
and restart most of userspace, which should hopefully free a good
amount of memory, nothing can be added back.
I'm attaching the dmesg of the failure below. Could anyone provide a
comment on this, or possibly point me to what can cause this behavior?
Is there any better debug output that could clarify this?
Thanks in advance,
Mirek Kratochvil
now how it happens:
# iptables -A FORWARD -s 192.168.0.0/24 -m recent -p tcp --name somelist --set
/// it waits around 10 seconds here
iptables: Memory allocation problem.
# dmesg
[3391568.085980] iptables: page allocation failure: order:9, mode:0xc0d0
[3391568.085983] Pid: 21115, comm: iptables Not tainted 3.1.1 #3
[3391568.085985] Call Trace:
[3391568.085991] [<ffffffff810a4172>] ? warn_alloc_failed+0xf2/0x140
[3391568.085993] [<ffffffff810b3fc0>] ? next_zone+0x30/0x40
[3391568.085995] [<ffffffff810a6fe0>] ? page_alloc_cpu_notify+0x40/0x40
[3391568.085997] [<ffffffff810a69f9>] ? __alloc_pages_nodemask+0x609/0x790
[3391568.086000] [<ffffffff810d3740>] ? alloc_pages_current+0xa0/0x110
[3391568.086002] [<ffffffff810a3c79>] ? __get_free_pages+0x9/0x40
[3391568.086006] [<ffffffff814d40c5>] ? recent_mt_check+0x165/0x2a0
[3391568.086007] [<ffffffff814d1ac2>] ? xt_check_match+0xb2/0x1f0
[3391568.086010] [<ffffffff8109f758>] ? find_get_page+0x18/0xa0
[3391568.086015] [<ffffffff815bfc69>] ? _raw_spin_lock_bh+0x9/0x20
[3391568.086024] [<ffffffff815be9b9>] ? mutex_lock_interruptible+0x9/0x40
[3391568.086026] [<ffffffff814d12f0>] ? xt_find_match+0xb0/0x110
[3391568.086029] [<ffffffff815226fe>] ? translate_table+0x29e/0x640
[3391568.086031] [<ffffffff815237ba>] ? do_ipt_set_ctl+0x13a/0x1b0
[3391568.086036] [<ffffffff814cdb0a>] ? nf_sockopt+0x5a/0xb0
[3391568.086039] [<ffffffff814cdb9a>] ? nf_setsockopt+0x1a/0x20
[3391568.086044] [<ffffffff814e2933>] ? ip_setsockopt+0x93/0xc0
[3391568.086048] [<ffffffff81485e02>] ? sockfd_lookup_light+0x22/0x90
[3391568.086051] [<ffffffff81488d7d>] ? sys_setsockopt+0x6d/0xd0
[3391568.086054] [<ffffffff815c043b>] ? system_call_fastpath+0x16/0x1b
[3391568.086057] Mem-Info:
[3391568.086058] Node 0 DMA per-cpu:
[3391568.086061] CPU 0: hi: 0, btch: 1 usd: 0
[3391568.086063] CPU 1: hi: 0, btch: 1 usd: 0
[3391568.086064] CPU 2: hi: 0, btch: 1 usd: 0
[3391568.086065] CPU 3: hi: 0, btch: 1 usd: 0
[3391568.086066] Node 0 DMA32 per-cpu:
[3391568.086067] CPU 0: hi: 186, btch: 31 usd: 0
[3391568.086068] CPU 1: hi: 186, btch: 31 usd: 0
[3391568.086069] CPU 2: hi: 186, btch: 31 usd: 25
[3391568.086071] CPU 3: hi: 186, btch: 31 usd: 0
[3391568.086075] active_anon:10259 inactive_anon:3453 isolated_anon:0
[3391568.086076] active_file:261 inactive_file:269 isolated_file:4
[3391568.086077] unevictable:0 dirty:0 writeback:3640 unstable:0
[3391568.086078] free:447441 slab_reclaimable:892 slab_unreclaimable:41475
[3391568.086079] mapped:4747 shmem:4488 pagetables:694 bounce:0
[3391568.086081] Node 0 DMA free:11104kB min:40kB low:48kB high:60kB
active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB
unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15648kB
mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB
slab_reclaimable:128kB slab_unreclaimable:4664kB kernel_stack:8kB
pagetables:0kB unstable:0kB bounce:0kB writeback_tmp:0kB
pages_scanned:0 all_unreclaimable? yes
[3391568.086091] lowmem_reserve[]: 0 1978 1978 1978
[3391568.086096] Node 0 DMA32 free:1778660kB min:5668kB low:7084kB
high:8500kB active_anon:41036kB inactive_anon:13812kB
active_file:1044kB inactive_file:1076kB unevictable:0kB
isolated(anon):0kB isolated(file):144kB present:2026068kB mlocked:0kB
dirty:0kB writeback:14560kB mapped:18988kB shmem:17952kB
slab_reclaimable:3440kB slab_unreclaimable:161236kB kernel_stack:704kB
pagetables:2776kB unstable:0kB bounce:0kB writeback_tmp:0kB
pages_scanned:288 all_unreclaimable? no
[3391568.086107] lowmem_reserve[]: 0 0 0 0
[3391568.086112] Node 0 DMA: 18*4kB 7*8kB 10*16kB 12*32kB 9*64kB
9*128kB 8*256kB 3*512kB 3*1024kB 1*2048kB 0*4096kB = 11104kB
[3391568.086119] Node 0 DMA32: 13255*4kB 14135*8kB 14291*16kB
11013*32kB 6973*64kB 2976*128kB 614*256kB 88*512kB 2*1024kB 0*2048kB
0*4096kB = 1778660kB
[3391568.086139] 8553 total pagecache pages
[3391568.086140] 3528 pages in swap cache
[3391568.086142] Swap cache stats: add 666897, delete 663369, find
317604632/317669671
[3391568.086144] Free swap = 973916kB
[3391568.086146] Total swap = 1048572kB
[3391568.091300] 522224 pages RAM
[3391568.091302] 14130 pages reserved
[3391568.091302] 14125 pages shared
[3391568.091303] 55020 pages non-shared
^ permalink raw reply
* [3.0.y, 3.2.y, 3.4.y] Re: [PATCH 2/2] [sky2] Fix for interrupt handler
From: Jonathan Nieder @ 2012-11-03 10:04 UTC (permalink / raw)
To: David S. Miller
Cc: Julian Gilbey, Mirko Lindner, Stephen Hemminger, netdev, stable
In-Reply-To: <20121025223646.GA1131@elie.Belkin>
On October 25, Jonathan Nieder wrote:
> Mirko Lindner wrote:
>> Re-enable interrupts if it is not our interrupt
>>
>> Signed-off-by: Mirko Lindner <mlindner@marvell.com>
[...]
> Tested-by: Julian Gilbey <jdg@debian.org> # 3.2.y, Inspiron 1545
Ping. Dave, is
d663d181b9e9 sky2: Fix for interrupt handler
a candidate for inclusion in 3.0-, 3.2-, and 3.4-stable? (It was
applied upstream during the 3.6 merge window.) I don't see it in
the list at [2].
Thanks,
Jonathan
> [1] http://bugs.debian.org/681280
> [2] http://patchwork.ozlabs.org/bundle/davem/stable/?state=*
^ permalink raw reply
* [PATCH] atp: remove set_rx_mode_8012()
From: Paul Bolle @ 2012-11-03 9:53 UTC (permalink / raw)
To: netdev; +Cc: linux-kernel
Building atp.o triggers this GCC warning:
drivers/net/ethernet/realtek/atp.c: In function ‘set_rx_mode’:
drivers/net/ethernet/realtek/atp.c:871:26: warning: ‘mc_filter[0]’ may be used uninitialized in this function [-Wuninitialized]
GCC is correct. In promiscuous mode 'mc_filter' will be used
uninitialized in set_rx_mode_8012(), which is apparently inlined into
set_rx_mode().
But it turns out set_rx_mode_8012() will never be called, since
net_local.chip_type will always be RTL8002. So we can just remove
set_rx_mode_8012() and do some related cleanups.
Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
---
Note: compile test only.
drivers/net/ethernet/realtek/atp.c | 58 ++------------------------------------
drivers/net/ethernet/realtek/atp.h | 2 --
2 files changed, 2 insertions(+), 58 deletions(-)
diff --git a/drivers/net/ethernet/realtek/atp.c b/drivers/net/ethernet/realtek/atp.c
index e02f04d..9f2d416 100644
--- a/drivers/net/ethernet/realtek/atp.c
+++ b/drivers/net/ethernet/realtek/atp.c
@@ -175,8 +175,7 @@ struct net_local {
unsigned int tx_unit_busy:1;
unsigned char re_tx, /* Number of packet retransmissions. */
addr_mode, /* Current Rx filter e.g. promiscuous, etc. */
- pac_cnt_in_tx_buf,
- chip_type;
+ pac_cnt_in_tx_buf;
};
/* This code, written by wwc@super.org, resets the adapter every
@@ -339,7 +338,6 @@ static int __init atp_probe1(long ioaddr)
write_reg_high(ioaddr, CMR1, CMR1h_RESET | CMR1h_MUX);
lp = netdev_priv(dev);
- lp->chip_type = RTL8002;
lp->addr_mode = CMR2h_Normal;
spin_lock_init(&lp->lock);
@@ -852,7 +850,7 @@ net_close(struct net_device *dev)
* Set or clear the multicast filter for this adapter.
*/
-static void set_rx_mode_8002(struct net_device *dev)
+static void set_rx_mode(struct net_device *dev)
{
struct net_local *lp = netdev_priv(dev);
long ioaddr = dev->base_addr;
@@ -864,58 +862,6 @@ static void set_rx_mode_8002(struct net_device *dev)
write_reg_high(ioaddr, CMR2, lp->addr_mode);
}
-static void set_rx_mode_8012(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
- long ioaddr = dev->base_addr;
- unsigned char new_mode, mc_filter[8]; /* Multicast hash filter */
- int i;
-
- if (dev->flags & IFF_PROMISC) { /* Set promiscuous. */
- new_mode = CMR2h_PROMISC;
- } else if ((netdev_mc_count(dev) > 1000) ||
- (dev->flags & IFF_ALLMULTI)) {
- /* Too many to filter perfectly -- accept all multicasts. */
- memset(mc_filter, 0xff, sizeof(mc_filter));
- new_mode = CMR2h_Normal;
- } else {
- struct netdev_hw_addr *ha;
-
- memset(mc_filter, 0, sizeof(mc_filter));
- netdev_for_each_mc_addr(ha, dev) {
- int filterbit = ether_crc_le(ETH_ALEN, ha->addr) & 0x3f;
- mc_filter[filterbit >> 5] |= 1 << (filterbit & 31);
- }
- new_mode = CMR2h_Normal;
- }
- lp->addr_mode = new_mode;
- write_reg(ioaddr, CMR2, CMR2_IRQOUT | 0x04); /* Switch to page 1. */
- for (i = 0; i < 8; i++)
- write_reg_byte(ioaddr, i, mc_filter[i]);
- if (net_debug > 2 || 1) {
- lp->addr_mode = 1;
- printk(KERN_DEBUG "%s: Mode %d, setting multicast filter to",
- dev->name, lp->addr_mode);
- for (i = 0; i < 8; i++)
- printk(" %2.2x", mc_filter[i]);
- printk(".\n");
- }
-
- write_reg_high(ioaddr, CMR2, lp->addr_mode);
- write_reg(ioaddr, CMR2, CMR2_IRQOUT); /* Switch back to page 0 */
-}
-
-static void set_rx_mode(struct net_device *dev)
-{
- struct net_local *lp = netdev_priv(dev);
-
- if (lp->chip_type == RTL8002)
- return set_rx_mode_8002(dev);
- else
- return set_rx_mode_8012(dev);
-}
-
-
static int __init atp_init_module(void) {
if (debug) /* Emit version even if no cards detected. */
printk(KERN_INFO "%s", version);
diff --git a/drivers/net/ethernet/realtek/atp.h b/drivers/net/ethernet/realtek/atp.h
index 0edc642..040b137 100644
--- a/drivers/net/ethernet/realtek/atp.h
+++ b/drivers/net/ethernet/realtek/atp.h
@@ -16,8 +16,6 @@ struct rx_header {
#define PAR_STATUS 1
#define PAR_CONTROL 2
-enum chip_type { RTL8002, RTL8012 };
-
#define Ctrl_LNibRead 0x08 /* LP_PSELECP */
#define Ctrl_HNibRead 0
#define Ctrl_LNibWrite 0x08 /* LP_PSELECP */
--
1.7.11.7
^ permalink raw reply related
* [PATCH v4 6/6] USB: forbid memory allocation with I/O during bus reset
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
If one storage interface or usb network interface(iSCSI case)
exists in current configuration, memory allocation with
GFP_KERNEL during usb_device_reset() might trigger I/O transfer
on the storage interface itself and cause deadlock because
the 'us->dev_mutex' is held in .pre_reset() and the storage
interface can't do I/O transfer when the reset is triggered
by other interface, or the error handling can't be completed
if the reset is triggered by the storage itself(error handling path).
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Oliver Neukum <oneukum@suse.de>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- mark current memalloc_noio for every usb device reset
---
drivers/usb/core/hub.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 5b131b6..788e652 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5044,6 +5044,7 @@ int usb_reset_device(struct usb_device *udev)
{
int ret;
int i;
+ unsigned int noio_flag;
struct usb_host_config *config = udev->actconfig;
if (udev->state == USB_STATE_NOTATTACHED ||
@@ -5053,6 +5054,17 @@ int usb_reset_device(struct usb_device *udev)
return -EINVAL;
}
+ /*
+ * Don't allocate memory with GFP_KERNEL in current
+ * context to avoid possible deadlock if usb mass
+ * storage interface or usbnet interface(iSCSI case)
+ * is included in current configuration. The easist
+ * approach is to do it for every device reset,
+ * because the device 'memalloc_noio' flag may have
+ * not been set before reseting the usb device.
+ */
+ memalloc_noio_save(noio_flag);
+
/* Prevent autosuspend during the reset */
usb_autoresume_device(udev);
@@ -5097,6 +5109,7 @@ int usb_reset_device(struct usb_device *udev)
}
usb_autosuspend_device(udev);
+ memalloc_noio_restore(noio_flag);
return ret;
}
EXPORT_SYMBOL_GPL(usb_reset_device);
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 5/6] PM / Runtime: force memory allocation with no I/O during Runtime PM callbcack
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
This patch applies the introduced memalloc_noio_save() and
memalloc_noio_restore() to force memory allocation with no I/O
during runtime_resume/runtime_suspend callback on device with
the flag of 'memalloc_noio' set.
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Oliver Neukum <oneukum@suse.de>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- runtime_suspend need this too because rpm_resume may wait for
completion of concurrent runtime_suspend, so deadlock still may
be triggered in runtime_suspend path.
---
drivers/base/power/runtime.c | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index d477924..7ed17a9 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -368,6 +368,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
int (*callback)(struct device *);
struct device *parent = NULL;
int retval;
+ unsigned int noio_flag;
trace_rpm_suspend(dev, rpmflags);
@@ -477,7 +478,20 @@ static int rpm_suspend(struct device *dev, int rpmflags)
if (!callback && dev->driver && dev->driver->pm)
callback = dev->driver->pm->runtime_suspend;
- retval = rpm_callback(callback, dev);
+ /*
+ * Deadlock might be caused if memory allocation with GFP_KERNEL
+ * happens inside runtime_suspend callback of one block device's
+ * ancestor or the block device itself. Network device might be
+ * thought as part of iSCSI block device, so network device and
+ * its ancestor should be marked as memalloc_noio.
+ */
+ if (dev->power.memalloc_noio) {
+ memalloc_noio_save(noio_flag);
+ retval = rpm_callback(callback, dev);
+ memalloc_noio_restore(noio_flag);
+ } else {
+ retval = rpm_callback(callback, dev);
+ }
if (retval)
goto fail;
@@ -560,6 +574,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
int (*callback)(struct device *);
struct device *parent = NULL;
int retval = 0;
+ unsigned int noio_flag;
trace_rpm_resume(dev, rpmflags);
@@ -709,7 +724,20 @@ static int rpm_resume(struct device *dev, int rpmflags)
if (!callback && dev->driver && dev->driver->pm)
callback = dev->driver->pm->runtime_resume;
- retval = rpm_callback(callback, dev);
+ /*
+ * Deadlock might be caused if memory allocation with GFP_KERNEL
+ * happens inside runtime_resume callback of one block device's
+ * ancestor or the block device itself. Network device might be
+ * thought as part of iSCSI block device, so network device and
+ * its ancestor should be marked as memalloc_noio.
+ */
+ if (dev->power.memalloc_noio) {
+ memalloc_noio_save(noio_flag);
+ retval = rpm_callback(callback, dev);
+ memalloc_noio_restore(noio_flag);
+ } else {
+ retval = rpm_callback(callback, dev);
+ }
if (retval) {
__update_runtime_status(dev, RPM_SUSPENDED);
pm_runtime_cancel_pending(dev);
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 4/6] net/core: apply pm_runtime_set_memalloc_noio on network devices
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei, Eric Dumazet,
David Decotigny, Tom Herbert, Ingo Molnar
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
Deadlock might be caused by allocating memory with GFP_KERNEL in
runtime_resume and runtime_suspend callback of network devices in
iSCSI situation, so mark network devices and its ancestor as
'memalloc_noio' with the introduced pm_runtime_set_memalloc_noio().
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Decotigny <david.decotigny@google.com>
Cc: Tom Herbert <therbert@google.com>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- call pm_runtime_set_memalloc_noio(ddev, true) after
device_add
---
net/core/net-sysfs.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c
index bcf02f6..a55d255 100644
--- a/net/core/net-sysfs.c
+++ b/net/core/net-sysfs.c
@@ -22,6 +22,7 @@
#include <linux/vmalloc.h>
#include <linux/export.h>
#include <linux/jiffies.h>
+#include <linux/pm_runtime.h>
#include <net/wext.h>
#include "net-sysfs.h"
@@ -1386,6 +1387,8 @@ void netdev_unregister_kobject(struct net_device * net)
remove_queue_kobjects(net);
+ pm_runtime_set_memalloc_noio(dev, false);
+
device_del(dev);
}
@@ -1421,6 +1424,8 @@ int netdev_register_kobject(struct net_device *net)
return error;
}
+ pm_runtime_set_memalloc_noio(dev, true);
+
return error;
}
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 3/6] block/genhd.c: apply pm_runtime_set_memalloc_noio on block devices
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
This patch applyes the introduced pm_runtime_set_memalloc_noio on
block device so that PM core will teach mm to not allocate memory with
GFP_IOFS when calling the runtime_resume and runtime_suspend callback
for block devices and its ancestors.
Cc: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- call pm_runtime_set_memalloc_noio(ddev, true) after device_add
---
block/genhd.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/block/genhd.c b/block/genhd.c
index 9e02cd6..f3fe3aa 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -18,6 +18,7 @@
#include <linux/mutex.h>
#include <linux/idr.h>
#include <linux/log2.h>
+#include <linux/pm_runtime.h>
#include "blk.h"
@@ -532,6 +533,13 @@ static void register_disk(struct gendisk *disk)
return;
}
}
+
+ /* avoid probable deadlock caused by allocating memory with
+ * GFP_KERNEL in runtime_resume callback of its all ancestor
+ * deivces
+ */
+ pm_runtime_set_memalloc_noio(ddev, true);
+
disk->part0.holder_dir = kobject_create_and_add("holders", &ddev->kobj);
disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
@@ -661,6 +669,7 @@ void del_gendisk(struct gendisk *disk)
disk->driverfs_dev = NULL;
if (!sysfs_deprecated)
sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
+ pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
device_del(disk_to_dev(disk));
}
EXPORT_SYMBOL(del_gendisk);
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 2/6] PM / Runtime: introduce pm_runtime_set_memalloc_noio()
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
The patch introduces the flag of memalloc_noio in 'struct dev_pm_info'
to help PM core to teach mm not allocating memory with GFP_KERNEL
flag for avoiding probable deadlock.
As explained in the comment, any GFP_KERNEL allocation inside
runtime_resume() or runtime_suspend() on any one of device in
the path from one block or network device to the root device
in the device tree may cause deadlock, the introduced
pm_runtime_set_memalloc_noio() sets or clears the flag on
device in the path recursively.
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- rename memalloc_noio_resume as memalloc_noio
- remove pm_runtime_get_memalloc_noio()
- add comments on pm_runtime_set_memalloc_noio
v3:
- introduce pm_runtime_get_memalloc_noio()
- hold one global lock on pm_runtime_set_memalloc_noio
- hold device power lock when accessing memalloc_noio_resume
flag suggested by Alan Stern
- implement pm_runtime_set_memalloc_noio without recursion
suggested by Alan Stern
v2:
- introduce pm_runtime_set_memalloc_noio()
---
drivers/base/power/runtime.c | 57 ++++++++++++++++++++++++++++++++++++++++++
include/linux/pm.h | 1 +
include/linux/pm_runtime.h | 3 +++
3 files changed, 61 insertions(+)
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 3148b10..d477924 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -124,6 +124,63 @@ unsigned long pm_runtime_autosuspend_expiration(struct device *dev)
}
EXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
+static int dev_memalloc_noio(struct device *dev, void *data)
+{
+ return dev->power.memalloc_noio;
+}
+
+/*
+ * pm_runtime_set_memalloc_noio - Set a device's memalloc_noio flag.
+ * @dev: Device to handle.
+ * @enable: True for setting the flag and False for clearing the flag.
+ *
+ * Set the flag for all devices in the path from the device to the
+ * root device in the device tree if @enable is true, otherwise clear
+ * the flag for devices in the path whose siblings don't set the flag.
+ *
+ * The function should only be called by block device, or network
+ * device driver for solving the deadlock problem during runtime
+ * resume/suspend:
+ * if memory allocation with GFP_KERNEL is called inside runtime
+ * resume/suspend callback of any one of its ancestors(or the
+ * block device itself), the deadlock may be triggered inside the
+ * memory allocation since it might not complete until the block
+ * device becomes active and the involed page I/O finishes. The
+ * situation is pointed out first by Alan Stern. Network device
+ * are involved in iSCSI kind of situation.
+ *
+ * The lock of dev_hotplug_mutex is held in the function for handling
+ * hotplug race because pm_runtime_set_memalloc_noio() may be called
+ * in async probe().
+ *
+ * The function should be called between device_add() and device_del()
+ * on the affected device(block/network device).
+ */
+void pm_runtime_set_memalloc_noio(struct device *dev, bool enable)
+{
+ static DEFINE_MUTEX(dev_hotplug_mutex);
+
+ mutex_lock(&dev_hotplug_mutex);
+ for(;;) {
+ /* hold power lock since bitfield is not SMP-safe. */
+ spin_lock_irq(&dev->power.lock);
+ dev->power.memalloc_noio = enable;
+ spin_unlock_irq(&dev->power.lock);
+
+ dev = dev->parent;
+
+ /* only clear the flag for one device if all
+ * children of the device don't set the flag.
+ */
+ if (!dev || (!enable &&
+ device_for_each_child(dev, NULL,
+ dev_memalloc_noio)))
+ break;
+ }
+ mutex_unlock(&dev_hotplug_mutex);
+}
+EXPORT_SYMBOL_GPL(pm_runtime_set_memalloc_noio);
+
/**
* rpm_check_suspend_allowed - Test whether a device may be suspended.
* @dev: Device to test.
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 03d7bb1..1a8a69d 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -538,6 +538,7 @@ struct dev_pm_info {
unsigned int irq_safe:1;
unsigned int use_autosuspend:1;
unsigned int timer_autosuspends:1;
+ unsigned int memalloc_noio:1;
enum rpm_request request;
enum rpm_status runtime_status;
int runtime_error;
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h
index f271860..775e063 100644
--- a/include/linux/pm_runtime.h
+++ b/include/linux/pm_runtime.h
@@ -47,6 +47,7 @@ extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay);
extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev);
extern void pm_runtime_update_max_time_suspended(struct device *dev,
s64 delta_ns);
+extern void pm_runtime_set_memalloc_noio(struct device *dev, bool enable);
static inline bool pm_children_suspended(struct device *dev)
{
@@ -149,6 +150,8 @@ static inline void pm_runtime_set_autosuspend_delay(struct device *dev,
int delay) {}
static inline unsigned long pm_runtime_autosuspend_expiration(
struct device *dev) { return 0; }
+static inline void pm_runtime_set_memalloc_noio(struct device *dev,
+ bool enable){}
#endif /* !CONFIG_PM_RUNTIME */
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 1/6] mm: teach mm by current context info to not do I/O during memory allocation
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm, Ming Lei, Jiri Kosina,
Mel Gorman, KAMEZAWA Hiroyuki, Michal Hocko, Ingo Molnar,
Peter Zijlstra
In-Reply-To: <1351931714-11689-1-git-send-email-ming.lei@canonical.com>
This patch introduces PF_MEMALLOC_NOIO on process flag('flags' field of
'struct task_struct'), so that the flag can be set by one task
to avoid doing I/O inside memory allocation in the task's context.
The patch trys to solve one deadlock problem caused by block device,
and the problem may happen at least in the below situations:
- during block device runtime resume, if memory allocation with
GFP_KERNEL is called inside runtime resume callback of any one
of its ancestors(or the block device itself), the deadlock may be
triggered inside the memory allocation since it might not complete
until the block device becomes active and the involed page I/O finishes.
The situation is pointed out first by Alan Stern. It is not a good
approach to convert all GFP_KERNEL[1] in the path into GFP_NOIO because
several subsystems may be involved(for example, PCI, USB and SCSI may
be involved for usb mass stoarage device, network devices involved too
in the iSCSI case)
- during block device runtime suspend, because runtime resume need
to wait for completion of concurrent runtime suspend.
- during error handling of usb mass storage deivce, USB bus reset
will be put on the device, so there shouldn't have any
memory allocation with GFP_KERNEL during USB bus reset, otherwise
the deadlock similar with above may be triggered. Unfortunately, any
usb device may include one mass storage interface in theory, so it
requires all usb interface drivers to handle the situation. In fact,
most usb drivers don't know how to handle bus reset on the device
and don't provide .pre_set() and .post_reset() callback at all, so
USB core has to unbind and bind driver for these devices. So it
is still not practical to resort to GFP_NOIO for solving the problem.
Also the introduced solution can be used by block subsystem or block
drivers too, for example, set the PF_MEMALLOC_NOIO flag before doing
actual I/O transfer.
It is not a good idea to convert all these GFP_KERNEL in the
affected path into GFP_NOIO because these functions doing that may be
implemented as library and will be called in many other contexts.
In fact, memalloc_noio() can convert some of current static GFP_NOIO
allocation into GFP_KERNEL back in other non-affected contexts, at least
almost all GFP_NOIO in USB subsystem can be converted into GFP_KERNEL
after applying the approach and make allocation with GFP_IO
only happen in runtime resume/bus reset/block I/O transfer contexts
generally.
[1], several GFP_KERNEL allocation examples in runtime resume path
- pci subsystem
acpi_os_allocate
<-acpi_ut_allocate
<-ACPI_ALLOCATE_ZEROED
<-acpi_evaluate_object
<-__acpi_bus_set_power
<-acpi_bus_set_power
<-acpi_pci_set_power_state
<-platform_pci_set_power_state
<-pci_platform_power_transition
<-__pci_complete_power_transition
<-pci_set_power_state
<-pci_restore_standard_config
<-pci_pm_runtime_resume
- usb subsystem
usb_get_status
<-finish_port_resume
<-usb_port_resume
<-generic_resume
<-usb_resume_device
<-usb_resume_both
<-usb_runtime_resume
- some individual usb drivers
usblp, uvc, gspca, most of dvb-usb-v2 media drivers, cpia2, az6007, ....
That is just what I have found. Unfortunately, this allocation can
only be found by human being now, and there should be many not found
since any function in the resume path(call tree) may allocate memory
with GFP_KERNEL.
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Oliver Neukum <oneukum@suse.de>
Cc: Jiri Kosina <jiri.kosina@suse.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Michal Hocko <mhocko@suse.cz>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "Rafael J. Wysocki" <rjw@sisk.pl>
Signed-off-by: Minchan Kim <minchan@kernel.org>
Signed-off-by: Ming Lei <ming.lei@canonical.com>
---
v4:
- fix comment
v3:
- no change
v2:
- remove changes on 'may_writepage' and 'may_swap' because that
isn't related with the patchset, and can't introduce I/O in
allocation path if GFP_IOFS is unset, so handing 'may_swap'
and may_writepage on GFP_NOIO or GFP_NOFS should be a
mm internal thing, and let mm guys deal with that, :-).
Looks clearing the two may_XXX flag only excludes dirty pages
and anon pages for relaiming, and the behaviour should be decided
by GFP FLAG, IMO.
- unset GFP_IOFS in try_to_free_pages() path since
alloc_page_buffers()
and dma_alloc_from_contiguous may drop into the path, as
pointed by KAMEZAWA Hiroyuki
v1:
- take Minchan's change to avoid the check in alloc_page hot
path
- change the helpers' style into save/restore as suggested by
Alan Stern
---
include/linux/sched.h | 10 ++++++++++
mm/page_alloc.c | 10 +++++++++-
mm/vmscan.c | 12 ++++++++++++
3 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index fb27acd..283fe86 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1805,6 +1805,7 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
#define PF_FROZEN 0x00010000 /* frozen for system suspend */
#define PF_FSTRANS 0x00020000 /* inside a filesystem transaction */
#define PF_KSWAPD 0x00040000 /* I am kswapd */
+#define PF_MEMALLOC_NOIO 0x00080000 /* Allocating memory without IO involved */
#define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */
#define PF_KTHREAD 0x00200000 /* I am a kernel thread */
#define PF_RANDOMIZE 0x00400000 /* randomize virtual address space */
@@ -1842,6 +1843,15 @@ extern void thread_group_times(struct task_struct *p, cputime_t *ut, cputime_t *
#define tsk_used_math(p) ((p)->flags & PF_USED_MATH)
#define used_math() tsk_used_math(current)
+#define memalloc_noio() (current->flags & PF_MEMALLOC_NOIO)
+#define memalloc_noio_save(flag) do { \
+ (flag) = current->flags & PF_MEMALLOC_NOIO; \
+ current->flags |= PF_MEMALLOC_NOIO; \
+} while (0)
+#define memalloc_noio_restore(flag) do { \
+ current->flags = (current->flags & ~PF_MEMALLOC_NOIO) | flag; \
+} while (0)
+
/*
* task->jobctl flags
*/
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 45c916b..3c47049 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2634,10 +2634,18 @@ retry_cpuset:
page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order,
zonelist, high_zoneidx, alloc_flags,
preferred_zone, migratetype);
- if (unlikely(!page))
+ if (unlikely(!page)) {
+ /*
+ * Runtime PM, block IO and its error handling path
+ * can deadlock because I/O on the device might not
+ * complete.
+ */
+ if (unlikely(memalloc_noio()))
+ gfp_mask &= ~GFP_IOFS;
page = __alloc_pages_slowpath(gfp_mask, order,
zonelist, high_zoneidx, nodemask,
preferred_zone, migratetype);
+ }
trace_mm_page_alloc(page, order, gfp_mask, migratetype);
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 10090c8..035088a 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2304,6 +2304,12 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
.gfp_mask = sc.gfp_mask,
};
+ if (unlikely(memalloc_noio())) {
+ gfp_mask &= ~GFP_IOFS;
+ sc.gfp_mask = gfp_mask;
+ shrink.gfp_mask = sc.gfp_mask;
+ }
+
throttle_direct_reclaim(gfp_mask, zonelist, nodemask);
/*
@@ -3304,6 +3310,12 @@ static int __zone_reclaim(struct zone *zone, gfp_t gfp_mask, unsigned int order)
};
unsigned long nr_slab_pages0, nr_slab_pages1;
+ if (unlikely(memalloc_noio())) {
+ gfp_mask &= ~GFP_IOFS;
+ sc.gfp_mask = gfp_mask;
+ shrink.gfp_mask = sc.gfp_mask;
+ }
+
cond_resched();
/*
* We need to be able to allocate from the reserves for RECLAIM_SWAP
--
1.7.9.5
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related
* [PATCH v4 0/6] solve deadlock caused by memory allocation with I/O
From: Ming Lei @ 2012-11-03 8:35 UTC (permalink / raw)
To: linux-kernel
Cc: Alan Stern, Oliver Neukum, Minchan Kim, Greg Kroah-Hartman,
Rafael J. Wysocki, Jens Axboe, David S. Miller, Andrew Morton,
netdev, linux-usb, linux-pm, linux-mm
This patchset try to solve one deadlock problem which might be caused
by memory allocation with block I/O during runtime PM and block device
error handling path. Traditionly, the problem is addressed by passing
GFP_NOIO statically to mm, but that is not a effective solution, see
detailed description in patch 1's commit log.
This patch set introduces one process flag and trys to fix the deadlock
problem on block device/network device during runtime PM or usb bus reset.
The 1st one is the change on include/sched.h and mm.
The 2nd patch introduces the flag of memalloc_noio on 'dev_pm_info',
and pm_runtime_set_memalloc_noio(), so that PM Core can teach mm to not
allocate mm with GFP_IOFS during the runtime_resume callback only on
device with the flag set.
The following 2 patches apply the introduced pm_runtime_set_memalloc_noio()
to mark all devices as memalloc_noio_resume in the path from the block or
network device to the root device in device tree.
The last 2 patches are applied again PM and USB subsystem to demonstrate
how to use the introduced mechanism to fix the deadlock problem.
Change logs:
V4:
- patches from the 2nd to the 6th changed
- call pm_runtime_set_memalloc_noio() after device_add() as pointed
by Alan
- set PF_MEMALLOC_NOIO during runtime_suspend()
V3:
- patch 2/6 and 5/6 changed, see their commit log
- remove RFC from title since several guys have expressed that
it is a reasonable solution
V2:
- remove changes on 'may_writepage' and 'may_swap'(1/6)
- unset GFP_IOFS in try_to_free_pages() path(1/6)
- introduce pm_runtime_set_memalloc_noio()
- only apply the meachnism on block/network device and its ancestors
for runtime resume context
V1:
- take Minchan's change to avoid the check in alloc_page hot path
- change the helpers' style into save/restore as suggested by Alan
- memory allocation with no io in usb bus reset path for all devices
as suggested by Greg and Oliver
block/genhd.c | 9 +++++
drivers/base/power/runtime.c | 89 +++++++++++++++++++++++++++++++++++++++++-
drivers/usb/core/hub.c | 13 ++++++
include/linux/pm.h | 1 +
include/linux/pm_runtime.h | 3 ++
include/linux/sched.h | 10 +++++
mm/page_alloc.c | 10 ++++-
mm/vmscan.c | 12 ++++++
net/core/net-sysfs.c | 5 +++
Thanks,
--
Ming Lei
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply
* [PATCH net-next 2/2] cpsw: fix leaking IO mappings
From: Richard Cochran @ 2012-11-03 8:25 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, David Miller, Cyril Chemparathy, Mugunthan V N,
Vaibhav Hiremath
In-Reply-To: <cover.1351930782.git.richardcochran@gmail.com>
The CPSW driver remaps two different IO regions, but fails to unmap them
both. This patch fixes the issue by calling iounmap in the appropriate
places.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 17 ++++++++---------
1 files changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 6215246..7654a62 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1252,14 +1252,12 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
ret = -ENOENT;
goto clean_clk_ret;
}
-
if (!request_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res), ndev->name)) {
dev_err(priv->dev, "failed request i/o region\n");
ret = -ENXIO;
goto clean_clk_ret;
}
-
regs = ioremap(priv->cpsw_res->start, resource_size(priv->cpsw_res));
if (!regs) {
dev_err(priv->dev, "unable to map i/o region\n");
@@ -1274,16 +1272,14 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
if (!priv->cpsw_wr_res) {
dev_err(priv->dev, "error getting i/o resource\n");
ret = -ENOENT;
- goto clean_clk_ret;
+ goto clean_iomap_ret;
}
-
if (!request_mem_region(priv->cpsw_wr_res->start,
resource_size(priv->cpsw_wr_res), ndev->name)) {
dev_err(priv->dev, "failed request i/o region\n");
ret = -ENXIO;
- goto clean_clk_ret;
+ goto clean_iomap_ret;
}
-
regs = ioremap(priv->cpsw_wr_res->start,
resource_size(priv->cpsw_wr_res));
if (!regs) {
@@ -1326,7 +1322,7 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
if (!priv->dma) {
dev_err(priv->dev, "error initializing dma\n");
ret = -ENOMEM;
- goto clean_iomap_ret;
+ goto clean_wr_iomap_ret;
}
priv->txch = cpdma_chan_create(priv->dma, tx_chan_num(0),
@@ -1407,11 +1403,13 @@ clean_dma_ret:
cpdma_chan_destroy(priv->txch);
cpdma_chan_destroy(priv->rxch);
cpdma_ctlr_destroy(priv->dma);
-clean_iomap_ret:
- iounmap(priv->regs);
+clean_wr_iomap_ret:
+ iounmap(priv->wr_regs);
clean_cpsw_wr_iores_ret:
release_mem_region(priv->cpsw_wr_res->start,
resource_size(priv->cpsw_wr_res));
+clean_iomap_ret:
+ iounmap(priv->regs);
clean_cpsw_iores_ret:
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
@@ -1442,6 +1440,7 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
iounmap(priv->regs);
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
+ iounmap(priv->wr_regs);
release_mem_region(priv->cpsw_wr_res->start,
resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
--
1.7.2.5
^ permalink raw reply related
* [PATCH net-next 1/2] cpsw: rename register banks to match the reference manual, part 2
From: Richard Cochran @ 2012-11-03 8:25 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, David Miller, Cyril Chemparathy, Mugunthan V N,
Vaibhav Hiremath
In-Reply-To: <cover.1351930782.git.richardcochran@gmail.com>
The code mixes up the CPSW_SS and the CPSW_WR register naming. This patch
changes the names to conform to the published Technical Reference Manual
from TI, in order to make working on the code less confusing.
Signed-off-by: Richard Cochran <richardcochran@gmail.com>
---
drivers/net/ethernet/ti/cpsw.c | 26 +++++++++++++-------------
1 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 023d439..6215246 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -286,7 +286,7 @@ struct cpsw_priv {
struct platform_device *pdev;
struct net_device *ndev;
struct resource *cpsw_res;
- struct resource *cpsw_ss_res;
+ struct resource *cpsw_wr_res;
struct napi_struct napi;
struct device *dev;
struct cpsw_platform_data data;
@@ -1270,25 +1270,25 @@ static int __devinit cpsw_probe(struct platform_device *pdev)
priv->host_port_regs = regs + data->host_port_reg_ofs;
priv->cpts.reg = regs + data->cpts_reg_ofs;
- priv->cpsw_ss_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!priv->cpsw_ss_res) {
+ priv->cpsw_wr_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!priv->cpsw_wr_res) {
dev_err(priv->dev, "error getting i/o resource\n");
ret = -ENOENT;
goto clean_clk_ret;
}
- if (!request_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res), ndev->name)) {
+ if (!request_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res), ndev->name)) {
dev_err(priv->dev, "failed request i/o region\n");
ret = -ENXIO;
goto clean_clk_ret;
}
- regs = ioremap(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
+ regs = ioremap(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
if (!regs) {
dev_err(priv->dev, "unable to map i/o region\n");
- goto clean_cpsw_ss_iores_ret;
+ goto clean_cpsw_wr_iores_ret;
}
priv->wr_regs = regs;
@@ -1409,9 +1409,9 @@ clean_dma_ret:
cpdma_ctlr_destroy(priv->dma);
clean_iomap_ret:
iounmap(priv->regs);
-clean_cpsw_ss_iores_ret:
- release_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
+clean_cpsw_wr_iores_ret:
+ release_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
clean_cpsw_iores_ret:
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
@@ -1442,8 +1442,8 @@ static int __devexit cpsw_remove(struct platform_device *pdev)
iounmap(priv->regs);
release_mem_region(priv->cpsw_res->start,
resource_size(priv->cpsw_res));
- release_mem_region(priv->cpsw_ss_res->start,
- resource_size(priv->cpsw_ss_res));
+ release_mem_region(priv->cpsw_wr_res->start,
+ resource_size(priv->cpsw_wr_res));
pm_runtime_disable(&pdev->dev);
clk_put(priv->clk);
kfree(priv->slaves);
--
1.7.2.5
^ permalink raw reply related
* [PATCH net-next 0/2] cpsw: fix resource leak for v3.8
From: Richard Cochran @ 2012-11-03 8:25 UTC (permalink / raw)
To: netdev
Cc: linux-arm-kernel, David Miller, Cyril Chemparathy, Mugunthan V N,
Vaibhav Hiremath
While looking at the idea of removing all of the register offsets in
the CPSW's device tree, I noticed that the driver would be leaking IO
mappings. Although this is, strictly speaking, a bug fix, still it can
wait to appear in v3.8, since there is no way to use the driver in
v3.7 (or earlier) anyhow.
Thanks,
Richard
Richard Cochran (2):
cpsw: rename register banks to match the reference manual, part 2
cpsw: fix leaking IO mappings
drivers/net/ethernet/ti/cpsw.c | 39 +++++++++++++++++++--------------------
1 files changed, 19 insertions(+), 20 deletions(-)
--
1.7.2.5
^ permalink raw reply
* Re: [PATCH v2 1/9] net: core: use this_cpu_ptr per-cpu helper
From: Steffen Klassert @ 2012-11-03 8:20 UTC (permalink / raw)
To: Christoph Lameter
Cc: Shan Wei, David Miller, timo.teras, NetDev, Kernel-Maillist
In-Reply-To: <0000013ac239c004-87f4c3e0-5c6a-4979-817f-0a0c4445a4e9-000000@email.amazonses.com>
On Fri, Nov 02, 2012 at 05:44:55PM +0000, Christoph Lameter wrote:
> On Sat, 3 Nov 2012, Shan Wei wrote:
> > +++ b/net/core/flow.c
> > @@ -327,11 +327,9 @@ static void flow_cache_flush_tasklet(unsigned long data)
> > static void flow_cache_flush_per_cpu(void *data)
> > {
> > struct flow_flush_info *info = data;
> > - int cpu;
> > struct tasklet_struct *tasklet;
> >
> > - cpu = smp_processor_id();
> > - tasklet = &per_cpu_ptr(info->cache->percpu, cpu)->flush_tasklet;
> > + tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet
>
> Another case for the use of this_cpu_read
Actually, smp_processor_id() is used if either preemtion is off or
in a thread that is bound to the current cpu. So all code that uses
smp_processor_id() should be able to use __this_cpu_read instead of
this_cpu_read.
In this case, flow_cache_flush_per_cpu() is called via smp_call_function(),
so it is bound on the current cpu.
^ permalink raw reply
* Query regarding pushing a patch series against net-next tree
From: Vipul Pandya @ 2012-11-03 7:48 UTC (permalink / raw)
To: netdev@vger.kernel.org, David Miller
Cc: Steve Wise, kumar Sanghvi, Divy Le Ray, Dimitrios Michailidis
Hi David Miller,
We have a important patch series fixing a bug as well as adding a
feature. This patch series is prepared against net-next tree. However to
be able to build it successfully it requires a patch from net tree which
was pushed recently. So, we cannot push this patch series until both the
trees are merged. We would like this patch series to be submitted as
soon as possible to net-next so that it can be accepted by OFED community.
Can you please suggest how should we proceed for submitting this patch
series?
Thanks,
Vipul Pandya
^ permalink raw reply
* Re: [net-next:master 122/152] drivers/ptp/ptp_chardev.c:36 ptp_ioctl() warn: 'sysoff' puts 832 bytes on stack
From: David Miller @ 2012-11-03 5:39 UTC (permalink / raw)
To: richardcochran; +Cc: yuanhan.liu, changlongx.xie, fengguang.wu, netdev
In-Reply-To: <20121103045339.GA2277@netboy.at.omicron.at>
From: Richard Cochran <richardcochran@gmail.com>
Date: Sat, 3 Nov 2012 05:53:39 +0100
> Isn't it being nicer to the memory allocation code not to repeatedly
> request small chunks?
Don't use performance as an argument against writing this code
correctly.
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox