Commit 41ef7218 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'nfsd-4.7-1' of git://linux-nfs.org/~bfields/linux

Pull nfsd bugfixes from Bruce Fields:
 "Oleg Drokin found and fixed races in the nfsd4 state code that go back
  to the big nfs4_lock_state removal around 3.17 (but that were also
  probably hard to reproduce before client changes in 3.20 allowed the
  client to perform parallel opens).

  Also fix a 4.1 backchannel crash due to rpc multipath changes in 4.6.
  Trond acked the client-side rpc fixes going through my tree"

* tag 'nfsd-4.7-1' of git://linux-nfs.org/~bfields/linux:
  nfsd: Make init_open_stateid() a bit more whole
  nfsd: Extend the mutex holding region around in nfsd4_process_open2()
  nfsd: Always lock state exclusively.
  rpc: share one xps between all backchannels
  nfsd4/rpc: move backchannel create logic into rpc code
  SUNRPC: fix xprt leak on xps allocation failure
  nfsd: Fix NFSD_MDS_PR_KEY on 32-bit by adding ULL postfix
parents 9c514bed 8c7245ab
...@@ -290,7 +290,7 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev, ...@@ -290,7 +290,7 @@ static int nfsd4_scsi_identify_device(struct block_device *bdev,
return error; return error;
} }
#define NFSD_MDS_PR_KEY 0x0100000000000000 #define NFSD_MDS_PR_KEY 0x0100000000000000ULL
/* /*
* We use the client ID as a unique key for the reservations. * We use the client ID as a unique key for the reservations.
......
...@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc ...@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
} }
} }
static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
{
struct rpc_xprt *xprt;
if (args->protocol != XPRT_TRANSPORT_BC_TCP)
return rpc_create(args);
xprt = args->bc_xprt->xpt_bc_xprt;
if (xprt) {
xprt_get(xprt);
return rpc_create_xprt(args, xprt);
}
return rpc_create(args);
}
static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
{ {
int maxtime = max_cb_time(clp->net); int maxtime = max_cb_time(clp->net);
...@@ -768,7 +752,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c ...@@ -768,7 +752,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
args.authflavor = ses->se_cb_sec.flavor; args.authflavor = ses->se_cb_sec.flavor;
} }
/* Create RPC client */ /* Create RPC client */
client = create_backchannel_client(&args); client = rpc_create(&args);
if (IS_ERR(client)) { if (IS_ERR(client)) {
dprintk("NFSD: couldn't create callback client: %ld\n", dprintk("NFSD: couldn't create callback client: %ld\n",
PTR_ERR(client)); PTR_ERR(client));
......
...@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open, ...@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
} }
static struct nfs4_ol_stateid * static struct nfs4_ol_stateid *
init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
struct nfsd4_open *open)
{ {
struct nfs4_openowner *oo = open->op_openowner; struct nfs4_openowner *oo = open->op_openowner;
struct nfs4_ol_stateid *retstp = NULL; struct nfs4_ol_stateid *retstp = NULL;
struct nfs4_ol_stateid *stp;
stp = open->op_stp;
/* We are moving these outside of the spinlocks to avoid the warnings */
mutex_init(&stp->st_mutex);
mutex_lock(&stp->st_mutex);
spin_lock(&oo->oo_owner.so_client->cl_lock); spin_lock(&oo->oo_owner.so_client->cl_lock);
spin_lock(&fp->fi_lock); spin_lock(&fp->fi_lock);
...@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, ...@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
retstp = nfsd4_find_existing_open(fp, open); retstp = nfsd4_find_existing_open(fp, open);
if (retstp) if (retstp)
goto out_unlock; goto out_unlock;
open->op_stp = NULL;
atomic_inc(&stp->st_stid.sc_count); atomic_inc(&stp->st_stid.sc_count);
stp->st_stid.sc_type = NFS4_OPEN_STID; stp->st_stid.sc_type = NFS4_OPEN_STID;
INIT_LIST_HEAD(&stp->st_locks); INIT_LIST_HEAD(&stp->st_locks);
...@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, ...@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
stp->st_access_bmap = 0; stp->st_access_bmap = 0;
stp->st_deny_bmap = 0; stp->st_deny_bmap = 0;
stp->st_openstp = NULL; stp->st_openstp = NULL;
init_rwsem(&stp->st_rwsem);
list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
list_add(&stp->st_perfile, &fp->fi_stateids); list_add(&stp->st_perfile, &fp->fi_stateids);
out_unlock: out_unlock:
spin_unlock(&fp->fi_lock); spin_unlock(&fp->fi_lock);
spin_unlock(&oo->oo_owner.so_client->cl_lock); spin_unlock(&oo->oo_owner.so_client->cl_lock);
return retstp; if (retstp) {
mutex_lock(&retstp->st_mutex);
/* To keep mutex tracking happy */
mutex_unlock(&stp->st_mutex);
stp = retstp;
}
return stp;
} }
/* /*
...@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
struct nfs4_file *fp = NULL; struct nfs4_file *fp = NULL;
struct nfs4_ol_stateid *stp = NULL; struct nfs4_ol_stateid *stp = NULL;
struct nfs4_ol_stateid *swapstp = NULL;
struct nfs4_delegation *dp = NULL; struct nfs4_delegation *dp = NULL;
__be32 status; __be32 status;
...@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
*/ */
if (stp) { if (stp) {
/* Stateid was found, this is an OPEN upgrade */ /* Stateid was found, this is an OPEN upgrade */
down_read(&stp->st_rwsem); mutex_lock(&stp->st_mutex);
status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
if (status) { if (status) {
up_read(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
goto out; goto out;
} }
} else { } else {
stp = open->op_stp; /* stp is returned locked. */
open->op_stp = NULL; stp = init_open_stateid(fp, open);
swapstp = init_open_stateid(stp, fp, open); /* See if we lost the race to some other thread */
if (swapstp) { if (stp->st_access_bmap != 0) {
nfs4_put_stid(&stp->st_stid);
stp = swapstp;
down_read(&stp->st_rwsem);
status = nfs4_upgrade_open(rqstp, fp, current_fh, status = nfs4_upgrade_open(rqstp, fp, current_fh,
stp, open); stp, open);
if (status) { if (status) {
up_read(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
goto out; goto out;
} }
goto upgrade_out; goto upgrade_out;
} }
down_read(&stp->st_rwsem);
status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
if (status) { if (status) {
up_read(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
release_open_stateid(stp); release_open_stateid(stp);
goto out; goto out;
} }
...@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf ...@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
} }
upgrade_out: upgrade_out:
nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
up_read(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
if (nfsd4_has_session(&resp->cstate)) { if (nfsd4_has_session(&resp->cstate)) {
if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) {
...@@ -4977,12 +4984,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_ ...@@ -4977,12 +4984,12 @@ static __be32 nfs4_seqid_op_checks(struct nfsd4_compound_state *cstate, stateid_
* revoked delegations are kept only for free_stateid. * revoked delegations are kept only for free_stateid.
*/ */
return nfserr_bad_stateid; return nfserr_bad_stateid;
down_write(&stp->st_rwsem); mutex_lock(&stp->st_mutex);
status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
if (status == nfs_ok) if (status == nfs_ok)
status = nfs4_check_fh(current_fh, &stp->st_stid); status = nfs4_check_fh(current_fh, &stp->st_stid);
if (status != nfs_ok) if (status != nfs_ok)
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
return status; return status;
} }
...@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs ...@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
return status; return status;
oo = openowner(stp->st_stateowner); oo = openowner(stp->st_stateowner);
if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid); nfs4_put_stid(&stp->st_stid);
return nfserr_bad_stateid; return nfserr_bad_stateid;
} }
...@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
oo = openowner(stp->st_stateowner); oo = openowner(stp->st_stateowner);
status = nfserr_bad_stateid; status = nfserr_bad_stateid;
if (oo->oo_flags & NFS4_OO_CONFIRMED) { if (oo->oo_flags & NFS4_OO_CONFIRMED) {
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
goto put_stateid; goto put_stateid;
} }
oo->oo_flags |= NFS4_OO_CONFIRMED; oo->oo_flags |= NFS4_OO_CONFIRMED;
nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
__func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
...@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, ...@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid); nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
status = nfs_ok; status = nfs_ok;
put_stateid: put_stateid:
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid); nfs4_put_stid(&stp->st_stid);
out: out:
nfsd4_bump_seqid(cstate, status); nfsd4_bump_seqid(cstate, status);
...@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (status) if (status)
goto out; goto out;
nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
nfsd4_close_open_stateid(stp); nfsd4_close_open_stateid(stp);
...@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo, ...@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
stp->st_access_bmap = 0; stp->st_access_bmap = 0;
stp->st_deny_bmap = open_stp->st_deny_bmap; stp->st_deny_bmap = open_stp->st_deny_bmap;
stp->st_openstp = open_stp; stp->st_openstp = open_stp;
init_rwsem(&stp->st_rwsem); mutex_init(&stp->st_mutex);
list_add(&stp->st_locks, &open_stp->st_locks); list_add(&stp->st_locks, &open_stp->st_locks);
list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
spin_lock(&fp->fi_lock); spin_lock(&fp->fi_lock);
...@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
&open_stp, nn); &open_stp, nn);
if (status) if (status)
goto out; goto out;
up_write(&open_stp->st_rwsem); mutex_unlock(&open_stp->st_mutex);
open_sop = openowner(open_stp->st_stateowner); open_sop = openowner(open_stp->st_stateowner);
status = nfserr_bad_stateid; status = nfserr_bad_stateid;
if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
...@@ -5600,7 +5607,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5600,7 +5607,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
status = lookup_or_create_lock_state(cstate, open_stp, lock, status = lookup_or_create_lock_state(cstate, open_stp, lock,
&lock_stp, &new); &lock_stp, &new);
if (status == nfs_ok) if (status == nfs_ok)
down_write(&lock_stp->st_rwsem); mutex_lock(&lock_stp->st_mutex);
} else { } else {
status = nfs4_preprocess_seqid_op(cstate, status = nfs4_preprocess_seqid_op(cstate,
lock->lk_old_lock_seqid, lock->lk_old_lock_seqid,
...@@ -5704,7 +5711,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5704,7 +5711,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
seqid_mutating_err(ntohl(status))) seqid_mutating_err(ntohl(status)))
lock_sop->lo_owner.so_seqid++; lock_sop->lo_owner.so_seqid++;
up_write(&lock_stp->st_rwsem); mutex_unlock(&lock_stp->st_mutex);
/* /*
* If this is a new, never-before-used stateid, and we are * If this is a new, never-before-used stateid, and we are
...@@ -5874,7 +5881,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, ...@@ -5874,7 +5881,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
fput: fput:
fput(filp); fput(filp);
put_stateid: put_stateid:
up_write(&stp->st_rwsem); mutex_unlock(&stp->st_mutex);
nfs4_put_stid(&stp->st_stid); nfs4_put_stid(&stp->st_stid);
out: out:
nfsd4_bump_seqid(cstate, status); nfsd4_bump_seqid(cstate, status);
......
...@@ -535,7 +535,7 @@ struct nfs4_ol_stateid { ...@@ -535,7 +535,7 @@ struct nfs4_ol_stateid {
unsigned char st_access_bmap; unsigned char st_access_bmap;
unsigned char st_deny_bmap; unsigned char st_deny_bmap;
struct nfs4_ol_stateid *st_openstp; struct nfs4_ol_stateid *st_openstp;
struct rw_semaphore st_rwsem; struct mutex st_mutex;
}; };
static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
......
...@@ -137,8 +137,6 @@ struct rpc_create_args { ...@@ -137,8 +137,6 @@ struct rpc_create_args {
#define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9) #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9)
struct rpc_clnt *rpc_create(struct rpc_create_args *args); struct rpc_clnt *rpc_create(struct rpc_create_args *args);
struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
struct rpc_xprt *xprt);
struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *,
const struct rpc_program *, u32); const struct rpc_program *, u32);
struct rpc_clnt *rpc_clone_client(struct rpc_clnt *); struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
......
...@@ -84,6 +84,7 @@ struct svc_xprt { ...@@ -84,6 +84,7 @@ struct svc_xprt {
struct net *xpt_net; struct net *xpt_net;
struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */ struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */
struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */
}; };
static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u) static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
......
...@@ -297,6 +297,7 @@ struct xprt_create { ...@@ -297,6 +297,7 @@ struct xprt_create {
size_t addrlen; size_t addrlen;
const char *servername; const char *servername;
struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */
struct rpc_xprt_switch *bc_xps;
unsigned int flags; unsigned int flags;
}; };
......
...@@ -446,16 +446,27 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args, ...@@ -446,16 +446,27 @@ static struct rpc_clnt * rpc_new_client(const struct rpc_create_args *args,
return ERR_PTR(err); return ERR_PTR(err);
} }
struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
struct rpc_xprt *xprt) struct rpc_xprt *xprt)
{ {
struct rpc_clnt *clnt = NULL; struct rpc_clnt *clnt = NULL;
struct rpc_xprt_switch *xps; struct rpc_xprt_switch *xps;
if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) {
WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
xps = args->bc_xprt->xpt_bc_xps;
xprt_switch_get(xps);
} else {
xps = xprt_switch_alloc(xprt, GFP_KERNEL); xps = xprt_switch_alloc(xprt, GFP_KERNEL);
if (xps == NULL) if (xps == NULL) {
xprt_put(xprt);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
}
if (xprt->bc_xprt) {
xprt_switch_get(xps);
xprt->bc_xprt->xpt_bc_xps = xps;
}
}
clnt = rpc_new_client(args, xps, xprt, NULL); clnt = rpc_new_client(args, xps, xprt, NULL);
if (IS_ERR(clnt)) if (IS_ERR(clnt))
return clnt; return clnt;
...@@ -483,7 +494,6 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, ...@@ -483,7 +494,6 @@ struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args,
return clnt; return clnt;
} }
EXPORT_SYMBOL_GPL(rpc_create_xprt);
/** /**
* rpc_create - create an RPC client and transport with one call * rpc_create - create an RPC client and transport with one call
...@@ -509,6 +519,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) ...@@ -509,6 +519,15 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args)
}; };
char servername[48]; char servername[48];
if (args->bc_xprt) {
WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP);
xprt = args->bc_xprt->xpt_bc_xprt;
if (xprt) {
xprt_get(xprt);
return rpc_create_xprt(args, xprt);
}
}
if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS) if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS)
xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS; xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT) if (args->flags & RPC_CLNT_CREATE_NO_IDLE_TIMEOUT)
......
...@@ -136,6 +136,8 @@ static void svc_xprt_free(struct kref *kref) ...@@ -136,6 +136,8 @@ static void svc_xprt_free(struct kref *kref)
/* See comment on corresponding get in xs_setup_bc_tcp(): */ /* See comment on corresponding get in xs_setup_bc_tcp(): */
if (xprt->xpt_bc_xprt) if (xprt->xpt_bc_xprt)
xprt_put(xprt->xpt_bc_xprt); xprt_put(xprt->xpt_bc_xprt);
if (xprt->xpt_bc_xps)
xprt_switch_put(xprt->xpt_bc_xps);
xprt->xpt_ops->xpo_free(xprt); xprt->xpt_ops->xpo_free(xprt);
module_put(owner); module_put(owner);
} }
......
...@@ -3057,6 +3057,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) ...@@ -3057,6 +3057,7 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args)
return xprt; return xprt;
args->bc_xprt->xpt_bc_xprt = NULL; args->bc_xprt->xpt_bc_xprt = NULL;
args->bc_xprt->xpt_bc_xps = NULL;
xprt_put(xprt); xprt_put(xprt);
ret = ERR_PTR(-EINVAL); ret = ERR_PTR(-EINVAL);
out_err: out_err:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment