#include "netinet/in_var.h"
#endif
#endif /* !defined(UKERNEL) */
-#ifdef AFS_LINUX22_ENV
-#include "h/smp_lock.h"
-#endif
#ifdef AFS_SUN510_ENV
#include "h/ksynch.h"
#include "h/sunddi.h"
#define AFS_MINBUFFERS 50
#endif
+#if (defined(AFS_SUN5_ENV) || (defined(AFS_LINUX24_ENV) && defined(HAVE_LINUX_COMPLETION_H)) || defined(AFS_DARWIN80_ENV)) && !defined(UKERNEL)
+/* If AFS_DAEMONOP_ENV is defined, it indicates we run "daemon" AFS syscalls by
+ * spawning a kernel thread to do the work, instead of running them in the
+ * calling process. */
+# define AFS_DAEMONOP_ENV
+#endif
+
struct afsop_cell {
afs_int32 hosts[AFS_MAXCELLHOSTS];
char cellName[100];
return code;
}
+
+#ifdef AFS_DAEMONOP_ENV
+static int
+daemonOp_common(long parm, long parm2, long parm3, long parm4, long parm5,
+ long parm6)
+{
+ int code;
+ if (parm == AFSOP_START_RXCALLBACK) {
+ if (afs_CB_Running)
+ return -1;
+# ifdef RXK_LISTENER_ENV
+ } else if (parm == AFSOP_RXLISTENER_DAEMON) {
+ if (afs_RX_Running)
+ return -1;
+ afs_RX_Running = 1;
+# endif
+ code = afs_InitSetup(parm2);
+ if (parm3) {
+ rx_enablePeerRPCStats();
+ }
+ if (parm4) {
+ rx_enableProcessRPCStats();
+ }
+ if (code)
+ return -1;
+ } else if (parm == AFSOP_START_AFS) {
+ if (AFS_Running)
+ return -1;
+ } /* other functions don't need setup in the parent */
+ return 0;
+}
+#endif /* AFS_DAEMONOP_ENV */
+
#if defined(AFS_DARWIN80_ENV)
struct afsd_thread_info {
unsigned long parm;
afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
long parm6)
{
- int code;
struct afsd_thread_info info;
thread_t thread;
- if (parm == AFSOP_START_RXCALLBACK) {
- if (afs_CB_Running)
- return;
-#ifdef RXK_LISTENER_ENV
- } else if (parm == AFSOP_RXLISTENER_DAEMON) {
- if (afs_RX_Running)
- return;
- afs_RX_Running = 1;
-#endif
- code = afs_InitSetup(parm2);
- if (parm3) {
- rx_enablePeerRPCStats();
- }
- if (parm4) {
- rx_enableProcessRPCStats();
- }
- if (code)
- return;
- } else if (parm == AFSOP_START_AFS) {
- if (AFS_Running)
- return;
- } /* other functions don't need setup in the parent */
+ if (daemonOp_common(parm, parm2, parm3, parm4, parm5, parm6)) {
+ return;
+ }
info.parm = parm;
kernel_thread_start((thread_continue_t)afsd_thread, &info, &thread);
AFS_GUNLOCK();
afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
long parm6)
{
- int code;
DECLARE_COMPLETION(c);
# if defined(AFS_LINUX26_ENV)
# if defined(INIT_WORK_HAS_DATA)
struct tq_struct tq;
# endif
struct afsd_thread_info info;
- if (parm == AFSOP_START_RXCALLBACK) {
- if (afs_CB_Running)
- return;
-#ifdef RXK_LISTENER_ENV
- } else if (parm == AFSOP_RXLISTENER_DAEMON) {
- if (afs_RX_Running)
- return;
- afs_RX_Running = 1;
-#endif
- code = afs_InitSetup(parm2);
- if (parm3) {
- rx_enablePeerRPCStats();
- }
- if (parm4) {
- rx_enableProcessRPCStats();
- }
- if (code)
- return;
- } else if (parm == AFSOP_START_AFS) {
- if (AFS_Running)
- return;
- } /* other functions don't need setup in the parent */
+ if (daemonOp_common(parm, parm2, parm3, parm4, parm5, parm6)) {
+ return;
+ }
info.complete = &c;
info.parm = parm;
# if defined(AFS_LINUX26_ENV)
}
#endif
+#ifdef AFS_SUN5_ENV
+struct afs_daemonop_args {
+ kcondvar_t cv;
+ long parm;
+};
+
+static void
+afsd_thread(struct afs_daemonop_args *args)
+{
+ long parm = args->parm;
+
+ AFS_GLOCK();
+ cv_signal(&args->cv);
+
+ switch (parm) {
+ case AFSOP_START_RXCALLBACK:
+ if (afs_CB_Running)
+ goto out;
+ afs_CB_Running = 1;
+ while (afs_RX_Running != 2)
+ afs_osi_Sleep(&afs_RX_Running);
+ afs_RXCallBackServer();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_START_AFS:
+ if (AFS_Running)
+ goto out;
+ AFS_Running = 1;
+ while (afs_initState < AFSOP_START_AFS)
+ afs_osi_Sleep(&afs_initState);
+ afs_initState = AFSOP_START_BKG;
+ afs_osi_Wakeup(&afs_initState);
+ afs_Daemon();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_START_BKG:
+ while (afs_initState < AFSOP_START_BKG)
+ afs_osi_Sleep(&afs_initState);
+ if (afs_initState < AFSOP_GO) {
+ afs_initState = AFSOP_GO;
+ afs_osi_Wakeup(&afs_initState);
+ }
+ afs_BackgroundDaemon();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_START_TRUNCDAEMON:
+ while (afs_initState < AFSOP_GO)
+ afs_osi_Sleep(&afs_initState);
+ afs_CacheTruncateDaemon();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_START_CS:
+ afs_CheckServerDaemon();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_RXEVENT_DAEMON:
+ while (afs_initState < AFSOP_START_BKG)
+ afs_osi_Sleep(&afs_initState);
+ afs_rxevent_daemon();
+ AFS_GUNLOCK();
+ return;
+ case AFSOP_RXLISTENER_DAEMON:
+ afs_initState = AFSOP_START_AFS;
+ afs_osi_Wakeup(&afs_initState);
+ afs_RX_Running = 2;
+ afs_osi_Wakeup(&afs_RX_Running);
+ afs_osi_RxkRegister();
+ rxk_Listener();
+ AFS_GUNLOCK();
+ return;
+ default:
+ AFS_GUNLOCK();
+ afs_warn("Unknown op %ld in afsd_thread()\n", parm);
+ return;
+ }
+ out:
+ AFS_GUNLOCK();
+ return;
+}
+
+static void
+afs_DaemonOp(long parm, long parm2, long parm3, long parm4, long parm5,
+ long parm6)
+{
+ struct afs_daemonop_args args;
+
+ if (daemonOp_common(parm, parm2, parm3, parm4, parm5, parm6)) {
+ return;
+ }
+
+ args.parm = parm;
+
+ cv_init(&args.cv, "AFS DaemonOp cond var", CV_DEFAULT, NULL);
+
+ if (thread_create(NULL, 0, afsd_thread, &args, 0, &p0, TS_RUN,
+ minclsyspri) == NULL) {
+
+ afs_warn("thread_create failed: AFS startup will not complete\n");
+ }
+
+ /* we passed &args to the new thread, which is on the stack. wait until
+ * it has read the arguments so it doesn't try to read the args after we
+ * have returned */
+ cv_wait(&args.cv, &afs_global_lock);
+
+ cv_destroy(&args.cv);
+}
+#endif /* AFS_SUN5_ENV */
+
#ifdef AFS_DARWIN100_ENV
# define AFSKPTR(X) k ## X
int
#ifdef AFS_DARWIN80_ENV
put_vfs_context();
#endif
-#if ((defined(AFS_LINUX24_ENV) && defined(HAVE_LINUX_COMPLETION_H)) || defined(AFS_DARWIN80_ENV)) && !defined(UKERNEL)
+#ifdef AFS_DAEMONOP_ENV
# if defined(AFS_DARWIN80_ENV)
if (parm == AFSOP_BKG_HANDLER) {
/* if afs_uspc_param grows this should be checked */
|| parm == AFSOP_RXLISTENER_DAEMON) {
afs_DaemonOp(parm, parm2, parm3, parm4, parm5, parm6);
}
-#else /* !(AFS_LINUX24_ENV && !UKERNEL) */
+#else /* !AFS_DAEMONOP_ENV */
if (parm == AFSOP_START_RXCALLBACK) {
if (afs_CB_Running)
goto out;
exit(CLD_EXITED, 0);
# endif /* AFS_SGI_ENV */
}
-# if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV)
+# if defined(AFS_SUN5_ENV) || defined(RXK_LISTENER_ENV) || defined(RXK_UPCALL_ENV)
else if (parm == AFSOP_RXEVENT_DAEMON) {
while (afs_initState < AFSOP_START_BKG)
afs_osi_Sleep(&afs_initState);
exit(CLD_EXITED, 0);
# endif /* AFS_SGI_ENV */
}
-# endif /* AFS_SUN5_ENV || RXK_LISTENER_ENV */
-#endif /* AFS_LINUX24_ENV && !UKERNEL */
+# endif /* AFS_SUN5_ENV || RXK_LISTENER_ENV || RXK_UPCALL_ENV */
+#endif /* AFS_DAEMONOP_ENV */
else if (parm == AFSOP_BASIC_INIT) {
afs_int32 temp;
if (refresh) {
afs_CheckServers(1, NULL); /* check down servers */
- afs_CheckServers(0, NULL); /* check down servers */
+ afs_CheckServers(0, NULL); /* check up servers */
}
}
#ifdef AFS_SGI53_ENV
if (afs_shuttingdown)
return;
- afs_FlushVCBs(2); /* Reasonable effort to free dynamically allocated callback returns */
+
+ /* Give up all of our callbacks if we can. This must be done before setting
+ * afs_shuttingdown, since it calls afs_InitReq, which will fail if
+ * afs_shuttingdown is set. */
+ afs_FlushVCBs(2);
afs_shuttingdown = 1;
+
if (afs_cold_shutdown)
afs_warn("afs: COLD ");
else