]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Windows: Insert Server Reference List changes
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 13 Aug 2011 18:35:53 +0000 (14:35 -0400)
committerDerrick Brashear <shadow@dementix.org>
Sun, 14 Aug 2011 03:32:56 +0000 (20:32 -0700)
When inserting a new cm_serverRef_t object into a server list
perform the following operations:

1. take advantage of the fact that the cm_serverLock is held
   exclusively to purge the list of any deleted entries that
   could not be removed previously.

2. check to ensure that the item that is being added does not
   already exist in the list.  If it does, discard it.

Reviewed-on: http://gerrit.openafs.org/5258
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Tested-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit 5b40c5f5294964fc09df2c8332ab63cd2d729264)

Change-Id: I94398476267dda82e82306a87aa0bba6aa41da00
Reviewed-on: http://gerrit.openafs.org/5264
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Tested-by: Derrick Brashear <shadow@dementix.org>
src/WINNT/afsd/cm_server.c

index 9d3f4acef17a0f5f66da4fbb19dfb13cd9987c38..224037c680ca627b9a2be3625abf244a172e7b8d 100644 (file)
@@ -1072,27 +1072,91 @@ void cm_InsertServerList(cm_serverRef_t** list, cm_serverRef_t* element)
     unsigned short ipRank;
 
     lock_ObtainWrite(&cm_serverLock);
-    current=*list;
-    ipRank = element->server->ipRank;
+    /*
+     * Since we are grabbing the serverLock exclusively remove any
+     * deleted serverRef objects with a zero refcount before
+     * inserting the new item.
+     */
+    if (*list) {
+        cm_serverRef_t  **currentp = list;
+        cm_serverRef_t  **nextp = NULL;
+        cm_serverRef_t  * next = NULL;
+
+        for (currentp = list; *currentp; currentp = nextp)
+        {
+            nextp = &(*currentp)->next;
+            if ((*currentp)->refCount == 0 &&
+                (*currentp)->status == srv_deleted) {
+                next = *nextp;
+
+                if ((*currentp)->volID)
+                    cm_RemoveVolumeFromServer((*currentp)->server, (*currentp)->volID);
+                cm_FreeServer((*currentp)->server);
+                free(*currentp);
+                nextp = &next;
+            }
+        }
+    }
 
     /* insertion into empty list  or at the beginning of the list */
-    if ( !current || (current->server->ipRank > ipRank) )
+    if (!(*list))
+    {
+        element->next = NULL;
+        *list = element;
+        goto done;
+    }
+
+    /*
+     * Now that deleted entries have been removed and we know that the
+     * list was not empty, look for duplicates.  If the element we are
+     * inserting already exists, discard it.
+     */
+    for ( current = *list; current; current = current->next)
+    {
+        cm_server_t * server1 = current->server;
+        cm_server_t * server2 = element->server;
+
+        if (current->status == srv_deleted)
+            continue;
+
+        if (server1->type != server2->type)
+            continue;
+
+        if (server1->addr.sin_addr.s_addr != server2->addr.sin_addr.s_addr)
+            continue;
+
+        if ((server1->flags & CM_SERVERFLAG_UUID) != (server2->flags & CM_SERVERFLAG_UUID))
+            continue;
+
+        if ((server1->flags & CM_SERVERFLAG_UUID) &&
+            !afs_uuid_equal(&server1->uuid, &server2->uuid))
+            continue;
+
+        /* we must have a match, discard the new element */
+        free(element);
+        goto done;
+    }
+
+    ipRank = element->server->ipRank;
+
+       /* insertion at the beginning of the list */
+    if ((*list)->server->ipRank > ipRank)
     {
         element->next = *list;
         *list = element;
-        lock_ReleaseWrite(&cm_serverLock);
-        return ;
+        goto done;
     }
 
-    while ( current->next ) /* find appropriate place to insert */
+    /* find appropriate place to insert */
+    for ( current = *list; current->next; current = current->next)
     {
         if ( current->next->server->ipRank > ipRank )
             break;
-        else current = current->next;
     }
     element->next = current->next;
     current->next = element;
 
+  done:
     lock_ReleaseWrite(&cm_serverLock);
 }
 /*