Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+70 -57
+1 -1
fs/nfsd/blocklayout.c
··· 290 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 296 * We use the client ID as a unique key for the reservations.
+1 -17
fs/nfsd/nfs4callback.c
··· 710 710 } 711 711 } 712 712 713 - static 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 - 729 713 static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *conn, struct nfsd4_session *ses) 730 714 { 731 715 int maxtime = max_cb_time(clp->net); ··· 752 768 args.authflavor = ses->se_cb_sec.flavor; 753 769 } 754 770 /* Create RPC client */ 755 - client = create_backchannel_client(&args); 771 + client = rpc_create(&args); 756 772 if (IS_ERR(client)) { 757 773 dprintk("NFSD: couldn't create callback client: %ld\n", 758 774 PTR_ERR(client));
+37 -30
fs/nfsd/nfs4state.c
··· 3480 3480 } 3481 3481 3482 3482 static struct nfs4_ol_stateid * 3483 - init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, 3484 - struct nfsd4_open *open) 3483 + init_open_stateid(struct nfs4_file *fp, struct nfsd4_open *open) 3485 3484 { 3486 3485 3487 3486 struct nfs4_openowner *oo = open->op_openowner; 3488 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 3495 spin_lock(&oo->oo_owner.so_client->cl_lock); 3491 3496 spin_lock(&fp->fi_lock); ··· 3498 3493 retstp = nfsd4_find_existing_open(fp, open); 3499 3494 if (retstp) 3500 3495 goto out_unlock; 3496 + 3497 + open->op_stp = NULL; 3501 3498 atomic_inc(&stp->st_stid.sc_count); 3502 3499 stp->st_stid.sc_type = NFS4_OPEN_STID; 3503 3500 INIT_LIST_HEAD(&stp->st_locks); ··· 3509 3502 stp->st_access_bmap = 0; 3510 3503 stp->st_deny_bmap = 0; 3511 3504 stp->st_openstp = NULL; 3512 - init_rwsem(&stp->st_rwsem); 3513 3505 list_add(&stp->st_perstateowner, &oo->oo_owner.so_stateids); 3514 3506 list_add(&stp->st_perfile, &fp->fi_stateids); 3515 3507 3516 3508 out_unlock: 3517 3509 spin_unlock(&fp->fi_lock); 3518 3510 spin_unlock(&oo->oo_owner.so_client->cl_lock); 3519 - return retstp; 3511 + if (retstp) { 3512 + mutex_lock(&retstp->st_mutex); 3513 + /* To keep mutex tracking happy */ 3514 + mutex_unlock(&stp->st_mutex); 3515 + stp = retstp; 3516 + } 3517 + return stp; 3520 3518 } 3521 3519 3522 3520 /* ··· 4317 4305 struct nfs4_client *cl = open->op_openowner->oo_owner.so_client; 4318 4306 struct nfs4_file *fp = NULL; 4319 4307 struct nfs4_ol_stateid *stp = NULL; 4320 - struct nfs4_ol_stateid *swapstp = NULL; 4321 4308 struct nfs4_delegation *dp = NULL; 4322 4309 __be32 status; 4323 4310 ··· 4346 4335 */ 4347 4336 if (stp) { 4348 4337 /* Stateid was found, this is an OPEN upgrade */ 4349 - down_read(&stp->st_rwsem); 4338 + mutex_lock(&stp->st_mutex); 4350 4339 status = nfs4_upgrade_open(rqstp, fp, current_fh, stp, open); 4351 4340 if (status) { 4352 - up_read(&stp->st_rwsem); 4341 + mutex_unlock(&stp->st_mutex); 4353 4342 goto out; 4354 4343 } 4355 4344 } else { 4356 - stp = open->op_stp; 4357 - open->op_stp = NULL; 4358 - swapstp = init_open_stateid(stp, fp, open); 4359 - if (swapstp) { 4360 - nfs4_put_stid(&stp->st_stid); 4361 - stp = swapstp; 4362 - down_read(&stp->st_rwsem); 4345 + /* stp is returned locked. */ 4346 + stp = init_open_stateid(fp, open); 4347 + /* See if we lost the race to some other thread */ 4348 + if (stp->st_access_bmap != 0) { 4363 4349 status = nfs4_upgrade_open(rqstp, fp, current_fh, 4364 4350 stp, open); 4365 4351 if (status) { 4366 - up_read(&stp->st_rwsem); 4352 + mutex_unlock(&stp->st_mutex); 4367 4353 goto out; 4368 4354 } 4369 4355 goto upgrade_out; 4370 4356 } 4371 - down_read(&stp->st_rwsem); 4372 4357 status = nfs4_get_vfs_file(rqstp, fp, current_fh, stp, open); 4373 4358 if (status) { 4374 - up_read(&stp->st_rwsem); 4359 + mutex_unlock(&stp->st_mutex); 4375 4360 release_open_stateid(stp); 4376 4361 goto out; 4377 4362 } ··· 4379 4372 } 4380 4373 upgrade_out: 4381 4374 nfs4_inc_and_copy_stateid(&open->op_stateid, &stp->st_stid); 4382 - up_read(&stp->st_rwsem); 4375 + mutex_unlock(&stp->st_mutex); 4383 4376 4384 4377 if (nfsd4_has_session(&resp->cstate)) { 4385 4378 if (open->op_deleg_want & NFS4_SHARE_WANT_NO_DELEG) { ··· 4984 4977 * revoked delegations are kept only for free_stateid. 4985 4978 */ 4986 4979 return nfserr_bad_stateid; 4987 - down_write(&stp->st_rwsem); 4980 + mutex_lock(&stp->st_mutex); 4988 4981 status = check_stateid_generation(stateid, &stp->st_stid.sc_stateid, nfsd4_has_session(cstate)); 4989 4982 if (status == nfs_ok) 4990 4983 status = nfs4_check_fh(current_fh, &stp->st_stid); 4991 4984 if (status != nfs_ok) 4992 - up_write(&stp->st_rwsem); 4985 + mutex_unlock(&stp->st_mutex); 4993 4986 return status; 4994 4987 } 4995 4988 ··· 5037 5030 return status; 5038 5031 oo = openowner(stp->st_stateowner); 5039 5032 if (!(oo->oo_flags & NFS4_OO_CONFIRMED)) { 5040 - up_write(&stp->st_rwsem); 5033 + mutex_unlock(&stp->st_mutex); 5041 5034 nfs4_put_stid(&stp->st_stid); 5042 5035 return nfserr_bad_stateid; 5043 5036 } ··· 5069 5062 oo = openowner(stp->st_stateowner); 5070 5063 status = nfserr_bad_stateid; 5071 5064 if (oo->oo_flags & NFS4_OO_CONFIRMED) { 5072 - up_write(&stp->st_rwsem); 5065 + mutex_unlock(&stp->st_mutex); 5073 5066 goto put_stateid; 5074 5067 } 5075 5068 oo->oo_flags |= NFS4_OO_CONFIRMED; 5076 5069 nfs4_inc_and_copy_stateid(&oc->oc_resp_stateid, &stp->st_stid); 5077 - up_write(&stp->st_rwsem); 5070 + mutex_unlock(&stp->st_mutex); 5078 5071 dprintk("NFSD: %s: success, seqid=%d stateid=" STATEID_FMT "\n", 5079 5072 __func__, oc->oc_seqid, STATEID_VAL(&stp->st_stid.sc_stateid)); 5080 5073 ··· 5150 5143 nfs4_inc_and_copy_stateid(&od->od_stateid, &stp->st_stid); 5151 5144 status = nfs_ok; 5152 5145 put_stateid: 5153 - up_write(&stp->st_rwsem); 5146 + mutex_unlock(&stp->st_mutex); 5154 5147 nfs4_put_stid(&stp->st_stid); 5155 5148 out: 5156 5149 nfsd4_bump_seqid(cstate, status); ··· 5203 5196 if (status) 5204 5197 goto out; 5205 5198 nfs4_inc_and_copy_stateid(&close->cl_stateid, &stp->st_stid); 5206 - up_write(&stp->st_rwsem); 5199 + mutex_unlock(&stp->st_mutex); 5207 5200 5208 5201 nfsd4_close_open_stateid(stp); 5209 5202 ··· 5429 5422 stp->st_access_bmap = 0; 5430 5423 stp->st_deny_bmap = open_stp->st_deny_bmap; 5431 5424 stp->st_openstp = open_stp; 5432 - init_rwsem(&stp->st_rwsem); 5425 + mutex_init(&stp->st_mutex); 5433 5426 list_add(&stp->st_locks, &open_stp->st_locks); 5434 5427 list_add(&stp->st_perstateowner, &lo->lo_owner.so_stateids); 5435 5428 spin_lock(&fp->fi_lock); ··· 5598 5591 &open_stp, nn); 5599 5592 if (status) 5600 5593 goto out; 5601 - up_write(&open_stp->st_rwsem); 5594 + mutex_unlock(&open_stp->st_mutex); 5602 5595 open_sop = openowner(open_stp->st_stateowner); 5603 5596 status = nfserr_bad_stateid; 5604 5597 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, ··· 5607 5600 status = lookup_or_create_lock_state(cstate, open_stp, lock, 5608 5601 &lock_stp, &new); 5609 5602 if (status == nfs_ok) 5610 - down_write(&lock_stp->st_rwsem); 5603 + mutex_lock(&lock_stp->st_mutex); 5611 5604 } else { 5612 5605 status = nfs4_preprocess_seqid_op(cstate, 5613 5606 lock->lk_old_lock_seqid, ··· 5711 5704 seqid_mutating_err(ntohl(status))) 5712 5705 lock_sop->lo_owner.so_seqid++; 5713 5706 5714 - up_write(&lock_stp->st_rwsem); 5707 + mutex_unlock(&lock_stp->st_mutex); 5715 5708 5716 5709 /* 5717 5710 * If this is a new, never-before-used stateid, and we are ··· 5881 5874 fput: 5882 5875 fput(filp); 5883 5876 put_stateid: 5884 - up_write(&stp->st_rwsem); 5877 + mutex_unlock(&stp->st_mutex); 5885 5878 nfs4_put_stid(&stp->st_stid); 5886 5879 out: 5887 5880 nfsd4_bump_seqid(cstate, status);
+1 -1
fs/nfsd/state.h
··· 535 535 unsigned char st_access_bmap; 536 536 unsigned char st_deny_bmap; 537 537 struct nfs4_ol_stateid *st_openstp; 538 - struct rw_semaphore st_rwsem; 538 + struct mutex st_mutex; 539 539 }; 540 540 541 541 static inline struct nfs4_ol_stateid *openlockstateid(struct nfs4_stid *s)
-2
include/linux/sunrpc/clnt.h
··· 137 137 #define RPC_CLNT_CREATE_NO_RETRANS_TIMEOUT (1UL << 9) 138 138 139 139 struct rpc_clnt *rpc_create(struct rpc_create_args *args); 140 - struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, 141 - struct rpc_xprt *xprt); 142 140 struct rpc_clnt *rpc_bind_new_program(struct rpc_clnt *, 143 141 const struct rpc_program *, u32); 144 142 struct rpc_clnt *rpc_clone_client(struct rpc_clnt *);
+1
include/linux/sunrpc/svc_xprt.h
··· 84 84 85 85 struct net *xpt_net; 86 86 struct rpc_xprt *xpt_bc_xprt; /* NFSv4.1 backchannel */ 87 + struct rpc_xprt_switch *xpt_bc_xps; /* NFSv4.1 backchannel */ 87 88 }; 88 89 89 90 static inline void unregister_xpt_user(struct svc_xprt *xpt, struct svc_xpt_user *u)
+1
include/linux/sunrpc/xprt.h
··· 297 297 size_t addrlen; 298 298 const char *servername; 299 299 struct svc_xprt *bc_xprt; /* NFSv4.1 backchannel */ 300 + struct rpc_xprt_switch *bc_xps; 300 301 unsigned int flags; 301 302 }; 302 303
+25 -6
net/sunrpc/clnt.c
··· 446 446 return ERR_PTR(err); 447 447 } 448 448 449 - struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, 449 + static struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, 450 450 struct rpc_xprt *xprt) 451 451 { 452 452 struct rpc_clnt *clnt = NULL; 453 453 struct rpc_xprt_switch *xps; 454 454 455 - xps = xprt_switch_alloc(xprt, GFP_KERNEL); 456 - if (xps == NULL) 457 - return ERR_PTR(-ENOMEM); 458 - 455 + if (args->bc_xprt && args->bc_xprt->xpt_bc_xps) { 456 + WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP); 457 + xps = args->bc_xprt->xpt_bc_xps; 458 + xprt_switch_get(xps); 459 + } else { 460 + xps = xprt_switch_alloc(xprt, GFP_KERNEL); 461 + if (xps == NULL) { 462 + xprt_put(xprt); 463 + return ERR_PTR(-ENOMEM); 464 + } 465 + if (xprt->bc_xprt) { 466 + xprt_switch_get(xps); 467 + xprt->bc_xprt->xpt_bc_xps = xps; 468 + } 469 + } 459 470 clnt = rpc_new_client(args, xps, xprt, NULL); 460 471 if (IS_ERR(clnt)) 461 472 return clnt; ··· 494 483 495 484 return clnt; 496 485 } 497 - EXPORT_SYMBOL_GPL(rpc_create_xprt); 498 486 499 487 /** 500 488 * rpc_create - create an RPC client and transport with one call ··· 518 508 .bc_xprt = args->bc_xprt, 519 509 }; 520 510 char servername[48]; 511 + 512 + if (args->bc_xprt) { 513 + WARN_ON(args->protocol != XPRT_TRANSPORT_BC_TCP); 514 + xprt = args->bc_xprt->xpt_bc_xprt; 515 + if (xprt) { 516 + xprt_get(xprt); 517 + return rpc_create_xprt(args, xprt); 518 + } 519 + } 521 520 522 521 if (args->flags & RPC_CLNT_CREATE_INFINITE_SLOTS) 523 522 xprtargs.flags |= XPRT_CREATE_INFINITE_SLOTS;
+2
net/sunrpc/svc_xprt.c
··· 136 136 /* See comment on corresponding get in xs_setup_bc_tcp(): */ 137 137 if (xprt->xpt_bc_xprt) 138 138 xprt_put(xprt->xpt_bc_xprt); 139 + if (xprt->xpt_bc_xps) 140 + xprt_switch_put(xprt->xpt_bc_xps); 139 141 xprt->xpt_ops->xpo_free(xprt); 140 142 module_put(owner); 141 143 }
+1
net/sunrpc/xprtsock.c
··· 3057 3057 return xprt; 3058 3058 3059 3059 args->bc_xprt->xpt_bc_xprt = NULL; 3060 + args->bc_xprt->xpt_bc_xps = NULL; 3060 3061 xprt_put(xprt); 3061 3062 ret = ERR_PTR(-EINVAL); 3062 3063 out_err: