volser transaction object race conditions
authorMichael Meffie <mmeffie@sinenomine.net>
Thu, 22 Oct 2009 19:51:33 +0000 (15:51 -0400)
committerDerrick Brashear <shadow|account-1000005@unknown>
Fri, 23 Oct 2009 20:48:26 +0000 (13:48 -0700)
Fix the transaction object races between VolMonitor and the
volume operation procedures which can cause the volume
server to crash.

Add a per transaction object mutex to safely set the
transaction call pointer and name. Fix VolMonitor to safely
traverse the transaction list and to access the call pointer
and last proc name while copying info to send to the vos
client.  Fix the sleep thread to safely access the last proc
name.

FIXES 125479

Change-Id: I59595b93522d111b6a771d3d93c246bfc2ce65de
Reviewed-on: http://gerrit.openafs.org/718
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Tested-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/volser/Makefile.in
src/volser/volmain.c
src/volser/volprocs.c
src/volser/volser.p.h
src/volser/voltrans.c
src/volser/voltrans_inline.h [new file with mode: 0644]

index 7626054..ac776c6 100644 (file)
@@ -15,7 +15,8 @@ HELPER_SPLINT=@HELPER_SPLINT@
 
 
 VINCLS=${TOP_INCDIR}/afs/partition.h ${TOP_INCDIR}/afs/volume.h \
-       ${TOP_INCDIR}/afs/vlserver.h vol.h dump.h volser.h  lockdata.h
+       ${TOP_INCDIR}/afs/vlserver.h vol.h dump.h volser.h  lockdata.h \
+       voltrans_inline.h
 
 RINCLS=${TOP_INCDIR}/rx/rx.h ${TOP_INCDIR}/rx/xdr.h \
        ${TOP_INCDIR}/afs/keys.h ${TOP_INCDIR}/afs/cellconfig.h \
index fb28bb5..244688f 100644 (file)
@@ -184,13 +184,17 @@ BKGSleep(void *unused)
 #endif
            VTRANS_LOCK;
            for (tt = TransList(); tt; tt = tt->next) {
+                VTRANS_OBJ_LOCK(tt);
                if ((strcmp(tt->lastProcName, "DeleteVolume") == 0)
                    || (strcmp(tt->lastProcName, "Clone") == 0)
                    || (strcmp(tt->lastProcName, "ReClone") == 0)
                    || (strcmp(tt->lastProcName, "Forward") == 0)
                    || (strcmp(tt->lastProcName, "Restore") == 0)
-                   || (strcmp(tt->lastProcName, "ForwardMulti") == 0))
+                   || (strcmp(tt->lastProcName, "ForwardMulti") == 0)) {
+                    VTRANS_OBJ_UNLOCK(tt);
                    break;
+                }
+                VTRANS_OBJ_UNLOCK(tt);
            }
            if (tt) {
                VTRANS_UNLOCK;
index 18cf505..9afc899 100644 (file)
@@ -64,6 +64,7 @@
 #include <afs/vol_prototypes.h>
 
 #include "volser.h"
+#include "voltrans_inline.h"
 #include "volint.h"
 
 #include "volser_internal.h"
@@ -498,12 +499,13 @@ VolCreateVolume(struct rx_call *acid, afs_int32 apart, char *aname,
        VDetachVolume(&junk, vp);       /* rather return the real error code */
        return error;
     }
+    VTRANS_OBJ_LOCK(tt);
     tt->volume = vp;
     *atrans = tt->tid;
-    strcpy(tt->lastProcName, "CreateVolume");
-    tt->rxCallPtr = acid;
+    TSetRxCall_r(tt, acid, "CreateVolume");
+    VTRANS_OBJ_UNLOCK(tt);
     Log("1 Volser: CreateVolume: volume %u (%s) created\n", volumeID, aname);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
     return 0;
@@ -539,12 +541,13 @@ VolDeleteVolume(struct rx_call *acid, afs_int32 atrans)
     }
     if (DoLogging)
        Log("%s is executing Delete Volume %u\n", caller, tt->volid);
