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

Reply via email to