lm_common_cmds.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 "lm.h"
#include <lm_proto.h>
static char *lm_c_priv_set[] = {
"LMMessageLevel",
"TraceLevel",
"TraceFileSize",
"SystemDiskMountTimeout",
NULL };
static char *lm_c_priv_unset[] = {
"LMMessageLevel",
"Tracelevel",
"TraceFileSize",
"SystemDiskMountTimeout",
NULL };
static char *lm_c_priv_get[] = {
NULL };
/*
* lm_common_ready
*
* Parameters:
* level The level that the LMPL command is to issue to MM
* tid The task id of the LMPM command that is responsible for
* the ready command to be issued.
* ret_msg If an error is detected while processing the ready command
* the error response is create here.
*
* This function sends the different forms of the LMPL ready command to MM
* based on the level sent to it.
*
* Return Values:
* LM_OK If LM was able to successfully complete the ready command.
*
* LM_ERROR If LM encountered an error while processing the ready
* command. This could mean either an internal processing error
* or just a command processing error. In either case an
* final error response is created in ret_msg with the error.
* This message would be used in the case where the ready is
* part of a LMPM command sequence. Currently only the LMPM
* activate command calls this function.
* NOTE: May not return a ret_msg here when more levels are
* called from other parts of the code. The caller would be
* responsible to generate a error message if required for a
* final response to a LMPM command.
*
*/
int
{
int rc;
int lmpl_tid;
char cmd_str[512];
const char *cfg_str;
char msg_str[256];
switch (level) {
case LM_READY:
break;
case LM_NOT:
break;
case LM_DISCONN:
break;
case LM_BROKE:
break;
case LM_PRESENT:
break;
default:
"- %d", level);
return (LM_ERROR);
}
"to get a taskid for LMPL ready command");
return (LM_ERROR);
}
} else {
}
"encountered while processing LMPL ready command:\n%s",
cmd_str);
return (LM_ERROR);
} else if (rc != LMPL_FINAL_OK) {
"received from MM for LMPL ready command:\n%s, cmd_str");
return (LM_ERROR);
}
"lm_c_ready: LMPL ready command was successfull:\n%s",
cmd_str);
return (LM_OK);
}
/*
* lm_common_activate
*
* Parameters:
* cmd Pointer to the parse tree of the activate command.
* tid The task id of the activate command.
* ret_msg The final response message that is to be sent back to MM.
* This could be either a success or error final response.
*
* This function executes the necessary steps that are common between
* all libraries when the LM receives an activate command. This routine
* is responsible for dynamically loading and unloading the library specific
* command modules when the LM is activated and deactivated.
*
* Return Values:
* LM_OK If LM was able to successfully complete the activate command.
* A final success response is created in ret_msg that will be
* sent to MM.
* LM_ERROR If LM encountered an error while processing the activate
* command. This could mean either an internal processing error
* or just a command processing error. In either case an
* final error response is created in ret_msg with the
* error information that will be sent to MM.
*
*/
int
{
int rc;
int lmpl_tid;
int connection = LM_GENERIC;
char cmd_str[512];
char msg_str[1024];
/* Create default final error response for MM */
!= NULL) {
"lm_c_activate: Processing activate enable");
"was unable to get a taskid for LMPL private "
"command to obtain library type and connection "
"information");
return (LM_ERROR);
}
cmd_str);
"lm_c_activate: Internal processing "
"error encountered while processing private "
"command to obtain library type:\n%s", cmd_str);
return (LM_ERROR);
} else if (rc != LMPL_FINAL_OK) {
"lm_c_activate: Non success response "
"received from MM for LMPL private command to "
"obtain library and connection type:\n%s", cmd_str);
return (LM_ERROR);
}
"LibraryType and LibraryConnection received a success "
"response");
"lm_c_activate: No text clause found "
"in final success response of private command to "
"obtain library type, response:\n%s",
return (LM_ERROR);
}
"attribute found in final success response of "
"private command to obtain library name, "
msg_str);
return (LM_ERROR);
}
"with LibraryName attribute found in final success "
"response of private command to obtain library "
"name, response:\n%s",
msg_str);
return (LM_ERROR);
}
"attribute found in final success response of "
"private command to obtain library type, "
msg_str);
return (LM_ERROR);
}
"with LibraryType attribute found in final success "
"response of private command to obtain library "
"type, response:\n%s",
msg_str);
return (LM_ERROR);
}
"lm_c_activate: No LibraryConnection "
"attribute found in finial success response of "
"private command to obtain library connection "
"type, response:\n%s",
msg_str);
return (LM_ERROR);
}
"with LibraryConnection attribute found in final "
"success response of private command to obtain "
"library connection type, response:\n%s",
msg_str);
return (LM_ERROR);
}
}
/* Private command to obtain library type completed */
/* Free up element components and response array */
"lm_c_activate: Load correct command handling "
/* Import in the correct cmd handling routines */
lm_cmdData)) == NULL) {
"command handling routines for library type - "
return (LM_ERROR);
}
/* Call library specific activate to finish */
/* the activation of the library */
"activate command failed, unable to activate LM");
return (LM_ERROR);
}
/*
* LM does not need to register for any events at this time
* This code is being left in in case it is required in the
* future
*
* if ((rc = lm_register_events(tid, ret_msg)) != LM_OK) {
* mms_trace(MMS_DEBUG, "c_activate: Failure while issueing "
* "event register command to MM. Unable to "
* "activate LM - %s", lm.lm_net_cfg.cli_inst);
* return (LM_ERROR);
* }
*
* LM is not going to send the LMPL ready command on the
* activate. MM will set LM state to ready when it receives
* the final success response to the activate command
*
* if ((rc = lm_common_ready(LM_READY, tid, ret_msg)) != LM_OK) {
* mms_trace(MMS_DEBUG, "lm_c_activate: Failure while issueing "
* "ready command to MM. Unable to enable LM");
* lm_unload_cmds(lm.lm_cmdHandle);
* return (LM_ERROR);
* }
*/
LM_7014_MSG, NULL);
"lm_c_activate: Processing activate disable");
/* Abort any abortable LMPM cmds on work queue */
/* Wait for all non abortable LMPM cmds to complete */
"outstanding LMPM commands to complete "
"before disable is complete");
(void) sleep(5);
}
"completed, ready to disable LM");
"lm_c_activate: Failure while issueing "
"ready command to MM. Unable to disable LM");
/* Reset state to ACTIVE */
return (LM_ERROR);
}
LM_7015_MSG, NULL);
} else {
return (LM_ERROR);
}
return (LM_OK);
}
/*
* lm_c_validate_private()
*
* Parameters:
* - cmd LMPM private command being processed.
* - tid Task id of private command being processed.
* - ret_msg Ptr to final response string. If an error message is
* to be sent to MM for the private command because of
* a failure, the response is copied here.
*
* Globals:
* - lm_c_priv_set The set-name values allowed in a LMPM private cmd.
* - lm_c_priv_get The get-name values allowed in a LMPM private cmd.
* - lm_c_priv_unset The unset-name values allowed in a LMPM private cmd.
*
* This function validates that all the set-name, get-name, and unset-name
* are valid. If the private command contains a name that is not known by
* LM, a error final response is sent in response the the LMPM private cmd.
* This function does not validate that the set-value is valid, while the
* set-name is being processed, the value needs to be validated. This function
* is only invoked if the LM has not yet activated. In the case of an
* activated LM where a library specific private command is available, the
* validation needs to be done by the library specific private command.
*
* Return Values:
* - LM_OK If all names are valid LM_OK is returned.
* - LM_ERROR If a name is encountered that is not know, LM_ERROR
* is returned and ret_msg is updated to reflect the
* error final response for the LMPM private cmd.
*/
static int
{
int i;
char *kw;
char msg_str[256];
MMS_PN_CLAUSE, &loc)) {
"lm_c_v_private:, Validating a get clause");
MMS_PN_STRING, &loc1)) {
for (i = 0; lm_c_priv_get[i] != NULL; i++) {
lm_c_priv_get[i]) == 0) {
"private get contains %s get-name",
mms_pn_token(name));
break;
}
}
if (lm_c_priv_get[i] == NULL) {
"command contains a unsupport get-name - "
msg_str);
return (LM_ERROR);
}
}
}
MMS_PN_CLAUSE, &loc)) {
"lm_c_v_private:, Validating a set clause");
MMS_PN_STRING, &loc1)) {
for (i = 0; lm_c_priv_set[i] != NULL; i++) {
lm_c_priv_set[i]) == 0) {
"private set contains %s set-name",
mms_pn_token(name));
break;
}
}
if (lm_c_priv_set[i] == NULL) {
"command contains a unsupport set-name - "
msg_str);
return (LM_ERROR);
}
/* For set clauses, the values asssociated */
/* with the set-name are validated when */
/* the set is acutally being processed, */
/* here just skip them to get next set-name */
&loc1);
}
}
MMS_PN_CLAUSE, &loc)) {
"lm_c_v_private:, Validating a unset clause");
MMS_PN_STRING, &loc1)) {
for (i = 0; lm_c_priv_unset[i] != NULL; i++) {
lm_c_priv_unset[i]) == 0) {
"private unset contains %s "
break;
}
}
if (lm_c_priv_unset[i] == NULL) {
"command contains a unsupport unset-name - "
msg_str);
return (LM_ERROR);
}
}
}
return (LM_OK);
return (LM_ERROR);
}
/*
* lm_common_private
*
* Parameters:
* cmd Pointer to the parse tree of the private command.
* tid The task id of the private command.
* ret_msg The final response message that is to be sent back to MM.
* This could be either a success or error final response.
*
* This function executes the necessary steps that are common between
* all libraries when the LM receives an private command. This routine
* is responsible for parsing through the parse tree to determine what
* attributes are to be updated based on the private command. This
* routine only handles what is common to all types of LMs. Once it has
* gone through the parse tree, it call the library specific private command
* handler.
*
* Return Values:
* LM_OK If LM was able to successfully complete the private command.
* A final success response is created in ret_msg that will be
* sent to MM.
* LM_ERROR If LM encountered an error while processing the private
* command. This could mean either an internal processing error
* or just a command processing error. In either case a
* final error response is created in ret_msg with the
* error information that will be sent to MM.
*/
int
{
char *kw;
char msg_str[256];
/* to accommodate larger get */
/* return text clauses, currently */
/* LM does not have any get-name */
/* that it supports */
/* Call library specific private to handle parts that */
/* are specific for library only */
"private command failed, unable to complete "
"private command");
return (LM_ERROR);
}
/* If the library specific private command processes */
/* cleanly any get library specific operations will */
/* return their text clauses in the ret_msg, copy them */
/* to the get_str to retain their values and add any */
/* common library get operations to them */
} else {
"lm_c_private: lm_c_validate_private() "
"failed");
return (LM_ERROR);
}
}
MMS_PN_CLAUSE, &loc)) {
/* Currently LM does not support any common get */
/* operations, just a place holder for when it */
/* does */
}
MMS_PN_CLAUSE, &loc)) {
MMS_PN_STRING, &loc1)) {
&loc1);
"mms_trace_str_filter failed");
(void) mms_buf_msgcl(msg_str,
sizeof (msg_str),
NULL);
tid,
msg_str);
return (LM_ERROR);
}
"lm_c_private: changing mms_trace "
}
== 0) {
"mms_trace_set_fsize failed");
(void) mms_buf_msgcl(msg_str,
sizeof (msg_str),
NULL);
tid,
msg_str);
return (LM_ERROR);
}
"lm_c_private: changing mms_trace "
"file rotation size to %s",
}
== 0) {
m_level =
"invalid message level - %s",
(void) mms_buf_msgcl(msg_str,
sizeof (msg_str),
NULL);
tid,
msg_str);
return (LM_ERROR);
}
"message level to %s",
}
"SystemDiskMountTimeout") == 0) {
"disk stat timeout to %s",
}
}
}
MMS_PN_CLAUSE, &loc)) {
MMS_PN_STRING, &loc1)) {
"lm_c_private: changing mms_trace "
"level to default of error");
(void) mms_trace_filter(MMS_SEV_ERROR);
}
== 0) {
"lm_c_private: changing mms_trace "
"file rotation size to 10M");
(void) mms_trace_set_fsize("10M");
}
== 0) {
"message level to warning");
}
"SystemDiskMountTimeout") == 0) {
"disk stat timeout to %d",
}
}
}
"lm_c_private: completed private command successfully");
return (LM_OK);
return (LM_ERROR);
}
/*
* lm_common_event
*
* Parameters:
* cmd Pointer to the parse tree of the event command.
* tid The task id of the event command.
* ret_msg Just a place holder, events do not get a response. The
* lm_cmd_handler() routine that calls this routine will
* skip the sending of the response.
*
* This function executes the necessary steps that are common between
* all libraries when the LM receives an event. The routine will first
* call the library specific lm_event() routine.
*
* Currently there are no events that LM registers for, so LM should
* never receive an event. If one is received, it is just ignored at this
* time. In the future if LM can receive events, this code will need to
* be updated to handle those events.
*
* Return Values:
* LM_OK If LM was able to successfully complete the event.
* LM_ERROR If LM encountered an error while processing the event
* This could mean either an internal processing error
* or just a command processing error.
*/
int
{
"lm_c_event: no library specific lm_event() "
"defined");
!= LM_OK) {
"failed");
return (LM_ERROR);
}
return (LM_OK);
}
/*
* lm_common_internal
*
* Parameters:
* cmd Pointer to the parse tree of the internal command.
* tid The task id of the internal command.
* ret_msg Just a place holder, internal commands do not get a
* response. The lm_cmd_handler() routine that calls this
* routine will skip the sending of the response.
*
* This function is used by the LM to be able to process another command
* on behalf of a different LMPM command.
*
* Currently, when lm_gen_lmpl_cmd() sends a LMPL command as part of
* processing a LMPM command, the routine processing the LMPM command
* can specifiy a timeout for how long it will wait for a response to
* the LMPL command. If the timeout is hit, the LM will need to send a
* cancel command for the LMPL command. This is done by adding an
* internal cancel command to the work queue, which will cause this
* routine to be invoked by the lm_cmd_handler().
*
* Note: No commands currently send a LMPL command with a timeout, thus
* nothing within LM currently will generate the internal command.
*
* Return Values:
* LM_OK If LM was able to successfully complete the internal command.
* LM_ERROR If LM encountered an error while processing the internal
* command. This could mean either an internal processing error
* or just a command processing error.
*/
int
{
int rc;
int lmpl_tid;
char cmd_str[256];
== NULL) {
return (LM_ERROR);
}
"cancel command");
== NULL) {
"the internal cancel command:\n%s",
return (LM_ERROR);
}
"generate cancel command for LMPL command "
return (LM_ERROR);
}
"processing error encountered while processing "
"internal cancel command to cancel LMPL "
return (LM_ERROR);
} else if (rc == LMPL_FINAL_ERROR) {
"lm_common_internal: Internal cancel "
"command received error response, unable to "
"cancel LMPL commmand with task id - %s",
} else if (rc != LMPL_FINAL_OK) {
"lm_common_internal: Internal cancel "
"command received a non success response, unable "
"to cancel LMPL command with taskid - %s",
ret_msg);
return (LM_ERROR);
} else {
"lm_common_internal: Internal cancel "
"command received a success final response");
}
} else {
"lm_c_internal: Unsupported internal command "
return (LM_ERROR);
}
return (LM_OK);
}
/*
* lm_message
*
* Parameters:
* who Specifies the who in the LMPL message
* severity Specifies the severity of the LMPL message
* msg The message to be sent out
*
* This function is used to send a message of some severity level to
* the destination defined by the argument "who".
*
* Return Values:
* None Since this is just a message going out, if it fails to
* be sent, it should not affect the running of the LM.
*
* Currently the messages are being sent out only to tell
* the operator of some other type of error that has
* occurred on a LMPM command; therefore, the error will be
* returned to the client in the error response.
*/
void
{
int rc;
int lmpl_tid;
char cmd_str[1024];
"severity of the message is less than what is currently "
"allowed. message ignored:\n%s", msg);
return;
}
"to get a taskid for LMPL message command");
return;
}
"encountered while processing LMPL message command");
return;
} else if (rc != LMPL_FINAL_OK) {
"received from MM for LMPL message command");
return;
}
}
/*
* lm_common_exit
*
* Parameters:
* cmd Pointer to the parse tree of the exit command.
* tid The task id of the exit command.
* ret_msg The final response message that is to be sent back to MM.
* This could be either a success or error final response.
*
* This function executes the necessary steps that are common between
* all libraries when the LM receives a exit command. This routine
* is responsible for shutting down the LM gracefully and then exiting.
* Even if something does not shutdown cleanly, the LM will still exit.
*
* Return Values:
* LM_OK If LM was able to successfully complete the exit command.
* A final success response is created in ret_msg that will be
* sent to MM.
* LM_ERROR If LM encountered an error while processing the exit
* command. This could mean either an internal processing error
* or just a command processing error. In either case a
* final error response is created in ret_msg with the
* error information that will be sent to MM.
*/
int
{
int rc;
char msg_str[1024];
/* Set state of lm to stop to abort any new commands */
/* Set LM state in MM to not ready */
"Unable to set LM's state to not ready");
}
/* Abort any abortable LMPM cmds on work queue */
/* Wait for all non abortable LMPM cmds to complete */
"lm_c_exit: Waiting for all outstanding LMPM "
"commands to complete before exit is complete");
(void) sleep(5);
}
/* Call library specific lm_exit() to handle any parts */
/* are specific for the library only */
"exit command failed to do pre exit cleanly");
} else {
LM_7016_MSG, NULL);
}
} else {
LM_7016_MSG, NULL);
}
}
ret_msg);
"completed, ready to exit LM");
return (LM_OK);
}
/*
* lm_common_reset
*
* Parameters:
* cmd Pointer to the parse tree of the reset command.
* tid The task id of the reset command.
* ret_msg The final response message that is to be sent back to MM.
* This could be either a success or error final response.
*
* This function executes the necessary steps that are common between
* all libraries when the LM receives a reset command. This routine
* is responsible for shutting down the LM gracefully and then restarting.
*
* Return Values:
* LM_OK If LM was able to successfully complete the reset command.
* A final success response is created in ret_msg that will be
* sent to MM.
* LM_ERROR If LM encountered an error while processing the reset
* command. This could mean either an internal processing error
* or just a command processing error. In either case a
* final error response is created in ret_msg with the
* error information that will be sent to MM.
*/
int
{
int rc;
char msg_str[1024];
char lret_msg[2048];
lret_msg[0] = '\0';
tid,
msg_str);
!= NULL) {
/* Set LM state in MM to not ready */
"unable to set LM's state to ready not prior to "
"reset");
return (LM_ERROR);
}
} else {
/* Set LM state in MM to not ready, ignore return */
/* value since the LM will reset itself */
"unable to set LM's state to ready not prior to "
"reset");
}
/* Set state of lm to stop to abort any new commands */
/* Abort any abortable LMPM cmds on work queue */
/* Wait for all non abortable LMPM cmds to complete */
"outstanding LMPM commands to complete before "
"reset is complete");
(void) sleep(5);
}
}
/* Call library specific lm_reset() to handle any parts */
/* are specific for the library only */
/* Use retmsg for resturn message */
"reset command failed to do reset cleanly");
if (partial) {
!= LM_OK) {
"a partial reset, LMPL ready "
"command failed to set LM's state "
"back to ready");
}
return (LM_ERROR);
} else {
"lm_c_reset: library specific "
"full reset failed");
}
} else {
if (partial) {
LM_7022_MSG, NULL);
} else {
LM_7017_MSG, NULL);
}
}
} else {
"exists");
if (partial) {
"lm_c_reset: During a partial "
"reset, LMPL ready command failed to set "
"LM's state back to ready");
return (LM_ERROR);
}
LM_7022_MSG, NULL);
return (LM_OK);
} else {
LM_7017_MSG, NULL);
}
}
}
if (partial) {
"reset, LMPL ready command failed to set "
"LM's state back to ready");
return (LM_ERROR);
}
} else {
"lm_c_reset: All outstanding LMPM commands have "
"completed, ready to reset LM");
}
ret_msg);
return (LM_OK);
}
/*
* lm_set_drive_disabled
*
* Parameters:
* - drive_name : ptr to string of drive name
* - drive_state : ptr to string of DriveDisabled state to set to
*
* Sends an attribute command to MM to set the DriveDisabled state to
* the drive_state string for a drive who's name is drive_name
*
* Return Values:
* None
*
*/
void
{
int rc;
int lmpl_tid;
if (drive_name == NULL) {
"lm_set_drive_disabled: "
"passed null drive_name");
return;
}
if (drive_state == NULL) {
"lm_set_drive_disabled: "
"passed null drive_state");
return;
}
"lm_set_drive_disabled: "
"set DriveDisabled = %s for %s",
"lm_set_drive_disabled: "
"lm_obtain_task_id was unable "
"to get a taskid for LMPL attribute command");
return;
}
"lm_set_drive_disabled: "
"attribute command:\n%s", cmd_str);
"lm_set_drive_disabled: "
"Internal processing error "
"encountered while processing LMPL attribute command");
return;
} else if (rc != LMPL_FINAL_OK) {
"lm_set_drive_disabled: "
"Non success response "
"received from MM for LMPL attribute command");
return;
}
"lm_set_drive_disabled: "
"Attribute sent successfully");
}