Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
[linux-drm-fsl-dcu.git] / net / tipc / ref.c
index 414fc34b8bea5550198a01036f68191f06d2f475..8dea66500cf5ce65d6427aad77152f437e0c92ac 100644 (file)
@@ -153,11 +153,11 @@ void tipc_ref_table_stop(void)
 
 u32 tipc_ref_acquire(void *object, spinlock_t **lock)
 {
-       struct reference *entry;
        u32 index;
        u32 index_mask;
        u32 next_plus_upper;
        u32 ref;
+       struct reference *entry = NULL;
 
        if (!object) {
                err("Attempt to acquire reference to non-existent object\n");
@@ -175,30 +175,36 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock)
                index = tipc_ref_table.first_free;
                entry = &(tipc_ref_table.entries[index]);
                index_mask = tipc_ref_table.index_mask;
-               /* take lock in case a previous user of entry still holds it */
-               spin_lock_bh(&entry->lock);
                next_plus_upper = entry->ref;
                tipc_ref_table.first_free = next_plus_upper & index_mask;
                ref = (next_plus_upper & ~index_mask) + index;
-               entry->ref = ref;
-               entry->object = object;
-               *lock = &entry->lock;
        }
        else if (tipc_ref_table.init_point < tipc_ref_table.capacity) {
                index = tipc_ref_table.init_point++;
                entry = &(tipc_ref_table.entries[index]);
                spin_lock_init(&entry->lock);
-               spin_lock_bh(&entry->lock);
                ref = tipc_ref_table.start_mask + index;
-               entry->ref = ref;
-               entry->object = object;
-               *lock = &entry->lock;
        }
        else {
                ref = 0;
        }
        write_unlock_bh(&ref_table_lock);
 
+       /*
+        * Grab the lock so no one else can modify this entry
+        * While we assign its ref value & object pointer
+        */
+       if (entry) {
+               spin_lock_bh(&entry->lock);
+               entry->ref = ref;
+               entry->object = object;
+               *lock = &entry->lock;
+               /*
+                * keep it locked, the caller is responsible
+                * for unlocking this when they're done with it
+                */
+       }
+
        return ref;
 }