When calling saLckResourceClose, we must remove that resource from the
cleanup list for the process calling saLckResourceClose. Without this,
it is possible that when the process exits and calls lck_lib_exit_fn,
the resource will have its reference count decremented again. This can
result in a resource not being removed correctly, since reference
count would be corrupt and would fail the the check we make before
removing a resource.

Once the details of the problem (and test case) are sorted out, the
fix is obvious: remove the resource from the cleanup list for every
close.

Thanks for Honza for finding this and Steve for his help diagnosing
the problem.

Ryan

Index: services/lck.c
===================================================================
--- services/lck.c      (revision 2025)
+++ services/lck.c      (working copy)
@@ -1593,6 +1593,28 @@
        return (0);
 }
 
+static struct resource_cleanup *lck_resource_cleanup_find (
+       void *conn,
+       const mar_name_t *resource_name)
+{
+       struct lck_pd *lck_pd = (struct lck_pd *)api->ipc_private_data_get 
(conn);
+
+       struct resource_cleanup *cleanup;
+       struct list_head *cleanup_list;
+
+       for (cleanup_list = lck_pd->resource_cleanup_list.next;
+            cleanup_list != &lck_pd->resource_cleanup_list;
+            cleanup_list = cleanup_list->next)
+       {
+               cleanup = list_entry (cleanup_list, struct resource_cleanup, 
cleanup_list);
+
+               if (mar_name_match (resource_name, &cleanup->resource_name)) {
+                       return (cleanup);
+               }
+       }
+       return (0);
+}
+
 static void lck_resourcelock_response_send (
        struct resource_lock *resource_lock,
        SaAisErrorT error)
@@ -2240,6 +2262,7 @@
        SaAisErrorT error = SA_AIS_OK;
 
        struct resource *resource = NULL;
+       struct resource_cleanup *cleanup = NULL;
 
        /* DEBUG */
        log_printf (LOGSYS_LEVEL_DEBUG, "EXEC request: saLckResourceClose\n");
@@ -2259,6 +2282,10 @@
                req_exec_lck_resourceclose->exit_flag,
                &req_exec_lck_resourceclose->source);
 
+       /*
+        * If reference count is zero and there are no granted locks,
+        * we can remove this resource.
+        */
        if ((resource->refcount == 0) &&
            (resource->ex_lock_granted == NULL) &&
            (list_empty (&resource->pr_lock_granted_list_head)))
@@ -2267,6 +2294,18 @@
                free (resource);
        }
 
+       /*
+        * Remove the cleanup entry for this resource.
+        */
+       cleanup = lck_resource_cleanup_find (
+               req_exec_lck_resourceclose->source.conn,
+               &req_exec_lck_resourceclose->resource_name);
+
+       assert (cleanup != NULL);
+
+       list_del (&cleanup->cleanup_list);
+       free (cleanup);
+
 error_exit:
        if (api->ipc_source_is_local (&req_exec_lck_resourceclose->source))
        {
_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to