#include <sys/file.h>
#endif
-#include <afs/afs_assert.h>
-
#include <afs/nfs.h> /* yuck. This is an abomination. */
#include <lwp.h>
#include <rx/rx.h>
#include "host.h"
#include "callback.h"
#ifdef AFS_DEMAND_ATTACH_FS
-#include "../tviced/serialize_state.h"
+#include "serialize_state.h"
#endif /* AFS_DEMAND_ATTACH_FS */
static int AddCallBack1_r(struct host *host, AFSFid * fid, afs_uint32 * thead,
int type, int locked);
static void MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
- struct AFSCBFids *afidp, struct host *xhost);
-static int MultiBreakVolumeCallBack_r(struct host *host, int isheld,
+ struct AFSCBFids *afidp);
+static int MultiBreakVolumeCallBack_r(struct host *host,
struct VCBParams *parms, int deletefe);
-static int MultiBreakVolumeLaterCallBack(struct host *host, int isheld,
- void *rock);
+static int MultiBreakVolumeLaterCallBack(struct host *host, void *rock);
static int GetSomeSpace_r(struct host *hostp, int locked);
static int ClearHostCallbacks_r(struct host *hp, int locked);
static int DumpCallBackState_r(void);
int j;
struct rx_connection *cb_conn = NULL;
-#ifdef ADAPT_MTU
rx_SetConnDeadTime(ahost->callback_rxcon, 4);
rx_SetConnHardDeadTime(ahost->callback_rxcon, AFS_HARDDEADTIME);
-#endif
code = 0;
j = 0;
}
/* 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.
+ * release the holds once you're done.
+ * Currently only works for a single Fid in afidp array.
* If you want to make this work with multiple fids, you need to fix
* the error handling. One approach would be to force a reset if a
* multi-fid call fails, or you could add delayed callbacks for each
* wherever that is done. */
static void
MultiBreakCallBack_r(struct cbstruct cba[], int ncbas,
- struct AFSCBFids *afidp, struct host *xhost)
+ struct AFSCBFids *afidp)
{
int i, j;
struct rx_connection *conns[MAX_CB_HOSTS];
multi_to_cba_map[j] = i;
conns[j++] = thishost->callback_rxcon;
-#ifdef ADAPT_MTU
rx_SetConnDeadTime(thishost->callback_rxcon, 4);
rx_SetConnHardDeadTime(thishost->callback_rxcon, AFS_HARDDEADTIME);
-#endif
}
if (j) { /* who knows what multi would do with 0 conns? */
for (i = 0; i < ncbas; i++) {
struct host *hp;
hp = cba[i].hp;
- if (hp && xhost != hp) {
+ if (hp) {
h_Release_r(hp);
}
}
int hostindex;
char hoststr[16];
- ViceLog(7,
- ("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));
+ if (xhost)
+ ViceLog(7,
+ ("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));
+ else
+ ViceLog(7,
+ ("BCB: BreakCallBack(No Host, (%u,%u,%u))\n",
+ fid->Volume, fid->Vnode, fid->Unique));
H_LOCK;
cbstuff.BreakCallBacks++;
if (!fe) {
goto done;
}
- hostindex = h_htoi(xhost);
+ hostindex = xhost ? h_htoi(xhost) : 0;
cb = itocb(fe->firstcb);
if (!cb || ((fe->ncbs == 1) && (cb->hhead == hostindex) && !flag)) {
/* the most common case is what follows the || */
for (cba2 = cba, num = ncbas; ncbas > 0; cba2 += num, ncbas -= num) {
num = (ncbas > MAX_CB_HOSTS) ? MAX_CB_HOSTS : ncbas;
- MultiBreakCallBack_r(cba2, num, &tf, xhost);
+ MultiBreakCallBack_r(cba2, num, &tf);
}
}
return (host->hostFlags & VENUSDOWN);
}
-/*
-** isheld is 0 if the host is held in h_Enumerate
-** isheld is 1 if the host is held in BreakVolumeCallBacks
-*/
static int
-MultiBreakVolumeCallBack_r(struct host *host, int isheld,
+MultiBreakVolumeCallBack_r(struct host *host,
struct VCBParams *parms, int deletefe)
{
char hoststr[16];
if (host->hostFlags & HOSTDELETED)
- return 0; /* host is deleted, release hold */
+ return 0;
if (!(host->hostFlags & HCBREAK))
return 0; /* host is not flagged to notify */
* later */
host->hostFlags &= ~(RESETDONE|HCBREAK); /* Do InitCallBackState when host returns */
h_Unlock_r(host);
- return 0; /* parent will release hold */
+ return 0;
}
osi_Assert(parms->ncbas <= MAX_CB_HOSTS);
tf.AFSCBFids_val = parms->fid;
/* this releases all the hosts */
- MultiBreakCallBack_r(parms->cba, parms->ncbas, &tf, 0 /* xhost */ );
+ MultiBreakCallBack_r(parms->cba, parms->ncbas, &tf);
parms->ncbas = 0;
}
parms->cba[parms->ncbas].hp = host;
parms->cba[(parms->ncbas)++].thead = parms->thead;
host->hostFlags &= ~HCBREAK;
- return 1; /* parent shouldn't release hold, more work to do */
+
+ /* we have more work to do on this host, so make sure we keep a reference
+ * to it */
+ h_Hold_r(host);
+
+ return 0;
}
-/*
-** isheld is 0 if the host is held in h_Enumerate
-** isheld is 1 if the host is held in BreakVolumeCallBacks
-*/
static int
-MultiBreakVolumeLaterCallBack(struct host *host, int isheld, void *rock)
+MultiBreakVolumeLaterCallBack(struct host *host, void *rock)
{
struct VCBParams *parms = (struct VCBParams *)rock;
int retval;
H_LOCK;
- retval = MultiBreakVolumeCallBack_r(host, isheld, parms, 0);
+ retval = MultiBreakVolumeCallBack_r(host, parms, 0);
H_UNLOCK;
return retval;
}
* Now uses multi-RX for CallBack RPC in a different thread,
* only marking them here.
*/
-#ifdef AFS_PTHREAD_ENV
extern pthread_cond_t fsync_cond;
-#else
-extern char fsync_wait[];
-#endif
int
BreakVolumeCallBacksLater(afs_uint32 volume)
}
ViceLog(25, ("Fsync thread wakeup\n"));
-#ifdef AFS_PTHREAD_ENV
FSYNC_LOCK;
CV_BROADCAST(&fsync_cond);
FSYNC_UNLOCK;
-#else
- LWP_NoYieldSignal(fsync_wait);
-#endif
return 0;
}
tf.AFSCBFids_len = 1;
tf.AFSCBFids_val = &fid;
- MultiBreakCallBack_r(henumParms.cba, henumParms.ncbas, &tf, 0);
+ MultiBreakCallBack_r(henumParms.cba, henumParms.ncbas, &tf);
henumParms.ncbas = 0;
}
}
* theory not give these to us anyway, but be paranoid.
*/
static int
-lih0_r(struct host *host, int flags, void *rock)
+lih0_r(struct host *host, void *rock)
{
struct lih_params *params = (struct lih_params *)rock;
h_Hold_r(host);
params->lih = host;
}
- return flags;
+ return 0;
}
/* same as lih0_r, except we do not prevent held hosts from being selected. */
static int
-lih1_r(struct host *host, int flags, void *rock)
+lih1_r(struct host *host, void *rock)
{
struct lih_params *params = (struct lih_params *)rock;
h_Hold_r(host);
params->lih = host;
}
- return flags;
+ return 0;
}
/* This could be upgraded to get more space each time */
struct lih_params params;
int i = 0;
+ if (cbstuff.GotSomeSpaces == 0) {
+ /* only log this once; if GSS is getting called constantly, that's not
+ * good but don't make things worse by spamming the log. */
+ ViceLog(0, ("We have run out of callback space; forcing callback revocation. "
+ "This suggests the fileserver is configured with insufficient "
+ "callbacks; you probably want to increase the -cb fileserver "
+ "parameter (current setting: %u). The fileserver will continue "
+ "to operate, but this may indicate a severe performance problem\n",
+ cbstuff.nblks));
+ ViceLog(0, ("This message is logged at most once; for more information "
+ "see the OpenAFS documentation and fileserver xstat collection 3\n"));
+ }
+
cbstuff.GotSomeSpaces++;
ViceLog(5,
("GSS: First looking for timed out call backs via CleanupCallBacks\n"));
for (idx = 0; idx < niovecs; idx++) {
cbdsk = (struct CBDiskEntry *) iov[idx].iov_base;
+
+ if (cbdsk->cb.hhead < state->h_map.len &&
+ state->h_map.entries[cbdsk->cb.hhead].valid == FS_STATE_IDX_SKIPPED) {
+ continue;
+ }
+
if ((cb = GetCB()) == NULL) {
ViceLog(0, ("cb_stateRestoreCBs: ran out of free CallBack structures\n"));
ret = 1;
ret = 1;
goto done;
}
+ state->fe_map.entries[in->index].valid = FS_STATE_IDX_VALID;
state->fe_map.entries[in->index].old_idx = in->index;
state->fe_map.entries[in->index].new_idx = fetoi(out);
ret = 1;
goto done;
}
+ state->cb_map.entries[in->index].valid = FS_STATE_IDX_VALID;
state->cb_map.entries[in->index].old_idx = in->index;
state->cb_map.entries[in->index].new_idx = cbtoi(out);
if (old >= state->fe_map.len) {
ViceLog(0, ("fe_OldToNew: index %d is out of range\n", old));
ret = 1;
- } else if (state->fe_map.entries[old].old_idx != old) { /* sanity check */
+ } else if (state->fe_map.entries[old].valid != FS_STATE_IDX_VALID ||
+ state->fe_map.entries[old].old_idx != old) { /* sanity check */
ViceLog(0, ("fe_OldToNew: index %d points to an invalid FileEntry record\n", old));
ret = 1;
} else {
if (old >= state->cb_map.len) {
ViceLog(0, ("cb_OldToNew: index %d is out of range\n", old));
ret = 1;
- } else if (state->cb_map.entries[old].old_idx != old) { /* sanity check */
+ } else if (state->cb_map.entries[old].valid != FS_STATE_IDX_VALID ||
+ state->cb_map.entries[old].old_idx != old) { /* sanity check */
ViceLog(0, ("cb_OldToNew: index %d points to an invalid CallBack record\n", old));
ret = 1;
} else {
if (host->callback_rxcon)
rx_DestroyConnection(host->callback_rxcon);
host->callback_rxcon = conns[multi_i];
- h_DeleteHostFromAddrHashTable_r(host->host, host->port, host);
+ /* add then remove */
+ addInterfaceAddr_r(host, interfaces[multi_i].addr,
+ interfaces[multi_i].port);
+ removeInterfaceAddr_r(host, host->host, host->port);
host->host = interfaces[multi_i].addr;
host->port = interfaces[multi_i].port;
- h_AddHostToAddrHashTable_r(host->host, host->port, host);
connSuccess = conns[multi_i];
rx_SetConnDeadTime(host->callback_rxcon, 50);
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);
if (host->callback_rxcon)
rx_DestroyConnection(host->callback_rxcon);
host->callback_rxcon = conns[multi_i];
- h_DeleteHostFromAddrHashTable_r(host->host, host->port, host);
+ /* add then remove */
+ addInterfaceAddr_r(host, interfaces[multi_i].addr,
+ interfaces[multi_i].port);
+ removeInterfaceAddr_r(host, host->host, host->port);
host->host = interfaces[multi_i].addr;
host->port = interfaces[multi_i].port;
- h_AddHostToAddrHashTable_r(host->host, host->port, host);
connSuccess = conns[multi_i];
rx_SetConnDeadTime(host->callback_rxcon, 50);
rx_SetConnHardDeadTime(host->callback_rxcon, AFS_HARDDEADTIME);