-    strcpy(tt->lastProcName, "DeleteVolume");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "DeleteVolume");
     VPurgeVolume(&error, tt->volume);  /* don't check error code, it is not set! */
     V_destroyMe(tt->volume) = DESTROY_ME; /* so endtrans does the right fssync opcode */
+    VTRANS_OBJ_LOCK(tt);
     tt->vflags |= VTDeleted;   /* so we know not to do anything else to it */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -619,8 +622,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        TRELE(tt);
        return VOLSERVOLBUSY;
     }
-    strcpy(tt->lastProcName, "Clone");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "Clone");
 
 
     if (purgeId) {
@@ -725,7 +727,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt)) {
        tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
@@ -740,7 +742,7 @@ VolClone(struct rx_call *acid, afs_int32 atrans, afs_uint32 purgeId,
     if (newvp)
        VDetachVolume(&code, newvp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     if (ttc)
@@ -791,8 +793,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        TRELE(tt);
        return VOLSERVOLBUSY;
     }
-    strcpy(tt->lastProcName, "ReClone");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "ReClone");
 
     originalvp = tt->volume;
     if ((V_type(originalvp) == backupVolume)
@@ -892,7 +893,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt)) {
        tt = (struct volser_trans *)0;
        error = VOLSERTRELE_ERROR;
@@ -911,7 +912,7 @@ VolReClone(struct rx_call *acid, afs_int32 atrans, afs_int32 cloneId)
     if (clonevp)
        VDetachVolume(&code, clonevp);
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     if (ttc)
@@ -976,11 +977,13 @@ VolTransCreate(struct rx_call *acid, afs_uint32 volume, afs_int32 partition,
        DeleteTrans(tt, 1);
        return error;
     }
+    VTRANS_OBJ_LOCK(tt);
     tt->volume = tv;
     *ttid = tt->tid;
     tt->iflags = iflags;
     tt->vflags = 0;
-    strcpy(tt->lastProcName, "TransCreate");
+    TSetRxCall_r(tt, NULL, "TransCreate");
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1036,10 +1039,9 @@ VolGetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 *aflags)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetFlags");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetFlags");
     *aflags = tt->vflags;
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1081,8 +1083,7 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetFlags");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetFlags");
     vp = tt->volume;           /* pull volume out of transaction */
 
     /* check if we're allowed to make any updates */
@@ -1104,8 +1105,10 @@ VolSetFlags(struct rx_call *acid, afs_int32 atid, afs_int32 aflags)
        V_inService(vp) = 1;
     }
     VUpdateVolume(&error, vp);
+    VTRANS_OBJ_LOCK(tt);
     tt->vflags = aflags;
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
@@ -1160,7 +1163,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        return ENOENT;
     }
     vp = tt->volume;
-    strcpy(tt->lastProcName, "Forward");
+    TSetRxCall(tt, NULL, "Forward");
 
     /* get auth info for the this connection (uses afs from ticket file) */
     code = afsconf_ClientAuth(tdir, &securityObject, &securityIndex);
@@ -1175,12 +1178,12 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
                         htons(destination->destPort), VOLSERVICE_ID,
                         securityObject, securityIndex);
     if (!tcon) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOTCONN;
     }
     tcall = rx_NewCall(tcon);
-    tt->rxCallPtr = tcall;
+    TSetRxCall(tt, tcall, "Forward");
     /* start restore going.  fromdate == 0 --> doing an incremental dump/restore */
     code = StartAFSVolRestore(tcall, destTrans, (fromDate ? 1 : 0), cookie);
     if (code) {
@@ -1192,7 +1195,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
     if (code)
        goto fail;
     EndAFSVolRestore(tcall);   /* probably doesn't do much */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     code = rx_EndCall(tcall, 0);
     rx_DestroyConnection(tcon);        /* done with the connection */
     tcon = NULL;
@@ -1209,7 +1212,7 @@ VolForward(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        rx_DestroyConnection(tcon);
     }
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
     }
     return code;
@@ -1260,7 +1263,7 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
        return ENOENT;
     }
     vp = tt->volume;
