| From b93d87c19821ba7d3ee11557403d782e541071ad Mon Sep 17 00:00:00 2001 |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| Date: Mon, 7 Nov 2011 16:37:57 -0500 |
| Subject: nfsd4: fix lockowner matching |
| |
| From: "J. Bruce Fields" <bfields@redhat.com> |
| |
| commit b93d87c19821ba7d3ee11557403d782e541071ad upstream. |
| |
| Lockowners are looked up by file as well as by owner, but we were |
| forgetting to do a comparison on the file. This could cause an |
| incorrect result from lockt. |
| |
| (Note looking up the inode from the lockowner is pretty awkward here. |
| The data structures need fixing.) |
| |
| Signed-off-by: J. Bruce Fields <bfields@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/nfsd/nfs4state.c | 17 +++++++++++++++-- |
| 1 file changed, 15 insertions(+), 2 deletions(-) |
| |
| --- a/fs/nfsd/nfs4state.c |
| +++ b/fs/nfsd/nfs4state.c |
| @@ -3809,16 +3809,29 @@ nevermind: |
| deny->ld_type = NFS4_WRITE_LT; |
| } |
| |
| +static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, clientid_t *clid, struct xdr_netobj *owner) |
| +{ |
| + struct nfs4_ol_stateid *lst; |
| + |
| + if (!same_owner_str(&lo->lo_owner, owner, clid)) |
| + return false; |
| + lst = list_first_entry(&lo->lo_owner.so_stateids, |
| + struct nfs4_ol_stateid, st_perstateowner); |
| + return lst->st_file->fi_inode == inode; |
| +} |
| + |
| static struct nfs4_lockowner * |
| find_lockowner_str(struct inode *inode, clientid_t *clid, |
| struct xdr_netobj *owner) |
| { |
| unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner); |
| + struct nfs4_lockowner *lo; |
| struct nfs4_stateowner *op; |
| |
| list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { |
| - if (same_owner_str(op, owner, clid)) |
| - return lockowner(op); |
| + lo = lockowner(op); |
| + if (same_lockowner_ino(lo, inode, clid, owner)) |
| + return lo; |
| } |
| return NULL; |
| } |