aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-06-16 23:25:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-06-16 23:25:52 -0400
commit41ef72181a9fde78f13d0966e3019fb37f6058e4 (patch)
treea2f6d64b8c9ffb4b2e59042891578eef91764113 /fs
parent9c514bedbe6948f31d29c53aceb9234c1484ae69 (diff)
parent8c7245abda877d4689b3371db8ae2a4400d7d9ce (diff)
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
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/blocklayout.c2
-rw-r--r--fs/nfsd/nfs4callback.c18
-rw-r--r--fs/nfsd/nfs4state.c67
-rw-r--r--fs/nfsd/state.h2
4 files changed, 40 insertions, 49 deletions
diff --git a/fs/nfsd/blocklayout.c b/fs/nfsd/blocklayout.c
index e55b5242614d..31f3df193bdb 100644
--- a/fs/nfsd/blocklayout.c
+++ b/fs/nfsd/blocklayout.c
@@ -290,7 +290,7 @@ out_free_buf:
290 return error; 290 return error;
291} 291}
292 292
293#define NFSD_MDS_PR_KEY 0x0100000000000000 293#define NFSD_MDS_PR_KEY 0x0100000000000000ULL
294 294
295/* 295/*
296 * We use the client ID as a unique key for the reservations. 296 * We use the client ID as a unique key for the reservations.
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 7389cb1d7409..04c68d900324 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -710,22 +710,6 @@ static struct rpc_cred *get_backchannel_cred(struct nfs4_client *clp, struct rpc
710 } 710 }
711} 711}
712 712
713static struct rpc_clnt *create_backchannel_client(struct rpc_create_args *args)
714{
715 struct rpc_xprt *xprt;
716
717 if (args->protocol != XPRT_TRANSPORT_BC_TCP)
718 return rpc_create(args);
719
720 xprt = args->bc_xprt->xpt_bc_xprt;
721 if (xprt) {
722 xprt_get(xprt);
723 return rpc_create_xprt(args, xprt);
724 }
725
726 return rpc_create(args);
727}
728
729static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) 713static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses)
730{ 714{
731 int maxtime = max_cb_time(clp->net); 715 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 args.authflavor = ses->se_cb_sec.flavor; 752 args.authflavor = ses->se_cb_sec.flavor;
769 } 753 }
770 /* Create RPC client */ 754 /* Create RPC client */
771 client = create_backchannel_client(&args); 755 client = rpc_create(&args);
772 if (IS_ERR(client)) { 756 if (IS_ERR(client)) {
773 dprintk("NFSD: couldn't create callback client: %ld\n", 757 dprintk("NFSD: couldn't create callback client: %ld\n",
774 PTR_ERR(client)); 758 PTR_ERR(client));
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f5f82e145018..70d0b9b33031 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3480,12 +3480,17 @@ alloc_init_open_stateowner(unsigned int strhashval, struct nfsd4_open *open,
3480} 3480}
3481 3481
3482static struct nfs4_ol_stateid * 3482static struct nfs4_ol_stateid *
3483init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, 3483init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open)
3484 struct nfsd4_open *open)
3485{ 3484{
3486 3485
3487 struct nfs4_openowner *oo = open->op_openowner; 3486 struct nfs4_openowner *oo = open->op_openowner;
3488 struct nfs4_ol_stateid *retstp = NULL; 3487 struct nfs4_ol_stateid *retstp = NULL;
3488 struct nfs4_ol_stateid *stp;
3489
3490 stp = open->op_stp;
3491 /* We are moving these outside of the spinlocks to avoid the warnings */
3492 mutex_init(&stp->st_mutex);
3493 mutex_lock(&stp->st_mutex);
3489 3494
3490 spin_lock(&oo->oo_owner.so_client->cl_lock); 3495 spin_lock(&oo->oo_owner.so_client->cl_lock);
3491 spin_lock(&fp->fi_lock); 3496 spin_lock(&fp->fi_lock);
@@ -3493,6 +3498,8 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
3493 retstp = nfsd4_find_existing_open(fp, open); 3498 retstp = nfsd4_find_existing_open(fp, open);
3494 if (retstp) 3499 if (retstp)
3495 goto out_unlock; 3500 goto out_unlock;
3501
3502 open->op_stp = NULL;
3496 atomic_inc(&stp->st_stid.sc_count); 3503 atomic_inc(&stp->st_stid.sc_count);
3497 stp->st_stid.sc_type = NFS4_OPEN_STID; 3504 stp->st_stid.sc_type = NFS4_OPEN_STID;
3498 INIT_LIST_HEAD(&stp->st_locks); 3505 INIT_LIST_HEAD(&stp->st_locks);
@@ -3502,14 +3509,19 @@ init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp,
3502 stp->st_access_bmap = 0; 3509 stp->st_access_bmap = 0;
3503 stp->st_deny_bmap = 0; 3510 stp->st_deny_bmap = 0;
3504 stp->st_openstp = NULL; 3511 stp->st_openstp = NULL;
3505 init_rwsem(&stp->st_rwsem);
3506 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); 3512 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids);
3507 list_add(&stp->st_perfile, &fp->fi_stateids); 3513 list_add(&stp->st_perfile, &fp->fi_stateids);
3508 3514
3509out_unlock: 3515out_unlock:
3510 spin_unlock(&fp->fi_lock); 3516 spin_unlock(&fp->fi_lock);
3511 spin_unlock(&oo->oo_owner.so_client->cl_lock); 3517 spin_unlock(&oo->oo_owner.so_client->cl_lock);
3512 return retstp; 3518 if (retstp) {
3519 mutex_lock(&retstp->st_mutex);
3520 /* To keep mutex tracking happy */
3521 mutex_unlock(&stp->st_mutex);
3522 stp = retstp;
3523 }
3524 return stp;
3513} 3525}
3514 3526
3515/* 3527/*
@@ -4305,7 +4317,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4305 struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; 4317 struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
4306 struct nfs4_file *fp = NULL; 4318 struct nfs4_file *fp = NULL;
4307 struct nfs4_ol_stateid *stp = NULL; 4319 struct nfs4_ol_stateid *stp = NULL;
4308 struct nfs4_ol_stateid *swapstp = NULL;
4309 struct nfs4_delegation *dp = NULL; 4320 struct nfs4_delegation *dp = NULL;
4310 __be32 status; 4321 __be32 status;
4311 4322
@@ -4335,32 +4346,28 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4335 */ 4346 */
4336 if (stp) { 4347 if (stp) {
4337 /* Stateid was found, this is an OPEN upgrade */ 4348 /* Stateid was found, this is an OPEN upgrade */
4338 down_read(&stp->st_rwsem); 4349 mutex_lock(&stp->st_mutex);
4339 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); 4350 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open);
4340 if (status) { 4351 if (status) {
4341 up_read(&stp->st_rwsem); 4352 mutex_unlock(&stp->st_mutex);
4342 goto out; 4353 goto out;
4343 } 4354 }
4344 } else { 4355 } else {
4345 stp = open->op_stp; 4356 /* stp is returned locked. */
4346 open->op_stp = NULL; 4357 stp = init_open_stateid(fp, open);
4347 swapstp = init_open_stateid(stp, fp, open); 4358 /* See if we lost the race to some other thread */
4348 if (swapstp) { 4359 if (stp->st_access_bmap != 0) {
4349 nfs4_put_stid(&stp->st_stid);
4350 stp = swapstp;
4351 down_read(&stp->st_rwsem);
4352 status = nfs4_upgrade_open(rqstp, fp, current_fh, 4360 status = nfs4_upgrade_open(rqstp, fp, current_fh,
4353 stp, open); 4361 stp, open);
4354 if (status) { 4362 if (status) {
4355 up_read(&stp->st_rwsem); 4363 mutex_unlock(&stp->st_mutex);
4356 goto out; 4364 goto out;
4357 } 4365 }
4358 goto upgrade_out; 4366 goto upgrade_out;
4359 } 4367 }
4360 down_read(&stp->st_rwsem);
4361 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); 4368 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open);
4362 if (status) { 4369 if (status) {
4363 up_read(&stp->st_rwsem); 4370 mutex_unlock(&stp->st_mutex);
4364 release_open_stateid(stp); 4371 release_open_stateid(stp);
4365 goto out; 4372 goto out;
4366 } 4373 }
@@ -4372,7 +4379,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
4372 } 4379 }
4373upgrade_out: 4380upgrade_out:
4374 nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); 4381 nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid);
4375 up_read(&stp->st_rwsem); 4382 mutex_unlock(&stp->st_mutex);
4376 4383
4377 if (nfsd4_has_session(&resp->cstate)) { 4384 if (nfsd4_has_session(&resp->cstate)) {
4378 if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { 4385 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 * revoked delegations are kept only for free_stateid. 4984 * revoked delegations are kept only for free_stateid.
4978 */ 4985 */
4979 return nfserr_bad_stateid; 4986 return nfserr_bad_stateid;
4980 down_write(&stp->st_rwsem); 4987 mutex_lock(&stp->st_mutex);
4981 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); 4988 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate));
4982 if (status == nfs_ok) 4989 if (status == nfs_ok)
4983 status = nfs4_check_fh(current_fh, &stp->st_stid); 4990 status = nfs4_check_fh(current_fh, &stp->st_stid);
4984 if (status != nfs_ok) 4991 if (status != nfs_ok)
4985 up_write(&stp->st_rwsem); 4992 mutex_unlock(&stp->st_mutex);
4986 return status; 4993 return status;
4987} 4994}
4988 4995
@@ -5030,7 +5037,7 @@ static __be32 nfs4_preprocess_confirmed_seqid_op(struct nfsd4_compound_state *cs
5030 return status; 5037 return status;
5031 oo = openowner(stp->st_stateowner); 5038 oo = openowner(stp->st_stateowner);
5032 if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { 5039 if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) {
5033 up_write(&stp->st_rwsem); 5040 mutex_unlock(&stp->st_mutex);
5034 nfs4_put_stid(&stp->st_stid); 5041 nfs4_put_stid(&stp->st_stid);
5035 return nfserr_bad_stateid; 5042 return nfserr_bad_stateid;
5036 } 5043 }
@@ -5062,12 +5069,12 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5062 oo = openowner(stp->st_stateowner); 5069 oo = openowner(stp->st_stateowner);
5063 status = nfserr_bad_stateid; 5070 status = nfserr_bad_stateid;
5064 if (oo->oo_flags & NFS4_OO_CONFIRMED) { 5071 if (oo->oo_flags & NFS4_OO_CONFIRMED) {
5065 up_write(&stp->st_rwsem); 5072 mutex_unlock(&stp->st_mutex);
5066 goto put_stateid; 5073 goto put_stateid;
5067 } 5074 }
5068 oo->oo_flags |= NFS4_OO_CONFIRMED; 5075 oo->oo_flags |= NFS4_OO_CONFIRMED;
5069 nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); 5076 nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid);
5070 up_write(&stp->st_rwsem); 5077 mutex_unlock(&stp->st_mutex);
5071 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", 5078 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n",
5072 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); 5079 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid));
5073 5080
@@ -5143,7 +5150,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
5143 nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid); 5150 nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid);
5144 status = nfs_ok; 5151 status = nfs_ok;
5145put_stateid: 5152put_stateid:
5146 up_write(&stp->st_rwsem); 5153 mutex_unlock(&stp->st_mutex);
5147 nfs4_put_stid(&stp->st_stid); 5154 nfs4_put_stid(&stp->st_stid);
5148out: 5155out:
5149 nfsd4_bump_seqid(cstate, status); 5156 nfsd4_bump_seqid(cstate, status);
@@ -5196,7 +5203,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5196 if (status) 5203 if (status)
5197 goto out; 5204 goto out;
5198 nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); 5205 nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid);
5199 up_write(&stp->st_rwsem); 5206 mutex_unlock(&stp->st_mutex);
5200 5207
5201 nfsd4_close_open_stateid(stp); 5208 nfsd4_close_open_stateid(stp);
5202 5209
@@ -5422,7 +5429,7 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
5422 stp->st_access_bmap = 0; 5429 stp->st_access_bmap = 0;
5423 stp->st_deny_bmap = open_stp->st_deny_bmap; 5430 stp->st_deny_bmap = open_stp->st_deny_bmap;
5424 stp->st_openstp = open_stp; 5431 stp->st_openstp = open_stp;
5425 init_rwsem(&stp->st_rwsem); 5432 mutex_init(&stp->st_mutex);
5426 list_add(&stp->st_locks, &open_stp->st_locks); 5433 list_add(&stp->st_locks, &open_stp->st_locks);
5427 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 5434 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids);
5428 spin_lock(&fp->fi_lock); 5435 spin_lock(&fp->fi_lock);
@@ -5591,7 +5598,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5591 &open_stp, nn); 5598 &open_stp, nn);
5592 if (status) 5599 if (status)
5593 goto out; 5600 goto out;
5594 up_write(&open_stp->st_rwsem); 5601 mutex_unlock(&open_stp->st_mutex);
5595 open_sop = openowner(open_stp->st_stateowner); 5602 open_sop = openowner(open_stp->st_stateowner);
5596 status = nfserr_bad_stateid; 5603 status = nfserr_bad_stateid;
5597 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, 5604 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 status = lookup_or_create_lock_state(cstate, open_stp, lock, 5607 status = lookup_or_create_lock_state(cstate, open_stp, lock,
5601 &lock_stp, &new); 5608 &lock_stp, &new);
5602 if (status == nfs_ok) 5609 if (status == nfs_ok)
5603 down_write(&lock_stp->st_rwsem); 5610 mutex_lock(&lock_stp->st_mutex);
5604 } else { 5611 } else {
5605 status = nfs4_preprocess_seqid_op(cstate, 5612 status = nfs4_preprocess_seqid_op(cstate,
5606 lock->lk_old_lock_seqid, 5613 lock->lk_old_lock_seqid,
@@ -5704,7 +5711,7 @@ out:
5704 seqid_mutating_err(ntohl(status))) 5711 seqid_mutating_err(ntohl(status)))
5705 lock_sop->lo_owner.so_seqid++; 5712 lock_sop->lo_owner.so_seqid++;
5706 5713
5707 up_write(&lock_stp->st_rwsem); 5714 mutex_unlock(&lock_stp->st_mutex);
5708 5715
5709 /* 5716 /*
5710 * If this is a new, never-before-used stateid, and we are 5717 * 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,
5874fput: 5881fput:
5875 fput(filp); 5882 fput(filp);
5876put_stateid: 5883put_stateid:
5877 up_write(&stp->st_rwsem); 5884 mutex_unlock(&stp->st_mutex);
5878 nfs4_put_stid(&stp->st_stid); 5885 nfs4_put_stid(&stp->st_stid);
5879out: 5886out:
5880 nfsd4_bump_seqid(cstate, status); 5887 nfsd4_bump_seqid(cstate, status);
diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h
index 986e51e5ceac..64053eadeb81 100644
--- a/fs/nfsd/state.h
+++ b/fs/nfsd/state.h
@@ -535,7 +535,7 @@ struct nfs4_ol_stateid {
535 unsigned char st_access_bmap; 535 unsigned char st_access_bmap;
536 unsigned char st_deny_bmap; 536 unsigned char st_deny_bmap;
537 struct nfs4_ol_stateid *st_openstp; 537 struct nfs4_ol_stateid *st_openstp;
538 struct rw_semaphore st_rwsem; 538 struct mutex st_mutex;
539}; 539};
540 540
541static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s) 541static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)