lkml.org 
[lkml]   [2022]   [Jan]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 061/846] cxl/pmem: Fix reference counting for delayed work
    Date
    From: Dan Williams <dan.j.williams@intel.com>

    commit 08b9e0ab8af48895337192e683de44ab1e1b7427 upstream.

    There is a potential race between queue_work() returning and the
    queued-work running that could result in put_device() running before
    get_device(). Introduce the cxl_nvdimm_bridge_state_work() helper that
    takes the reference unconditionally, but drops it if no new work was
    queued, to keep the references balanced.

    Fixes: 8fdcb1704f61 ("cxl/pmem: Add initial infrastructure for pmem support")
    Cc: <stable@vger.kernel.org>
    Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
    Reviewed-by: Ben Widawsky <ben.widawsky@intel.com>
    Link: https://lore.kernel.org/r/163553734757.2509761.3305231863616785470.stgit@dwillia2-desk3.amr.corp.intel.com
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/cxl/pmem.c | 17 +++++++++++++----
    1 file changed, 13 insertions(+), 4 deletions(-)

    --- a/drivers/cxl/pmem.c
    +++ b/drivers/cxl/pmem.c
    @@ -149,14 +149,24 @@ static void cxl_nvb_update_state(struct
    put_device(&cxl_nvb->dev);
    }

    +static void cxl_nvdimm_bridge_state_work(struct cxl_nvdimm_bridge *cxl_nvb)
    +{
    + /*
    + * Take a reference that the workqueue will drop if new work
    + * gets queued.
    + */
    + get_device(&cxl_nvb->dev);
    + if (!queue_work(cxl_pmem_wq, &cxl_nvb->state_work))
    + put_device(&cxl_nvb->dev);
    +}
    +
    static void cxl_nvdimm_bridge_remove(struct device *dev)
    {
    struct cxl_nvdimm_bridge *cxl_nvb = to_cxl_nvdimm_bridge(dev);

    if (cxl_nvb->state == CXL_NVB_ONLINE)
    cxl_nvb->state = CXL_NVB_OFFLINE;
    - if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work))
    - get_device(&cxl_nvb->dev);
    + cxl_nvdimm_bridge_state_work(cxl_nvb);
    }

    static int cxl_nvdimm_bridge_probe(struct device *dev)
    @@ -177,8 +187,7 @@ static int cxl_nvdimm_bridge_probe(struc
    }

    cxl_nvb->state = CXL_NVB_ONLINE;
    - if (queue_work(cxl_pmem_wq, &cxl_nvb->state_work))
    - get_device(&cxl_nvb->dev);
    + cxl_nvdimm_bridge_state_work(cxl_nvb);

    return 0;
    }

    \
     
     \ /
      Last update: 2022-01-24 22:09    [W:2.798 / U:0.600 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site