Using atomic operations for the reference count of the vnode_info structure allows for grabbing additional references from the main thread. Grabbing the initial references as well as releasing one must still happen from the main thread.
Signed-off-by: Christoph Hellwig <[email protected]> --- sheep/group.c | 41 +++++++++++++++++++++++++++++++++++------ sheep/sheep_priv.h | 1 + 2 files changed, 36 insertions(+), 6 deletions(-) Index: sheepdog/sheep/group.c =================================================================== --- sheepdog.orig/sheep/group.c 2012-05-08 15:46:50.372688949 +0200 +++ sheepdog/sheep/group.c 2012-05-08 15:49:30.652687422 +0200 @@ -16,6 +16,7 @@ #include <arpa/inet.h> #include <sys/time.h> #include <sys/epoll.h> +#include <urcu/uatomic.h> #include "sheepdog_proto.h" #include "sheep_priv.h" @@ -153,17 +154,45 @@ int get_max_nr_copies_from(struct sd_nod return min((int)sys->nr_copies, get_zones_nr_from(nodes, nr_nodes)); } +/* + * Grab an additional reference to the passed in vnode info. + * + * The caller must already hold a reference to vnode_info, this function must + * only be used to grab an additional reference from code that wants the + * vnode information to outlive the request structure. + */ +struct vnode_info *grab_vnode_info(struct vnode_info *vnode_info) +{ + assert(uatomic_read(&vnode_info->refcnt) > 0); + + uatomic_inc(&vnode_info->refcnt); + return vnode_info; +} + +/* + * Get a reference to the currently active vnode information structure, + * this must only be called from the main thread. + */ struct vnode_info *get_vnode_info(void) { assert(current_vnode_info); - current_vnode_info->refcnt++; - return current_vnode_info; + + return grab_vnode_info(current_vnode_info); } -void put_vnode_info(struct vnode_info *vnodes) +/* + * Release a reference to the current vnode information. + * + * Must be called from the main thread. + */ +void put_vnode_info(struct vnode_info *vnode_info) { - if (vnodes && --vnodes->refcnt == 0) - free(vnodes); + if (vnode_info) { + assert(uatomic_read(&vnode_info->refcnt) > 0); + + if (uatomic_sub_return(&vnode_info->refcnt, 1) == 0) + free(vnode_info); + } } struct sd_vnode *oid_to_vnode(struct vnode_info *vnode_info, uint64_t oid, @@ -190,7 +219,7 @@ static int update_vnode_info(void) vnode_info->nr_vnodes = nodes_to_vnodes(sys->nodes, sys->nr_nodes, vnode_info->entries); vnode_info->nr_zones = get_zones_nr_from(sys->nodes, sys->nr_nodes); - vnode_info->refcnt = 1; + uatomic_set(&vnode_info->refcnt, 1); put_vnode_info(current_vnode_info); current_vnode_info = vnode_info; Index: sheepdog/sheep/sheep_priv.h =================================================================== --- sheepdog.orig/sheep/sheep_priv.h 2012-05-08 15:46:50.372688949 +0200 +++ sheepdog/sheep/sheep_priv.h 2012-05-08 15:47:05.840688801 +0200 @@ -241,6 +241,7 @@ int get_vdi_attr(uint32_t epoch, struct int write, int excl, int delete); int get_zones_nr_from(struct sd_node *nodes, int nr_nodes); +struct vnode_info *grab_vnode_info(struct vnode_info *vnode_info); struct vnode_info *get_vnode_info(void); void put_vnode_info(struct vnode_info *vnodes); -- sheepdog mailing list [email protected] http://lists.wpkg.org/mailman/listinfo/sheepdog
