Prevent deadlock if fs_stateSave panics
authorAndrew Deason <adeason@sinenomine.net>
Mon, 22 Feb 2010 17:56:07 +0000 (11:56 -0600)
committerDerrick Brashear <shadow@dementia.org>
Mon, 22 Feb 2010 18:35:52 +0000 (10:35 -0800)
fs_stateSave can call ShutDownAndCore(PANIC) if it detects host list
corruption. Right now this will deadlock the shutdown thread, since
we're still holding a read lock on the FS state when we do so, and
ShutDownAndCore will attempt to acquire a write lock. Do two things to
make this a bit better:

 -- Unlock the FS state before calling fs_stateSave, sine we're no
 longer looking at the FS state (the 'state' in fs_stateSave refers to
 the host list and callback lists, not the state locked by
 FS_STATE_*LOCK)

 -- If ShutDownAndCore detects that it was called inside of
 ShutDownAndCore, skip shutting down the volume and host packages, since
 they have already been shut down

Change-Id: I24a994ff85a6d866a5800b777c0cf5ab2ba466e4
Reviewed-on: http://gerrit.openafs.org/1362
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/viced/viced.c

index 4874a6f..1cb5584 100644 (file)
@@ -802,6 +802,15 @@ ShutDownAndCore(int dopanic)
 
 #ifdef AFS_DEMAND_ATTACH_FS
     FS_STATE_WRLOCK;
+    if (fs_state.mode == FS_MODE_SHUTDOWN) {
+       /* it is possible for at least fs_stateSave() (called below) to call
+        * ShutDownAndCore if there's host list corruption; prevent
+        * deinitializing some stuff twice */
+       ViceLog(0, ("ShutDownAndCore called during shutdown? Skipping volume "
+                   "and host package shutdown\n"));
+       FS_STATE_UNLOCK;
+       goto done_vol_host;
+    }
     fs_state.mode = FS_MODE_SHUTDOWN;
     FS_STATE_UNLOCK;
 #endif
@@ -847,11 +856,14 @@ ShutDownAndCore(int dopanic)
                FS_UNLOCK;
                FS_STATE_RDLOCK;
            }
+           FS_STATE_UNLOCK;
 
            /* ok. it should now be fairly safe. let's do the state dump */
            fs_stateSave();
        }
     }
+ done_vol_host:
+
 #endif /* AFS_DEMAND_ATTACH_FS */
 
     if (debugFile) {