#include <afs/dir.h>
#include <afs/afsutil.h>
#include <afs/vol_prototypes.h>
+#include <afs/errors.h>
#include "volser.h"
+#include "voltrans_inline.h"
#include "volint.h"
-#include "volser_prototypes.h"
+#include "volser_internal.h"
#include "physio.h"
#include "dumpstuff.h"
/* this call unlocks all of the partition locks we've set */
int
-VPFullUnlock(void)
+VPFullUnlock_r(void)
{
register struct DiskPartition64 *tp;
for (tp = DiskPartitionList; tp; tp = tp->next) {
return 0;
}
+int
+VPFullUnlock(void)
+{
+ int code;
+ VOL_LOCK;
+ code = VPFullUnlock_r();
+ VOL_UNLOCK;
+ return code;
+}
+
/* get partition id from a name */
afs_int32
PartitionID(char *aname)
return 0;
}
+static struct Volume *
+VAttachVolumeByName_retry(Error *ec, char *partition, char *name, int mode)
+{
+ struct Volume *vp;
+
+ *ec = 0;
+ vp = VAttachVolumeByName(ec, partition, name, mode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ {
+ int i;
+ /*
+ * The fileserver will take care of keeping track of how many
+ * demand-salvages have been performed, and will force the volume to
+ * ERROR if we've done too many. The limit on This loop is just a
+ * failsafe to prevent trying to salvage forever. We want to attempt
+ * attachment at least SALVAGE_COUNT_MAX times, since we want to
+ * avoid prematurely exiting this loop, if we can.
+ */
+ for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+ sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+ vp = VAttachVolumeByName(ec, partition, name, mode);
+ }
+
+ if (*ec == VSALVAGING) {
+ *ec = VSALVAGE;
+ }
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+ return vp;
+}
+
+static struct Volume *
+VAttachVolume_retry(Error *ec, afs_uint32 avolid, int amode)
+{
+ struct Volume *vp;
+
+ *ec = 0;
+ vp = VAttachVolume(ec, avolid, amode);
+
+#ifdef AFS_DEMAND_ATTACH_FS
+ {
+ int i;
+ /* see comment above in VAttachVolumeByName_retry */
+ for (i = 0; i < SALVAGE_COUNT_MAX*2 && *ec == VSALVAGING; i++) {
+ sleep(SALVAGE_PRIO_UPDATE_INTERVAL);
+ vp = VAttachVolume(ec, avolid, amode);
+ }
+
+ if (*ec == VSALVAGING) {
+ *ec = VSALVAGE;
+ }
+ }
+#endif /* AFS_DEMAND_ATTACH_FS */
+
+ return vp;
+}
+
/* the only attach function that takes a partition is "...ByName", so we use it */
-struct Volume *
+static struct Volume *
XAttachVolume(afs_int32 *error, afs_uint32 avolid, afs_int32 apartid, int amode)
{
char pbuf[30], vbuf[20];
- register struct Volume *tv;
if (ConvertPartition(apartid, pbuf, sizeof(pbuf))) {
*error = EINVAL;
*error = EINVAL;
return NULL;
}
- tv = VAttachVolumeByName((Error *)error, pbuf, vbuf, amode);
- return tv;
+
+ return VAttachVolumeByName_retry((Error *)error, pbuf, vbuf, amode);
}
/* Adapted from the file server; create a root directory for this volume */
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;
}
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;
TRELE(tt);
return VOLSERVOLBUSY;
}
- strcpy(tt->lastProcName, "Clone");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "Clone");
if (purgeId) {
- purgevp = VAttachVolume(&error, purgeId, V_VOLUPD);
+ purgevp = VAttachVolume_retry(&error, purgeId, V_VOLUPD);
if (error) {
Log("1 Volser: Clone: Could not attach 'purge' volume %u; clone aborted\n", purgeId);
goto fail;
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt)) {
tt = (struct volser_trans *)0;
error = VOLSERTRELE_ERROR;
if (newvp)
VDetachVolume(&code, newvp);
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
if (ttc)
TRELE(tt);
return VOLSERVOLBUSY;
}
- strcpy(tt->lastProcName, "ReClone");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "ReClone");
originalvp = tt->volume;
if ((V_type(originalvp) == backupVolume)
goto fail;
}
- clonevp = VAttachVolume(&error, cloneId, V_VOLUPD);
+ clonevp = VAttachVolume_retry(&error, cloneId, V_VOLUPD);
if (error) {
Log("1 Volser: can't attach clone %d\n", cloneId);
goto fail;
LogError(error);
goto fail;
}
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
if (TRELE(tt)) {
tt = (struct volser_trans *)0;
error = VOLSERTRELE_ERROR;
if (clonevp)
VDetachVolume(&code, clonevp);
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
if (ttc)
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;
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;
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 */
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;
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);
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) {
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;
rx_DestroyConnection(tcon);
}
if (tt) {
- tt->rxCallPtr = (struct rx_call *)0;
+ TClearRxCall(tt);
TRELE(tt);
}
return code;
return ENOENT;
}
vp = tt->volume;
- strcpy(tt->lastProcName, "ForwardMulti");
+ TSetRxCall(tt, NULL, "ForwardMulti");
/* (fromDate == 0) ==> full dump */
is_incremental = (fromDate ? 1 : 0);
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;
}
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;
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);
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;
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;
}
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;
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;
}
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;
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;
}
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;
* Copy out the stat fields in a single operation.
*/
if ((now - hdr->dayUseDate) > OneDay) {
- memset((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
+ memset(&(handle->volinfo_ptr.ext->stat_reads[0]),
0, numStatBytes);
} else {
memcpy((char *)&(handle->volinfo_ptr.ext->stat_reads[0]),
}
/* Get volume from volserver */
- tv = VAttachVolumeByName(&error, pname, volname, V_PEEK);
+ tv = VAttachVolumeByName_retry(&error, pname, volname, V_PEEK);
if (error) {
Log("1 Volser: GetVolInfo: Could not attach volume %u (%s:%s) error=%d\n",
volumeId, pname, volname, error);
{
transDebugInfo *pntr;
afs_int32 allocSize = 50;
- struct volser_trans *tt, *allTrans;
+ struct volser_trans *tt, *nt, *allTrans;
transInfo->transDebugEntries_val =
(transDebugInfo *) malloc(allocSize * sizeof(transDebugInfo));
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 */
- for (tt = allTrans; tt; tt = tt->next) { /*copy relevant info into pntr */
+ goto done; /*no active transactions */
+ for (tt = allTrans; tt; tt = nt) { /*copy relevant info into pntr */
+ nt = tt->next;
+ VTRANS_OBJ_LOCK(tt);
pntr->tid = tt->tid;
pntr->time = tt->time;
pntr->creationTime = tt->creationTime;
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 */
}
}
+done:
+ VTRANS_UNLOCK;
return 0;
}
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetIdsTypes");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetIdsTypes");
tv = tt->volume;
V_type(tv) = type;
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;
TRELE(tt);
return ENOENT;
}
- strcpy(tt->lastProcName, "SetDate");
- tt->rxCallPtr = acid;
+ TSetRxCall(tt, acid, "SetDate");
tv = tt->volume;
V_creationDate(tv) = 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;
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;
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) {
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);