lkml.org 
[lkml]   [2022]   [Apr]   [14]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 270/475] NFSv4/pNFS: Fix another issue with a list iterator pointing to the head
    Date
    From: Trond Myklebust <trond.myklebust@hammerspace.com>

    [ Upstream commit 7c9d845f0612e5bcd23456a2ec43be8ac43458f1 ]

    In nfs4_callback_devicenotify(), if we don't find a matching entry for
    the deviceid, we're left with a pointer to 'struct nfs_server' that
    actually points to the list of super blocks associated with our struct
    nfs_client.
    Furthermore, even if we have a valid pointer, nothing pins the super
    block, and so the struct nfs_server could end up getting freed while
    we're using it.

    Since all we want is a pointer to the struct pnfs_layoutdriver_type,
    let's skip all the iteration over super blocks, and just use APIs to
    find the layout driver directly.

    Reported-by: Xiaomeng Tong <xiam0nd.tong@gmail.com>
    Fixes: 1be5683b03a7 ("pnfs: CB_NOTIFY_DEVICEID")
    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/callback_proc.c | 27 +++++++++------------------
    fs/nfs/pnfs.c | 11 +++++++++++
    fs/nfs/pnfs.h | 2 ++
    3 files changed, 22 insertions(+), 18 deletions(-)

    diff --git a/fs/nfs/callback_proc.c b/fs/nfs/callback_proc.c
    index b8a7b223b5b1..31922657e836 100644
    --- a/fs/nfs/callback_proc.c
    +++ b/fs/nfs/callback_proc.c
    @@ -364,12 +364,11 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
    struct cb_process_state *cps)
    {
    struct cb_devicenotifyargs *args = argp;
    + const struct pnfs_layoutdriver_type *ld = NULL;
    uint32_t i;
    __be32 res = 0;
    - struct nfs_client *clp = cps->clp;
    - struct nfs_server *server = NULL;

    - if (!clp) {
    + if (!cps->clp) {
    res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
    goto out;
    }
    @@ -377,23 +376,15 @@ __be32 nfs4_callback_devicenotify(void *argp, void *resp,
    for (i = 0; i < args->ndevs; i++) {
    struct cb_devicenotifyitem *dev = &args->devs[i];

    - if (!server ||
    - server->pnfs_curr_ld->id != dev->cbd_layout_type) {
    - rcu_read_lock();
    - list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
    - if (server->pnfs_curr_ld &&
    - server->pnfs_curr_ld->id == dev->cbd_layout_type) {
    - rcu_read_unlock();
    - goto found;
    - }
    - rcu_read_unlock();
    - continue;
    + if (!ld || ld->id != dev->cbd_layout_type) {
    + pnfs_put_layoutdriver(ld);
    + ld = pnfs_find_layoutdriver(dev->cbd_layout_type);
    + if (!ld)
    + continue;
    }
    -
    - found:
    - nfs4_delete_deviceid(server->pnfs_curr_ld, clp, &dev->cbd_dev_id);
    + nfs4_delete_deviceid(ld, cps->clp, &dev->cbd_dev_id);
    }
    -
    + pnfs_put_layoutdriver(ld);
    out:
    kfree(args->devs);
    return res;
    diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
    index 1b512df1003f..0471b6e0da16 100644
    --- a/fs/nfs/pnfs.c
    +++ b/fs/nfs/pnfs.c
    @@ -92,6 +92,17 @@ find_pnfs_driver(u32 id)
    return local;
    }

    +const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id)
    +{
    + return find_pnfs_driver(id);
    +}
    +
    +void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld)
    +{
    + if (ld)
    + module_put(ld->owner);
    +}
    +
    void
    unset_pnfs_layoutdriver(struct nfs_server *nfss)
    {
    diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
    index 3d55edd6b25a..68339680bb7d 100644
    --- a/fs/nfs/pnfs.h
    +++ b/fs/nfs/pnfs.h
    @@ -226,6 +226,8 @@ struct pnfs_devicelist {

    extern int pnfs_register_layoutdriver(struct pnfs_layoutdriver_type *);
    extern void pnfs_unregister_layoutdriver(struct pnfs_layoutdriver_type *);
    +extern const struct pnfs_layoutdriver_type *pnfs_find_layoutdriver(u32 id);
    +extern void pnfs_put_layoutdriver(const struct pnfs_layoutdriver_type *ld);

    /* nfs4proc.c */
    extern size_t max_response_pages(struct nfs_server *server);
    --
    2.34.1


    \
     
     \ /
      Last update: 2022-04-14 17:07    [W:4.208 / U:0.024 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site