450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * CDDL HEADER START
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * The contents of this file are subject to the terms of the
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Common Development and Distribution License (the "License").
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * You may not use this file except in compliance with the License.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * See the License for the specific language governing permissions
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * and limitations under the License.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * If applicable, add the following below this CDDL HEADER, with the
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * CDDL HEADER END
91159e90831fc9243576f2ec1a483b3bb462bcf4John Forte * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte#define USAGE "Usage: %s [-d][-f][-n nodeid] nodename\n" \
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte "Note: nodename must be the same on both nodes\n"
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * static functions
450396635f70344c58b6b1e4db38cf17ff34445cJohn Fortestatic void daemonInit(void);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Fortestatic int postMsg(uint_t nelem, uchar_t *aluaMsg);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Fortechar aluaNode[256]; /* one of the two alua peers */
91159e90831fc9243576f2ec1a483b3bb462bcf4John Fortepthread_mutex_t send_mutex = PTHREAD_MUTEX_INITIALIZER;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * killHandler
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Terminates this process on SIGQUIT, SIGINT, SIGTERM
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte/* ARGSUSED */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * doorHandler
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Recieve data from the local proxy port provider and relay
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * it to the peer node.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte/* ARGSUSED */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte "empty message passed to door %p %d", args, alen);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (void) door_return((char *)&result, sizeof (result), NULL, 0);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_WARNING, "door_return FAILED %d", errno);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte "postMsg() no transport handle");
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte buflen = htonl(nelem); /* length in network byte order */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte ns = pt_ops->stmf_proxy_send(t_handle, buf, nelem + sizeof (buflen));
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_CRIT, "send() call failed: %d", ret);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Multi-thread the data path from the peer node to the local
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * proxy port provider. During discover, there can be a large
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * burst of messages from the peer node proportional to the number
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * of LUs. Multiple threads allow these messages to be processed
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * simultaneously.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Fortepthread_mutex_t pq_mutex = PTHREAD_MUTEX_INITIALIZER;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Fortepthread_cond_t pq_cond = PTHREAD_COND_INITIALIZER;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Relay the message to the local kernel */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte rc = stmfPostProxyMsg(proxy_hdl, (void *)pq->buf, pq->buflen);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* XXX die ? */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_CRIT, "ioctl failed - %d", errno);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /*NOTREACHED*/
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Receive data from peer and queue it up for the proxy driver.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* first receive the length of the message */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if ((pt_ops->stmf_proxy_recv(t_handle, (uchar_t *)&buflen,
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_WARNING, "recv() call failed: %d",
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte "recvMsg: size of buffer - %d", (int)pq->buflen);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if ((pt_ops->stmf_proxy_recv(t_handle, pq->buf, pq->buflen)) !=
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_WARNING, "recv() call failed: %d",
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Eat the first message from peer */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Queue the message to the driver */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* add to the tail */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Make sure there is a thread to service this message */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* wake an available thread */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* no threads available, create a new thread */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte rc = pthread_create(&tid, NULL, push_to_drv, NULL);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if (rc != 0) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* never created a thread */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Initialization for a daemon process
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_CRIT, "Could not fork(). Exiting");
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte } else if (pid != 0) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Simple approach for now - let the service go online.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Later, set-up a pipe to the child and wait until the
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * child indicates service is setup.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte "Failed to open /dev/null. Exiting");
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * XXX inform the parent about the service state
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * For now, just exit on error.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Create communication channel for the driver.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if ((drv_door_fd = door_create(doorHandler, NULL, 0)) < 0) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte stmf_ret = stmfInitProxyDoor(&proxy_hdl, drv_door_fd);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * daemon entry
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * parse arguments
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * create resources to talk to child
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if !foreground
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * daemonize, run as child
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * open proxy driver
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * install door in proxy driver
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * create socket
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if server-side
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * bind socket
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if !foreground
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * inform parent things aok
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * exit(SMF_EXIT_OK)
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if server-side
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * if client-side
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * send hello
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * recv hello
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * loop on recieve
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * XXX anyway to check in envp that we are started by SMF?
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte extern char *optarg;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte switch (c) {
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Should never happen from smf
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * After the options, only the server argument should remain.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_DEBUG, "aluaNode %s", aluaNode);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Not ipaddr, try hostname match.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte server_match = (strcmp(aluaNode, myNode)) ? 0 : 1;
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * see if this is our ip address
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (void) fprintf(stderr, "Sorry, cannot use ip adress format\n");
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Allow SIGQUIT, SIGINT and SIGTERM signals to terminate us
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Install the signal handler */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* block all signals */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* unblock SIGQUIT, SIGINT, SIGTERM */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* time to go backstage */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte if ((rc = stmf_proxy_transport_init("sockets", &pt_ops)) != 0)
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Establish connection
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * At this point, the parent has exited and the service
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * is online. But there are no real proxy services until
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * this connect call succeeds. That could take a long time if
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * the peer node is down.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte t_handle = pt_ops->stmf_proxy_connect(server_node, aluaNode);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* The first message is a greeting */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte (void) postMsg((uint_t)strlen(myNode)+1, (uchar_t *)myNode);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* Read the greeting from peer node */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Set the alua state in stmf. No need to keep
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * the device open since the proxy driver has a reference.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte syslog(LOG_DAEMON|LOG_CRIT, "stmf ioctl failed - %x", stmf_ret);
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte /* service is online */
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Loop relaying data from the peer daemon to the local kernel.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * Data coming from the local kernel is handled asynchronously
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte * by the door server.
450396635f70344c58b6b1e4db38cf17ff34445cJohn Forte for (;;) { /* loop forever */