lkml.org 
[lkml]   [2016]   [Mar]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.14 129/130] xen/pcifront: Fix mysterious crashes when NUMA locality information was extracted.
    Date
    3.14-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

    commit 4d8c8bd6f2062c9988817183a91fe2e623c8aa5e upstream.

    Occasionaly PV guests would crash with:

    pciback 0000:00:00.1: Xen PCI mapped GSI0 to IRQ16
    BUG: unable to handle kernel paging request at 0000000d1a8c0be0
    .. snip..
    <ffffffff8139ce1b>] find_next_bit+0xb/0x10
    [<ffffffff81387f22>] cpumask_next_and+0x22/0x40
    [<ffffffff813c1ef8>] pci_device_probe+0xb8/0x120
    [<ffffffff81529097>] ? driver_sysfs_add+0x77/0xa0
    [<ffffffff815293e4>] driver_probe_device+0x1a4/0x2d0
    [<ffffffff813c1ddd>] ? pci_match_device+0xdd/0x110
    [<ffffffff81529657>] __device_attach_driver+0xa7/0xb0
    [<ffffffff815295b0>] ? __driver_attach+0xa0/0xa0
    [<ffffffff81527622>] bus_for_each_drv+0x62/0x90
    [<ffffffff8152978d>] __device_attach+0xbd/0x110
    [<ffffffff815297fb>] device_attach+0xb/0x10
    [<ffffffff813b75ac>] pci_bus_add_device+0x3c/0x70
    [<ffffffff813b7618>] pci_bus_add_devices+0x38/0x80
    [<ffffffff813dc34e>] pcifront_scan_root+0x13e/0x1a0
    [<ffffffff817a0692>] pcifront_backend_changed+0x262/0x60b
    [<ffffffff814644c6>] ? xenbus_gather+0xd6/0x160
    [<ffffffff8120900f>] ? put_object+0x2f/0x50
    [<ffffffff81465c1d>] xenbus_otherend_changed+0x9d/0xa0
    [<ffffffff814678ee>] backend_changed+0xe/0x10
    [<ffffffff81463a28>] xenwatch_thread+0xc8/0x190
    [<ffffffff810f22f0>] ? woken_wake_function+0x10/0x10

    which was the result of two things:

    When we call pci_scan_root_bus we would pass in 'sd' (sysdata)
    pointer which was an 'pcifront_sd' structure. However in the
    pci_device_add it expects that the 'sd' is 'struct sysdata' and
    sets the dev->node to what is in sd->node (offset 4):

    set_dev_node(&dev->dev, pcibus_to_node(bus));

    __pcibus_to_node(const struct pci_bus *bus)
    {
    const struct pci_sysdata *sd = bus->sysdata;

    return sd->node;
    }

    However our structure was pcifront_sd which had nothing at that
    offset:

    struct pcifront_sd {
    int domain; /* 0 4 */
    /* XXX 4 bytes hole, try to pack */
    struct pcifront_device * pdev; /* 8 8 */
    }

    That is an hole - filled with garbage as we used kmalloc instead of
    kzalloc (the second problem).

    This patch fixes the issue by:
    1) Use kzalloc to initialize to a well known state.
    2) Put 'struct pci_sysdata' at the start of 'pcifront_sd'. That
    way access to the 'node' will access the right offset.

    Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
    Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
    Signed-off-by: David Vrabel <david.vrabel@citrix.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/pci/xen-pcifront.c | 10 ++++++----
    1 file changed, 6 insertions(+), 4 deletions(-)

    --- a/drivers/pci/xen-pcifront.c
    +++ b/drivers/pci/xen-pcifront.c
    @@ -52,7 +52,7 @@ struct pcifront_device {
    };

    struct pcifront_sd {
    - int domain;
    + struct pci_sysdata sd;
    struct pcifront_device *pdev;
    };

    @@ -66,7 +66,9 @@ static inline void pcifront_init_sd(stru
    unsigned int domain, unsigned int bus,
    struct pcifront_device *pdev)
    {
    - sd->domain = domain;
    + /* Because we do not expose that information via XenBus. */
    + sd->sd.node = first_online_node;
    + sd->sd.domain = domain;
    sd->pdev = pdev;
    }

    @@ -464,8 +466,8 @@ static int pcifront_scan_root(struct pci
    dev_info(&pdev->xdev->dev, "Creating PCI Frontend Bus %04x:%02x\n",
    domain, bus);

    - bus_entry = kmalloc(sizeof(*bus_entry), GFP_KERNEL);
    - sd = kmalloc(sizeof(*sd), GFP_KERNEL);
    + bus_entry = kzalloc(sizeof(*bus_entry), GFP_KERNEL);
    + sd = kzalloc(sizeof(*sd), GFP_KERNEL);
    if (!bus_entry || !sd) {
    err = -ENOMEM;
    goto err_out;
    \
     
     \ /
      Last update: 2016-03-02 03:21    [W:4.037 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site