lkml.org 
[lkml]   [2021]   [Jul]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.12 221/292] NFSv4/pNFS: Dont call _nfs4_pnfs_v3_ds_connect multiple times
    Date
    From: Trond Myklebust <trond.myklebust@hammerspace.com>

    [ Upstream commit f46f84931a0aa344678efe412d4b071d84d8a805 ]

    After we grab the lock in nfs4_pnfs_ds_connect(), there is no check for
    whether or not ds->ds_clp has already been initialised, so we can end up
    adding the same transports multiple times.

    Fixes: fc821d59209d ("pnfs/NFSv4.1: Add multipath capabilities to pNFS flexfiles servers over NFSv3")
    Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    fs/nfs/pnfs_nfs.c | 52 +++++++++++++++++++++++------------------------
    1 file changed, 26 insertions(+), 26 deletions(-)

    diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
    index 49d3389bd813..1c2c0d08614e 100644
    --- a/fs/nfs/pnfs_nfs.c
    +++ b/fs/nfs/pnfs_nfs.c
    @@ -805,19 +805,16 @@ out:
    }
    EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add);

    -static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
    +static int nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds)
    {
    might_sleep();
    - wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING,
    - TASK_KILLABLE);
    + return wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING, TASK_KILLABLE);
    }

    static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds)
    {
    smp_mb__before_atomic();
    - clear_bit(NFS4DS_CONNECTING, &ds->ds_state);
    - smp_mb__after_atomic();
    - wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING);
    + clear_and_wake_up_bit(NFS4DS_CONNECTING, &ds->ds_state);
    }

    static struct nfs_client *(*get_v3_ds_connect)(
    @@ -993,30 +990,33 @@ int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds,
    {
    int err;

    -again:
    - err = 0;
    - if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) {
    - if (version == 3) {
    - err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo,
    - retrans);
    - } else if (version == 4) {
    - err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo,
    - retrans, minor_version);
    - } else {
    - dprintk("%s: unsupported DS version %d\n", __func__,
    - version);
    - err = -EPROTONOSUPPORT;
    - }
    + do {
    + err = nfs4_wait_ds_connect(ds);
    + if (err || ds->ds_clp)
    + goto out;
    + if (nfs4_test_deviceid_unavailable(devid))
    + return -ENODEV;
    + } while (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) != 0);

    - nfs4_clear_ds_conn_bit(ds);
    - } else {
    - nfs4_wait_ds_connect(ds);
    + if (ds->ds_clp)
    + goto connect_done;

    - /* what was waited on didn't connect AND didn't mark unavail */
    - if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid))
    - goto again;
    + switch (version) {
    + case 3:
    + err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo, retrans);
    + break;
    + case 4:
    + err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo, retrans,
    + minor_version);
    + break;
    + default:
    + dprintk("%s: unsupported DS version %d\n", __func__, version);
    + err = -EPROTONOSUPPORT;
    }

    +connect_done:
    + nfs4_clear_ds_conn_bit(ds);
    +out:
    /*
    * At this point the ds->ds_clp should be ready, but it might have
    * hit an error.
    --
    2.30.2


    \
     
     \ /
      Last update: 2021-07-19 20:14    [W:4.122 / U:0.408 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site