613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER START
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The contents of this file are subject to the terms of the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Common Development and Distribution License (the "License").
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You may not use this file except in compliance with the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or http://www.opensolaris.org/os/licensing.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * See the License for the specific language governing permissions
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * and limitations under the License.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * If applicable, add the following below this CDDL HEADER, with the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * CDDL HEADER END
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Ross * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * SMBFS I/O Daemon (Per-user IOD)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/types.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/stat.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <sys/note.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <errno.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <fcntl.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <signal.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdarg.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdio.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <string.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <strings.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <stdlib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <synch.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <time.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <unistd.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <ucred.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <err.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <door.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <libscf.h>
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross#include <locale.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <thread.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#include <netsmb/smb_lib.h>
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define DPRINT(...) do \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{ \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug) \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fprintf(stderr, __VA_ARGS__); \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross _NOTE(CONSTCOND) \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross} while (0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossmutex_t iod_mutex = DEFAULTMUTEX;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_thr_count; /* threads, excluding main */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_terminating;
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Rossint iod_alarm_time = 30; /* sec. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid iod_dispatch(void *cookie, char *argp, size_t argsz,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_desc_t *dp, uint_t n_desc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint iod_newvc(smb_iod_ssn_t *clnt_ssn);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid * iod_work(void *arg);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossmain(int argc, char **argv)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigset_t oldmask, tmpmask;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char *env, *door_path = NULL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int door_fd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int err, sig;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross int rc = SMF_EXIT_ERR_FATAL;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross boolean_t attached = B_FALSE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* set locale and text domain for i18n */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) setlocale(LC_ALL, "");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross (void) textdomain(TEXT_DOMAIN);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Debugging support. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((env = getenv("SMBFS_DEBUG")) != NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_debug = atoi(env);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (smb_debug < 1)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_debug = 1;
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Ross iod_alarm_time = 300;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * If a user runs this command (i.e. by accident)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * don't interfere with any already running IOD.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_iod_open_door(&door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross close(door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_fd = -1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross DPRINT("%s: already running\n", argv[0]);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross exit(SMF_EXIT_OK);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Want all signals blocked, as we're doing
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * synchronous delivery via sigwait below.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigfillset(&tmpmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sigprocmask(SIG_BLOCK, &tmpmask, &oldmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Setup the door service. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_path = smb_iod_door_path();
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_fd = door_create(iod_dispatch, NULL,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross DOOR_REFUSE_DESC | DOOR_NO_CANCEL);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (door_fd == -1) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross perror("iod door_create");
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross fdetach(door_path);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (fattach(door_fd, door_path) < 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "%s: fattach failed, %s\n",
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_path, strerror(errno));
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross attached = B_TRUE;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Initializations done. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross rc = SMF_EXIT_OK;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Post the initial alarm, and then just
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * wait for signals.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Ross alarm(iod_alarm_time);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossagain:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross sig = sigwait(&tmpmask);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("main: sig=%d\n", sig);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross switch (sig) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGCONT:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto again;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGALRM:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* No threads active for a while. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_lock(&iod_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (iod_thr_count > 0) {
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * Door call thread creation raced with
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * the alarm. Ignore this alaram.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross mutex_unlock(&iod_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross goto again;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Prevent a race with iod_thr_count */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross iod_terminating = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGINT:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross case SIGTERM:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break; /* normal termination */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross default:
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /* Unexpected signal. */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fprintf(stderr, "iod_main: unexpected sig=%d\n", sig);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross iod_terminating = 1;
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (attached)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross fdetach(door_path);
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross if (door_fd != -1)
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross door_revoke(door_fd);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross /*
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * We need a reference in -lumem to satisfy check_rtime,
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * else we get build hoise. This is sufficient.
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross */
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross free(NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (rc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*ARGSUSED*/
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_dispatch(void *cookie, char *argp, size_t argsz,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_desc_t *dp, uint_t n_desc)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_iod_ssn_t *ssn;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred_t *ucred;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross uid_t cl_uid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int rc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Verify that the calling process has the same UID.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Paranoia: The door we created has mode 0600, so
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * this check is probably redundant.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (door_ucred(&ucred) != 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EACCES;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cl_uid = ucred_getruid(ucred);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred_free(ucred);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ucred = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (cl_uid != getuid()) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: wrong UID\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EACCES;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * The library uses a NULL arg call to check if
a547be5daca7e465ca82df6d179f6b1f8e0cda72Gordon Ross * the daemon is running. Just return zero.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (argp == NULL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Otherwise, the arg must be the (fixed size)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * smb_iod_ssn_t
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (argsz != sizeof (*ssn)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EINVAL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_terminating) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: terminating\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = EINTR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_thr_count++ == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: cancelled alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ssn = (void *) argp;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rc = iod_newvc(ssn);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (--iod_thr_count == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_dispatch: schedule alarm\n");
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Ross alarm(iod_alarm_time);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross door_return((void *)&rc, sizeof (rc), NULL, 0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Try making a connection with the server described by
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the info in the smb_iod_ssn_t arg. If successful,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * start an IOD thread to service it, then return to
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the client side of the door.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossint
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_newvc(smb_iod_ssn_t *clnt_ssn)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_t *ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross thread_t tid;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int err;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This needs to essentially "clone" the smb_ctx_t
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * from the client side of the door, or at least
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * as much of it as we need while creating a VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = smb_ctx_alloc(&ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bcopy(clnt_ssn, &ctx->ct_iod_ssn, sizeof (ctx->ct_iod_ssn));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * Create the driver session first, so that any subsequent
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * requests for the same session will find this one and
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * wait, the same as when a reconnect is triggered.
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross *
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * There is still an inherent race here, where two callers
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * both find no VC in the driver, and both come here trying
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * to create the VC. In this case, we want the first one
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * to actually do the VC setup, and the second to proceed
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * as if the VC had been found in the driver. The second
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * caller gets an EEXIST error from the ioctl in this case,
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * which we therefore ignore here so that the caller will
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * go ahead and look again in the driver for the new VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((err = smb_ctx_gethandle(ctx)) != 0)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = errno;
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross if (err == EEXIST)
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross err = 0; /* see above */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross goto out;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross /*
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * Do the initial connection setup here, so we can
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross * report the outcome to the door client.
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross */
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross err = smb_iod_connect(ctx);
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross if (err != 0)
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross goto out;
fabf08ae7a95a47c3e249ee651d83d26f798bcfaGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* The rest happens in the iod_work thread. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (err == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Given to the new thread.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * free at end of iod_work
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossout:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_free(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (err);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/*
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * Be the reader thread for some VC.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is started by a door call thread, which means
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * this is always at least the 2nd thread, therefore
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * it should never see thr_count==0 or terminating.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossvoid *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossiod_work(void *arg)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_t *ctx = arg;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (iod_thr_count++ == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross alarm(0);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_work: cancelled alarm\n");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (void) smb_iod_work(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_lock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (--iod_thr_count == 0) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross DPRINT("iod_work: schedule alarm\n");
15359501f7d4b9abebd7b7bf6efd5982a8e7eb27Gordon Ross alarm(iod_alarm_time);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross mutex_unlock(&iod_mutex);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross smb_ctx_free(ctx);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return (NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}