diff options
author | J. Bruce Fields <bfields@redhat.com> | 2013-06-17 17:29:40 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2013-07-01 17:32:06 -0400 |
commit | 0a262ffb75275e48caa17e80b96504354e94f6c2 (patch) | |
tree | 5f75b398e0ea586e6d1664cf817072d566fe100b /fs | |
parent | 89f6c3362cb5a6bce96dbe6aa15b4749c2262b21 (diff) |
nfsd4: do not throw away 4.1 lock state on last unlock
This reverts commit eb2099f31b0f090684a64ef8df44a30ff7c45fc2 "nfsd4:
release lockowners on last unlock in 4.1 case". Trond identified
language in rfc 5661 section 8.2.4 which forbids this behavior:
Stateids associated with byte-range locks are an exception.
They remain valid even if a LOCKU frees all remaining locks, so
long as the open file with which they are associated remains
open, unless the client frees the stateids via the FREE_STATEID
operation.
And bakeathon 2013 testing found a 4.1 freebsd client was getting an
incorrect BAD_STATEID return from a FREE_STATEID in the above situation
and then failing.
The spec language honestly was probably a mistake but at this point with
implementations already following it we're probably stuck with that.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/nfs4state.c | 9 |
1 files changed, 1 insertions, 8 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fcc0610fe308..a7d8a11943ee 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -4514,7 +4514,6 @@ __be32 | |||
4514 | nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 4514 | nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, |
4515 | struct nfsd4_locku *locku) | 4515 | struct nfsd4_locku *locku) |
4516 | { | 4516 | { |
4517 | struct nfs4_lockowner *lo; | ||
4518 | struct nfs4_ol_stateid *stp; | 4517 | struct nfs4_ol_stateid *stp; |
4519 | struct file *filp = NULL; | 4518 | struct file *filp = NULL; |
4520 | struct file_lock *file_lock = NULL; | 4519 | struct file_lock *file_lock = NULL; |
@@ -4547,10 +4546,9 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
4547 | status = nfserr_jukebox; | 4546 | status = nfserr_jukebox; |
4548 | goto out; | 4547 | goto out; |
4549 | } | 4548 | } |
4550 | lo = lockowner(stp->st_stateowner); | ||
4551 | locks_init_lock(file_lock); | 4549 | locks_init_lock(file_lock); |
4552 | file_lock->fl_type = F_UNLCK; | 4550 | file_lock->fl_type = F_UNLCK; |
4553 | file_lock->fl_owner = (fl_owner_t)lo; | 4551 | file_lock->fl_owner = (fl_owner_t)lockowner(stp->st_stateowner); |
4554 | file_lock->fl_pid = current->tgid; | 4552 | file_lock->fl_pid = current->tgid; |
4555 | file_lock->fl_file = filp; | 4553 | file_lock->fl_file = filp; |
4556 | file_lock->fl_flags = FL_POSIX; | 4554 | file_lock->fl_flags = FL_POSIX; |
@@ -4569,11 +4567,6 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
4569 | update_stateid(&stp->st_stid.sc_stateid); | 4567 | update_stateid(&stp->st_stid.sc_stateid); |
4570 | memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); | 4568 | memcpy(&locku->lu_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t)); |
4571 | 4569 | ||
4572 | if (nfsd4_has_session(cstate) && !check_for_locks(stp->st_file, lo)) { | ||
4573 | WARN_ON_ONCE(cstate->replay_owner); | ||
4574 | release_lockowner(lo); | ||
4575 | } | ||
4576 | |||
4577 | out: | 4570 | out: |
4578 | nfsd4_bump_seqid(cstate, status); | 4571 | nfsd4_bump_seqid(cstate, status); |
4579 | if (!cstate->replay_owner) | 4572 | if (!cstate->replay_owner) |