diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 67 |
1 files changed, 37 insertions, 30 deletions
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 | ||
3482 | static struct nfs4_ol_stateid * | 3482 | static struct nfs4_ol_stateid * |
3483 | init_open_stateid(struct nfs4_ol_stateid *stp, struct nfs4_file *fp, | 3483 | init_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 | ||
3509 | out_unlock: | 3515 | out_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 | } |
4373 | upgrade_out: | 4380 | upgrade_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; |
5145 | put_stateid: | 5152 | put_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); |
5148 | out: | 5155 | out: |
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, | |||
5874 | fput: | 5881 | fput: |
5875 | fput(filp); | 5882 | fput(filp); |
5876 | put_stateid: | 5883 | put_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); |
5879 | out: | 5886 | out: |
5880 | nfsd4_bump_seqid(cstate, status); | 5887 | nfsd4_bump_seqid(cstate, status); |