9p: Make sure we are able to clunk the cached fid on umount
[safe/jmp/linux-2.6] / net / netfilter / nf_conntrack_extend.c
index ba1c491..fdc8fb4 100644 (file)
@@ -65,6 +65,12 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
        return (void *)(*ext) + off;
 }
 
+static void __nf_ct_ext_free_rcu(struct rcu_head *head)
+{
+       struct nf_ct_ext *ext = container_of(head, struct nf_ct_ext, rcu);
+       kfree(ext);
+}
+
 void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
 {
        struct nf_ct_ext *new;
@@ -88,7 +94,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
        newlen = newoff + t->len;
        rcu_read_unlock();
 
-       new = krealloc(ct->ext, newlen, gfp);
+       new = __krealloc(ct->ext, newlen, gfp);
        if (!new)
                return NULL;
 
@@ -104,14 +110,14 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
                                        (void *)ct->ext + ct->ext->offset[i]);
                        rcu_read_unlock();
                }
-               kfree(ct->ext);
+               call_rcu(&ct->ext->rcu, __nf_ct_ext_free_rcu);
                ct->ext = new;
        }
 
-       ct->ext->offset[id] = newoff;
-       ct->ext->len = newlen;
-       memset((void *)ct->ext + newoff, 0, newlen - newoff);
-       return (void *)ct->ext + newoff;
+       new->offset[id] = newoff;
+       new->len = newlen;
+       memset((void *)new + newoff, 0, newlen - newoff);
+       return (void *)new + newoff;
 }
 EXPORT_SYMBOL(__nf_ct_ext_add);
 
@@ -179,6 +185,6 @@ void nf_ct_extend_unregister(struct nf_ct_ext_type *type)
        rcu_assign_pointer(nf_ct_ext_types[type->id], NULL);
        update_alloc_size(type);
        mutex_unlock(&nf_ct_ext_type_mutex);
-       synchronize_rcu();
+       rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 EXPORT_SYMBOL_GPL(nf_ct_extend_unregister);