summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Cheng <Simon.S.Cheng@Sun.COM>2008-10-24 14:23:54 -0500
committerSimon Cheng <Simon.S.Cheng@Sun.COM>2008-10-24 14:23:54 -0500
commit4f2e01b27b6f050ac264ee29e4fea7a9045ce86e (patch)
tree8db070cf0876d06798853132313b08bd71534803
parentaf71cc4ed6be914d26e9de3a90a2bb56e4bbe78d (diff)
downloadillumos-gate-4f2e01b27b6f050ac264ee29e4fea7a9045ce86e.tar.gz
6631129 More descriptive error codes required in begin-end response
-rw-r--r--usr/src/cmd/mms/mm/common/mm.c2
-rw-r--r--usr/src/cmd/mms/mm/common/mm.h20
-rw-r--r--usr/src/cmd/mms/mm/common/mm_lmp_sql.c7
-rw-r--r--usr/src/cmd/mms/mm/common/mm_mmp_mount.c171
-rw-r--r--usr/src/cmd/mms/mm/common/mm_msg.c20
-rw-r--r--usr/src/cmd/mms/mm/common/mm_task.c340
-rw-r--r--usr/src/cmd/mms/mm/common/mm_util.c490
-rw-r--r--usr/src/cmd/mms/mm/common/mm_util.h14
-rw-r--r--usr/src/common/mms/mms/mms_mm_msg.h4
9 files changed, 885 insertions, 183 deletions
diff --git a/usr/src/cmd/mms/mm/common/mm.c b/usr/src/cmd/mms/mm/common/mm.c
index ec6e8e6376..3561890c0a 100644
--- a/usr/src/cmd/mms/mm/common/mm.c
+++ b/usr/src/cmd/mms/mm/common/mm.c
@@ -984,6 +984,8 @@ mm_destroy_cmd(mm_command_t *cmd)
mms_list_destroy(&cmd->cmd_const_list);
mm_free_list(&cmd->cmd_resp_list);
mms_list_destroy(&cmd->cmd_resp_list);
+ mm_free_err_list(cmd);
+ mms_list_destroy(&cmd->cmd_err_list);
}
/* Message */
diff --git a/usr/src/cmd/mms/mm/common/mm.h b/usr/src/cmd/mms/mm/common/mm.h
index 182c6d0ffc..706f37e8aa 100644
--- a/usr/src/cmd/mms/mm/common/mm.h
+++ b/usr/src/cmd/mms/mm/common/mm.h
@@ -276,6 +276,7 @@ struct cmi_cart_list {
int cmi_remove_cart;
int cmi_cart_not_ready;
int cmi_cart_loaded;
+ int cmi_cart_used;
};
typedef struct cmi_drive_list cmi_drive_list_t;
@@ -292,6 +293,7 @@ struct cmi_drive_list {
int cmi_drive_not_ready;
int cmi_dm_shape_priority;
int cmi_dm_density_priority;
+ int cmi_drive_used;
};
#define MM_MOUNT 0
@@ -311,6 +313,7 @@ struct cmd_mount_info {
char *cmi_handle;
mms_list_t cmi_cart_list;
int cmi_total_carts;
+ int cmi_mount_ok;
/* Recovery */
int cmi_retries;
@@ -433,6 +436,19 @@ struct mm_msg {
int msg_flags;
};
+typedef struct mm_cmd_err mm_cmd_err_t;
+struct mm_cmd_err {
+ mms_list_node_t mm_cmd_err_next;
+ char *ecode;
+ char *eclass;
+ char *err_buf;
+ int err_bufsize;
+ char *retry_drive;
+ char *retry_cart;
+ char *retry_lib;
+ int err_already_used;
+};
+
typedef struct mm_wka {
cci_t wka_conn;
mms_list_node_t wka_next;
@@ -499,6 +515,10 @@ struct mm_command {
mms_list_t cmd_source_list;
mms_list_t cmd_dest_list;
mms_list_t cmd_const_list;
+ /* error list */
+ mms_list_t cmd_err_list;
+ mm_cmd_err_t *cmd_err_ptr;
+
mms_list_t cmd_beginend_list;
int cmd_begin_has_end;
diff --git a/usr/src/cmd/mms/mm/common/mm_lmp_sql.c b/usr/src/cmd/mms/mm/common/mm_lmp_sql.c
index 7c276d2a84..168199ca4b 100644
--- a/usr/src/cmd/mms/mm/common/mm_lmp_sql.c
+++ b/usr/src/cmd/mms/mm/common/mm_lmp_sql.c
@@ -772,7 +772,12 @@ mm_lmp_activate_cmd_func(mm_wka_t *mm_wka, mm_command_t *cmd)
}
}
- mms_trace(MMS_ERR, "lm activate %d failed", flag);
+ mms_trace(MMS_ERR, "lm activate %d failed, set LM to present", flag);
+ if (mm_lm_state_soft(mm_wka, "present")) {
+ mms_trace(MMS_ERR,
+ "mm_lmp_activate_cmd_func: "
+ "LM state changed failed");
+ }
cmd->cmd_remove = 1;
return (MM_CMD_ERROR);
}
diff --git a/usr/src/cmd/mms/mm/common/mm_mmp_mount.c b/usr/src/cmd/mms/mm/common/mm_mmp_mount.c
index 68f7c2d7c6..da2b7409aa 100644
--- a/usr/src/cmd/mms/mm/common/mm_mmp_mount.c
+++ b/usr/src/cmd/mms/mm/common/mm_mmp_mount.c
@@ -510,18 +510,28 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
" DriveStateSoft != ready ",
candidate_drive);
drive->cmi_drive_not_ready = 1;
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "EDRVINUSE",
+ MM_5025_MSG,
+ "drive", candidate_drive,
+ NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
if (mount_info->cmi_when == MM_IMMEDIATE) {
+ rc = 0; goto end;
+ } else {
+ mms_trace(MMS_DEVP,
+ "drive in use, keep as"
+ " candidate for blocking mounts");
mm_response_error(cmd,
ECLASS_RETRY,
"EDRVINUSE",
MM_5025_MSG,
"drive", candidate_drive,
NULL);
- rc = 0; goto end;
- } else {
- mms_trace(MMS_DEVP,
- "drive in use, keep as"
- " candidate for blocking mounts");
+ mm_set_retry_drive(cmd,
+ candidate_drive);
}
/* Keep this drive as a candidate for blocking mounts */
@@ -543,14 +553,15 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
"This drive is in the process of "
"unloading/loading");
drive->cmi_drive_not_ready = 1;
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "EDRVUNLOADING",
+ MM_5102_MSG,
+ "drive", candidate_drive,
+ NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
if (mount_info->cmi_when == MM_IMMEDIATE) {
- /* make a real error message for this */
- mm_response_error(cmd,
- ECLASS_RETRY,
- "EDRVUNLOADING",
- MM_5102_MSG,
- "drive", candidate_drive,
- NULL);
rc = 0; goto end;
}
} else {
@@ -564,13 +575,15 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
drive->cmi_drive_not_ready = 1;
mms_trace(MMS_DEVP,
"drive is loaded with a non-mms tape");
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "EDRVINUSE",
+ MM_5028_MSG,
+ "drive", candidate_drive,
+ NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
if (mount_info->cmi_when == MM_IMMEDIATE) {
- mm_response_error(cmd,
- ECLASS_RETRY,
- "EDRVINUSE",
- MM_5028_MSG,
- "drive", candidate_drive,
- NULL);
rc = 0; goto end;
}
}
@@ -677,28 +690,29 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
"drive",
candidate_drive,
NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
rc = 0; goto end;
} else if (strcmp(dm_stat->dm_stat_soft,
"not ready") == 0) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "EDMSTILLBOOTING",
+ MM_5034_MSG,
+ "dm",
+ dm_stat->dm_stat_name,
+ "drive",
+ candidate_drive,
+ NULL);
if (mount_info->cmi_when == MM_IMMEDIATE) {
- mm_response_error(cmd,
- ECLASS_RETRY,
- "EDMSTILLBOOTING",
- MM_5034_MSG,
- "dm",
- dm_stat->dm_stat_name,
- "drive",
- candidate_drive,
- NULL);
rc = 0; goto end;
}
} else if (strcmp(dm_stat->dm_stat_soft,
"present") == 0) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
- if (mount_info->cmi_when == MM_IMMEDIATE) {
mm_response_error(cmd,
ECLASS_CONFIG,
"EDRVNODMCONFIGURED",
@@ -708,6 +722,9 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
"drive",
candidate_drive,
NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
+ if (mount_info->cmi_when == MM_IMMEDIATE) {
rc = 0; goto end;
}
} else if ((mount_info->cmi_operation == MM_MOUNT) &&
@@ -715,14 +732,16 @@ mm_candidate_drive_ok(mm_wka_t *mm_wka,
"reserved") == 0)) {
/* drive is not ready for blocked */
drive->cmi_drive_not_ready = 1;
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "EDRVINUSE",
+ MM_5098_MSG,
+ "dm",
+ dm_stat->dm_stat_name,
+ NULL);
+ mm_set_retry_drive(cmd,
+ candidate_drive);
if (mount_info->cmi_when == MM_IMMEDIATE) {
- mm_response_error(cmd,
- ECLASS_RETRY,
- "EDRVINUSE",
- MM_5098_MSG,
- "dm",
- dm_stat->dm_stat_name,
- NULL);
rc = 0; goto end;
}
}
@@ -873,16 +892,17 @@ mm_candidate_cartridge_ok(mm_wka_t *mm_wka,
/* mark this cartridge not ready */
/* for blocked mounts */
cart_struct->cmi_cart_not_ready = 1;
-
+ /* State is 'in use' */
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "ECARTINUSE",
+ MM_5038_MSG,
+ "cart",
+ candidate_cartid,
+ NULL);
+ mm_set_retry_cart(cmd,
+ (char *)candidate_cartid);
if (mount_info->cmi_when == MM_IMMEDIATE) {
- /* State is 'in use' */
- mm_response_error(cmd,
- ECLASS_RETRY,
- "ECARTINUSE",
- MM_5038_MSG,
- "cart",
- candidate_cartid,
- NULL);
rc = 0; goto end;
}
}
@@ -1115,6 +1135,8 @@ mm_candidate_library_ok(mm_command_t *cmd, mm_db_t *db,
"lib",
lib_stat->lib_stat_name,
NULL);
+ mm_set_retry_lib(cmd,
+ candidate_library);
}
if (strcmp(lm_stat->lm_stat_soft,
"present") == 0) {
@@ -1127,6 +1149,8 @@ mm_candidate_library_ok(mm_command_t *cmd, mm_db_t *db,
"lib",
lib_stat->lib_stat_name,
NULL);
+ mm_set_retry_lib(cmd,
+ candidate_library);
}
if (strcmp(lm_stat->lm_stat_soft,
"disconnected") == 0) {
@@ -1152,6 +1176,8 @@ mm_candidate_library_ok(mm_command_t *cmd, mm_db_t *db,
"lib",
lib_stat->lib_stat_name,
NULL);
+ mm_set_retry_lib(cmd,
+ candidate_library);
}
rc = 0; goto end;
}
@@ -1297,6 +1323,7 @@ mm_setup_drive_unmount(mm_command_t *cmd,
strdup(candidate_drive);
drive->cmi_mode_valid = 1;
drive->cmi_drive_not_ready = 0;
+ drive->cmi_drive_used = 0;
drive->cmi_dm_name = mms_strapp(drive->cmi_dm_name, dm_name);
drive->cmi_dm_shape_priority = 0;
@@ -1503,6 +1530,7 @@ mm_setup_drive(mm_command_t *cmd,
strdup(candidate_drive);
drive->cmi_mode_valid = 1;
drive->cmi_drive_not_ready = drive_not_ready;
+ drive->cmi_drive_used = 0;
drive->cmi_dm_name =
strdup(PQgetvalue(dm,
@@ -1606,6 +1634,7 @@ mm_setup_cart(mm_command_t *cmd,
bit_format);
cart->cmi_cart_not_ready = 0;
+ cart->cmi_cart_used = 0;
cart->cmi_cart_priority = atoi(candidate_priority);
cart->cmi_cart_num_mounts = atoi(candidate_num_mounts);
@@ -1657,11 +1686,13 @@ mm_mount_candidate_loaded(mm_command_t *cmd) {
cur_cartid = cart->cmi_cart_id;
/* The list should already be ordered */
/* select the 1st available */
- if (cart->cmi_cart_not_ready) {
+ if (cart->cmi_cart_not_ready ||
+ cart->cmi_cart_used) {
continue;
}
mms_list_foreach(&cart->cmi_drive_list, drive) {
- if (drive->cmi_drive_not_ready) {
+ if (drive->cmi_drive_not_ready ||
+ drive->cmi_drive_used) {
continue;
}
if (drive->cmi_drive_loaded) {
@@ -1711,7 +1742,8 @@ mm_mount_open_drive(mm_command_t *cmd) {
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
- if (cart->cmi_cart_not_ready) {
+ if (cart->cmi_cart_not_ready ||
+ cart->cmi_cart_used) {
continue;
}
cur_library = cart->cmi_library;
@@ -1723,7 +1755,8 @@ mm_mount_open_drive(mm_command_t *cmd) {
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&cart->cmi_drive_list, drive) {
- if (drive->cmi_drive_not_ready) {
+ if (drive->cmi_drive_not_ready ||
+ drive->cmi_drive_used) {
continue;
}
/* only look at non-loaded drives */
@@ -1770,14 +1803,16 @@ mm_unmount_2_drive(mm_command_t *cmd, mm_db_t *db) {
"mm_unmount_2_drive: ");
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
- if (cart->cmi_cart_not_ready) {
+ if (cart->cmi_cart_not_ready ||
+ cart->cmi_cart_used) {
continue;
}
cur_library = cart->cmi_library;
cur_cartid = cart->cmi_cart_id;
cur_pcl = cart->cmi_cart_pcl;
mms_list_foreach(&cart->cmi_drive_list, drive) {
- if (drive->cmi_drive_not_ready) {
+ if (drive->cmi_drive_not_ready ||
+ drive->cmi_drive_used) {
continue;
}
cur_drive = drive->cmi_drive_name;
@@ -1874,7 +1909,8 @@ mm_mount_loaded_drive(mm_command_t *cmd, mm_db_t *db,
/* The list should already be ordered */
/* select the 1st available */
mms_list_foreach(&mount_info->cmi_cart_list, cart) {
- if (cart->cmi_cart_not_ready) {
+ if (cart->cmi_cart_not_ready ||
+ cart->cmi_cart_used) {
continue;
}
cur_library = cart->cmi_library;
@@ -1887,7 +1923,8 @@ mm_mount_loaded_drive(mm_command_t *cmd, mm_db_t *db,
/* select the 1st available */
mms_list_foreach(&cart->cmi_drive_list, drive) {
- if (drive->cmi_drive_not_ready) {
+ if (drive->cmi_drive_not_ready ||
+ drive->cmi_drive_used) {
continue;
}
cur_drive = drive->cmi_drive_name;
@@ -2141,6 +2178,8 @@ void
mm_set_mount_objs(mm_command_t *cmd, mm_db_t *db) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
+
+
if (mm_db_exec(HERE, db, "delete from \"TASK\" "
"where \"TaskID\" = '%s';",
cmd->cmd_uuid) != MM_DB_OK) {
@@ -2149,12 +2188,6 @@ mm_set_mount_objs(mm_command_t *cmd, mm_db_t *db) {
"db error deleting TASK");
}
- if (mm_new_tm_task(db, cmd, "dispatched") != MM_DB_OK) {
- mms_trace(MMS_ERR,
- "mm_set_mount_objs: "
- "db error inserting TASK");
- }
-
/* Delete all old TASK objects and create them anew */
if (mm_db_exec(HERE, db, "delete from \"TASKDRIVE\" "
"where \"TaskID\" = '%s';",
@@ -2178,6 +2211,24 @@ mm_set_mount_objs(mm_command_t *cmd, mm_db_t *db) {
"db error deleting TASKCARTRIDGE");
}
+ if ((mount_info->cmi_drive == NULL) ||
+ (mount_info->cmi_library == NULL) ||
+ (mount_info->cmi_cartridge == NULL) ||
+ (mount_info->cmi_dm == NULL)) {
+ mms_trace(MMS_ERR,
+ "mm_set_mount_objs: "
+ "mount info incomplete");
+ mm_system_error(cmd,
+ "internal error setting task info, "
+ "mount info incomplete");
+ return;
+ }
+
+ if (mm_new_tm_task(db, cmd, "dispatched") != MM_DB_OK) {
+ mms_trace(MMS_ERR,
+ "mm_set_mount_objs: "
+ "db error inserting TASK");
+ }
if (mm_set_tm_drive(db,
cmd->cmd_uuid,
@@ -3485,6 +3536,8 @@ mm_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db, int is_retry) {
"No candidate "
"cartridge/library/drive "
"combination found");
+ /* set least severe error */
+ mm_set_least_severe(cmd);
return (MM_MOUNT_ERROR);
}
if (found_ready_cart_drive == 0) {
@@ -3527,6 +3580,8 @@ mm_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db, int is_retry) {
if (rc == MM_CMD_ERROR) {
mms_trace(MMS_ERR,
"error setting up immediate mount");
+ /* set least severe error */
+ mm_set_least_severe(cmd);
return (MM_MOUNT_ERROR);
} else if (rc == MM_DISPATCH_DEPEND) {
/* this immediate mount needs to */
diff --git a/usr/src/cmd/mms/mm/common/mm_msg.c b/usr/src/cmd/mms/mm/common/mm_msg.c
index 0125c9186e..1624df481d 100644
--- a/usr/src/cmd/mms/mm/common/mm_msg.c
+++ b/usr/src/cmd/mms/mm/common/mm_msg.c
@@ -1320,6 +1320,9 @@ mm_response_error(mm_command_t *cmd, char *eclass, char *ecode,
char *buf;
char *text;
+ mm_cmd_err_t *err = NULL;
+
+
mms_trace(MMS_ERR, "mm_response_error");
mms_trace(MMS_ERR, "Class:: %s",
eclass);
@@ -1355,6 +1358,23 @@ mm_response_error(mm_command_t *cmd, char *eclass, char *ecode,
SQL_CHK_LEN(&cmd->cmd_buf, 0, &cmd->cmd_bufsize, strlen(buf) + 1);
strcpy(cmd->cmd_buf, buf);
free(buf);
+
+ /* insert this error into the cmd's err_list */
+ if ((err = mm_alloc_err()) == NULL) {
+ mms_trace(MMS_ERR,
+ "mm_response_error: "
+ "could not allocate err struct");
+ return;
+ }
+ err->eclass = strdup(eclass);
+ err->ecode = strdup(ecode);
+ err->err_bufsize = cmd->cmd_bufsize;
+ err->err_buf = strdup(cmd->cmd_buf);
+ err->retry_drive = NULL;
+ err->retry_cart = NULL;
+ err->retry_lib = NULL;
+ mms_list_insert_tail(&cmd->cmd_err_list, err);
+
return;
no_mem:
diff --git a/usr/src/cmd/mms/mm/common/mm_task.c b/usr/src/cmd/mms/mm/common/mm_task.c
index 886451a1e2..273e13487b 100644
--- a/usr/src/cmd/mms/mm/common/mm_task.c
+++ b/usr/src/cmd/mms/mm/common/mm_task.c
@@ -395,6 +395,8 @@ tm_be_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db,
int found_cart_drive = 0;
int found_ready_cart_drive = 0;
+ char *err_text = NULL;
+
/* Need to set end_cmd buf correctly for any MM_MOUNT_ERROR return */
@@ -499,13 +501,14 @@ tm_be_mount_ready(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db,
NULL);
return (MM_MOUNT_ERROR);
}
-
+ err_text = mm_return_err_text(cmd->cmd_err_ptr);
mm_response_error(end_cmd,
ECLASS_EXPLICIT,
"ENOSOLUTIONS",
- MM_5105_MSG,
+ MM_5110_MSG,
+ "err_text", err_text,
NULL);
-
+ free(err_text);
return (MM_MOUNT_ERROR);
}
if (found_ready_cart_drive == 0) {
@@ -557,7 +560,7 @@ tm_be_cancel_all(mm_command_t *cmd) {
}
int
-tm_be_set_mount(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db,
+tm_be_set_mount(mm_command_t *cmd, mm_db_t *db,
mm_command_t *end_cmd) {
cmd_mount_info_t *mount_info = &cmd->cmd_mount_info;
@@ -630,22 +633,18 @@ tm_be_set_mount(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db,
MM_UNSET_FLAG(cmd->cmd_flags, MM_CMD_DISPATCHABLE);
} else {
-
mms_trace(MMS_ERR,
"no drives found due to other candidates");
- if (mm_wka->wka_begin_end.be_mode ==
- ACCESS_MODE_BLOCKING) {
- return (MM_BE_BLOCKING);
+ mm_set_least_severe(cmd);
+ if (cmd->cmd_err_ptr == NULL) {
+ mms_trace(MMS_ERR,
+ "cmd has no errors, set ENOMATCH");
+ mm_response_error(end_cmd,
+ ECLASS_EXPLICIT, ENOMATCH,
+ MM_5052_MSG,
+ NULL);
}
- /* May want to add additional arg's to this message? */
- mm_response_error(end_cmd,
- ECLASS_RETRY,
- "ETMPUNAVAIL",
- MM_5104_MSG,
- NULL);
-
return (MM_BE_ERROR);
-
}
/* Select Is done - print the results */
@@ -661,6 +660,17 @@ tm_be_set_mount(mm_wka_t *mm_wka, mm_command_t *cmd, mm_db_t *db,
mms_trace(MMS_DEVP, "DM is %s",
mount_info->cmi_dm);
+ /* since this mount will work, clear the error flags for it */
+ if (cmd->cmd_eclass != NULL) {
+ free(cmd->cmd_eclass);
+ cmd->cmd_eclass = NULL;
+ }
+ if (cmd->cmd_ecode != NULL) {
+ free(cmd->cmd_ecode);
+ cmd->cmd_ecode = NULL;
+ }
+ cmd->cmd_mount_info.cmi_mount_ok = 1;
+
return (MM_BE_DISPATCH);
}
@@ -745,6 +755,86 @@ tm_be_set_unmount(mm_wka_t *mm_wka, mm_command_t *cmd,
}
void
+tm_be_rm_error_candidates(mm_command_t *cmd, mm_command_t *err_cmd) {
+ /* remove candidates set in err_cmd */
+ /* from the beginend candidatea list in cmd */
+
+ mm_cmd_err_t *err = err_cmd->cmd_err_ptr;
+ mm_command_t *cur_cmd;
+ cmd_mount_info_t *cur_mount_info;
+
+ cmi_cart_list_t *cart = NULL;
+ cmi_drive_list_t *drive = NULL;
+
+ mms_list_t *cart_list;
+
+ int seen_same = 0;
+ mm_cmd_err_t *cur_err = NULL;
+
+ mms_trace(MMS_DEVP,
+ "tm_be_rm_error_candidates: ");
+ if (err == NULL) {
+ mms_trace(MMS_ERR,
+ "tm_be_rm_error_candidates: "
+ "error ptr set to NULL");
+ return;
+ }
+
+ mms_trace(MMS_DEVP,
+ " Error to remove:");
+ mm_print_err(err);
+
+ mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
+ /* same command */
+ if (cur_cmd == err_cmd) {
+ seen_same = 1;
+ continue;
+ }
+ if (seen_same == 0) {
+ continue;
+ }
+
+ /* check cur_cmd's error */
+ mms_list_foreach(&cur_cmd->cmd_err_list, cur_err) {
+ if (mm_same_err(err, cur_err)) {
+ cur_err->err_already_used = 1;
+ mms_trace(MMS_DEVP,
+ " matched an err");
+ }
+ }
+ cur_cmd->cmd_err_ptr = NULL;
+ mm_set_least_severe(cur_cmd);
+
+ cur_mount_info = &cur_cmd->cmd_mount_info;
+ cart_list = &cur_mount_info->cmi_cart_list;
+ mms_list_foreach(cart_list, cart) {
+ /* Check this cart */
+ if ((err->retry_cart != NULL) &&
+ (cart->cmi_cart_id != NULL) &&
+ (strcmp(err->retry_cart,
+ cart->cmi_cart_id) == 0)) {
+ cart->cmi_cart_used = 1;
+ mms_trace(MMS_DEVP,
+ "tm_be_rm_error_candidates: "
+ "set a cart as used");
+ }
+ mms_list_foreach(&cart->cmi_drive_list, drive) {
+ /* check this drive */
+ if ((err->retry_drive != NULL) &&
+ (drive->cmi_drive_name != NULL) &&
+ (strcmp(err->retry_drive,
+ drive->cmi_drive_name) == 0)) {
+ drive->cmi_drive_used = 1;
+ mms_trace(MMS_DEVP,
+ "tm_be_rm_error_candidates: "
+ "set a drive as used");
+ }
+ }
+ }
+ }
+}
+
+void
tm_be_rm_mount_candidates(mm_command_t *cmd, mm_command_t *set_cmd) {
/* remove candidates set in set_cmd */
/* from the beginend candidatea list in cmd */
@@ -760,7 +850,7 @@ tm_be_rm_mount_candidates(mm_command_t *cmd, mm_command_t *set_cmd) {
int seen_same = 0;
mms_trace(MMS_DEVP,
- "remove %s and %s from candidate lists",
+ "set %s and %s as used candidates",
set_mount_info->cmi_cartridge,
set_mount_info->cmi_drive);
mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
@@ -777,16 +867,15 @@ tm_be_rm_mount_candidates(mm_command_t *cmd, mm_command_t *set_cmd) {
mms_list_foreach(cart_list, cart) {
if (strcmp(set_mount_info->cmi_cartridge,
cart->cmi_cart_id) == 0) {
- cart->cmi_remove_cart = 1;
+ cart->cmi_cart_used = 1;
}
mms_list_foreach(&cart->cmi_drive_list, drive) {
if (strcmp(set_mount_info->cmi_drive,
drive->cmi_drive_name) == 0) {
- drive->cmi_remove_drive = 1;
+ drive->cmi_drive_used = 1;
}
}
}
- mm_mount_clean_candidates(cur_cmd);
}
}
@@ -1280,9 +1369,8 @@ tm_be_mounts(mm_command_t *cmd, mm_data_t *mm_data) {
/* Errors */
int mount_has_error = 0;
- int mount_would_block = 0;
- int only_retry = 1;
- int retry_in_use = 1;
+
+ char *err_text = NULL;
/* This is the function can return */
/* MM_BE_ERROR */
@@ -1298,12 +1386,14 @@ tm_be_mounts(mm_command_t *cmd, mm_data_t *mm_data) {
/* Instead of returning set mount_has_error or mount_would_block */
/* After calling for ever mount generate the correct error code */
mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
+ cur_cmd->cmd_mount_info.cmi_mount_ok = 0;
rc = tm_be_mount_ready(cur_cmd->wka_ptr, cur_cmd, db, cmd);
switch (rc) {
case MM_MOUNT_ERROR:
/* Error code should be set */
mms_trace(MMS_ERR,
+ "tm_be_mounts: "
"internal error, tm_be_mount_ready");
mount_has_error = 1;
break;
@@ -1312,36 +1402,31 @@ tm_be_mounts(mm_command_t *cmd, mm_data_t *mm_data) {
/* The mount is ready, mount_info should be set */
/* continue to state 1 */
mms_trace(MMS_DEVP,
+ "tm_be_mounts: "
"mount is ready to go ");
+ cur_cmd->cmd_mount_info.cmi_mount_ok = 1;
break;
case MM_MOUNT_NEED_UNLOAD:
/* this immediate mount needs to */
/* wait for an unload */
mms_trace(MMS_DEVP,
+ "tm_be_mounts: "
"mount needs to wait "
"for unload to complete");
+ cur_cmd->cmd_mount_info.cmi_mount_ok = 1;
break;
case MM_MOUNT_NOT_READY:
- if (mm_wka->wka_begin_end.be_mode ==
- ACCESS_MODE_IMMEDIATE) {
- /* Error code should be set */
- mms_trace(MMS_ERR,
- "immediate begin-end group "
- "is not ready");
- mount_has_error = 1;
- break;
- }
- /* Error code should be set */
+ mount_has_error = 1;
mms_trace(MMS_ERR,
- "blocking mount not ready, "
+ "tm_be_mounts: "
+ "mount not ready, "
"wait longer and try later");
- mount_would_block = 1;
- break;
-
+ break;
default:
mms_trace(MMS_ERR,
+ "tm_be_mounts: "
"bad rc mm_mount_ready");
mm_system_error(cmd,
"bad rc mm_mount_ready");
@@ -1356,107 +1441,120 @@ tm_be_mounts(mm_command_t *cmd, mm_data_t *mm_data) {
mms_trace(MMS_ERR,
"at least one mount had "
"an error for this begin-end");
- /* Check every command's error class */
- /* If there are only retry errors use the retry class */
+
+ /* at least one mount had an error */
+ /* for each mount set the least sever errror */
+ /* if any mount has a error more severe than retry */
+ /* return error for the end command */
+ /* since this mount will not work for immediate or blocking */
mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
- if ((cur_cmd->cmd_eclass != NULL) &&
- (strcmp(cur_cmd->cmd_eclass, ECLASS_RETRY) != 0)) {
- /* found a mount where class is not retry */
- only_retry = 0;
- } else if ((cur_cmd->cmd_eclass != NULL) &&
- (strcmp(cur_cmd->cmd_eclass,
- ECLASS_RETRY) == 0)) {
- /* This is a retry class */
- /* Check if this is an inuse error */
- if ((strcmp(cur_cmd->cmd_ecode,
- "EDRVINUSE") == 0) ||
- (strcmp(cur_cmd->cmd_ecode,
- "ECARTINUSE") == 0)) {
- retry_in_use = 1;
+ if (cur_cmd->cmd_mount_info.cmi_mount_ok) {
+ mms_trace(MMS_ERR,
+ "tm_be_mounts: "
+ "this mount is ok, no errors");
+ } else {
+ mms_trace(MMS_ERR,
+ "tm_be_mounts: "
+ "this mount has errors, set least severe");
+
+ mm_set_least_severe(cur_cmd);
+ if (strcmp(cur_cmd->cmd_eclass,
+ ECLASS_RETRY) != 0) {
+ /* this is not a retry error class */
+ /* return error for this end command */
+ mms_trace(MMS_ERR,
+ "at least one mount's "
+ "least severe error is"
+ " more severe than retry, "
+ "this begin-end group "
+ "will not work");
+ /* One or more mount has errors */
+ /* that are non retry */
+ err_text =
+ mm_return_err_text(cur_cmd->
+ cmd_err_ptr);
+ mm_response_error(cmd,
+ ECLASS_EXPLICIT,
+ "ENOSOLUTIONS",
+ MM_5110_MSG,
+ "err_text", err_text,
+ NULL);
+ free(err_text);
+ return (MM_BE_ERROR);
}
}
+ }
- if ((cur_cmd->cmd_eclass != NULL) &&
- (strcmp(cur_cmd->cmd_eclass,
- ECLASS_INTERNAL) == 0)) {
- /* This mount had a system error */
- /* Set system error and return */
- mm_system_error(cmd,
- "internal error processing "
- "a begin-end mount cmd");
- return (MM_BE_ERROR);
- }
+
+ }
+
+ /* All mounts are either ok or retry */
+ /* Determine which error to return/block */
+ /* for immediate, return retry or nosolutions */
+ /* for blocking, block or return nosolutions */
+
+
+ /* Mount candidate lists have been set up, */
+ /* divide the resources and set up the exact */
+ /* Drive/cartridge combination */
+
+ mount_has_error = 0;
+ mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
+
+ mms_trace(MMS_DEVP, "set up a mount for dispatch");
+
+ /* tm_be_set_mount returns MM_BE_ERROR or MM_BE_DISPATCH */
+
+ if (cur_cmd->cmd_mount_info.cmi_mount_ok) {
+ rc = tm_be_set_mount(cur_cmd,
+ db, cmd);
+ } else {
+ rc = MM_BE_ERROR;
}
- if (only_retry) {
- mms_trace(MMS_ERR,
- "all mounts have retry error class ");
- if (retry_in_use) {
+ if (rc == MM_BE_ERROR) {
+ mount_has_error = 1;
+ /* If the cur err ptr is null or */
+ /* pointing to a non-retry error class */
+ /* This begin-end group cannot succeede */
+ if ((cur_cmd->cmd_err_ptr == NULL) ||
+ (strcmp(cur_cmd->cmd_err_ptr->eclass,
+ ECLASS_RETRY) != 0)) {
mms_trace(MMS_ERR,
- "at least one mount "
- "has an in-use error");
- /* Set error for retry */
- mm_response_error(cmd,
- ECLASS_RETRY,
- "ETMPINUSE",
- MM_5104_MSG,
- NULL);
+ "tm_be_mounts: "
+ "There are no valid "
+ "solutions to this mount ");
- } else {
- /* Set error for retry */
+ err_text =
+ mm_return_err_text(cur_cmd->
+ cmd_err_ptr);
mm_response_error(cmd,
- ECLASS_RETRY,
- "ETMPUNAVAIL",
- MM_5104_MSG,
+ ECLASS_EXPLICIT,
+ "ENOSOLUTIONS",
+ MM_5110_MSG,
+ "err_text", err_text,
NULL);
+ free(err_text);
+ return (MM_BE_ERROR);
}
+ tm_be_rm_error_candidates(cmd, cur_cmd);
} else {
- mms_trace(MMS_ERR,
- "at least one mount had a eclass"
- " more severe than retry ");
- /* One or more mount has errors */
- /* that are non retry */
- mm_response_error(cmd,
- ECLASS_EXPLICIT,
- "ENOSOLUTIONS",
- MM_5105_MSG,
- NULL);
+ tm_be_rm_mount_candidates(cmd, cur_cmd);
}
- return (MM_BE_ERROR);
}
- if (mount_would_block) {
- mms_trace(MMS_ERR,
- "at least one mount has "
- "to block for this begin-end");
+
+ if (mount_has_error) {
+ /* If this is immediate, return retry error class for the end */
+ /* if this is blocking, then block for the whole group */
+ /* Set error for retry */
+ mm_response_error(cmd,
+ ECLASS_RETRY,
+ "ETMPUNAVAIL",
+ MM_5104_MSG,
+ NULL);
return (MM_BE_BLOCKING);
}
- /* Mount candidate lists have been set up, */
- /* divide the resources and set up the exact */
- /* Drive/cartridge combination */
- mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
- mms_trace(MMS_DEVP, "set up a mount for dispatch");
- rc = tm_be_set_mount(cur_cmd->wka_ptr,
- cur_cmd, db, cmd);
- if (rc == MM_BE_ERROR) {
- mms_trace(MMS_ERR, "error setting up mount");
- /* error set for end command already */
- return (MM_BE_ERROR);
- } else if (rc == MM_BE_BLOCKING) {
- mms_trace(MMS_ERR,
- "blocking mount not ready, "
- "wait longer and try later");
- return (MM_BE_BLOCKING);
- }
- /* remove cmi_cart and cmi_drive from */
- /* above from the remaining */
- /* unmount candidates */
- tm_be_rm_mount_candidates(cmd, cur_cmd);
- }
-
-
- /* Need to remove all dispatch releated stuff from the functions */
- /* used by tm_be_set_mount or mm_set_immediate_mount */
mms_list_foreach(&cmd->cmd_beginend_list, cur_cmd) {
if (mm_dispatch_now(mm_wka, cur_cmd, db)) {
/* error should be set */
diff --git a/usr/src/cmd/mms/mm/common/mm_util.c b/usr/src/cmd/mms/mm/common/mm_util.c
index d749104bb1..0c151dd0f1 100644
--- a/usr/src/cmd/mms/mm/common/mm_util.c
+++ b/usr/src/cmd/mms/mm/common/mm_util.c
@@ -72,9 +72,328 @@ extern void uuid_generate_random(uuid_t uu);
extern void uuid_generate(uuid_t uu); /* hits bug id 6397009 */
extern void uuid_unparse(uuid_t uu, char *out);
+/*
+ * mm_err_eclass_rank
+ * return int of the rank of this eclass
+ * higher numbers mean more severe
+ */
+int
+mm_err_eclass_rank(char *eclass)
+{
+ /* 13 total error classes */
+
+ if (strcmp(eclass, ECLASS_LANGUAGE) == 0)
+ return (13);
+ if (strcmp(eclass, ECLASS_EXPLICIT) == 0)
+ return (12);
+ if (strcmp(eclass, ECLASS_INTERNAL) == 0)
+ return (11);
+ if (strcmp(eclass, ECLASS_INVALID) == 0)
+ return (10);
+ if (strcmp(eclass, ECLASS_DM_INVALID) == 0)
+ return (9);
+ if (strcmp(eclass, ECLASS_DM_CONFIG) == 0)
+ return (8);
+ if (strcmp(eclass, ECLASS_EXIST) == 0)
+ return (7);
+ if (strcmp(eclass, ECLASS_SUBOP) == 0)
+ return (6);
+ if (strcmp(eclass, ECLASS_CONFIG) == 0)
+ return (5);
+ if (strcmp(eclass, ECLASS_STATE) == 0)
+ return (4);
+ if (strcmp(eclass, ECLASS_PERMPRIV) == 0)
+ return (3);
+ if (strcmp(eclass, ECLASS_COMPAT) == 0)
+ return (2);
+ if (strcmp(eclass, ECLASS_RETRY) == 0)
+ return (1);
+ return (0);
+}
+
+char *
+mm_return_err_text(mm_cmd_err_t *err) {
+ /* Generate a quick text for this error */
+ /* to be used as error text for an end command */
+ char *buf = NULL;
+
+ mms_trace(MMS_DEVP,
+ "mm_return_err_text: ");
+
+ if (err == NULL) {
+ mms_trace(MMS_DEVP,
+ "err ptr is NULL");
+ buf = mms_strapp(buf,
+ "none");
+ return (buf);
+ }
+
+ if (err->eclass != NULL) {
+ buf = mms_strapp(buf,
+ "%s ", err->eclass);
+ mms_trace(MMS_DEVP,
+ " %s", err->eclass);
+
+ }
+ if (err->ecode != NULL) {
+ buf = mms_strapp(buf,
+ "%s ", err->ecode);
+ mms_trace(MMS_DEVP,
+ " %s", err->ecode);
+ }
+ if (err->retry_cart != NULL) {
+ buf = mms_strapp(buf,
+ "%s ", err->retry_cart);
+ mms_trace(MMS_DEVP,
+ " %s", err->retry_cart);
+ }
+ if (err->retry_drive != NULL) {
+ buf = mms_strapp(buf,
+ "%s ", err->retry_drive);
+ mms_trace(MMS_DEVP,
+ " %s", err->retry_drive);
+ }
+ if (err->retry_lib != NULL) {
+ buf = mms_strapp(buf,
+ "%s ", err->retry_lib);
+ mms_trace(MMS_DEVP,
+ " %s", err->retry_lib);
+ }
+ if (buf == NULL) {
+ buf = mms_strapp(buf,
+ "none");
+ mms_trace(MMS_DEVP,
+ "err ptr not NULL, but empty");
+ }
+ return (buf);
+}
+
+
+
+int
+mm_same_err_helper(char *str1, char *str2) {
+ if (str1 == NULL) {
+ if (str2 == NULL) {
+ /* both ptrs are NULL, return 0 */
+ return (0);
+ } else {
+ /* str1 is NULL, str2 is not */
+ return (1);
+ }
+ } else {
+ /* str1 is not NULL */
+ if (str2 == NULL) {
+ /* str1 is not, str2 is NULL */
+ return (1);
+ }
+ }
+
+ /* both str's are not NULL */
+ return (strcmp(str1, str2));
+}
+
+
+int
+mm_same_err(mm_cmd_err_t *err1, mm_cmd_err_t *err2) {
+
+ if ((err1 == NULL) ||
+ (err2 == NULL)) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "err1 or err2 is NULL");
+ return (0);
+ }
+ if ((err1->eclass == NULL) ||
+ (err2->eclass == NULL)) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "one or both err class was NULL");
+ return (0);
+ }
+ if (strcmp(err1->eclass, err2->eclass) != 0) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "eclasses are different");
+ return (0);
+ }
+
+ if (mm_same_err_helper(err1->retry_cart,
+ err2->retry_cart) != 0) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "retry cart is different");
+ return (0);
+ }
+ if (mm_same_err_helper(err1->retry_drive,
+ err2->retry_drive) != 0) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "retry drive is different");
+ return (0);
+ }
+ if (mm_same_err_helper(err1->retry_lib,
+ err2->retry_lib) != 0) {
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "retry lib is different");
+ return (0);
+ }
+ mms_trace(MMS_DEVP,
+ "mm_same_err: "
+ "errors are the same");
+ return (1);
+}
void
-mm_clear_db(PGresult **results) {
+mm_set_buf_to_err(mm_command_t *cmd, mm_cmd_err_t *err)
+{
+
+ /* set current cmd_buf to least_err */
+ if (cmd->cmd_buf != NULL) {
+ free(cmd->cmd_buf);
+ cmd->cmd_buf = NULL;
+ }
+ cmd->cmd_buf = strdup(err->err_buf);
+ cmd->cmd_bufsize = err->err_bufsize;
+ if (cmd->cmd_ecode != NULL) {
+ free(cmd->cmd_ecode);
+ cmd->cmd_ecode = NULL;
+ }
+ if (cmd->cmd_eclass != NULL) {
+ free(cmd->cmd_eclass);
+ cmd->cmd_eclass = NULL;
+ }
+ cmd->cmd_ecode = strdup(err->ecode);
+ cmd->cmd_eclass = strdup(err->eclass);
+}
+
+void
+mm_clear_cur_err(mm_command_t *cmd)
+{
+ if (cmd->cmd_ecode != NULL) {
+ free(cmd->cmd_ecode);
+ cmd->cmd_ecode = NULL;
+ }
+ if (cmd->cmd_eclass != NULL) {
+ free(cmd->cmd_eclass);
+ cmd->cmd_eclass = NULL;
+ }
+ if (cmd->cmd_buf != NULL) {
+ free(cmd->cmd_buf);
+ cmd->cmd_buf = NULL;
+ }
+ cmd->cmd_bufsize = 0;
+
+}
+
+
+void
+mm_set_least_severe(mm_command_t *cmd)
+{
+
+ mm_cmd_err_t *err = NULL;
+ mm_cmd_err_t *least_err = NULL;
+ int cur_rank = 0;
+ int least_rank = 0;
+ int first = 1;
+
+
+ mms_list_foreach(&cmd->cmd_err_list, err) {
+ if (err->err_already_used) {
+ continue;
+ }
+ if (err->eclass == NULL)
+ continue;
+ if (first) {
+ least_err = err;
+ least_rank =
+ mm_err_eclass_rank(least_err->eclass);
+ first = 0;
+ continue;
+ }
+ cur_rank = mm_err_eclass_rank(err->eclass);
+ if (cur_rank < least_rank) {
+ least_rank = cur_rank;
+ least_err = err;
+ }
+
+ }
+ if (first) {
+ mms_trace(MMS_ERR,
+ "mm_set_least_severe: "
+ "there are no unused "
+ "errors in the list");
+ cmd->cmd_err_ptr = NULL;
+ return;
+ }
+ mms_trace(MMS_ERR,
+ "mm_set_least_severe: "
+ "setting error %s %s",
+ least_err->eclass,
+ least_err->ecode);
+ mm_set_buf_to_err(cmd, least_err);
+ cmd->cmd_err_ptr = least_err;
+}
+
+void
+mm_set_retry_drive(mm_command_t *cmd, char *drive)
+{
+ mm_cmd_err_t *err = NULL;
+ if ((err = mms_list_tail(&cmd->cmd_err_list)) == NULL) {
+ return;
+ }
+ if (err->retry_drive != NULL) {
+ free(err->retry_drive);
+ err->retry_drive = NULL;
+ }
+ if (drive == NULL) {
+ return;
+ }
+ err->retry_drive =
+ mms_strapp(err->retry_drive,
+ drive);
+}
+
+void
+mm_set_retry_lib(mm_command_t *cmd, char *lib)
+{
+ mm_cmd_err_t *err = NULL;
+ if ((err = mms_list_tail(&cmd->cmd_err_list)) == NULL) {
+ return;
+ }
+ if (err->retry_lib != NULL) {
+ free(err->retry_lib);
+ err->retry_lib = NULL;
+ }
+ if (lib == NULL) {
+ return;
+ }
+ err->retry_lib=
+ mms_strapp(err->retry_lib,
+ lib);
+}
+void
+mm_set_retry_cart(mm_command_t *cmd, char *cart)
+{
+ mm_cmd_err_t *err = NULL;
+ if ((err = mms_list_tail(&cmd->cmd_err_list)) == NULL) {
+ return;
+ }
+ if (err->retry_cart != NULL) {
+ free(err->retry_cart);
+ err->retry_cart = NULL;
+ }
+ if (cart == NULL) {
+ return;
+ }
+ err->retry_cart =
+ mms_strapp(err->retry_cart,
+ cart);
+}
+
+void
+mm_clear_db(PGresult **results)
+{
if (*results != NULL) {
PQclear(*results);
*results = NULL;
@@ -82,7 +401,74 @@ mm_clear_db(PGresult **results) {
}
void
-mm_system_error(mm_command_t *cmd, char *fmt, ...) {
+mm_rm_err(mm_command_t *cmd, mm_cmd_err_t *err)
+{
+ mm_cmd_err_t *cur_err = NULL;
+ mm_cmd_err_t *next_err = NULL;
+
+ for (cur_err = mms_list_head(&cmd->cmd_err_list);
+ cur_err != NULL;
+ cur_err = next_err) {
+ next_err = mms_list_next(&cmd->cmd_err_list,
+ cur_err);
+ if (mm_same_err(err, cur_err)) {
+ cur_err->err_already_used = 1;
+ mms_trace(MMS_DEVP,
+ "mm_rm_err: "
+ "an error marked as used");
+ }
+
+ }
+
+
+}
+
+void
+mm_print_err(mm_cmd_err_t *err)
+{
+
+ mms_trace(MMS_DEVP,
+ " %s, %s %s",
+ err->eclass,
+ err->ecode,
+ err->err_buf);
+ if (err->retry_drive != NULL)
+ mms_trace(MMS_DEVP,
+ " retry_drive = %s",
+ err->retry_drive);
+ if (err->retry_cart != NULL)
+ mms_trace(MMS_DEVP,
+ " retry_cart = %s",
+ err->retry_cart);
+ if (err->retry_lib != NULL)
+ mms_trace(MMS_DEVP,
+ " retry_lib = %s",
+ err->retry_lib);
+}
+
+void
+mm_print_err_list(mm_command_t *cmd)
+{
+ mm_cmd_err_t *err = NULL;
+ int err_count = 1;
+
+ mms_trace(MMS_DEVP,
+ "mm_print_err_list: "
+ "error list is :");
+ mms_list_foreach(&cmd->cmd_err_list, err) {
+ if (err->err_already_used)
+ continue;
+ mms_trace(MMS_DEVP,
+ " Error # %d:",
+ err_count);
+ mm_print_err(err);
+ err_count ++;
+ }
+}
+
+void
+mm_system_error(mm_command_t *cmd, char *fmt, ...)
+{
va_list args;
char *text;
@@ -336,6 +722,7 @@ mm_alloc_cmd(mm_wka_t *mm_wka) {
mm_cmd->cmd_task = NULL;
mm_cmd->cmd_textcmd = NULL;
mm_cmd->cmd_report = NULL;
+ mm_cmd->cmd_err_ptr = NULL;
/* mount command info */
mm_cmd->cmd_mount_info.cmi_dm = NULL;
@@ -370,6 +757,11 @@ mm_alloc_cmd(mm_wka_t *mm_wka) {
offsetof(mm_char_list_t, mm_char_list_next));
mms_list_create(&mm_cmd->cmd_resp_list, sizeof (mm_char_list_t),
offsetof(mm_char_list_t, mm_char_list_next));
+ /* error list */
+
+ mms_list_create(&mm_cmd->cmd_err_list, sizeof (mm_cmd_err_t),
+ offsetof(mm_cmd_err_t, mm_cmd_err_next));
+
/* Initalize the access mode list */
mms_list_create(&mm_cmd->cmd_mount_info.cmi_mode_list,
@@ -1080,3 +1472,97 @@ mm_add_to_const(mm_command_t *cmd, char *str) {
}
return (1);
}
+
+/*
+ * mm_free_err:
+ * -free's memory inside mm_cmd_err_t
+ * -caller should free the struct itself
+ */
+
+void
+mm_free_err(mm_cmd_err_t *cmd_error) {
+ if (cmd_error->ecode != NULL) {
+ free(cmd_error->ecode);
+ cmd_error->ecode = NULL;
+ }
+ if (cmd_error->eclass != NULL) {
+ free(cmd_error->eclass);
+ cmd_error->eclass = NULL;
+ }
+ if (cmd_error->err_buf != NULL) {
+ free(cmd_error->err_buf);
+ cmd_error->err_buf = NULL;
+ }
+ if (cmd_error->retry_drive != NULL) {
+ free(cmd_error->retry_drive);
+ cmd_error->retry_drive = NULL;
+ }
+ if (cmd_error->retry_cart != NULL) {
+ free(cmd_error->retry_cart);
+ cmd_error->retry_cart = NULL;
+ }
+ if (cmd_error->retry_lib != NULL) {
+ free(cmd_error->retry_lib);
+ cmd_error->retry_lib = NULL;
+ }
+ cmd_error->err_bufsize = 0;
+}
+
+/*
+ * mm_free_err_list:
+ * -free's an entire cmd's err list
+ * -caller should call list destroy on the actual list
+ */
+void
+mm_free_err_list(mm_command_t *cmd) {
+
+ mm_cmd_err_t *cur_err;
+ mm_cmd_err_t *next_err;
+
+ mms_list_t *err_list;
+
+ err_list = &cmd->cmd_err_list;
+
+ /* If the obj is already in the list, skip */
+ for (cur_err = mms_list_head(err_list);
+ cur_err != NULL;
+ cur_err = next_err) {
+ next_err = mms_list_next(err_list, cur_err);
+ /* remove this from the list and free */
+ mms_list_remove(err_list,
+ cur_err);
+ mm_free_err(cur_err);
+ free(cur_err);
+ }
+
+}
+
+/*
+ * mm_alloc_err:
+ * -allocates and initializes a new mm_cmd_err_t struct
+ */
+
+mm_cmd_err_t *
+mm_alloc_err() {
+
+ mm_cmd_err_t *err = NULL;
+
+ err = (mm_cmd_err_t *)calloc(1, sizeof (mm_cmd_err_t));
+ if (err == NULL) {
+ mms_trace(MMS_ERR,
+ "mm_alloc_err: "
+ "Unable to malloc mm_cmd_err_t: %s",
+ strerror(errno));
+ return (NULL);
+ }
+ err->eclass = NULL;
+ err->ecode = NULL;
+ err->err_buf = NULL;
+ err->err_bufsize = 0;
+ err->retry_drive = NULL;
+ err->retry_cart = NULL;
+ err->retry_lib = NULL;
+ err->err_already_used = 0;
+
+ return (err);
+}
diff --git a/usr/src/cmd/mms/mm/common/mm_util.h b/usr/src/cmd/mms/mm/common/mm_util.h
index e8375c7143..d8716a27ce 100644
--- a/usr/src/cmd/mms/mm/common/mm_util.h
+++ b/usr/src/cmd/mms/mm/common/mm_util.h
@@ -22,10 +22,10 @@
* Use is subject to license terms.
*/
-
#ifndef _MM_UTIL_H
#define _MM_UTIL_H
+
/*
* Parser command xml text file line callback structure
*/
@@ -103,4 +103,16 @@ extern int mm_in_char_list(mms_list_t *list, char *str);
extern char *mm_return_char(mms_list_t *list, int index);
extern void mm_free_list(mms_list_t *list);
extern char *mm_ret_response_msg(mm_command_t *cmd);
+extern void mm_free_err_list(mm_command_t *cmd);
+extern mm_cmd_err_t *mm_alloc_err();
+extern void mm_print_err_list(mm_command_t *cmd);
+extern void mm_print_err(mm_cmd_err_t *err);
+extern void mm_set_retry_drive(mm_command_t *cmd, char *drive);
+extern void mm_set_retry_lib(mm_command_t *cmd, char *lib);
+extern void mm_set_retry_cart(mm_command_t *cmd, char *cart);
+extern void mm_set_least_severe(mm_command_t *cmd);
+extern int mm_same_err(mm_cmd_err_t *err1, mm_cmd_err_t *err2);
+extern void mm_clear_cur_err(mm_command_t *cmd);
+extern void mm_rm_err(mm_command_t *cmd, mm_cmd_err_t *err);
+extern char *mm_return_err_text(mm_cmd_err_t *err);
#endif /* _MM_UTIL_H */
diff --git a/usr/src/common/mms/mms/mms_mm_msg.h b/usr/src/common/mms/mms/mms_mm_msg.h
index 511cfa6435..5e65fa7b46 100644
--- a/usr/src/common/mms/mms/mms_mm_msg.h
+++ b/usr/src/common/mms/mms/mms_mm_msg.h
@@ -377,6 +377,10 @@ MM_MSG(MM_5108_MSG, gettext("Standard privilege client may not modify " \
MM_MSG(MM_5109_MSG, gettext("Administrator privilege client may not modify " \
"object $object$ attribute $attribute$."))
+#define MM_5110_MSG 5110
+MM_MSG(MM_5110_MSG, gettext("No solutions to this begin-end group, " \
+ "one or more mounts cannot complete - $err_text$"))
+
#ifdef __cplusplus
}
#endif