-    strcpy(tt->lastProcName, "ForwardMulti");
+    TSetRxCall(tt, NULL, "ForwardMulti");
 
     /* (fromDate == 0) ==> full dump */
     is_incremental = (fromDate ? 1 : 0);
@@ -1336,7 +1339,7 @@ SAFSVolForwardMultiple(struct rx_call *acid, afs_int32 fromTrans, afs_int32
     free(tcalls);
 
     if (tt) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        if (TRELE(tt) && !code) /* return the first code if it's set */
            return VOLSERTRELE_ERROR;
     }
@@ -1383,16 +1386,15 @@ VolDump(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "Dump");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "Dump");
     code = DumpVolume(acid, tt->volume, fromDate, (flags & VOLDUMPV2_OMITDIRS)
                      ? 0 : 1); /* squirt out the volume's data, too */
     if (code) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return code;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
 
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
@@ -1432,14 +1434,13 @@ VolRestore(struct rx_call *acid, afs_int32 atrans, afs_int32 aflags,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "Restore");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "Restore");
 
     DFlushVolume(V_parentId(tt->volume)); /* Ensure dir buffers get dropped */
 
     code = RestoreVolume(acid, tt->volume, (aflags & 1), cookie);      /* last is incrementalp */
     FSYNC_VolOp(tt->volid, NULL, FSYNC_VOL_BREAKCBKS, 0l, NULL);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     tcode = TRELE(tt);
 
     return (code ? code : tcode);
@@ -1503,13 +1504,12 @@ VolSetForwarding(struct rx_call *acid, afs_int32 atid, afs_int32 anewsite)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetForwarding");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetForwarding");
     if (volutil_PartitionName2_r(tt->partition, partName, sizeof(partName)) != 0) {
        partName[0] = '\0';
     }
     FSYNC_VolOp(tt->volid, partName, FSYNC_VOL_MOVE, anewsite, NULL);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1545,11 +1545,10 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetStatus");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetStatus");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
@@ -1571,7 +1570,7 @@ VolGetStatus(struct rx_call *acid, afs_int32 atrans,
     astatus->expirationDate = td->expirationDate;
     astatus->backupDate = td->backupDate;
     astatus->copyDate = td->copyDate;
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -1609,11 +1608,10 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetStatus");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetStatus");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
@@ -1633,7 +1631,7 @@ VolSetInfo(struct rx_call *acid, afs_int32 atrans,
     if (astatus->spare2 != -1)
        td->volUpdateCounter = (unsigned int)astatus->spare2;
     VUpdateVolume(&error, tv);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
     return 0;
@@ -1670,11 +1668,10 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetName");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetName");
     tv = tt->volume;
     if (!tv) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return ENOENT;
     }
@@ -1682,13 +1679,13 @@ VolGetName(struct rx_call *acid, afs_int32 atrans, char **aname)
     td = &tv->header->diskstuff;
     len = strlen(td->name) + 1;        /* don't forget the null */
     if (len >= SIZE) {
-       tt->rxCallPtr = (struct rx_call *)0;
+        TClearRxCall(tt);
        TRELE(tt);
        return E2BIG;
     }
     *aname = (char *)realloc(*aname, len);
     strcpy(*aname, td->name);
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -2712,10 +2709,15 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
        return ENOMEM;
     pntr = transInfo->transDebugEntries_val;
     transInfo->transDebugEntries_len = 0;
+
+    VTRANS_LOCK;
     allTrans = TransList();
     if (allTrans == (struct volser_trans *)0)
-       return 0;               /*no active transactions */
+       goto done;              /*no active transactions */
     for (tt = allTrans; tt; tt = tt->next) {   /*copy relevant info into pntr */
+        THOLD(tt);  /* do not delete tt while copying info */
+        VTRANS_UNLOCK;
+        VTRANS_OBJ_LOCK(tt);
        pntr->tid = tt->tid;
        pntr->time = tt->time;
        pntr->creationTime = tt->creationTime;
@@ -2734,6 +2736,7 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
            pntr->lastSendTime = tt->rxCallPtr->lastSendTime;
            pntr->lastReceiveTime = tt->rxCallPtr->lastReceiveTime;
        }
