VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / net / xfrm / xfrm_state.c
index 44cb524..f45fa55 100644 (file)
@@ -65,7 +65,6 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
                xfrm_put_type(x->type);
        }
        kfree(x);
-       wake_up(&km_waitq);
 }
 
 static void xfrm_state_gc_task(void *data)
@@ -82,6 +81,7 @@ static void xfrm_state_gc_task(void *data)
                x = list_entry(entry, struct xfrm_state, bydst);
                xfrm_state_gc_destroy(x);
        }
+       wake_up(&km_waitq);
 }
 
 static inline unsigned long make_jiffies(long secs)
@@ -400,23 +400,17 @@ int xfrm_state_add(struct xfrm_state *x)
        spin_lock_bh(&xfrm_state_lock);
 
        x1 = afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto);
-       if (!x1) {
-               x1 = afinfo->find_acq(
-                       x->props.mode, x->props.reqid, x->id.proto,
-                       &x->id.daddr, &x->props.saddr, 0);
-               if (x1 && x1->id.spi != x->id.spi && x1->id.spi) {
-                       xfrm_state_put(x1);
-                       x1 = NULL;
-               }
-       }
-
-       if (x1 && x1->id.spi) {
+       if (x1) {
                xfrm_state_put(x1);
                x1 = NULL;
                err = -EEXIST;
                goto out;
        }
 
+       x1 = afinfo->find_acq(
+               x->props.mode, x->props.reqid, x->id.proto,
+               &x->id.daddr, &x->props.saddr, 0);
+
        __xfrm_state_insert(x);
        err = 0;
 
@@ -531,6 +525,16 @@ int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb)
        return 0;
 }
 
+int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb)
+{
+       int err = xfrm_state_check_expire(x);
+       if (err < 0)
+               goto err;
+       err = xfrm_state_check_space(x, skb);
+err:
+       return err;
+}
+
 struct xfrm_state *
 xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto,
                  unsigned short family)
@@ -620,11 +624,12 @@ xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi)
                for (h=0; h<maxspi-minspi+1; h++) {
                        spi = minspi + net_random()%(maxspi-minspi+1);
                        x0 = xfrm_state_lookup(&x->id.daddr, htonl(spi), x->id.proto, x->props.family);
-                       if (x0 == NULL)
+                       if (x0 == NULL) {
+                               x->id.spi = htonl(spi);
                                break;
+                       }
                        xfrm_state_put(x0);
                }
-               x->id.spi = htonl(spi);
        }
        if (x->id.spi) {
                spin_lock_bh(&xfrm_state_lock);