dm.c revision d1d2228c6cf3ec632d28262810ab7902932a5d33
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <limits.h>
#include <pthread.h>
#include <synch.h>
#include <dirent.h>
#include <netdb.h>
#include <syslog.h>
#include <ctype.h>
#include <signal.h>
#include <unistd.h>
#include <stropts.h>
#include <fcntl.h>
#include <strings.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <link.h>
#include <netdb.h>
#include <libgen.h>
#include <mms_list.h>
#include <mms_parser.h>
#include <dmd_impl.h>
#include <dm_impl.h>
#include <mms_network.h>
#include <dm_drive.h>
#include <mms_sym.h>
#include <dm_msg.h>
#include <mms_trace.h>
#include <mms_dmd.h>
#include <dm_proto.h>
#include <host_ident.h>
#include <mms_strapp.h>
#include <mms_cores.h>
#include <mms_cat.h>
static int dm_caught_usr1 = 0;
static int dm_caught_usr2 = 0;
static int dm_caught_term = 0;
static int dm_caught_int = 0;
static drv_drive_t drv_drv;
static drv_jtab_t drv_jtab;
static drv_mount_t drv_mount;
static drv_scsi_err_t drv_scsi_err;
static drv_cart_access_t drv_dca;
/*
* Function name
* dm_init_log(void)
*
* Parameters:
* none
*
* Description:
* open a trace file for DM.
*
* Note:
*
*
*/
void
dm_init_log(void)
{
char *trfile;
trfile);
}
}
/*
* Function name
* dm_init_wka
*
* Parameters:
* none
*
* Description:
* initialize work area.
* The work area hold objects needed by DM, including mutexes,
* condition variables, lists pointers, etc.
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_init_wka(void)
{
if (wka->dm_pwbuf_size <= 0) {
}
}
/*
* Function name
* dm_init_dev_lib(void *hdl)
*
* Parameters:
* hdl pointer to the handle of the shared library that was
* opened by dlopen and contains device
* dependent code.
*
* Description:
* This function fills in the jump table used by DM to call device
* dependent functions and the drive table that holds some device
* specific information.
* DM initializes device libraries twice. Firstthe default library which
* has all the default functions and information. Then the device
* specific library which has only device specific information.
* Anything in the device specific library replaces those of the
* default library.
*
* Return code:
* none
*
* Note:
*
*
*/
void
{
#define DM_INIT_DRV(x, type) { \
} else if (init) { \
} \
}
#define DM_INIT_JTAB(x) { \
} else if (init) { \
} \
}
void *addr;
DM_INIT_DRV(drv_prsv_supported, (int *));
/* persistent reservation supported */
} else {
}
}
DM_INIT_DRV(drv_dev_dir, (char *));
DM_INIT_DRV(drv_shape, (char **));
DM_INIT_DRV(drv_drive_type, (char *));
DM_INIT_DRV(drv_disallowed_cmds, (int *));
DM_INIT_DRV(drv_num_disallowed_cmds, (int *));
DM_INIT_DRV(drv_disallowed_ioctls, (int *));
DM_INIT_DRV(drv_num_disallowed_ioctls, (int *));
/*
* Fill the jump table with devlib functions
*/
/*
* The following are functions to execute scsi commands
*/
}
/*
* Function name
* dm_load_default_lib(void)
*
* Parameters:
* none
*
* Description:
* loads the default library and initialize the jump table.
*
* Return code:
* 0 success
* -1 failed
*
* Note:
*
*
*/
int
dm_load_default_lib(void)
{
char *libpath;
/*
* Load the default device library
*/
"default device library %s open error: %s",
return (-1);
}
/* Init jtab with default lib */
return (0);
}
/*
* Function name
* dm_load_devlib(void)
*
* Parameters:
* none
*
* Description:
* get the device type and dlopen the device dependent library.
* initialize jump table with it.
*
* Return code:
* 0 success
* -1 error
*
* Note:
*
*
*/
int
dm_load_devlib(void)
{
char *libpath;
/*
* get device library name
*/
if (dm_get_dev_lib_name() != 0) {
return (-1);
}
"dynamic library open error: %s", dlerror()));
return (-1);
}
/* Init jtab with device lib */
dm_clear_dev();
return (0);
}
/*
* Function name
* dm_read_cfg(char *cfgname)
*
* Parameters:
* pointer to config file name
*
* Description:
* read the confige file passed to DM on the command line.
* Parse it and collect specified values.
*
* Return code:
* 0 success
* -1 error
*
* Note:
*
*
*/
int
dm_read_cfg(char *cfgname)
{
int fd;
char *buf;
int i;
char *kw;
if (fd < 0) {
}
/*
* Allocate a buffer to read in the entire config file
*/
}
}
/*
* Read in config file
*/
if (i < 0) {
}
buf[i] = '\0';
/*
* Parse the config file
*/
if (i < 0) {
"line %d, col %d, near token \"%s\", "
"err code %d, %s\n",
}
}
/*
* Pick up the args
*/
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
MMS_PN_KEYWORD, NULL)) {
}
return (0);
cfgname);
return (0);
}
/*
* Function name
* dm_ssl_cfg(void)
*
* Parameters:
* none
*
* Description:
* Configure SSL if it is enabled
*
* Return code:
* 0 success
* DM_NO_RESTART terminate DM if error
*
* Note:
*
*
*/
static int
dm_ssl_cfg(void)
{
char ebuf[MMS_EBUF_LEN];
#ifdef MMS_OPENSSL
if (wka->dm_ssl_enabled) {
}
}
#endif /* MMS_OPENSSL */
return (0);
}
/*
* Function name
* void dm_rem_old_handle(void)
*
* Parameters:
* none
*
* Description:
* deletes handles left over from the previous
* run.
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_rem_old_handle(void)
{
int len;
char *hdl;
int err;
/*
* If directory doe not exist, then create one.
*/
MMS_HDL_DIR));
/*
* create a directory named MMS_HDL_DIR,
* with read, write, and search permissions for
* owner and group, and with read and search
* permissions for others.
*/
/*
* create handle directory error
*/
"already created by another DM",
MMS_HDL_DIR));
return;
}
"directory %s: %s",
"Unable to create handle directory %s: %s",
}
/*
* Created new handle directoru
*/
return;
}
"Unable to open handle directory %s: %s",
}
/* found an old handle */
"dm_rem_old_handle: Removing handle %s",
}
}
}
/*
* Function name
* dm_init(int argc, char **argv)
*
* Parameters:
* the command line arguments which is the pathname of
* the config file.
*
* Description:
* - close all files and reopen the std* files.
* - read config file
* - initialize log, wka and ssl
* - open the drm device
*
* Return code:
* 0 success
* exit DM if error.
*
* Note:
*
*
*/
/* ARGSUSED */
int
{
int i;
int retries = 0;
char *corename;
/*
* Close all opened files.
*/
for (i = 0; i < OPEN_MAX; i++)
close(i);
/*
*/
setsid(); /* become session leader */
umask(0); /* clear file mode create mask */
/*
* Init message catalog
*/
mms_cat_open();
/*
* Initialize work area
*/
dm_init_wka();
/*
* Read config file
* Path of config file is argv[1]
*/
}
/* Move to where core files will be placed */
}
/* Check to see how many core files exist */
}
/*
* Init message logging
*/
dm_init_log();
DMNAME));
/*
* Open the DM device
*/
while (dm_open_dm_device() < 0) {
/* device is still opened */
retries++;
}
}
/*
* Init ssl
*/
if (dm_ssl_cfg()) {
}
/*
* Start session with SMM
*/
if (dm_init_session(0)) {
}
return (0);
}
/*
* Function name
* dm_get_dev_lib_name(void)
*
* Parameters:
* none
*
* Description:
* Get device dependent library name and save it in work area.
* Library name is constructed from the vendor and product ID's from
* the inquiry data like this:
* lib<vendor>-<product>.o
* where :
* <vendor> is the vendor id with trailing blanks removed and
* each remaining blank substituted with a '_' character.
* <product> is the product id with trailing blanks removed and
* each remaining blank substituted with a '_' character.
*
* Return code:
* 0 success
* -1 error
*
* Note:
*
*
*/
int
dm_get_dev_lib_name(void)
{
char vendor[9];
char prod[17];
int i;
return (EIO);
}
/*
* Read the inquiry data
*/
if (DRV_CALL(drv_get_drivetype, ())) {
"unable to get vendor and product ID: %s",
return (-1);
}
/* trim trailing blanks */
vendor[i] = '\0';
}
prod[i] = '\0';
}
/* Convert remaining blanks to '_' */
for (i = 0; vendor[i] != '\0'; i++) {
if (vendor[i] == ' ') {
vendor[i] = '_';
}
}
for (i = 0; prod[i] != '\0'; i++) {
if (prod[i] == ' ') {
prod[i] = '_';
}
}
return (0);
}
/*
* Function name
* dm_init_session(int retries)
*
* Parameters:
* number of retries
*
* Description:
* initialize a session with the Media Manager
* retry until success or until the number of retries is exceeded.
*
* Return code:
* fd If a welcome response was received from MM, then
* this routine returns the file descriptor that the
* client will use to communicate with MM.
* MMS_ERROR If an error occurred while processing or if an
* unwelcome response was receieved from MM.
*
*
* Note:
*
*
*/
int
dm_init_session(int retries)
{
int rc;
int err;
/*
* 0 retries means forever
*/
if (retries == 0) {
retries = 0x7fffffff;
}
if (wka->dm_mm_passwd) {
}
/*
* Unable to connect to mm
*/
"to MM: %d: %s", DMNAME,
if (retries > 1) {
} else {
break;
}
} else {
/*
* Successfully connected to MM
*/
"DM %s connected to MM on %s %s",
break;
}
}
return (rc);
}
/*
* Signal catching functions
*/
/*
* Function name
* dm_sigusr1(void)
*
* Parameters:
* none
*
* Description:
* SIGUSR1 catcher
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_sigusr1(void)
{
dm_caught_usr1 = 1;
}
/*
* Function name
* dm_sigusr2(void)
*
* Parameters:
* none
*
* Description:
* SIGUSR2 catcher
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_sigusr2(void)
{
dm_caught_usr2 = 1;
}
/*
* Function name
* dm_sigint(void)
*
* Parameters:
* void
*
* Description:
* SIGINT catcher
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_sigint(void)
{
/*
* Terminate this drive manager
*/
dm_caught_int = 1;
}
/*
* Function name
* dm_sigterm(void)
*
* Parameters:
* none
*
* Description:
* SIGTERM catcher
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_sigterm(void)
{
/*
* Terminate this drive manager
*/
dm_caught_term = 1;
}
/*
* Function name
* dm_sighup(void)
*
* Parameters:
* none
*
* Description:
* SIGHUP catcher
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_sighup(void)
{
/*
* Ignore Sighup
*/
/* Ignore sighup */
}
/*
* Function name
* dm_signal(int sig, void (*handler) ())
*
* Parameters:
* sig signal number
* handler signal handler
*
* Description:
* install signal handler
*
* Return code:
* none if success
* exit if error
*
* Note:
*
*
*/
void
{
/*
* Setup to catch signals
*/
/*
* Allow alarm signal to interrupt
*/
}
"Unable to set signal handler for "
}
}
/*
* Function name
* dm_setup_sig_handler(void)
*
* Parameters:
* none
*
* Description:
* setup to install all signal handlers
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_setup_sig_handler(void)
{
/*
* Setup SIGTERM handler
* Terminate drive manager
*/
/*
* Setup SIGUSR1 handler
* Driver request
*/
/*
* Setup SIGUSR2 handler
* tdv device closed
*/
/*
* Setup SIGHUP handler
*/
/*
* Setup SIGINT handler
*/
}
int
{
int rc = 0;
int nfds;
int always = 1;
/*
* Initialize message
*/
/*
* Init the drive manager
*/
"Unable to initialize the drive manager\n"));
}
/*
* Create handle prefix
*/
"%s.%s.%s",
/*
* Setup to block signals DM cares about.
* This is inherited by the worker thread so that it will not
* be interrupted by signals.
*/
/*
* DM successfully started
*/
/*
* Start processing threads.
*/
/*
* Setup signal handlers
*/
/*
* Main loop
*/
while (always) {
/* wakeup worker thread to do work */
/*
* Setup for pselect
*/
nfds = 0;
}
/*
* pselect will unblock signals blocked earlier
*/
if (dm_caught_term) {
dm_caught_term = 0;
}
if (dm_caught_int) {
dm_caught_int = 0;
}
if (dm_caught_usr2) {
dm_caught_usr2 = 0;
"Waking up waiting command"));
}
if (dm_caught_usr1) {
dm_caught_usr1 = 0;
}
if (rc > 0) {
/* Input pending */
/* Read input and put it on input list */
}
}
/*
* If connection to MM is closed, try reconnect
*/
}
/* Try sending accept again */
}
}
}
return (0);
}
/*
* Function name
* dm_restart_session(void)
*
* Parameters:
* none
*
* Description:
* restart a session with MM if it was disconnected
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_restart_session(void)
{
(void) dm_init_session(1);
}
/*
* Function name
* dm_worker(void *arg)
*
* Parameters:
* arg work area pointer
*
* Description:
* main loop of worker thread. This is where all the work is done.
*
* Return code:
* none
*
* Note:
*
*
*/
void *
{
int always = 1;
/*
* Remove old handles created by this DM
*/
/*
* Dispatch any commands from MM
*/
/*
* Wait for work to do
*/
while (always) {
mms_trace_flush(); /* flush mms_trace buffer */
/*
* Wait for work to do
*/
while (wka->dm_work_todo == 0) {
&wka->dm_worker_mutex);
}
wka->dm_work_todo = 0;
/*
* Update capacity
*/
}
/*
* Update EOF pos
*/
(void) dm_send_eof_pos();
}
}
if (wka->dm_request) {
}
}
return (NULL);
}
/*
* Function name
* dm_exit(int code, char *file, int line)
*
* Parameters:
* code exit code, DM_RESTART/DM_NO_RESTART
* file source file from which dm_exit is called
* line line number in file
*
* Description:
* close and flush trace file before exiting
*
* Return code:
* none
*
* Note:
*
*
*/
/*
* Exit DM
*/
void
{
"file %s, line %d with %s ########",
}
/*
* Function name
* dm_mk_prsv_key(void)
*
* Parameters:
* none
*
* Description:
* Make a persistent reservation key
* 1st 4 bytes are a constant character array (DRV_PRSV_KEY_PFX)
* followed by 4 bytes of IP mms_address (in hex).
*
* Return code:
* none
*
* Note:
*
*
*/
void
dm_mk_prsv_key(void)
{
char *ipp;
char *cp;
int tmp;
char dumpbuf[512];
int i;
/*
* Get IP mms_address - a string
*/
/*
* Convert to 4 hex digits.
*/
for (i = 0; i < 4; i++) {
*cp = '\0';
}
}
sizeof (drv->drv_prsv_key));
/*
* Tell driver
*/
}
/*
* Function name
* dm_silent(void)
*
* Parameters:
* none
*
* Description:
* return silent mode status
*
* Return code:
* 0 not silent
* > 0 silent
*
* Note:
*
*
*/
int
dm_silent(void)
{
}
/*
* Function name
* dm_trace(mms_trace_sev_t severity, char *file, int line, char *fmt, ...)
*
* Parameters:
* severity severity of trace msg
* file source filename
* line source file line number
* fmt, ... format and args of printf
*
* Description:
* trace function for DM. If in silent mode, don't trace.
*
* Return code:
* 1 dm_trace returns 1 in macro DRV_CALL so that it may
* trace and call the function.
*
* Note:
*
*
*/
int
{
if (!dm_silent()) {
}
return (1);
}