+        VTRANS_OBJ_UNLOCK(tt);
        pntr++;
        transInfo->transDebugEntries_len += 1;
        if ((allocSize - transInfo->transDebugEntries_len) < 5) {       /*alloc some more space */
@@ -2750,7 +2753,11 @@ VolMonitor(struct rx_call *acid, transDebugEntries *transInfo)
            /*set pntr to right position */
        }
 
+        TRELE(tt);
+        VTRANS_LOCK;
     }
+done:
+    VTRANS_UNLOCK;
 
     return 0;
 }
@@ -2792,8 +2799,7 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetIdsTypes");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetIdsTypes");
     tv = tt->volume;
 
     V_type(tv) = type;
@@ -2807,13 +2813,13 @@ VolSetIdsTypes(struct rx_call *acid, afs_int32 atid, char name[],
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
     return error;
   fail:
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
     return error;
@@ -2849,8 +2855,7 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "SetDate");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "SetDate");
     tv = tt->volume;
 
     V_creationDate(tv) = cdate;
@@ -2860,13 +2865,13 @@ VolSetDate(struct rx_call *acid, afs_int32 atid, afs_int32 cdate)
        LogError(error);
        goto fail;
     }
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
 
     return error;
   fail:
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt) && !error)
        return VOLSERTRELE_ERROR;
     return error;
@@ -2950,10 +2955,9 @@ SAFSVolGetSize(struct rx_call *acid, afs_int32 fromTrans, afs_int32 fromDate,
        TRELE(tt);
        return ENOENT;
     }
-    strcpy(tt->lastProcName, "GetSize");
-    tt->rxCallPtr = acid;
+    TSetRxCall(tt, acid, "GetSize");
     code = SizeDumpVolume(acid, tt->volume, fromDate, 1, size);        /* measure volume's data */
-    tt->rxCallPtr = (struct rx_call *)0;
+    TClearRxCall(tt);
     if (TRELE(tt))
        return VOLSERTRELE_ERROR;
 
@@ -3015,9 +3019,11 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
         VDetachVolume(&code2, newvol);
         return VOLSERVOLBUSY;
     } 
+    VTRANS_OBJ_LOCK(tt);
     tt->iflags = ITBusy;
     tt->vflags = 0;
