diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/include/linux/vs_network.h linux-2.6.11.10-vs2.0.1/include/linux/vs_network.h --- linux-2.6.11.10-vs2.0-p2/include/linux/vs_network.h 2005-05-22 15:11:14 +0200 +++ linux-2.6.11.10-vs2.0.1/include/linux/vs_network.h 2005-05-22 06:32:08 +0200 @@ -40,6 +40,25 @@ static inline void __put_nx_info(struct free_nx_info(nxi); } + +#define init_nx_info(p,i) __init_nx_info(p,i,__FILE__,__LINE__) + +static inline void __init_nx_info(struct nx_info **nxp, struct nx_info *nxi, + const char *_file, int _line) +{ + if (nxi) { + vxlprintk(VXD_CBIT(nid, 3), + "init_nx_info(%p[#%d.%d])", + nxi, nxi?nxi->nx_id:0, + nxi?atomic_read(&nxi->nx_usecnt):0, + _file, _line); + + atomic_inc(&nxi->nx_usecnt); + } + *nxp = nxi; +} + + #define set_nx_info(p,i) __set_nx_info(p,i,__FILE__,__LINE__) static inline void __set_nx_info(struct nx_info **nxp, struct nx_info *nxi, @@ -50,14 +69,13 @@ static inline void __set_nx_info(struct if (!nxi) return; - vxlprintk(VXD_CBIT(nid, 3), "set_nx_info(%p[#%d.%d.%d])", + vxlprintk(VXD_CBIT(nid, 3), "set_nx_info(%p[#%d.%d])", nxi, nxi?nxi->nx_id:0, nxi?atomic_read(&nxi->nx_usecnt):0, - nxi?atomic_read(&nxi->nx_refcnt):0, _file, _line); - atomic_inc(&nxi->nx_refcnt); // nxo = xchg(nxp, __get_nx_info(nxi, _file, _line)); + atomic_inc(&nxi->nx_usecnt); nxo = xchg(nxp, nxi); BUG_ON(nxo); } @@ -73,15 +91,49 @@ static inline void __clr_nx_info(struct if (!nxo) return; - vxlprintk(VXD_CBIT(nid, 3), "clr_nx_info(%p[#%d.%d.%d])", + vxlprintk(VXD_CBIT(nid, 3), "clr_nx_info(%p[#%d.%d])", nxo, nxo?nxo->nx_id:0, nxo?atomic_read(&nxo->nx_usecnt):0, - nxo?atomic_read(&nxo->nx_refcnt):0, _file, _line); - if (atomic_dec_and_test(&nxo->nx_refcnt)) - unhash_nx_info(nxo); // __put_nx_info(nxo, _file, _line); + if (atomic_dec_and_test(&nxo->nx_usecnt)) + free_nx_info(nxo); +} + + +#define claim_nx_info(v,p) __claim_nx_info(v,p,__FILE__,__LINE__) + +static inline void __claim_nx_info(struct nx_info *nxi, + struct task_struct *task, const char *_file, int _line) +{ + vxlprintk(VXD_CBIT(nid, 3), "claim_nx_info(%p[#%d.%d.%d]) %p", + nxi, nxi?nxi->nx_id:0, + nxi?atomic_read(&nxi->nx_usecnt):0, + nxi?atomic_read(&nxi->nx_tasks):0, + task, _file, _line); + + atomic_inc(&nxi->nx_tasks); +} + + +extern void unhash_nx_info(struct nx_info *); + +#define release_nx_info(v,p) __release_nx_info(v,p,__FILE__,__LINE__) + +static inline void __release_nx_info(struct nx_info *nxi, + struct task_struct *task, const char *_file, int _line) +{ + vxlprintk(VXD_CBIT(nid, 3), "release_nx_info(%p[#%d.%d.%d]) %p", + nxi, nxi?nxi->nx_id:0, + nxi?atomic_read(&nxi->nx_usecnt):0, + nxi?atomic_read(&nxi->nx_tasks):0, + task, _file, _line); + + might_sleep(); + + if (atomic_dec_and_test(&nxi->nx_tasks)) + unhash_nx_info(nxi); } diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/include/linux/vserver/network.h linux-2.6.11.10-vs2.0.1/include/linux/vserver/network.h --- linux-2.6.11.10-vs2.0-p2/include/linux/vserver/network.h 2005-05-22 15:11:14 +0200 +++ linux-2.6.11.10-vs2.0.1/include/linux/vserver/network.h 2005-05-22 07:05:51 +0200 @@ -29,7 +29,7 @@ struct nx_info { // struct rcu_head nx_rcu; /* the rcu head */ nid_t nx_id; /* vnet id */ atomic_t nx_usecnt; /* usage count */ - atomic_t nx_refcnt; /* reference count */ + atomic_t nx_tasks; /* tasks count */ int nx_state; /* context state */ uint64_t nx_flags; /* network flag word */ diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/kernel/exit.c linux-2.6.11.10-vs2.0.1/kernel/exit.c --- linux-2.6.11.10-vs2.0-p2/kernel/exit.c 2005-05-22 14:58:04 +0200 +++ linux-2.6.11.10-vs2.0.1/kernel/exit.c 2005-05-22 07:17:30 +0200 @@ -105,6 +105,8 @@ repeat: release_thread(p); if (p->vx_info) release_vx_info(p->vx_info, p); + if (p->nx_info) + release_nx_info(p->nx_info, p); put_task_struct(p); p = leader; diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/kernel/fork.c linux-2.6.11.10-vs2.0.1/kernel/fork.c --- linux-2.6.11.10-vs2.0-p2/kernel/fork.c 2005-05-21 04:29:23 +0200 +++ linux-2.6.11.10-vs2.0.1/kernel/fork.c 2005-05-22 05:56:27 +0200 @@ -834,8 +834,7 @@ static task_t *copy_process(unsigned lon goto fork_out; init_vx_info(&p->vx_info, current->vx_info); - p->nx_info = NULL; - set_nx_info(&p->nx_info, current->nx_info); + init_nx_info(&p->nx_info, current->nx_info); /* check vserver memory */ if (p->mm && !(clone_flags & CLONE_VM)) { diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/kernel/vserver/legacynet.c linux-2.6.11.10-vs2.0.1/kernel/vserver/legacynet.c --- linux-2.6.11.10-vs2.0-p2/kernel/vserver/legacynet.c 2005-05-21 04:29:23 +0200 +++ linux-2.6.11.10-vs2.0.1/kernel/vserver/legacynet.c 2005-05-22 07:18:44 +0200 @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,7 @@ int vc_set_ipv4root(uint32_t nbip, void return err; new_nxi = create_nx_info(); - if (!new_nxi) + if (IS_ERR(new_nxi)) return -EINVAL; new_nxi->nbipv4 = nbip; @@ -75,10 +76,9 @@ int vc_set_ipv4root(uint32_t nbip, void } new_nxi->v4_bcast = vc_data.broadcast; // current->nx_info = new_nxi; - if (nxi) { + if (nxi) printk("!!! switching nx_info %p->%p\n", nxi, new_nxi); - clr_nx_info(¤t->nx_info); - } + nx_migrate_task(current, new_nxi); // set_nx_info(¤t->nx_info, new_nxi); // current->nid = new_nxi->nx_id; diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/kernel/vserver/network.c linux-2.6.11.10-vs2.0.1/kernel/vserver/network.c --- linux-2.6.11.10-vs2.0-p2/kernel/vserver/network.c 2005-05-22 15:11:14 +0200 +++ linux-2.6.11.10-vs2.0.1/kernel/vserver/network.c 2005-05-22 06:45:23 +0200 @@ -42,8 +42,8 @@ static struct nx_info *__alloc_nx_info(n new->nx_id = nid; // INIT_RCU_HEAD(&new->nx_rcu); INIT_HLIST_NODE(&new->nx_hlist); - atomic_set(&new->nx_refcnt, 0); atomic_set(&new->nx_usecnt, 0); + atomic_set(&new->nx_tasks, 0); new->nx_state = 0; /* rest of init goes here */ @@ -66,7 +66,7 @@ static void __dealloc_nx_info(struct nx_ nxi->nx_id = -1; BUG_ON(atomic_read(&nxi->nx_usecnt)); - BUG_ON(atomic_read(&nxi->nx_refcnt)); + BUG_ON(atomic_read(&nxi->nx_tasks)); nxi->nx_state |= NXS_RELEASED; kfree(nxi); @@ -66,21 +66,9 @@ static void __dealloc_nx_info(struct nx_ kfree(nxi); } -static inline int __free_nx_info(struct nx_info *nxi) +static void __shutdown_nx_info(struct nx_info *nxi) { - int usecnt, refcnt; - - BUG_ON(!nxi); - - usecnt = atomic_read(&nxi->nx_usecnt); - BUG_ON(usecnt < 0); - - refcnt = atomic_read(&nxi->nx_refcnt); - BUG_ON(refcnt < 0); - - if (!usecnt) - __dealloc_nx_info(nxi); - return usecnt; + nxi->nx_state |= NXS_SHUTDOWN; } /* exported stuff */ @@ -94,11 +82,15 @@ static inline int __free_nx_info(struct void free_nx_info(struct nx_info *nxi) { /* context shutdown is mandatory */ - // BUG_ON(nxi->nx_state != NXS_SHUTDOWN); + BUG_ON(nxi->nx_state != NXS_SHUTDOWN); - // BUG_ON(nxi->nx_state & NXS_HASHED); + /* context must not be hashed */ + BUG_ON(nxi->nx_state & NXS_HASHED); - BUG_ON(__free_nx_info(nxi)); + BUG_ON(atomic_read(&nxi->nx_usecnt)); + BUG_ON(atomic_read(&nxi->nx_tasks)); + + __dealloc_nx_info(nxi); } @@ -127,9 +119,15 @@ static inline void __hash_nx_info(struct { struct hlist_head *head; + vxd_assert_lock(&nx_info_hash_lock); vxdprintk(VXD_CBIT(nid, 4), "__hash_nx_info: %p[#%d]", nxi, nxi->nx_id); - get_nx_info(nxi); + + /* context must not be hashed */ + BUG_ON(nx_info_state(nxi, NXS_HASHED)); + + // get_nx_info(nxi); + nxi->nx_state |= NXS_HASHED; head = &nx_info_hash[__hashval(nxi->nx_id)]; hlist_add_head(&nxi->nx_hlist, head); } @@ -144,8 +142,13 @@ static inline void __unhash_nx_info(stru vxd_assert_lock(&nx_info_hash_lock); vxdprintk(VXD_CBIT(nid, 4), "__unhash_nx_info: %p[#%d]", nxi, nxi->nx_id); + + /* context must be hashed */ + BUG_ON(!nx_info_state(nxi, NXS_HASHED)); + + nxi->nx_state &= ~NXS_HASHED; hlist_del(&nxi->nx_hlist); - put_nx_info(nxi); + // put_nx_info(nxi); } @@ -265,6 +267,7 @@ out_unlock: void unhash_nx_info(struct nx_info *nxi) { + __shutdown_nx_info(nxi); spin_lock(&nx_info_hash_lock); __unhash_nx_info(nxi); spin_unlock(&nx_info_hash_lock); @@ -376,7 +366,7 @@ int nx_migrate_task(struct task_struct * "nx_migrate_task(%p,%p[#%d.%d.%d])", p, nxi, nxi->nx_id, atomic_read(&nxi->nx_usecnt), - atomic_read(&nxi->nx_refcnt)); + atomic_read(&nxi->nx_tasks)); old_nxi = task_get_nx_info(p); if (old_nxi == nxi) @@ -384,8 +374,11 @@ int nx_migrate_task(struct task_struct * task_lock(p); /* should be handled in set_nx_info !! */ - if (old_nxi) + if (old_nxi) { + release_nx_info(old_nxi, p); clr_nx_info(&p->nx_info); + } + claim_nx_info(nxi, p); set_nx_info(&p->nx_info, nxi); p->nid = nxi->nx_id; diff -NurpP --minimal linux-2.6.11.10-vs2.0-p2/kernel/vserver/proc.c linux-2.6.11.10-vs2.0.1/kernel/vserver/proc.c --- linux-2.6.11.10-vs2.0-p2/kernel/vserver/proc.c 2005-05-21 04:29:23 +0200 +++ linux-2.6.11.10-vs2.0.1/kernel/vserver/proc.c 2005-05-22 06:16:43 +0200 @@ -221,9 +221,9 @@ int proc_nid_status (int vid, char *buff return 0; length = sprintf(buffer, "UseCnt:\t%d\n" - "RefCnt:\t%d\n" + "Tasks:\t%d\n" ,atomic_read(&nxi->nx_usecnt) - ,atomic_read(&nxi->nx_refcnt) + ,atomic_read(&nxi->nx_tasks) ); put_nx_info(nxi); return length;