Modify the NFSv4.1 pNFS client to use separate TCP connections for DSs.

Without this patch, the NFSv4.1 pNFS client shared a single TCP connection
for all DSs that resided on the same machine. This made disabling one of
the DSs impossible. Although unlikely, it is possible that the storage
subsystem has failed in such a way that the storage for one DS on a machine
is no longer functioning correctly, but the storage used by another DS on
the same machine is still ok. For this case, it would be nice if a system
can fail one of the DSs without failing them all.
This patch changes the default behaviour to use separate TCP connections
for each DS even if they reside on the same machine.
I do not believe that this will be a problem for extant pNFS servers, but
a sysctl can be set to restore the old behaviour if this change causes a
problem for an extant pNFS server.
This patch only affects the NFSv4.1 pNFS client.

MFC after:	2 weeks
This commit is contained in:
Rick Macklem 2018-07-12 20:46:22 +00:00
parent 8c44114a46
commit a6fed5f514
2 changed files with 25 additions and 19 deletions

View File

@ -94,6 +94,7 @@ struct nfsclds {
#define NFSCLDS_MDS 0x0002
#define NFSCLDS_DS 0x0004
#define NFSCLDS_CLOSED 0x0008
#define NFSCLDS_SAMECONN 0x0010
struct nfsclclient {
LIST_ENTRY(nfsclclient) nfsc_list;

View File

@ -57,6 +57,10 @@ static int nfsignore_eexist = 0;
SYSCTL_INT(_vfs_nfs, OID_AUTO, ignore_eexist, CTLFLAG_RW,
&nfsignore_eexist, 0, "NFS ignore EEXIST replies for mkdir/symlink");
static int nfscl_dssameconn = 0;
SYSCTL_INT(_vfs_nfs, OID_AUTO, dssameconn, CTLFLAG_RW,
&nfscl_dssameconn, 0, "Use same TCP connection to multiple DSs");
/*
* Global variables
*/
@ -162,7 +166,7 @@ static int nfsrpc_writedsmir(vnode_t, int *, int *, nfsv4stateid_t *,
struct nfsclds *, uint64_t, int, struct nfsfh *, struct mbuf *, int, int,
struct ucred *, NFSPROC_T *);
static enum nfsclds_state nfscl_getsameserver(struct nfsmount *,
struct nfsclds *, struct nfsclds **);
struct nfsclds *, struct nfsclds **, uint32_t *);
static int nfsio_commitds(vnode_t, uint64_t, int, struct nfsclds *,
struct nfsfh *, int, int, struct nfsclwritedsdorpc *, struct ucred *,
NFSPROC_T *);
@ -5498,9 +5502,14 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin,
dsp->nfsclds_sockp = nrp;
if (vers == NFS_VER4) {
NFSLOCKMNT(nmp);
retv = nfscl_getsameserver(nmp, dsp, &tdsp);
retv = nfscl_getsameserver(nmp, dsp, &tdsp,
&sequenceid);
NFSCL_DEBUG(3, "getsame ret=%d\n", retv);
if (retv == NFSDSP_USETHISSESSION) {
if (retv == NFSDSP_USETHISSESSION &&
nfscl_dssameconn != 0) {
NFSLOCKDS(tdsp);
tdsp->nfsclds_flags |= NFSCLDS_SAMECONN;
NFSUNLOCKDS(tdsp);
NFSUNLOCKMNT(nmp);
/*
* If there is already a session for this
@ -5511,10 +5520,7 @@ nfsrpc_fillsa(struct nfsmount *nmp, struct sockaddr_in *sin,
*dspp = tdsp;
return (0);
}
if (retv == NFSDSP_SEQTHISSESSION)
sequenceid =
tdsp->nfsclds_sess.nfsess_sequenceid;
else
if (retv == NFSDSP_NOTFOUND)
sequenceid =
dsp->nfsclds_sess.nfsess_sequenceid;
NFSUNLOCKMNT(nmp);
@ -6516,15 +6522,16 @@ nfscl_freenfsclds(struct nfsclds *dsp)
static enum nfsclds_state
nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp,
struct nfsclds **retdspp)
struct nfsclds **retdspp, uint32_t *sequencep)
{
struct nfsclds *dsp, *cur_dsp;
struct nfsclds *dsp;
int fndseq;
/*
* Search the list of nfsclds structures for one with the same
* server.
*/
cur_dsp = NULL;
fndseq = 0;
TAILQ_FOREACH(dsp, &nmp->nm_sess, nfsclds_list) {
if (dsp->nfsclds_servownlen == newdsp->nfsclds_servownlen &&
dsp->nfsclds_servownlen != 0 &&
@ -6534,24 +6541,22 @@ nfscl_getsameserver(struct nfsmount *nmp, struct nfsclds *newdsp,
NFSCL_DEBUG(4, "fnd same fdsp=%p dsp=%p flg=0x%x\n",
TAILQ_FIRST(&nmp->nm_sess), dsp,
dsp->nfsclds_flags);
if (fndseq == 0) {
/* Get sequenceid# from first entry. */
*sequencep =
dsp->nfsclds_sess.nfsess_sequenceid;
fndseq = 1;
}
/* Server major id matches. */
if ((dsp->nfsclds_flags & NFSCLDS_DS) != 0) {
*retdspp = dsp;
return (NFSDSP_USETHISSESSION);
}
/*
* Note the first match, so it can be used for
* sequence'ing new sessions.
*/
if (cur_dsp == NULL)
cur_dsp = dsp;
}
}
if (cur_dsp != NULL) {
*retdspp = cur_dsp;
if (fndseq != 0)
return (NFSDSP_SEQTHISSESSION);
}
return (NFSDSP_NOTFOUND);
}