[OpenAFS-devel] deadlock on linux-2.4

Nickolai Zeldovich kolya@MIT.EDU
Wed, 05 Jun 2002 11:29:09 -0400


>   I have found more info and created a temorary hack, which fixes it,
> but it will not be probably the correct solution.

Thanks for tracking this down.  As you point out, we shouldn't obtain
vcache locks while holding any dcache locks, due to lock ordering.
The right solution is probably to delay calling afs_ProcessFS() until
after we've released the dcache entries; can you try the patch below
and see if it works for you?

> I don't know why other architectures are OK, may be it is not possible
> to call afs_StoreAllSegment and afs_UFSRead together on them.

I suspect other architectures also have the same bug.  Note that this
only affects the development branch (the dcache locking code has only
been added recently), which is probably why this bug hasn't been seen
by others yet.

-- kolya

--- afs_segments.c	2002/02/28 06:08:11	1.11
+++ afs_segments.c	2002/06/05 15:26:36
@@ -311,6 +311,8 @@
       if (j) {
 	static afs_uint32 lp1 = 10000, lp2 = 10000;
 	struct AFSStoreStatus InStatus;
+	struct AFSFetchStatus OutStatus;
+	int doProcessFS = 0;
 	afs_size_t base, bytes;
 	afs_uint32 nchunks;
 	int nomore;
@@ -530,26 +532,13 @@
                      * one which has the writing bit turned on. */
 		}
 		if (!code) {
-		    struct AFSFetchStatus OutStatus;
 		    struct AFSVolSync tsync;
 		    RX_AFS_GUNLOCK();
 		    code = EndRXAFS_StoreData(tcall, &OutStatus, &tsync);
 		    RX_AFS_GLOCK();
 		    hadd32(newDV, 1);
 		    XSTATS_END_TIME;
-      
-		    /* Now copy out return params */
-		    UpgradeSToWLock(&avc->lock,28);    /* keep out others for a while */
-		    if (!code) {  /* must wait til RPC completes to be sure of this info */
-			afs_ProcessFS(avc, &OutStatus, areq);
-			/* Keep last (max) size of file on server to see if
-			 * we need to call afs_StoreMini to extend the file.
-			 */
-			if (!moredata)
-			    maxStoredLength = OutStatus.Length;
-
-		    }
-		    ConvertWToSLock(&avc->lock);
+		    if (!code) doProcessFS = 1;	/* Flag to run afs_ProcessFS() later on */
 		}
 		if (tcall) {
 		    RX_AFS_GUNLOCK();
@@ -591,6 +580,19 @@
 		afs_PutDCache(tdc);
 		/* Mark the entry as released */
 		dclist[i] = NULL;
+	    }
+
+	    if (doProcessFS) {
+		/* Now copy out return params */
+		UpgradeSToWLock(&avc->lock,28);    /* keep out others for a while */
+		afs_ProcessFS(avc, &OutStatus, areq);
+		/* Keep last (max) size of file on server to see if
+		 * we need to call afs_StoreMini to extend the file.
+		 */
+		if (!moredata)
+		    maxStoredLength = OutStatus.Length;
+		ConvertWToSLock(&avc->lock);
+		doProcessFS = 0;
 	    }
 
 	    if (code) {