| From a1b8ff4c97b4375d21b6d6c45d75877303f61b3b Mon Sep 17 00:00:00 2001 |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| Date: Tue, 20 May 2014 15:55:21 -0400 |
| Subject: nfsd4: remove lockowner when removing lock stateid |
| |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| |
| commit a1b8ff4c97b4375d21b6d6c45d75877303f61b3b upstream. |
| |
| The nfsv4 state code has always assumed a one-to-one correspondance |
| between lock stateid's and lockowners even if it appears not to in some |
| places. |
| |
| We may actually change that, but for now when FREE_STATEID releases a |
| lock stateid it also needs to release the parent lockowner. |
| |
| Symptoms were a subsequent LOCK crashing in find_lockowner_str when it |
| calls same_lockowner_ino on a lockowner that unexpectedly has an empty |
| so_stateids list. |
| |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| fs/nfsd/nfs4state.c | 11 +++++++++-- |
| 1 file changed, 9 insertions(+), 2 deletions(-) |
| |
| --- a/fs/nfsd/nfs4state.c |
| +++ b/fs/nfsd/nfs4state.c |
| @@ -3599,9 +3599,16 @@ out: |
| static __be32 |
| nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp) |
| { |
| - if (check_for_locks(stp->st_file, lockowner(stp->st_stateowner))) |
| + struct nfs4_lockowner *lo = lockowner(stp->st_stateowner); |
| + |
| + if (check_for_locks(stp->st_file, lo)) |
| return nfserr_locks_held; |
| - release_lock_stateid(stp); |
| + /* |
| + * Currently there's a 1-1 lock stateid<->lockowner |
| + * correspondance, and we have to delete the lockowner when we |
| + * delete the lock stateid: |
| + */ |
| + unhash_lockowner(lo); |
| return nfs_ok; |
| } |
| |