diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/include/linux/vs_context.h linux-2.6.9-vs1.9.4-rc3.2/include/linux/vs_context.h --- linux-2.6.9-vs1.9.4-rc3.1/include/linux/vs_context.h 2005-01-13 15:19:20.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/include/linux/vs_context.h 2005-01-13 21:50:47.000000000 +0100 @@ -23,6 +23,9 @@ static inline struct vx_info *__get_vx_i return vxi; } + +extern void free_vx_info(struct vx_info *); + #define put_vx_info(i) __put_vx_info(i,__FILE__,__LINE__) static inline void __put_vx_info(struct vx_info *vxi, const char *_file, int _line) @@ -23,7 +23,6 @@ static inline struct vx_info *__get_vx_i { if (!vxi) return; - vxlprintk(VXD_CBIT(xid, 2), "put_vx_info(%p[#%d.%d])", vxi, vxi?vxi->vx_id:0, vxi?atomic_read(&vxi->vx_usecnt):0, _file, _line); @@ -57,7 +59,8 @@ static inline void __set_vx_info(struct vxh_set_vx_info(vxi, vxp); atomic_inc(&vxi->vx_refcnt); - vxo = xchg(vxp, __get_vx_info(vxi, _file, _line)); + // vxo = xchg(vxp, __get_vx_info(vxi, _file, _line)); + vxo = xchg(vxp, vxi); BUG_ON(vxo); } @@ -81,7 +84,7 @@ static inline void __clr_vx_info(struct if (atomic_dec_and_test(&vxo->vx_refcnt)) unhash_vx_info(vxo); - __put_vx_info(vxo, _file, _line); + // __put_vx_info(vxo, _file, _line); } @@ -101,20 +104,6 @@ static __inline__ struct vx_info *__task } -#define vx_verify_info(p,i) \ - __vx_verify_info((p)->vx_info,i,__FILE__,__LINE__) - -static __inline__ void __vx_verify_info( - struct vx_info *vxa, struct vx_info *vxb, - const char *_file, int _line) -{ - if (vxa == vxb) - return; - printk(KERN_ERR "vx bad assumption (%p==%p) at %s:%d\n", - vxa, vxb, _file, _line); -} - - #else #warning duplicate inclusion #endif diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/include/linux/vs_network.h linux-2.6.9-vs1.9.4-rc3.2/include/linux/vs_network.h --- linux-2.6.9-vs1.9.4-rc3.1/include/linux/vs_network.h 2005-01-13 15:19:15.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/include/linux/vs_network.h 2005-01-13 21:56:44.000000000 +0100 @@ -20,6 +20,9 @@ static inline struct nx_info *__get_nx_i return nxi; } + +extern void free_nx_info(struct nx_info *); + #define put_nx_info(i) __put_nx_info(i,__FILE__,__LINE__) static inline void __put_nx_info(struct nx_info *nxi, const char *_file, int _line) @@ -50,7 +53,8 @@ static inline void __set_nx_info(struct _file, _line); atomic_inc(&nxi->nx_refcnt); - nxo = xchg(nxp, __get_nx_info(nxi, _file, _line)); + // nxo = xchg(nxp, __get_nx_info(nxi, _file, _line)); + nxo = xchg(nxp, nxi); BUG_ON(nxo); } @@ -73,7 +77,7 @@ static inline void __clr_nx_info(struct if (atomic_dec_and_test(&nxo->nx_refcnt)) unhash_nx_info(nxo); - __put_nx_info(nxo, _file, _line); + // __put_nx_info(nxo, _file, _line); } @@ -92,19 +96,6 @@ static __inline__ struct nx_info *__task return nxi; } -#define nx_verify_info(p,i) \ - __nx_verify_info((p)->nx_info,i,__FILE__,__LINE__) - -static __inline__ void __nx_verify_info( - struct nx_info *ipa, struct nx_info *ipb, - const char *_file, int _line) -{ - if (ipa == ipb) - return; - printk(KERN_ERR "ip bad assumption (%p==%p) at %s:%d\n", - ipa, ipb, _file, _line); -} - #define nx_task_nid(t) ((t)->nid) diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/context.h linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/context.h --- linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/context.h 2005-01-13 15:19:15.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/context.h 2005-01-13 19:37:03.000000000 +0100 @@ -133,8 +133,6 @@ struct vx_info { extern void unhash_vx_info(struct vx_info *); -extern void free_vx_info(struct vx_info *); - extern struct vx_info *locate_vx_info(int); extern struct vx_info *locate_or_create_vx_info(int); @@ -145,6 +144,9 @@ extern int vx_info_is_hashed(xid_t); extern int vx_migrate_task(struct task_struct *, struct vx_info *); extern long vs_context_state(unsigned int); + +extern void free_vx_info(struct vx_info *); + #endif /* __KERNEL__ */ #else /* _VX_CONTEXT_H */ diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/debug.h linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/debug.h --- linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/debug.h 2005-01-13 15:19:20.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/debug.h 2005-01-13 21:55:32.000000000 +0100 @@ -266,4 +266,12 @@ extern void vxh_dump_history(void); #endif /* CONFIG_VSERVER_HISTORY */ + +#if defined(CONFIG_VSERVER_DEBUG) && defined(CONFIG_DEBUG_SPINLOCK) +#define vxd_assert_lock(l) BUG_ON(!spin_is_locked(l)) +#else +#define vxd_assert_lock(l) do { } while (0) +#endif + + #endif /* _VX_DEBUG_H */ diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/network.h linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/network.h --- linux-2.6.9-vs1.9.4-rc3.1/include/linux/vserver/network.h 2005-01-13 15:12:41.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/include/linux/vserver/network.h 2005-01-13 19:37:03.000000000 +0100 @@ -45,8 +45,6 @@ struct nx_info { extern void unhash_nx_info(struct nx_info *); -extern void free_nx_info(struct nx_info *); - extern struct nx_info *locate_nx_info(int); extern struct nx_info *locate_or_create_nx_info(int); Files linux-2.6.9-vs1.9.4-rc3.1/kernel/vserver/.context.c.swo and linux-2.6.9-vs1.9.4-rc3.2/kernel/vserver/.context.c.swo differ diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/kernel/vserver/context.c linux-2.6.9-vs1.9.4-rc3.2/kernel/vserver/context.c --- linux-2.6.9-vs1.9.4-rc3.1/kernel/vserver/context.c 2005-01-13 15:19:20.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/kernel/vserver/context.c 2005-01-13 22:27:06.000000000 +0100 @@ -15,6 +15,7 @@ * V0.08 switch to RCU based hash * V0.09 revert to non RCU for now * V0.10 and back to working RCU hash + * V0.11 and back to locking again * */ @@ -58,7 +59,7 @@ static struct vx_info *__alloc_vx_info(x memset (new, 0, sizeof(struct vx_info)); new->vx_id = xid; - INIT_RCU_HEAD(&new->vx_rcu); + // INIT_RCU_HEAD(&new->vx_rcu); INIT_HLIST_NODE(&new->vx_hlist); atomic_set(&new->vx_refcnt, 0); atomic_set(&new->vx_usecnt, 0); @@ -130,18 +131,6 @@ static inline int __free_vx_info(struct return usecnt; } -static void __rcu_put_vx_info(struct rcu_head *head) -{ - struct vx_info *vxi = container_of(head, struct vx_info, vx_rcu); - - vxdprintk(VXD_CBIT(xid, 3), - "__rcu_put_vx_info(%p[#%d]): %d,%d", - vxi, vxi->vx_id, - atomic_read(&vxi->vx_usecnt), - atomic_read(&vxi->vx_refcnt)); - put_vx_info(vxi); -} - void __shutdown_vx_info(struct vx_info *vxi) { struct namespace *namespace; @@ -199,14 +188,18 @@ static inline void __hash_vx_info(struct { struct hlist_head *head; + vxd_assert_lock(&vx_info_hash_lock); vxdprintk(VXD_CBIT(xid, 4), "__hash_vx_info: %p[#%d]", vxi, vxi->vx_id); vxh_hash_vx_info(vxi); + /* context must not be hashed */ + BUG_ON(vxi->vx_state & VXS_HASHED); + get_vx_info(vxi); vxi->vx_state |= VXS_HASHED; head = &vx_info_hash[__hashval(vxi->vx_id)]; - hlist_add_head_rcu(&vxi->vx_hlist, head); + hlist_add_head(&vxi->vx_hlist, head); } /* __unhash_vx_info() @@ -216,20 +209,24 @@ static inline void __hash_vx_info(struct static inline void __unhash_vx_info(struct vx_info *vxi) { + vxd_assert_lock(&vx_info_hash_lock); vxdprintk(VXD_CBIT(xid, 4), "__unhash_vx_info: %p[#%d]", vxi, vxi->vx_id); vxh_unhash_vx_info(vxi); - vxi->vx_state &= ~VXS_HASHED; - hlist_del_rcu(&vxi->vx_hlist); + /* maybe warn on that? */ + if (!(vxi->vx_state & VXS_HASHED)) + return; - call_rcu(&vxi->vx_rcu, __rcu_put_vx_info); + vxi->vx_state &= ~VXS_HASHED; + hlist_del(&vxi->vx_hlist); + put_vx_info(vxi); } /* __lookup_vx_info() - * requires the rcu_read_lock() + * requires the hash_lock to be held * doesn't increment the vx_refcnt */ static inline struct vx_info *__lookup_vx_info(xid_t xid) @@ -238,11 +235,11 @@ static inline struct vx_info *__lookup_v struct hlist_node *pos; struct vx_info *vxi; - hlist_for_each_rcu(pos, head) { + vxd_assert_lock(&vx_info_hash_lock); + hlist_for_each(pos, head) { vxi = hlist_entry(pos, struct vx_info, vx_hlist); - if ((vxi->vx_id == xid) && - vx_info_state(vxi, VXS_HASHED)) + if (vxi->vx_id == xid) goto found; } vxi = NULL; @@ -258,7 +255,6 @@ found: /* __vx_dynamic_id() * find unused dynamic xid - * requires the rcu_read_lock() * requires the hash_lock to be held */ static inline xid_t __vx_dynamic_id(void) @@ -266,6 +262,7 @@ static inline xid_t __vx_dynamic_id(void static xid_t seq = MAX_S_CONTEXT; xid_t barrier = seq; + vxd_assert_lock(&vx_info_hash_lock); do { if (++seq > MAX_S_CONTEXT) seq = MIN_D_CONTEXT; @@ -294,8 +291,6 @@ static struct vx_info * __loc_vx_info(in return NULL; } - /* FIXME is this required at all ? */ - rcu_read_lock(); /* required to make dynamic xids unique */ spin_lock(&vx_info_hash_lock); @@ -334,7 +328,6 @@ static struct vx_info * __loc_vx_info(in out_unlock: spin_unlock(&vx_info_hash_lock); - rcu_read_unlock(); vxh_loc_vx_info(id, vxi); if (new) __dealloc_vx_info(new); @@ -366,9 +359,9 @@ struct vx_info *locate_vx_info(int id) if (id < 0) { vxi = get_vx_info(current->vx_info); } else { - rcu_read_lock(); + spin_lock(&vx_info_hash_lock); vxi = get_vx_info(__lookup_vx_info(id)); - rcu_read_unlock(); + spin_unlock(&vx_info_hash_lock); } return vxi; } @@ -381,21 +374,14 @@ int vx_info_is_hashed(xid_t xid) { int hashed; - rcu_read_lock(); + spin_lock(&vx_info_hash_lock); hashed = (__lookup_vx_info(xid) != NULL); - rcu_read_unlock(); + spin_unlock(&vx_info_hash_lock); return hashed; } #ifdef CONFIG_VSERVER_LEGACY -#if 0 -struct vx_info *alloc_vx_info(xid_t xid) -{ - return __alloc_vx_info(xid); -} -#endif - struct vx_info *locate_or_create_vx_info(int id) { int err; @@ -411,12 +397,12 @@ int get_xid_list(int index, unsigned int { int hindex, nr_xids = 0; - rcu_read_lock(); for (hindex = 0; hindex < VX_HASH_SIZE; hindex++) { struct hlist_head *head = &vx_info_hash[hindex]; struct hlist_node *pos; - hlist_for_each_rcu(pos, head) { + spin_lock(&vx_info_hash_lock); + hlist_for_each(pos, head) { struct vx_info *vxi; if (--index > 0) @@ -424,12 +410,15 @@ int get_xid_list(int index, unsigned int vxi = hlist_entry(pos, struct vx_info, vx_hlist); xids[nr_xids] = vxi->vx_id; - if (++nr_xids >= size) + if (++nr_xids >= size) { + spin_unlock(&vx_info_hash_lock); goto out; + } } + /* keep the lock time short */ + spin_unlock(&vx_info_hash_lock); } out: - rcu_read_unlock(); return nr_xids; } #endif diff -NurpP --minimal linux-2.6.9-vs1.9.4-rc3.1/kernel/vserver/network.c linux-2.6.9-vs1.9.4-rc3.2/kernel/vserver/network.c --- linux-2.6.9-vs1.9.4-rc3.1/kernel/vserver/network.c 2005-01-13 15:12:41.000000000 +0100 +++ linux-2.6.9-vs1.9.4-rc3.2/kernel/vserver/network.c 2005-01-13 22:29:38.000000000 +0100 @@ -86,16 +86,16 @@ static inline int __free_nx_info(struct return usecnt; } -static void __rcu_put_nx_info(struct rcu_head *head) +/* exported stuff */ + +void free_nx_info(struct nx_info *nxi) { - struct nx_info *nxi = container_of(head, struct nx_info, nx_rcu); + /* context shutdown is mandatory */ + // BUG_ON(nxi->nx_state != NXS_SHUTDOWN); - vxdprintk(VXD_CBIT(nid, 3), - "__rcu_put_nx_info(%p[#%d]): %d,%d", - nxi, nxi->nx_id, - atomic_read(&nxi->nx_usecnt), - atomic_read(&nxi->nx_refcnt)); - put_nx_info(nxi); + // BUG_ON(nxi->nx_state & NXS_HASHED); + + BUG_ON(__free_nx_info(nxi)); } @@ -128,7 +128,7 @@ static inline void __hash_nx_info(struct "__hash_nx_info: %p[#%d]", nxi, nxi->nx_id); get_nx_info(nxi); head = &nx_info_hash[__hashval(nxi->nx_id)]; - hlist_add_head_rcu(&nxi->nx_hlist, head); + hlist_add_head(&nxi->nx_hlist, head); } /* __unhash_nx_info() @@ -138,16 +138,17 @@ static inline void __hash_nx_info(struct static inline void __unhash_nx_info(struct nx_info *nxi) { + vxd_assert_lock(&nx_info_hash_lock); vxdprintk(VXD_CBIT(nid, 4), "__unhash_nx_info: %p[#%d]", nxi, nxi->nx_id); - hlist_del_rcu(&nxi->nx_hlist); - call_rcu(&nxi->nx_rcu, __rcu_put_nx_info); + hlist_del(&nxi->nx_hlist); + put_nx_info(nxi); } /* __lookup_nx_info() - * requires the rcu_read_lock() + * requires the hash_lock to be held * doesn't increment the nx_refcnt */ static inline struct nx_info *__lookup_nx_info(nid_t nid) @@ -155,7 +156,8 @@ static inline struct nx_info *__lookup_n struct hlist_head *head = &nx_info_hash[__hashval(nid)]; struct hlist_node *pos; - hlist_for_each_rcu(pos, head) { + vxd_assert_lock(&nx_info_hash_lock); + hlist_for_each(pos, head) { struct nx_info *nxi = hlist_entry(pos, struct nx_info, nx_hlist); @@ -170,7 +172,6 @@ static inline struct nx_info *__lookup_n /* __nx_dynamic_id() * find unused dynamic nid - * requires the rcu_read_lock() * requires the hash_lock to be held */ static inline nid_t __nx_dynamic_id(void) @@ -178,6 +179,7 @@ static inline nid_t __nx_dynamic_id(void static nid_t seq = MAX_N_CONTEXT; nid_t barrier = seq; + vxd_assert_lock(&nx_info_hash_lock); do { if (++seq > MAX_N_CONTEXT) seq = MIN_D_CONTEXT; @@ -206,8 +208,6 @@ static struct nx_info * __loc_nx_info(in return NULL; } - /* FIXME is this required at all ? */ - rcu_read_lock(); /* required to make dynamic xids unique */ spin_lock(&nx_info_hash_lock); @@ -246,7 +245,6 @@ static struct nx_info * __loc_nx_info(in out_unlock: spin_unlock(&nx_info_hash_lock); - rcu_read_unlock(); if (new) __dealloc_nx_info(new); return nxi; @@ -256,10 +254,6 @@ out_unlock: /* exported stuff */ -void free_nx_info(struct nx_info *nxi) -{ - BUG_ON(__free_nx_info(nxi)); -} void unhash_nx_info(struct nx_info *nxi) { @@ -280,9 +274,9 @@ struct nx_info *locate_nx_info(int id) if (id < 0) { nxi = get_nx_info(current->nx_info); } else { - rcu_read_lock(); + spin_lock(&nx_info_hash_lock); nxi = get_nx_info(__lookup_nx_info(id)); - rcu_read_unlock(); + spin_unlock(&nx_info_hash_lock); } return nxi; } @@ -295,9 +289,9 @@ int nx_info_is_hashed(nid_t nid) { int hashed; - rcu_read_lock(); + spin_lock(&nx_info_hash_lock); hashed = (__lookup_nx_info(nid) != NULL); - rcu_read_unlock(); + spin_unlock(&nx_info_hash_lock); return hashed; } @@ -330,12 +324,12 @@ int get_nid_list(int index, unsigned int { int hindex, nr_nids = 0; - rcu_read_lock(); for (hindex = 0; hindex < NX_HASH_SIZE; hindex++) { struct hlist_head *head = &nx_info_hash[hindex]; struct hlist_node *pos; - hlist_for_each_rcu(pos, head) { + spin_lock(&nx_info_hash_lock); + hlist_for_each(pos, head) { struct nx_info *nxi; if (--index > 0) @@ -343,12 +337,15 @@ int get_nid_list(int index, unsigned int nxi = hlist_entry(pos, struct nx_info, nx_hlist); nids[nr_nids] = nxi->nx_id; - if (++nr_nids >= size) + if (++nr_nids >= size) { + spin_unlock(&nx_info_hash_lock); goto out; + } } + /* keep the lock time short */ + spin_unlock(&nx_info_hash_lock); } out: - rcu_read_unlock(); return nr_nids; } #endif