-    strcpy(tt->lastProcName, "SplitVolume");
+    TSetRxCall_r(tt, NULL, "SplitVolume");
+    VTRANS_OBJ_UNLOCK(tt);
 
     tt2 = NewTrans(new, V_device(newvol));
     if (!tt2) {
@@ -3030,9 +3036,11 @@ SAFSVolSplitVolume(struct rx_call *acall, afs_uint32 vid, afs_uint32 new,
         VDetachVolume(&code2, newvol);
         return VOLSERVOLBUSY;
     } 
+    VTRANS_OBJ_LOCK(tt2);
     tt2->iflags = ITBusy;
     tt2->vflags = 0;
-    strcpy(tt2->lastProcName, "SplitVolume");
+    TSetRxCall_r(tt2, NULL, "SplitVolume");
+    VTRANS_OBJ_UNLOCK(tt2);
 
     code = split_volume(acall, vol, newvol, where, verbose);
 
index 19121e6..7fe5995 100644 (file)
@@ -58,6 +58,9 @@ struct volser_trans {
     /* the fields below are useful for debugging */
     char lastProcName[30];     /* name of the last procedure which used transaction */
     struct rx_call *rxCallPtr; /* pointer to latest associated rx_call */
+#ifdef AFS_PHTREAD_ENV
+    pthread_mutex_t lock;       /* per transaction lock */
+#endif
 
 };
 
@@ -72,6 +75,22 @@ struct volser_dest {
     afs_int32 destSSID;
 };
 
+#ifdef AFS_PHTREAD_ENV
+#define VTRANS_OBJ_LOCK_INIT(tt) \
+  assert(pthread_mutex_init(&((tt)->lock)) == 0)
+#define VTRANS_OBJ_LOCK_DESTROY(tt) \
+  assert(pthread_mutex_destroy(&((tt)->lock)) == 0)
+#define VTRANS_OBJ_LOCK(tt) \
+  assert(pthread_mutex_lock(&((tt)->lock)) == 0)
+#define VTRANS_OBJ_UNLOCK(tt) \
+  assert(pthread_mutex_unlock(&((tt)->lock)) == 0)
+#else
+#define VTRANS_OBJ_LOCK_INIT(tt)
+#define VTRANS_OBJ_LOCK_DESTROY(tt)
+#define VTRANS_OBJ_LOCK(tt)
+#define VTRANS_OBJ_UNLOCK(tt)
+#endif /* AFS_PTHREAD_ENV */
+
 #define        MAXHELPERS          10
 /* flags for vol helper busyFlags array.  First, VHIdle goes on when a server
  * becomes idle.  Next, idle flag is cleared and VHRequest goes on when
index bda887a..dba02fd 100644 (file)
@@ -98,6 +98,7 @@ NewTrans(afs_int32 avol, afs_int32 apart)
     tt->time = FT_ApproxTime();
     tt->tid = transCounter++;
     tt->next = allTrans;
+    VTRANS_OBJ_LOCK_INIT(tt);
     allTrans = tt;
     VTRANS_UNLOCK;
     return tt;
@@ -147,6 +148,7 @@ DeleteTrans(register struct volser_trans *atrans, afs_int32 lock)
            if (tt->rxCallPtr)
                rxi_CallError(tt->rxCallPtr, RX_CALL_DEAD);
            *lt = tt->next;
+            VTRANS_OBJ_LOCK_DESTROY(tt);
            free(tt);
            if (lock) VTRANS_UNLOCK;
            return 0;
diff --git a/src/volser/voltrans_inline.h b/src/volser/voltrans_inline.h
new file mode 100644 (file)
index 0000000..b3736f7
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * Copyright 2009, Sine Nomine Associates
+ * All Rights Reserved.
+ *
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+#ifndef _VOLTRANS_INLINE_H
+#define _VOLTRANS_INLINE_H
+
+#include "volser.h"
+
+/**
+ * Save the most recent call and procedure name for
+ * transaction status reporting.
+ *
+ * \param tt    transaction object
+ * \param call  the rx call object, NULL if none
+ * \param name  procedure name, NULL if none
+ *
+ * \pre VTRANS_OBJ_LOCK on tt must be held
+ */
+static_inline void
+TSetRxCall_r(struct volser_trans *tt, struct rx_call *call, const char *name)
+{
+    if (name) {
+        strlcpy(tt->lastProcName, name, sizeof(tt->lastProcName));
+    }
+    if (call) {
+        tt->rxCallPtr = call;
+    }
+}
+
+/**
+ * Clears the most recent call object.
+ *
+ * \param tt    transaction object
+ *
+ * \pre VTRANS_OBJ_LOCK on tt must be held
+ */
+static_inline void
+TClearRxCall_r(struct volser_trans *tt)
+{
+    tt->rxCallPtr = NULL;
+}
+
+/**
+ * Save the most recent call and procedure name for
+ * transaction status reporting.
+ *
+ * \param tt    transaction object
+ * \param call  the rx call object, NULL if none
+ * \param name  procedure name, NULL if none
+ *
+ * \pre VTRANS_OBJ_LOCK on tt must not be held
+ */
+static_inline void
+TSetRxCall(struct volser_trans *tt, struct rx_call *call, const char *name)
+{
+    VTRANS_OBJ_LOCK(tt);
+    TSetRxCall_r(tt, call, name);
+    VTRANS_OBJ_UNLOCK(tt);
+}
+
+/**
+ * Clears the most recent call object.
+ *
+ * \param tt    transaction object
+ *
+ * \pre VTRANS_OBJ_LOCK on tt must not be held
+ */
+static_inline void
+TClearRxCall(struct volser_trans *tt)
+{
+    VTRANS_OBJ_LOCK(tt);
+    TClearRxCall_r(tt);
+    VTRANS_OBJ_UNLOCK(tt);
+}
+
+#endif /* _VOLTRANS_INLINE_H */