#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 (defined(AFS_SUN5_ENV) || defined(AFS_LINUX26_ENV) || 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. */
static int afscall_set_rxpck_received = 0;
+extern afs_int32 afs_volume_ttl;
+
+/* From afs_util.c */
+extern afs_int32 afs_md5inum;
+
/* This is code which needs to be called once when the first daemon enters
* the client. A non-zero return means an error and AFS should not start.
*/
afs_InitSetup(int preallocs)
{
int code;
+ afs_uint32 host;
if (afs_InitSetup_done)
return EAGAIN;
/* start RX */
if(!afscall_set_rxpck_received)
rx_extraPackets = AFS_NRXPACKETS; /* smaller # of packets */
+
+ host = ntohl(rx_bindhost);
+ afs_warn("afs: Binding rx to %d.%d.%d.%d:%d\n",
+ (host >> 24),
+ (host >> 16) & 0xff,
+ (host >> 8) & 0xff,
+ (host) & 0xff,
+ 7001);
code = rx_InitHost(rx_bindhost, htons(7001));
if (code) {
afs_warn("AFS: RX failed to initialize %d).\n", code);
#endif
-#if defined(AFS_LINUX24_ENV) && defined(HAVE_LINUX_COMPLETION_H)
+#if defined(AFS_LINUX26_ENV)
struct afsd_thread_info {
-# if defined(AFS_LINUX26_ENV) && !defined(INIT_WORK_HAS_DATA)
+# if !defined(INIT_WORK_HAS_DATA)
struct work_struct tq;
# endif
unsigned long parm;
}
#endif /* AFS_SUN5_ENV */
+#ifdef AFS_SOCKPROXY_ENV
+/**
+ * Deallocate packets.
+ *
+ * @param[inout] a_pktlist list of packets to be freed
+ * @param[in] a_npkts number of packets
+ */
+static void
+sockproxy_pkts_free(struct afs_pkt_hdr **a_pktlist, size_t a_npkts)
+{
+ int pkt_i;
+ struct afs_pkt_hdr *pktlist = *a_pktlist;
+
+ if (pktlist == NULL) {
+ return;
+ }
+ *a_pktlist = NULL;
+
+ for (pkt_i = 0; pkt_i < a_npkts; pkt_i++) {
+ struct afs_pkt_hdr *pkt = &pktlist[pkt_i];
+ afs_osi_Free(pkt->payload, pkt->size);
+ pkt->payload = NULL;
+ }
+ afs_osi_Free(pktlist, a_npkts * sizeof(pktlist[0]));
+}
+
+/**
+ * Copy packets from user-space.
+ *
+ * @param[in] a_uaddr address of list of packets in user-space
+ * @param[out] a_pktlist packets copied from user-space
+ * @param[in] a_npkts number of packets to be copied
+ *
+ * @return errno error codes.
+ */
+static int
+sockproxy_pkts_copyin(user_addr_t a_uaddr, struct afs_pkt_hdr **a_pktlist,
+ size_t a_npkts)
+{
+ int code, pkt_i;
+ struct afs_pkt_hdr *pktlist_u;
+ struct afs_pkt_hdr *pktlist_k = NULL;
+
+ *a_pktlist = NULL;
+ if (a_npkts == 0) {
+ return 0;
+ }
+ if (a_npkts > AFS_SOCKPROXY_PKT_MAX) {
+ return E2BIG;
+ }
+
+ pktlist_u = afs_osi_Alloc(a_npkts * sizeof(pktlist_u[0]));
+ if (pktlist_u == NULL) {
+ code = ENOMEM;
+ goto done;
+ }
+
+ pktlist_k = afs_osi_Alloc(a_npkts * sizeof(pktlist_k[0]));
+ if (pktlist_k == NULL) {
+ code = ENOMEM;
+ goto done;
+ }
+ memset(pktlist_k, 0, a_npkts * sizeof(pktlist_k[0]));
+
+ AFS_COPYIN(a_uaddr, pktlist_u, a_npkts * sizeof(pktlist_u[0]), code);
+ if (code != 0) {
+ goto done;
+ }
+
+ for (pkt_i = 0; pkt_i < a_npkts; pkt_i++) {
+ struct afs_pkt_hdr *pkt_k = &pktlist_k[pkt_i];
+ struct afs_pkt_hdr *pkt_u = &pktlist_u[pkt_i];
+
+ if (pkt_u->size > AFS_SOCKPROXY_PAYLOAD_MAX) {
+ code = E2BIG;
+ goto done;
+ }
+ /*
+ * Notice that pkt_u->payload points to a user-space address. When
+ * copying the data from pkt_u to pkt_k, make sure that pkt_k->payload
+ * points to a valid address in kernel-space.
+ */
+ *pkt_k = *pkt_u;
+ pkt_k->payload = afs_osi_Alloc(pkt_k->size);
+ if (pkt_k->payload == NULL) {
+ code = ENOMEM;
+ goto done;
+ }
+
+ AFS_COPYIN((user_addr_t)pkt_u->payload, pkt_k->payload, pkt_k->size,
+ code);
+ if (code != 0) {
+ goto done;
+ }
+ }
+
+ *a_pktlist = pktlist_k;
+ pktlist_k = NULL;
+ code = 0;
+
+ done:
+ sockproxy_pkts_free(&pktlist_k, a_npkts);
+ afs_osi_Free(pktlist_u, a_npkts * sizeof(pktlist_u[0]));
+
+ return code;
+}
+
+/**
+ * Copy packets to user-space.
+ *
+ * @param[in] a_uaddr dst address of list of packets in user-space
+ * @param[in] a_pktlist packets to be copied to user-space
+ * @param[in] a_npkts number of packets to be copied
+ *
+ * @return 0 on success; non-zero otherwise.
+ */
+static int
+sockproxy_pkts_copyout(user_addr_t a_uaddr, struct afs_pkt_hdr *a_pktlist,
+ size_t a_npkts)
+{
+ int code, pkt_i;
+ struct afs_pkt_hdr *pktlist_u = NULL;
+ struct afs_pkt_hdr *pktlist_k = a_pktlist;
+
+ if (a_npkts == 0) {
+ return 0;
+ }
+ if (a_npkts > AFS_SOCKPROXY_PKT_MAX) {
+ return E2BIG;
+ }
+ if (a_pktlist == NULL) {
+ return EINVAL;
+ }
+
+ pktlist_u = afs_osi_Alloc(a_npkts * sizeof(pktlist_u[0]));
+ if (pktlist_u == NULL) {
+ code = ENOMEM;
+ goto done;
+ }
+
+ AFS_COPYIN(a_uaddr, pktlist_u, a_npkts * sizeof(pktlist_u[0]), code);
+ if (code != 0) {
+ goto done;
+ }
+
+ for (pkt_i = 0; pkt_i < a_npkts; pkt_i++) {
+ struct afs_pkt_hdr *pkt_k = &pktlist_k[pkt_i];
+ struct afs_pkt_hdr *pkt_u = &pktlist_u[pkt_i];
+ void *payload_uaddr;
+
+ if (pkt_k->size > pkt_u->size) {
+ code = ENOSPC;
+ goto done;
+ }
+
+ /* Copy pkt_k -> pkt_u, but preserve pkt_u->payload */
+ payload_uaddr = pkt_u->payload;
+ *pkt_u = *pkt_k;
+ pkt_u->payload = payload_uaddr;
+
+ AFS_COPYOUT(pkt_k->payload, (user_addr_t)pkt_u->payload, pkt_k->size,
+ code);
+ if (code != 0) {
+ goto done;
+ }
+ }
+
+ AFS_COPYOUT(pktlist_u, a_uaddr, a_npkts * sizeof(pktlist_u[0]), code);
+ if (code != 0) {
+ goto done;
+ }
+
+ done:
+ afs_osi_Free(pktlist_u, a_npkts * sizeof(pktlist_u[0]));
+ return code;
+}
+
+/**
+ * Receive / send packets from / to user-space.
+ *
+ * @param[in] a_parm_uspc afs_uspc_param struct
+ * @param[in] a_parm_pkts packets to be received / sent
+ *
+ * @return 0 on success; non-zero otherwise.
+ */
+static int
+sockproxy_handler(user_addr_t a_parm_uspc, user_addr_t a_parm_pkts)
+{
+ int code;
+ size_t orig_npkts, npkts;
+ struct afs_uspc_param uspc;
+
+ struct afs_pkt_hdr *pkts_recv;
+ struct afs_pkt_hdr *pkts_send;
+
+ AFS_GUNLOCK();
+
+ orig_npkts = 0;
+ memset(&uspc, 0, sizeof(uspc));
+
+ pkts_recv = NULL;
+ pkts_send = NULL;
+
+ /* get response from user-space */
+ AFS_COPYIN(a_parm_uspc, &uspc, sizeof(uspc), code);
+ if (code != 0) {
+ afs_warn("afs: AFSOP_SOCKPROXY_HANDLER can't read uspc\n");
+ goto done;
+ }
+
+ npkts = uspc.req.usp.npkts;
+ orig_npkts = npkts;
+
+ if (uspc.reqtype == AFS_USPC_SOCKPROXY_RECV && npkts > 0) {
+ /* copyin packets in from user-space */
+ code = sockproxy_pkts_copyin(a_parm_pkts, &pkts_recv, npkts);
+ if (code) {
+ afs_warn("afs: AFSOP_SOCKPROXY_HANDLER can't read pkts\n");
+ goto done;
+ }
+ }
+
+ /*
+ * send response from user-space (if any) to the rx layer and wait for a
+ * new request.
+ */
+ code = rxk_SockProxyReply(&uspc, pkts_recv, &pkts_send);
+ if (code) {
+ afs_warn("afs: AFSOP_SOCKPROXY_HANDLER rxk_SockProxyReply failed\n");
+ goto done;
+ }
+
+ /* send request to user-space process */
+ AFS_COPYOUT(&uspc, a_parm_uspc, sizeof(uspc), code);
+ if (code) {
+ afs_warn("afs: AFSOP_SOCKPROXY_HANDLER can't write uspc\n");
+ goto done;
+ }
+
+ npkts = uspc.req.usp.npkts;
+ if (uspc.reqtype == AFS_USPC_SOCKPROXY_SEND && npkts > 0) {
+ /* check if process allocated enough memory to receive the packets */
+ if (npkts > orig_npkts) {
+ code = ENOSPC;
+ goto done;
+ }
+
+ /* copyout packets to user-space */
+ code = sockproxy_pkts_copyout(a_parm_pkts, pkts_send, npkts);
+ if (code != 0) {
+ afs_warn("afs: AFSOP_SOCKPROXY_HANDLER can't write pkts\n");
+ goto done;
+ }
+ }
+ done:
+ sockproxy_pkts_free(&pkts_recv, orig_npkts);
+ AFS_GLOCK();
+
+ return code;
+}
+#endif /* AFS_SOCKPROXY_ENV */
+
#ifdef AFS_DARWIN100_ENV
# define AFSKPTR(X) k ## X
int
if (!code) {
mvParam->retval = 0;
/* for reqs where pointers are strings: */
+# ifdef AFS_DARWIN_ENV
if (mvParam->reqtype == AFS_USPC_UMV) {
/* don't copy out random kernel memory */
AFS_COPYOUT(param2, AFSKPTR(parm4),
AFS_COPYOUT(param1, AFSKPTR(parm3),
MIN(namebufsz, strlen((char *)param1)+1), code);
}
+# endif /* AFS_DARWIN_ENV */
AFS_COPYOUT((caddr_t)mvParam, AFSKPTR(parm2),
sizeof(struct afs_uspc_param), code);
}
osi_Assert(tbuffer1 != NULL);
code = afs_InitDynroot();
if (!code) {
-#if 0
- /* wait for basic init - XXX can't find any reason we need this? */
- while (afs_initState < AFSOP_START_BKG)
- afs_osi_Sleep(&afs_initState);
-#endif
-
AFS_COPYIN(AFSKPTR(parm2), (caddr_t)tcell->hosts, sizeof(tcell->hosts),
code);
}
if (afs_uuid_create(&afs_cb_interface.uuid) != 0)
memset(&afs_cb_interface.uuid, 0, sizeof(afsUUID));
+#if defined(AFS_SUN5_ENV)
+ afs_kstat_init();
+#endif
+
printf("found %d non-empty cache files (%d%%).\n",
afs_stats_cmperf.cacheFilesReused,
(100 * afs_stats_cmperf.cacheFilesReused) /
}
}
else if (parm == AFSOP_SHUTDOWN) {
- afs_cold_shutdown = 0;
- if (parm2 == 1)
- afs_cold_shutdown = 1;
if (afs_globalVFS != 0) {
afs_warn("AFS isn't unmounted yet! Call aborted\n");
code = EACCES;
- } else
- afs_shutdown();
+ } else if (parm2 == AFS_COLD) {
+ afs_shutdown(AFS_COLD);
+ } else {
+ afs_shutdown(AFS_WARM);
+ }
} else if (parm == AFSOP_AFS_VFSMOUNT) {
#ifdef AFS_HPUX_ENV
vfsmount(parm2, parm3, parm4, parm5);
mtu = ((i == -1) ? htonl(1500) : afs_cb_interface.mtu[i]);
# else /* AFS_USERSPACE_IP_ADDR */
rx_ifnet_t tifnp;
+ RX_NET_EPOCH_ENTER();
tifnp = rxi_FindIfnet(parm2, NULL); /* make iterative */
mtu = (tifnp ? rx_ifnet_mtu(tifnp) : htonl(1500));
+
+ RX_NET_EPOCH_EXIT();
# endif /* else AFS_USERSPACE_IP_ADDR */
#endif /* !AFS_SUN5_ENV */
if (!code)
AFS_COPYOUT((caddr_t) & mtu, AFSKPTR(parm3),
sizeof(afs_int32), code);
-#ifdef AFS_AIX32_ENV
-/* this is disabled for now because I can't figure out how to get access
- * to these kernel variables. It's only for supporting user-mode rx
- * programs -- it makes a huge difference on the 220's in my testbed,
- * though I don't know why. The bosserver does this with /etc/no, so it's
- * being handled a different way for the servers right now. */
-/* {
- static adjusted = 0;
- extern u_long sb_max_dflt;
- if (!adjusted) {
- adjusted = 1;
- if (sb_max_dflt < 131072) sb_max_dflt = 131072;
- if (sb_max < 131072) sb_max = 131072;
- }
- } */
-#endif /* AFS_AIX32_ENV */
} else if (parm == AFSOP_GETMASK) { /* parm2 == addr in net order */
afs_uint32 mask = 0;
#if !defined(AFS_SUN5_ENV)
}
# else /* AFS_USERSPACE_IP_ADDR */
rx_ifnet_t tifnp;
+ RX_NET_EPOCH_ENTER();
tifnp = rxi_FindIfnet(parm2, &mask); /* make iterative */
if (!tifnp)
code = -1;
+
+ RX_NET_EPOCH_EXIT();
# endif /* else AFS_USERSPACE_IP_ADDR */
#endif /* !AFS_SUN5_ENV */
if (!code)
else if (parm == AFSOP_SET_DYNROOT) {
code = afs_SetDynrootEnable(parm2);
} else if (parm == AFSOP_SET_FAKESTAT) {
- afs_fakestat_enable = parm2;
- code = 0;
+ if (parm2 >= 0 && parm2 <= 2) {
+ afs_fakestat_enable = parm2;
+ code = 0;
+ } else {
+ afs_warn("afs: afsd gave us unknown fakestat value %ld (are afsd "
+ "and libafs running the same version?\n", parm2);
+ code = EINVAL;
+ }
} else if (parm == AFSOP_SET_BACKUPTREE) {
afs_bkvolpref = parm2;
} else if (parm == AFSOP_SET_RXPCK) {
afs_osi_Free(seedbuf, parm3);
}
#endif
+ } else if (parm == AFSOP_SET_INUMCALC) {
+ switch (parm2) {
+ case AFS_INUMCALC_COMPAT:
+ afs_md5inum = 0;
+ code = 0;
+ break;
+ case AFS_INUMCALC_MD5:
+ afs_md5inum = 1;
+ code = 0;
+ break;
+ default:
+ code = EINVAL;
+ }
+ } else if (parm == AFSOP_SET_VOLUME_TTL) {
+ if ((parm2 < AFS_MIN_VOLUME_TTL) || (parm2 > AFS_MAX_VOLUME_TTL)) {
+ code = EFAULT;
+ } else {
+ afs_volume_ttl = parm2;
+ code = 0;
+ }
+#ifdef AFS_SOCKPROXY_ENV
+ } else if (parm == AFSOP_SOCKPROXY_HANDLER) {
+ code = sockproxy_handler(AFSKPTR(parm2), AFSKPTR(parm3));
+#endif
} else {
code = EINVAL;
}
enum afs_shutdown_state afs_shuttingdown = AFS_RUNNING;
void
-afs_shutdown(void)
+afs_shutdown(enum afs_shutdown_type cold_flag)
{
extern short afs_brsDaemons;
extern afs_int32 afs_CheckServerDaemonStarted;
if (afs_shuttingdown != AFS_RUNNING)
return;
+ afs_cold_shutdown = ((cold_flag == AFS_COLD) ? 1 : 0);
+
afs_shuttingdown = AFS_FLUSHING_CB;
/* Give up all of our callbacks if we can. */
afs_shuttingdown = AFS_SHUTDOWN;
+#if defined(AFS_SUN5_ENV)
+ afs_kstat_shutdown();
+#endif
+
if (afs_cold_shutdown)
afs_warn("afs: COLD ");
else
afs_warn("NetIfPoller... ");
osi_StopNetIfPoller();
#endif
+ rxi_FreeAllPackets();
afs_termState = AFSOP_STOP_COMPLETE;
shutdown_nfsclnt();
#endif
shutdown_afstest();
+ shutdown_dynroot();
shutdown_AFS();
/* The following hold the cm stats */
memset(&afs_cmstats, 0, sizeof(struct afs_CMStats));