#include <afsconfig.h>
#include <afs/param.h>
-RCSID
- ("$Header$");
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#include <time.h> /* ANSI standard location for time stuff */
+#include <string.h>
#ifdef AFS_NT40_ENV
#include <fcntl.h>
#include <io.h>
#else
#include <sys/time.h>
#include <sys/file.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#else
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
+#include <unistd.h>
#endif
#include <afs/assert.h>
#include <afs/nfs.h> /* yuck. This is an abomination. */
#include <lwp.h>
#include <rx/rx.h>
-#include <afscbint.h>
+#include <afs/afscbint.h>
#include <afs/afsutil.h>
#include <lock.h>
#include <afs/ihandle.h>
extern afsUUID FS_HostUUID;
extern int hostCount;
+
+#ifndef INTERPRET_DUMP
static int ShowProblems = 1;
+#endif
struct cbcounters cbstuff;
}; /* Anything more: MinTimeOut */
/* minimum time given for a call back */
+#ifndef INTERPRET_DUMP
static int MinTimeOut = (7 * 60);
+#endif
/* Heads of CB queues; a timeout index is 1+index into this array */
static afs_uint32 timeout[CB_NUM_TIMEOUT_QUEUES];
/* Prototypes for static routines */
static struct FileEntry *FindFE(register AFSFid * fid);
+
+#ifndef INTERPRET_DUMP
static struct CallBack *iGetCB(register int *nused);
static int iFreeCB(register struct CallBack *cb, register int *nused);
static struct FileEntry *iGetFE(register int *nused);
static int MultiBreakVolumeCallBack_r(struct host *host, int isheld,
struct VCBParams *parms, int deletefe);
static int MultiBreakVolumeCallBack(struct host *host, int isheld,
- struct VCBParams *parms);
+ void *rock);
static int MultiBreakVolumeLaterCallBack(struct host *host, int isheld,
- struct VCBParams *parms);
+ void *rock);
static int GetSomeSpace_r(struct host *hostp, int locked);
static int ClearHostCallbacks_r(struct host *hp, int locked);
+#endif
#define GetCB() ((struct CallBack *)iGetCB(&cbstuff.nCBs))
#define GetFE() ((struct FileEntry *)iGetFE(&cbstuff.nFEs))
CcdelB++;
*cbp = cb->cnext;
FreeCB(cb);
- if (deletefe && (--fe->ncbs == 0))
+ if ((--fe->ncbs == 0) && deletefe)
FDel(fe);
return 0;
}
AddCallBack1(struct host *host, AFSFid * fid, afs_uint32 * thead, int type,
int locked)
{
- int retVal;
+ int retVal = 0;
H_LOCK;
if (!locked) {
h_Lock_r(host);
}
- retVal = AddCallBack1_r(host, fid, thead, type, 1);
+ if (!(host->hostFlags & HOSTDELETED))
+ retVal = AddCallBack1_r(host, fid, thead, type, 1);
if (!locked) {
h_Unlock_r(host);
struct FileEntry *fe;
struct CallBack *cb = 0, *lastcb = 0;
struct FileEntry *newfe = 0;
- afs_uint32 time_out;
+ afs_uint32 time_out = 0;
afs_uint32 *Thead = thead;
struct CallBack *newcb = 0;
int safety;
+ cbstuff.AddCallBacks++;
+
host->Console |= 2;
/* allocate these guys first, since we can't call the allocator with
if (!locked) {
h_Lock_r(host); /* this can yield, so do it before we get any */
/* fragile info */
+ if (host->hostFlags & HOSTDELETED) {
+ host->Console &= ~2;
+ h_Unlock_r(host);
+ return 0;
+ }
}
fe = FindFE(fid);
return 0;
}
+static int
+CompareCBA(const void *e1, const void *e2)
+{
+ const struct cbstruct *cba1 = (const struct cbstruct *)e1;
+ const struct cbstruct *cba2 = (const struct cbstruct *)e2;
+ return ((cba1->hp)->index - (cba2->hp)->index);
+}
+
/* Take an array full of hosts, all held. Break callbacks to them, and
* release the holds once you're done, except don't release xhost. xhost
* may be NULL. Currently only works for a single Fid in afidp array.
assert(ncbas <= MAX_CB_HOSTS);
+ /* sort cba list to avoid makecall issues */
+ qsort(cba, ncbas, sizeof(struct cbstruct), CompareCBA);
+
/* set up conns for multi-call */
for (i = 0, j = 0; i < ncbas; i++) {
struct host *thishost = cba[i].hp;
if (!hp || !idx) {
ViceLog(0,
- ("BCB: INTERNAL ERROR: hp=%x, cba=%x, thead=%u\n",
+ ("BCB: INTERNAL ERROR: hp=%p, cba=%p, thead=%u\n",
hp, cba, idx));
} else {
/*
if (MultiBreakCallBackAlternateAddress(hp, afidp)) {
if (ShowProblems) {
ViceLog(7,
- ("BCB: Failed on file %u.%u.%u, Host %x (%s:%d) is down\n",
+ ("BCB: Failed on file %u.%u.%u, "
+ "Host %p (%s:%d) is down\n",
afidp->AFSCBFids_val->Volume,
afidp->AFSCBFids_val->Vnode,
afidp->AFSCBFids_val->Unique,
H_LOCK;
h_Lock_r(hp);
- hp->hostFlags |= VENUSDOWN;
- /**
- * We always go into AddCallBack1_r with the host locked
- */
- AddCallBack1_r(hp, afidp->AFSCBFids_val, itot(idx),
- CB_DELAYED, 1);
+ if (!(hp->hostFlags & HOSTDELETED)) {
+ hp->hostFlags |= VENUSDOWN;
+ /**
+ * We always go into AddCallBack1_r with the host locked
+ */
+ AddCallBack1_r(hp, afidp->AFSCBFids_val, itot(idx),
+ CB_DELAYED, 1);
+ }
h_Unlock_r(hp);
H_UNLOCK;
}
char hoststr[16];
ViceLog(7,
- ("BCB: BreakCallBack(Host %x all but %s:%d, (%u,%u,%u))\n",
+ ("BCB: BreakCallBack(Host %p all but %s:%d, (%u,%u,%u))\n",
xhost, afs_inet_ntoa_r(xhost->host, hoststr), ntohs(xhost->port),
fid->Volume, fid->Vnode, fid->Unique));
ViceLog(0, ("BCB: BOGUS! cb->hhead is NULL!\n"));
} else if (thishost->hostFlags & VENUSDOWN) {
ViceLog(7,
- ("BCB: %x (%s:%d) is down; delaying break call back\n",
+ ("BCB: %p (%s:%d) is down; delaying break call back\n",
thishost, afs_inet_ntoa_r(thishost->host, hoststr),
ntohs(thishost->port)));
cb->status = CB_DELAYED;
} else {
- h_Hold_r(thishost);
- cba[ncbas].hp = thishost;
- cba[ncbas].thead = cb->thead;
- ncbas++;
+ if (!(thishost->hostFlags & HOSTDELETED)) {
+ h_Hold_r(thishost);
+ cba[ncbas].hp = thishost;
+ cba[ncbas].thead = cb->thead;
+ ncbas++;
+ }
TDel(cb);
HDel(cb);
CDel(cb, 1); /* Usually first; so this delete
register afs_uint32 *pcb;
char hoststr[16];
+ H_LOCK;
cbstuff.DeleteCallBacks++;
- H_LOCK;
h_Lock_r(host);
+ /* do not care if the host has been HOSTDELETED */
fe = FindFE(fid);
if (!fe) {
h_Unlock_r(host);
pcb = FindCBPtr(fe, host);
if (!*pcb) {
ViceLog(8,
- ("DCB: No call back for host %x (%s:%d), (%u, %u, %u)\n",
+ ("DCB: No call back for host %p (%s:%d), (%u, %u, %u)\n",
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port),
fid->Volume, fid->Vnode, fid->Unique));
h_Unlock_r(host);
TDel(cb);
HDel(cb);
FreeCB(cb);
+ fe->ncbs--;
}
FDel(fe);
H_UNLOCK;
if (code) {
if (ShowProblems) {
ViceLog(0,
- ("CB: Call back connect back failed (in break delayed) for Host %x (%s:%d)\n",
+ ("CB: Call back connect back failed (in break delayed) "
+ "for Host %p (%s:%d)\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port)));
}
host->hostFlags |= VENUSDOWN;
} else {
ViceLog(25,
- ("InitCallBackState success on %x (%s:%d)\n",
- host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+ ("InitCallBackState success on %p (%s:%d)\n",
+ host, afs_inet_ntoa_r(host->host, hoststr),
+ ntohs(host->port)));
/* reset was done successfully */
host->hostFlags |= RESETDONE;
host->hostFlags &= ~VENUSDOWN;
int i;
if (ShowProblems) {
ViceLog(0,
- ("CB: XCallBackBulk failed, Host %x (%s:%d); callback list follows:\n",
+ ("CB: XCallBackBulk failed, Host %p (%s:%d); "
+ "callback list follows:\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port)));
}
for (i = 0; i < nfids; i++) {
if (ShowProblems) {
ViceLog(0,
- ("CB: Host %x (%s:%d), file %u.%u.%u (part of bulk callback)\n",
+ ("CB: Host %p (%s:%d), file %u.%u.%u "
+ "(part of bulk callback)\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port), fids[i].Volume,
fids[i].Vnode, fids[i].Unique));
cbstuff.nbreakers--;
/* If we succeeded it's always ok to unset HFE_LATER */
- if (!host->hostFlags & VENUSDOWN)
+ if (!(host->hostFlags & VENUSDOWN))
host->hostFlags &= ~HFE_LATER;
return (host->hostFlags & VENUSDOWN);
}
if (host->hostFlags & VENUSDOWN) {
h_Lock_r(host);
- if (host->hostFlags & HOSTDELETED) {
- h_Unlock_r(host);
- return 0; /* Release hold */
- }
- ViceLog(8,
- ("BVCB: volume call back for Host %x (%s:%d) failed\n",
- host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
+ /* Do not care if the host is now HOSTDELETED */
if (ShowProblems) {
ViceLog(0,
- ("CB: volume callback for Host %x (%s:%d) failed\n",
+ ("BVCB: volume callback for Host %p (%s:%d) failed\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port)));
}
** isheld is 1 if the host is held in BreakVolumeCallBacks
*/
static int
-MultiBreakVolumeCallBack(struct host *host, int isheld,
- struct VCBParams *parms)
+MultiBreakVolumeCallBack(struct host *host, int isheld, void *rock)
{
+ struct VCBParams *parms = (struct VCBParams *) rock;
+
int retval;
H_LOCK;
retval = MultiBreakVolumeCallBack_r(host, isheld, parms, 1);
** isheld is 1 if the host is held in BreakVolumeCallBacks
*/
static int
-MultiBreakVolumeLaterCallBack(struct host *host, int isheld,
- struct VCBParams *parms)
+MultiBreakVolumeLaterCallBack(struct host *host, int isheld, void *rock)
{
+ struct VCBParams *parms = (struct VCBParams *)rock;
int retval;
H_LOCK;
retval = MultiBreakVolumeCallBack_r(host, isheld, parms, 0);
register struct CallBack *cbnext;
for (cb = itocb(fe->firstcb); cb; cb = cbnext) {
host = h_itoh(cb->hhead);
- h_Hold_r(host);
- cbnext = itocb(cb->cnext);
- if (!tthead || (TNorm(tthead) < TNorm(cb->thead))) {
- tthead = cb->thead;
+
+ if (!(host->hostFlags & HOSTDELETED)) {
+ h_Hold_r(host);
+ if (!tthead || (TNorm(tthead) < TNorm(cb->thead))) {
+ tthead = cb->thead;
+ }
}
+ cbnext = itocb(cb->cnext);
TDel(cb);
HDel(cb);
FreeCB(cb);
henumParms.fid = &fid;
henumParms.thead = tthead;
H_UNLOCK;
- h_Enumerate(MultiBreakVolumeCallBack, (char *)&henumParms);
+ h_Enumerate(MultiBreakVolumeCallBack, &henumParms);
H_LOCK;
if (henumParms.ncbas) { /* do left-overs */
struct AFSCBFids tf;
fe->volid));
fid.Volume = fe->volid;
*feip = fe->fnext;
+ fe->status &= ~FE_LATER; /* not strictly needed */
/* Works since volid is deeper than the largest pointer */
tmpfe = (struct object *)fe;
tmpfe->next = (struct object *)myfe;
cbnext = itocb(cb->cnext);
host = h_itoh(cb->hhead);
if (cb->status == CB_DELAYED) {
- h_Hold_r(host);
- if (!tthead || (TNorm(tthead) < TNorm(cb->thead))) {
- tthead = cb->thead;
+ if (!(host->hostFlags & HOSTDELETED)) {
+ h_Hold_r(host);
+ if (!tthead || (TNorm(tthead) < TNorm(cb->thead))) {
+ tthead = cb->thead;
+ }
}
TDel(cb);
HDel(cb);
/* leave hold for MultiBreakVolumeCallBack to clear */
} else {
ViceLog(125,
- ("Found host %x (%s:%d) non-DELAYED cb for %u:%u:%u\n",
+ ("Found host %p (%s:%d) non-DELAYED cb for %u:%u:%u\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port), fe->vnode, fe->unique, fe->volid));
}
return (ntimedout > 0);
}
-static struct host *lih_host;
-static int lih_host_held;
+/**
+ * parameters to pass to lih*_r from h_Enumerate_r when trying to find a host
+ * from which to clear callbacks.
+ */
+struct lih_params {
+ /**
+ * Points to the least interesting host found; try to clear callbacks on
+ * this host after h_Enumerate_r(lih*_r)'ing.
+ */
+ struct host *lih;
+
+ /**
+ * The last host we got from lih*_r, but we couldn't clear its callbacks
+ * for some reason. Choose the next-best host after this one (with the
+ * current lih*_r, this means to only select hosts that have an ActiveCall
+ * newer than lastlih).
+ */
+ struct host *lastlih;
+};
+
+/* Value of host->refCount that allows us to reliably infer that
+ * host may be held by some other thread */
+#define OTHER_MUSTHOLD_LIH 2
/* This version does not allow 'host' to be selected unless its ActiveCall
- * is newer than 'hostp' which is the host with the oldest ActiveCall from
- * the last pass (if it is provided). We filter out any hosts that are
- * are held by other threads.
+ * is newer than 'params->lastlih' which is the host with the oldest
+ * ActiveCall from the last pass (if it is provided). We filter out any hosts
+ * that are are held by other threads.
+ *
+ * There is a small problem here, but it may not be easily fixable. Say we
+ * select some host A, and give it back to GetSomeSpace_r. GSS_r for some
+ * reason cannot clear the callbacks on A, and so calls us again with
+ * lastlih = A. Suppose there is another host B that has the same ActiveCall
+ * time as A. We will now skip over host B, since
+ * 'hostB->ActiveCall > hostA->ActiveCall' is not true. This could result in
+ * us prematurely going to the GSS_r 2nd or 3rd pass, and making us a little
+ * inefficient. This should be pretty rare, though, except perhaps in cases
+ * with very small numbers of hosts.
+ *
+ * Also filter out any hosts with HOSTDELETED set. h_Enumerate_r should in
+ * theory not give these to us anyway, but be paranoid.
*/
static int
-lih0_r(register struct host *host, register int held,
- register struct host *hostp)
+lih0_r(register struct host *host, register int flags, void *rock)
{
+ struct lih_params *params = (struct lih_params *)rock;
+
+ /* OTHER_MUSTHOLD_LIH is because the h_Enum loop holds us once */
if (host->cblist
- && (hostp && host != hostp)
- && (!held && !h_OtherHolds_r(host))
- && (!lih_host || host->ActiveCall < lih_host->ActiveCall)
- && (!hostp || host->ActiveCall > hostp->ActiveCall)) {
- if (lih_host != NULL && lih_host_held) {
- h_Release_r(lih_host);
+ && (!(host->hostFlags & HOSTDELETED))
+ && (host->refCount < OTHER_MUSTHOLD_LIH)
+ && (!params->lih || host->ActiveCall < params->lih->ActiveCall)
+ && (!params->lastlih || host->ActiveCall > params->lastlih->ActiveCall)) {
+
+ if (params->lih) {
+ h_Release_r(params->lih); /* release prev host */
}
- lih_host = host;
- lih_host_held = !held;
- held = 1;
+
+ h_Hold_r(host);
+ params->lih = host;
}
- return held;
+ return flags;
}
-/* This version does not allow 'host' to be selected unless its ActiveCall
- * is newer than 'hostp' which is the host with the oldest ActiveCall from
- * the last pass (if it is provided). In this second varient, we do not
- * prevent held hosts from being selected.
- */
+/* same as lih0_r, except we do not prevent held hosts from being selected. */
static int
-lih1_r(register struct host *host, register int held,
- register struct host *hostp)
+lih1_r(register struct host *host, register int flags, void *rock)
{
+ struct lih_params *params = (struct lih_params *)rock;
+
if (host->cblist
- && (hostp && host != hostp)
- && (!lih_host || host->ActiveCall < lih_host->ActiveCall)
- && (!hostp || host->ActiveCall > hostp->ActiveCall)) {
- if (lih_host != NULL && lih_host_held) {
- h_Release_r(lih_host);
+ && (!(host->hostFlags & HOSTDELETED))
+ && (!params->lih || host->ActiveCall < params->lih->ActiveCall)
+ && (!params->lastlih || host->ActiveCall > params->lastlih->ActiveCall)) {
+
+ if (params->lih) {
+ h_Release_r(params->lih); /* release prev host */
}
- lih_host = host;
- lih_host_held = !held;
- held = 1;
+
+ h_Hold_r(host);
+ params->lih = host;
}
- return held;
+ return flags;
}
/* This could be upgraded to get more space each time */
static int
GetSomeSpace_r(struct host *hostp, int locked)
{
- register struct host *hp, *hp1, *hp2;
+ struct host *hp;
+ struct lih_params params;
int i = 0;
cbstuff.GotSomeSpaces++;
}
i = 0;
- hp1 = NULL;
- hp2 = hostList;
+ params.lastlih = NULL;
+
do {
- lih_host = 0;
- h_Enumerate_r(i == 0 ? lih0_r : lih1_r, hp2, (char *)hp1);
- hp = lih_host;
+ params.lih = NULL;
+
+ h_Enumerate_r(i == 0 ? lih0_r : lih1_r, hostList, ¶ms);
+
+ hp = params.lih;
+ if (params.lastlih) {
+ h_Release_r(params.lastlih);
+ params.lastlih = NULL;
+ }
+
if (hp) {
- /* set in lih_r! private copy before giving up H_LOCK */
- int lih_host_held2=lih_host_held;
+ /* note that 'hp' was held by lih*_r; we will need to release it */
cbstuff.GSS4++;
if ((hp != hostp) && !ClearHostCallbacks_r(hp, 0 /* not locked or held */ )) {
- if (lih_host_held2)
- h_Release_r(hp);
+ h_Release_r(hp);
return 0;
}
- if (lih_host_held2)
- h_Release_r(hp);
- hp1 = hp;
- hp2 = hostList;
+
+ params.lastlih = hp;
+ /* params.lastlih will be released on the next iteration, after
+ * h_Enumerate_r */
+
} else {
/*
* Next time try getting callbacks from any host even if
- * it's deleted (that's actually great since we can freely
- * remove its callbacks) or it's held since the only other
- * option is starvation for the file server (i.e. until the
- * callback timeout arrives).
+ * it's held, since the only other option is starvation for
+ * the file server (i.e. until the callback timeout arrives).
*/
i++;
- hp1 = NULL;
- hp2 = hostList;
+ params.lastlih = NULL;
cbstuff.GSS1++;
ViceLog(5,
("GSS: Try harder for longest inactive host cnt= %d\n",
ClearHostCallbacks_r(struct host *hp, int locked)
{
int code;
- int held = 0;
char hoststr[16];
struct rx_connection *cb_conn = NULL;
ViceLog(5,
- ("GSS: Delete longest inactive host %x (%s:%d)\n",
+ ("GSS: Delete longest inactive host %p (%s:%d)\n",
hp, afs_inet_ntoa_r(hp->host, hoststr), ntohs(hp->port)));
- if (!(held = h_Held_r(hp)))
- h_Hold_r(hp);
+
+ if ((hp->hostFlags & HOSTDELETED)) {
+ /* hp could go away after reacquiring H_LOCK in h_NBLock_r, so we can't
+ * really use it; its callbacks will get cleared anyway when
+ * h_TossStuff_r gets its hands on it */
+ return 1;
+ }
+
+ h_Hold_r(hp);
/** Try a non-blocking lock. If the lock is already held return
* after releasing hold on hp
*/
if (!locked) {
- if (h_NBLock_r(hp)) {
- if (!held)
- h_Release_r(hp);
- return 1;
- }
+ if (h_NBLock_r(hp)) {
+ h_Release_r(hp);
+ return 1;
+ }
}
if (hp->Console & 2) {
/*
DeleteAllCallBacks_r(hp, 1);
if (hp->hostFlags & VENUSDOWN) {
hp->hostFlags &= ~RESETDONE; /* remember that we must do a reset */
- } else {
+ } else if (!(hp->hostFlags & HOSTDELETED)) {
/* host is up, try a call */
hp->hostFlags &= ~ALTADDR; /* alternate addresses are invalid */
cb_conn = hp->callback_rxcon;
hp->hostFlags |= RESETDONE;
}
}
- if (!locked) {
- h_Unlock_r(hp);
- }
- if (!held)
- h_Release_r(hp);
+ if (!locked)
+ h_Unlock_r(hp);
+ h_Release_r(hp);
return 0;
}
}
#define MAGIC 0x12345678 /* To check byte ordering of dump when it is read in */
+#define MAGICV2 0x12345679 /* To check byte ordering & version of dump when it is read in */
+
#ifndef INTERPRET_DUMP
ret = 1;
}
- done:
return ret;
}
}
}
- done:
return ret;
}
if ((fe->firstcb && !fe->ncbs) ||
(!fe->firstcb && fe->ncbs)) {
- ViceLog(0, ("cb_stateVerifyFE: error: fe->firstcb does not agree with fe->ncbs (fei=%d, fe->firstcb=%d, fe->ncbs=%d)\n",
- fetoi(fe), fe->firstcb, fe->ncbs));
+ ViceLog(0, ("cb_stateVerifyFE: error: fe->firstcb does not agree with fe->ncbs (fei=%lu, fe->firstcb=%lu, fe->ncbs=%lu)\n",
+ afs_printable_uint32_lu(fetoi(fe)),
+ afs_printable_uint32_lu(fe->firstcb),
+ afs_printable_uint32_lu(fe->ncbs)));
ret = 1;
}
if (cb_stateVerifyFCBList(state, fe)) {
- ViceLog(0, ("cb_stateVerifyFE: error: FCBList failed verification (fei=%d)\n", fetoi(fe)));
+ ViceLog(0, ("cb_stateVerifyFE: error: FCBList failed verification (fei=%lu)\n",
+ afs_printable_uint32_lu(fetoi(fe))));
ret = 1;
}
- done:
return ret;
}
}
}
- done:
return ret;
}
static int
cb_stateSaveFE(struct fs_dump_state * state, struct FileEntry * fe)
{
- int ret = 0, iovcnt, cbi, idx, len, written = 0;
+ int ret = 0, iovcnt, cbi, written = 0;
afs_uint32 fei;
struct callback_state_entry_header hdr;
struct FEDiskEntry fedsk;
}
iov[0].iov_base = (char *)&hdr;
- len = iov[0].iov_len = sizeof(hdr);
+ iov[0].iov_len = sizeof(hdr);
iov[1].iov_base = (char *)&fedsk;
- len += iov[1].iov_len = sizeof(struct FEDiskEntry);
+ iov[1].iov_len = sizeof(struct FEDiskEntry);
iovcnt = 2;
- for (cbi = fe->firstcb, cb = itocb(cbi), idx = 2;
+ for (cbi = fe->firstcb, cb = itocb(cbi);
cb != NULL;
- cbi = cb->cnext, cb = itocb(cbi), idx++, hdr.nCBs++) {
+ cbi = cb->cnext, cb = itocb(cbi), hdr.nCBs++) {
if (cbi > state->cb_hdr->cb_max) {
state->cb_hdr->cb_max = cbi;
}
- if (cb_stateCBToDiskEntry(cb, &cbdsk[idx])) {
+ if (cb_stateCBToDiskEntry(cb, &cbdsk[iovcnt])) {
ret = 1;
goto done;
}
- cbdsk[idx].index = cbi;
- iov[idx].iov_base = (char *)&cbdsk[idx];
- len += iov[idx].iov_len = sizeof(struct CBDiskEntry);
+ cbdsk[iovcnt].index = cbi;
+ iov[iovcnt].iov_base = (char *)&cbdsk[iovcnt];
+ iov[iovcnt].iov_len = sizeof(struct CBDiskEntry);
iovcnt++;
if ((iovcnt == 16) || (!cb->cnext)) {
if (fs_stateWriteV(state, iov, iovcnt)) {
}
written = 1;
iovcnt = 0;
- len = 0;
}
}
static int
cb_stateRestoreFE(struct fs_dump_state * state)
{
- int ret = 0, iovcnt, len, nCBs, idx;
+ int ret = 0, iovcnt, nCBs;
struct callback_state_entry_header hdr;
struct FEDiskEntry fedsk;
struct CBDiskEntry cbdsk[16];
struct iovec iov[16];
struct FileEntry * fe;
- struct CallBack * cb;
iov[0].iov_base = (char *)&hdr;
- len = iov[0].iov_len = sizeof(hdr);
+ iov[0].iov_len = sizeof(hdr);
iov[1].iov_base = (char *)&fedsk;
- len += iov[1].iov_len = sizeof(fedsk);
+ iov[1].iov_len = sizeof(fedsk);
iovcnt = 2;
if (fs_stateReadV(state, iov, iovcnt)) {
}
if (hdr.nCBs) {
- for (iovcnt = 0, idx = 0, len = 0, nCBs = 0;
+ for (iovcnt = 0, nCBs = 0;
nCBs < hdr.nCBs;
- idx++, nCBs++) {
- iov[idx].iov_base = (char *)&cbdsk[idx];
- len += iov[idx].iov_len = sizeof(struct CBDiskEntry);
+ nCBs++) {
+ iov[iovcnt].iov_base = (char *)&cbdsk[iovcnt];
+ iov[iovcnt].iov_len = sizeof(struct CBDiskEntry);
iovcnt++;
if ((iovcnt == 16) || (nCBs == hdr.nCBs - 1)) {
if (fs_stateReadV(state, iov, iovcnt)) {
ret = 1;
goto done;
}
- len = 0;
iovcnt = 0;
}
}
int
DumpCallBackState(void)
{
- int fd;
- afs_uint32 magic = MAGIC, now = FT_ApproxTime(), freelisthead;
+ int fd, oflag;
+ afs_uint32 magic = MAGICV2, now = (afs_int32) FT_ApproxTime(), freelisthead;
- fd = open(AFSDIR_SERVER_CBKDUMP_FILEPATH, O_WRONLY | O_CREAT | O_TRUNC,
- 0666);
+ oflag = O_WRONLY | O_CREAT | O_TRUNC;
+#ifdef AFS_NT40_ENV
+ oflag |= O_BINARY;
+#endif
+ fd = open(AFSDIR_SERVER_CBKDUMP_FILEPATH, oflag, 0666);
if (fd < 0) {
ViceLog(0,
("Couldn't create callback dump file %s\n",
/* This is only compiled in for the callback analyzer program */
/* Returns the time of the dump */
time_t
-ReadDump(char *file)
+ReadDump(char *file, int timebits)
{
- int fd;
+ int fd, oflag;
afs_uint32 magic, freelisthead;
- time_t now;
+ afs_uint32 now;
+#ifdef AFS_64BIT_ENV
+ afs_int64 now64;
+#endif
- fd = open(file, O_RDONLY);
+ oflag = O_RDONLY;
+#ifdef AFS_NT40_ENV
+ oflag |= O_BINARY;
+#endif
+ fd = open(file, oflag);
if (fd < 0) {
fprintf(stderr, "Couldn't read dump file %s\n", file);
exit(1);
}
read(fd, &magic, sizeof(magic));
- if (magic != MAGIC) {
- fprintf(stderr,
- "Magic number of %s is invalid. You might be trying to\n",
- file);
- fprintf(stderr,
- "run this program on a machine type with a different byte ordering.\n");
- exit(1);
+ if (magic == MAGICV2) {
+ timebits = 32;
+ } else {
+ if (magic != MAGIC) {
+ fprintf(stderr,
+ "Magic number of %s is invalid. You might be trying to\n",
+ file);
+ fprintf(stderr,
+ "run this program on a machine type with a different byte ordering.\n");
+ exit(1);
+ }
}
- read(fd, &now, sizeof(now));
+#ifdef AFS_64BIT_ENV
+ if (timebits == 64) {
+ read(fd, &now64, sizeof(afs_int64));
+ now = (afs_int32) now64;
+ } else
+#endif
+ read(fd, &now, sizeof(afs_int32));
read(fd, &cbstuff, sizeof(cbstuff));
read(fd, TimeOuts, sizeof(TimeOuts));
read(fd, timeout, sizeof(timeout));
read(fd, &tfirst, sizeof(tfirst));
read(fd, &freelisthead, sizeof(freelisthead));
CB = ((struct CallBack
- *)(calloc(cbstuff.nblks, sizeof(struct FileEntry)))) - 1;
+ *)(calloc(cbstuff.nblks, sizeof(struct CallBack)))) - 1;
FE = ((struct FileEntry
*)(calloc(cbstuff.nblks, sizeof(struct FileEntry)))) - 1;
CBfree = (struct CallBack *)itocb(freelisthead);
static AFSFid fid;
register struct FileEntry *fe;
register struct CallBack *cb;
- time_t now;
-
+ afs_int32 now;
+ int timebits = 32;
+
memset(&fid, 0, sizeof(fid));
argc--;
argv++;
all = 1;
} else if (!strcmp(*argv, "-raw")) {
raw = 1;
+ } else if (!strcmp(*argv, "-timebits")) {
+ if (argc < 1) {
+ err++;
+ break;
+ }
+ argc--;
+ timebits = atoi(*++argv);
+ if ((timebits != 32)
+#ifdef AFS_64BIT_ENV
+ && (timebits != 64)
+#endif
+ )
+ err++;
} else if (!strcmp(*argv, "-volume")) {
if (argc < 1) {
err++;
}
if (err || argc != 1) {
fprintf(stderr,
- "Usage: cbd [-host cbid] [-fid volume vnode] [-stats] [-all] callbackdumpfile\n");
+ "Usage: cbd [-host cbid] [-fid volume vnode] [-stats] [-all] [-timebits 32"
+#ifdef AFS_64BIT_ENV
+ "|64"
+#endif
+ "] callbackdumpfile\n");
fprintf(stderr,
"[cbid is shown for each host in the hosts.dump file]\n");
exit(1);
}
- now = ReadDump(*argv);
+ now = ReadDump(*argv, timebits);
if (stats || noptions == 0) {
- time_t uxtfirst = UXtime(tfirst);
- printf("The time of the dump was %u %s", now, ctime(&now));
- printf("The last time cleanup ran was %u %s", uxtfirst,
+ time_t uxtfirst = UXtime(tfirst), tnow = now;
+ printf("The time of the dump was %u %s", (unsigned int) now, ctime(&tnow));
+ printf("The last time cleanup ran was %u %s", (unsigned int) uxtfirst,
ctime(&uxtfirst));
PrintCallBackStats();
}
struct FileEntry *fe;
for (hash = 0; hash < FEHASH_SIZE; hash++) {
- for (feip = &HashTable[hash]; fe = itofe(*feip);) {
+ for (feip = &HashTable[hash]; (fe = itofe(*feip));) {
if (!vol || (fe->volid == vol)) {
register struct CallBack *cbnext;
for (cb = itocb(fe->firstcb); cb; cb = cbnext) {
if (fe == NULL)
return;
- printf("vol=%u vn=%u cbs=%d hi=%d st=%d fest=%d, exp in %d secs at %s",
+ printf("vol=%u vn=%u cbs=%d hi=%d st=%d fest=%d, exp in %lu secs at %s",
fe->volid, fe->vnode, fe->ncbs, cb->hhead, cb->status, fe->status,
expires - now, ctime(&expires));
}
assert(j); /* at least one alternate address */
ViceLog(125,
- ("Starting multibreakcall back on all addr for host %x (%s:%d)\n",
+ ("Starting multibreakcall back on all addr for host %p (%s:%d)\n",
host, afs_inet_ntoa_r(host->host, hoststr), ntohs(host->port)));
H_UNLOCK;
multi_Rx(conns, j) {
assert(j); /* at least one alternate address */
ViceLog(125,
- ("Starting multiprobe on all addr for host %x (%s:%d)\n",
+ ("Starting multiprobe on all addr for host %p (%s:%d)\n",
host, afs_inet_ntoa_r(host->host, hoststr),
ntohs(host->port)));
H_UNLOCK;