Re: [PATCH 004 of 19] knfsd: lockd: introduce nsm_handle

Neil Brown
2006-09-01T23:50:11Z

On Thursday August 31, akpm@osdl.org wrote:
> On Fri, 1 Sep 2006 14:38:25 +1000
> NeilBrown <neilb@suse.de> wrote:
>
> > +nsm_release(struct nsm_handle *nsm)
> > +{
> > + if (!nsm)
> > + return;
> > + if (atomic_read(&nsm->sm_count) == 1) {
> > + down(&nsm_sema);
> > + if (atomic_dec_and_test(&nsm->sm_count)) {
> > + list_del(&nsm->sm_link);
> > + kfree(nsm);
> > + }
> > + up(&nsm_sema);
> > + }
> > +}
>
> That's weird-looking. Are you sure? afaict, if ->sm_count ever gets a
> value of 2 or more, it's unfreeable.

How do you *do* that? I thought I had already found the bugs...

Thanks :-)
NeilBrown

---
Subject: Fix locking in nsm_release

The locking is all backwards and broken.

We first atomic_dec_and_test.
If this fails, someone else has an active reference and we need do
no more.
If it succeeds, then the only ref is in the hash table, but someone
might be about to find and use that reference. nsm_mutex provides
exclusion against this. If sm_count is still 0 once the
mutex has been gained, then it is safe to discard the nsm.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
./fs/lockd/host.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff .prev/fs/lockd/host.c ./fs/lockd/host.c
--- .prev/fs/lockd/host.c 2006-09-01 18:56:39.000000000 +1000
+++ ./fs/lockd/host.c 2006-09-02 09:44:04.000000000 +1000
@@ -507,9 +507,9 @@ nsm_release(struct nsm_handle *nsm)
{
if (!nsm)
return;
- if (atomic_read(&nsm->sm_count) == 1) {
+ if (atomic_dec_and_test(&nsm->sm_count)) {
mutex_lock(&nsm_mutex);
- if (atomic_dec_and_test(&nsm->sm_count)) {
+ if (atomic_read(&nsm->sm_count) == 0) {
list_del(&nsm->sm_link);
kfree(nsm);
}

--
VGER BF report: H 0