aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/dns_resolve.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-03-02 13:06:22 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-03-02 13:06:22 -0500
commitebed9203b68a4f333ce5d17e874b26c3afcfeff1 (patch)
treeec0c24396061eb662594a3b879acc760e41532b7 /fs/nfs/dns_resolve.c
parent9fcfe0c83c3b04a759cde6b8c5f961237f17808b (diff)
NFS: Fix an allocation-under-spinlock bug
sunrpc_cache_update() will always call detail->update() from inside the detail->hash_lock, so it cannot allocate memory. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: stable@kernel.org
Diffstat (limited to 'fs/nfs/dns_resolve.c')
-rw-r--r--fs/nfs/dns_resolve.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c
index 95e1ca765d47..3f0cd4dfddaf 100644
--- a/fs/nfs/dns_resolve.c
+++ b/fs/nfs/dns_resolve.c
@@ -36,6 +36,19 @@ struct nfs_dns_ent {
36}; 36};
37 37
38 38
39static void nfs_dns_ent_update(struct cache_head *cnew,
40 struct cache_head *ckey)
41{
42 struct nfs_dns_ent *new;
43 struct nfs_dns_ent *key;
44
45 new = container_of(cnew, struct nfs_dns_ent, h);
46 key = container_of(ckey, struct nfs_dns_ent, h);
47
48 memcpy(&new->addr, &key->addr, key->addrlen);
49 new->addrlen = key->addrlen;
50}
51
39static void nfs_dns_ent_init(struct cache_head *cnew, 52static void nfs_dns_ent_init(struct cache_head *cnew,
40 struct cache_head *ckey) 53 struct cache_head *ckey)
41{ 54{
@@ -49,8 +62,7 @@ static void nfs_dns_ent_init(struct cache_head *cnew,
49 new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL); 62 new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL);
50 if (new->hostname) { 63 if (new->hostname) {
51 new->namelen = key->namelen; 64 new->namelen = key->namelen;
52 memcpy(&new->addr, &key->addr, key->addrlen); 65 nfs_dns_ent_update(cnew, ckey);
53 new->addrlen = key->addrlen;
54 } else { 66 } else {
55 new->namelen = 0; 67 new->namelen = 0;
56 new->addrlen = 0; 68 new->addrlen = 0;
@@ -234,7 +246,7 @@ static struct cache_detail nfs_dns_resolve = {
234 .cache_show = nfs_dns_show, 246 .cache_show = nfs_dns_show,
235 .match = nfs_dns_match, 247 .match = nfs_dns_match,
236 .init = nfs_dns_ent_init, 248 .init = nfs_dns_ent_init,
237 .update = nfs_dns_ent_init, 249 .update = nfs_dns_ent_update,
238 .alloc = nfs_dns_ent_alloc, 250 .alloc = nfs_dns_ent_alloc,
239}; 251};
240 252