X-Git-Url: http://git.openafs.org/?p=openafs.git;a=blobdiff_plain;f=src%2Fvolser%2Fvoltrans.c;h=7a7af3e3dd1a95df592af7b259c1b6c1aa69415e;hp=158fec603c3070e6feda9ba1a2197bdc73afb431;hb=930d8ee638112ca8bf27a9528c0a527cfab54c7d;hpb=89b50fdec9ab2dafe24b873f25c2cdb71b154e44 diff --git a/src/volser/voltrans.c b/src/volser/voltrans.c index 158fec6..7a7af3e 100644 --- a/src/volser/voltrans.c +++ b/src/volser/voltrans.c @@ -180,7 +180,6 @@ GCTrans(void) VTRANS_LOCK; for (tt = allTrans; tt; tt = nt) { - nt = tt->next; /* remember in case we zap it */ if (tt->time + OLDTRANSWARN < now) { Log("trans %u on volume %" AFS_VOLID_FMT " %s than %d seconds\n", tt->tid, afs_printable_VolumeId_lu(tt->volid), @@ -206,12 +205,27 @@ GCTrans(void) VTRANS_UNLOCK; VPurgeVolume(&error, tt->volume); + /* + * While the lock was dropped, tt->next may have changed. + * Therefore, defer reading tt->next until _after_ we regain the lock. + */ VTRANS_LOCK; } - - DeleteTrans(tt, 0); /* drops refCount or deletes it */ + nt = tt->next; + /* + * DeleteTrans() will decrement tt->refCount; if it falls to 0, it will + * also delete tt itself. Therefore, we must read tt->next _before_ + * calling DeleteTrans(). + */ + DeleteTrans(tt, 0); GCDeletes++; + continue; } + /* + * This path never dropped VTRANS_LOCK or modified the allTrans list. + * Therefore, no special care is required to determine the next trans in the chain. + */ + nt = tt->next; } VTRANS_UNLOCK; return 0;