Merge to Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.13-vs2...
[linux-2.6.git] / kernel / vserver / network.c
index 66e09de..1ceb1fc 100644 (file)
@@ -488,13 +488,25 @@ int nx_addr_conflict(struct nx_info *nxi, uint32_t addr, struct sock *sk)
 
 void nx_set_persistent(struct nx_info *nxi)
 {
-       if (nx_info_flags(nxi, NXF_PERSISTENT, 0)) {
-               get_nx_info(nxi);
-               claim_nx_info(nxi, current);
-       } else {
-               release_nx_info(nxi, current);
-               put_nx_info(nxi);
-       }
+       get_nx_info(nxi);
+       claim_nx_info(nxi, current);
+}
+
+void nx_clear_persistent(struct nx_info *nxi)
+{
+       vxdprintk(VXD_CBIT(nid, 6),
+               "nx_clear_persistent(%p[#%d])", nxi, nxi->nx_id);
+
+       release_nx_info(nxi, current);
+       put_nx_info(nxi);
+}
+
+void nx_update_persistent(struct nx_info *nxi)
+{
+       if (nx_info_flags(nxi, NXF_PERSISTENT, 0))
+               nx_set_persistent(nxi);
+       else
+               nx_clear_persistent(nxi);
 }
 
 /* vserver syscall commands below here */
@@ -577,10 +589,22 @@ int vc_net_create(uint32_t nid, void __user *data)
        if ((vc_data.flagword & NXF_PERSISTENT))
                nx_set_persistent(new_nxi);
 
-       vs_net_change(new_nxi, VSC_NETUP);
-       ret = new_nxi->nx_id;
-       nx_migrate_task(current, new_nxi);
-       /* if this fails, we might end up with a hashed nx_info */
+       ret = -ENOEXEC;
+       if (vs_net_change(new_nxi, VSC_NETUP))
+               goto out_unhash;
+       ret = nx_migrate_task(current, new_nxi);
+       if (!ret) {
+               /* return context id on success */
+               ret = new_nxi->nx_id;
+               goto out;
+       }
+out_unhash:
+       /* prepare for context disposal */
+       new_nxi->nx_state |= NXS_SHUTDOWN;
+       if ((vc_data.flagword & NXF_PERSISTENT))
+               nx_clear_persistent(new_nxi);
+       __unhash_nx_info(new_nxi);
+out:
        put_nx_info(new_nxi);
        return ret;
 }
@@ -668,7 +692,7 @@ int vc_net_remove(uint32_t nid, void __user *data)
        if (!nxi)
                return -ESRCH;
 
-       switch ((unsigned)vc_data.type) {
+       switch (vc_data.type) {
        case NXA_TYPE_ANY:
                nxi->nbipv4 = 0;
                break;
@@ -728,7 +752,7 @@ int vc_set_nflags(uint32_t id, void __user *data)
        nxi->nx_flags = vx_mask_flags(nxi->nx_flags,
                vc_data.flagword, mask);
        if (trigger & NXF_PERSISTENT)
-               nx_set_persistent(nxi);
+               nx_update_persistent(nxi);
 
        put_nx_info(nxi);
        return 0;