diff --git a/messages/tape_linux_sg/root.txt b/messages/tape_linux_sg/root.txt index c674b83d..5bfc632b 100644 --- a/messages/tape_linux_sg/root.txt +++ b/messages/tape_linux_sg/root.txt @@ -100,6 +100,7 @@ root:table { 30258W:string { "Cannot retrieve drive dump: failed to read buffer (%d)." } 30259W:string { "Cannot retrieve drive dump: failed to write to dump file (%d)." } 30260W:string { "Cannot retrieve drive dump: wrote %d bytes out, expected %d." } + 30261W:string { "Cannot retrieve drive dump: failed to write to communicate with drive. Tried (%d) times." } 30261I:string { "Taking drive dump in buffer." } 30262I:string { "Forcing drive dump." } 30263I:string { "%s returns %s (%d) %s." } @@ -136,6 +137,7 @@ root:table { 30294I:string { "Setting up timeout values from %s." } 30295I:string { "Have unstable TUR response, start over (Cur = %d, Prev = %d)." } 30296I:string { "Capturing a stable TUR at line %d." } + 30297W:string { "Cannot retrieve drive dump: failed to communicate with drive. Tried (%d) times." } 30392D:string { "Backend %s %s." } 30393D:string { "Backend %s: %d %s." } diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 19b6ca99..19f2beb8 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -103,6 +103,8 @@ struct sg_global_data global_data; #define TU_DEFAULT_TIMEOUT (60) #define MAX_RETRY (100) +#define MAX_TAKE_DUMP_ATTEMPTS (10) + /* Forward references (For keep function order to struct tape_ops) */ int sg_readpos(void *device, struct tc_position *pos); int sg_locate(void *device, struct tc_position dest, struct tc_position *pos); @@ -118,19 +120,17 @@ static inline int _parse_logPage(const unsigned char *logdata, const uint16_t param, uint32_t *param_size, unsigned char *buf, const size_t bufsize) { - uint16_t page_len, param_code, param_len; - uint32_t i; + const uint16_t page_len = ((uint16_t)logdata[2] << 8) | (uint16_t)logdata[3]; + uint16_t param_code, param_len; + uint32_t i = LOG_PAGE_HEADER_SIZE; uint32_t ret = -EDEV_INTERNAL_ERROR; - page_len = ((uint16_t)logdata[2] << 8) + (uint16_t)logdata[3]; - i = LOG_PAGE_HEADER_SIZE; - while(i < page_len) { - param_code = ((uint16_t)logdata[i] << 8) + (uint16_t)logdata[i+1]; + param_code = ((uint16_t)logdata[i] << 8) | (uint16_t)logdata[i+1]; param_len = (uint16_t)logdata[i + LOG_PAGE_PARAMSIZE_OFFSET]; - if(param_code == param) + if (param_code == param) { *param_size = param_len; if(bufsize < param_len){ @@ -143,6 +143,7 @@ static inline int _parse_logPage(const unsigned char *logdata, break; } } + i += param_len + LOG_PAGE_PARAM_OFFSET; } @@ -392,6 +393,13 @@ static int _take_dump(struct sg_data *priv, bool capture_unforced) time_t now; struct tm *tm_now; + /* To check if the function became recursive */ + if (priv->recursive_counter > MAX_TAKE_DUMP_ATTEMPTS) { + ltfsmsg(LTFS_WARN, 30297W, priv->recursive_counter); + return 0; + } + priv->recursive_counter++; + if (priv->vendor != VENDOR_IBM) return 0; @@ -426,6 +434,8 @@ static int _take_dump(struct sg_data *priv, bool capture_unforced) ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_EXIT(REQ_TC_TAKEDUMPDRV)); + priv->recursive_counter = 0; + return 0; } diff --git a/src/tape_drivers/linux/sg/sg_tape.h b/src/tape_drivers/linux/sg/sg_tape.h index 4d9de00e..2220d0f1 100644 --- a/src/tape_drivers/linux/sg/sg_tape.h +++ b/src/tape_drivers/linux/sg/sg_tape.h @@ -82,6 +82,7 @@ struct sg_data { struct timeout_tape *timeouts; /**< Timeout table */ struct tc_drive_info info; /**< Drive information */ FILE* profiler; /**< The file pointer for profiler */ + int recursive_counter; /**< Recursive counter for take dump */ }; struct sg_global_data {