diff options
author | NeilBrown <neilb@suse.de> | 2006-05-23 01:35:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-05-23 13:35:31 -0400 |
commit | f2d395865faa2a7cd4620b07178e58cbb160ba08 (patch) | |
tree | 01d3b090a4ce73eb346a2c55d99fe12d07d52906 | |
parent | e46e490368f87032a6e54969194413339b35a385 (diff) |
[PATCH] knfsd: Fix two problems that can cause rmmod nfsd to die
Both cause the 'entries' count in the export cache to be non-zero at module
removal time, so unregistering that cache fails and results in an oops.
1/ exp_pseudoroot (used for NFSv4 only) leaks a reference to an export
entry.
2/ sunrpc_cache_update doesn't increment the entries count when it adds
an entry.
Thanks to "david m. richter" <richterd@citi.umich.edu> for triggering the
problem and finding one of the bugs.
Cc: "david m. richter" <richterd@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/nfsd/export.c | 4 | ||||
-rw-r--r-- | net/sunrpc/cache.c | 1 |
2 files changed, 4 insertions, 1 deletions
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 4e0578121d9a..3eec30000f3f 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c | |||
@@ -1066,9 +1066,11 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, | |||
1066 | rv = nfserr_perm; | 1066 | rv = nfserr_perm; |
1067 | else if (IS_ERR(exp)) | 1067 | else if (IS_ERR(exp)) |
1068 | rv = nfserrno(PTR_ERR(exp)); | 1068 | rv = nfserrno(PTR_ERR(exp)); |
1069 | else | 1069 | else { |
1070 | rv = fh_compose(fhp, exp, | 1070 | rv = fh_compose(fhp, exp, |
1071 | fsid_key->ek_dentry, NULL); | 1071 | fsid_key->ek_dentry, NULL); |
1072 | exp_put(exp); | ||
1073 | } | ||
1072 | cache_put(&fsid_key->h, &svc_expkey_cache); | 1074 | cache_put(&fsid_key->h, &svc_expkey_cache); |
1073 | return rv; | 1075 | return rv; |
1074 | } | 1076 | } |
diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 3ac4193a78ed..7026b0866b7b 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c | |||
@@ -159,6 +159,7 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, | |||
159 | detail->update(tmp, new); | 159 | detail->update(tmp, new); |
160 | tmp->next = *head; | 160 | tmp->next = *head; |
161 | *head = tmp; | 161 | *head = tmp; |
162 | detail->entries++; | ||
162 | cache_get(tmp); | 163 | cache_get(tmp); |
163 | is_new = cache_fresh_locked(tmp, new->expiry_time); | 164 | is_new = cache_fresh_locked(tmp, new->expiry_time); |
164 | cache_fresh_locked(old, 0); | 165 | cache_fresh_locked(old, 0); |