afs: Retry unlock after afs_StoreAllSegments
authorAndrew Deason <adeason@sinenomine.net>
Fri, 1 Apr 2011 18:43:13 +0000 (13:43 -0500)
committerDerrick Brashear <shadow@dementia.org>
Tue, 7 Jun 2011 16:23:36 +0000 (09:23 -0700)
HandleFlock calls afs_StoreAllSegments when unlocking an exclusive
flock lock. This can drop the write lock on avc, so we must
effectively retry the entire lock operation again, since the world may
have changed while we were waiting to reacquire the lock on avc. So,
retry once all of the lock checks up to that point, to ensure that a
lock on the file actually still exists.

FIXES 125446

Reviewed-on: http://gerrit.openafs.org/4393
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
(cherry picked from commit 601fcf1d7f7c88cfc0ffd877c5458340b3e59098)

Change-Id: I8b12175bfd082f7fb75e7cfc1fb0e7662912e6e8
Reviewed-on: http://gerrit.openafs.org/4435
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/afs/VNOPS/afs_vnop_flock.c

index 1557e2a..750eb78 100644 (file)
@@ -240,6 +240,8 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
 #endif
     ObtainWriteLock(&avc->lock, 118);
     if (acom & LOCK_UN) {
+       int stored_segments = 0;
+     retry_unlock:
 
 /* defect 3083 */
 
@@ -286,7 +288,14 @@ HandleFlock(register struct vcache *avc, int acom, struct vrequest *areq,
                }
            }
        } else if (avc->flockCount == -1) {
-           afs_StoreAllSegments(avc, areq, AFS_ASYNC); /* fsync file early */
+           if (!stored_segments) {
+               afs_StoreAllSegments(avc, areq, AFS_ASYNC);     /* fsync file early */
+               /* afs_StoreAllSegments can drop and reacquire the write lock
+                * on avc and GLOCK, so the flocks may be completely different
+                * now. Go back and perform all checks again. */
+                stored_segments = 1;
+                goto retry_unlock;
+           }
            avc->flockCount = 0;
            /* And remove the (only) exclusive lock entry from the list... */
            osi_FreeSmallSpace(avc->slocks);