From 31830b4297b854dd4a2ea1b2d414b2b068453fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20Gabriel=20Hern=C3=A1ndez=20Hern=C3=A1ndez?= Date: Mon, 27 Jul 2026 13:34:00 -0600 Subject: [PATCH 01/15] Docs: MD updates (#584) --- .github/CONTRIBUTING.md | 77 ++++++++++++++- docs/CODE_OF_CONDUCT.md | 201 ++++++++++++++++------------------------ docs/CODING_STYLEmd | 133 ++++++++++++++++++++++++++ 3 files changed, 287 insertions(+), 124 deletions(-) create mode 100644 docs/CODING_STYLEmd diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 8e7a5a7c..b20fcf24 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -4,7 +4,7 @@ We love pull requests from everyone. When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. -Please note we have a [coding style guide](/docs/CODE_OF_CONDUCT.md), please follow it in all your interactions with the project. +Please note we have a [coding style guide](../docs/CODING_STYLE.md), please follow it in all your interactions with the project. 1. Fork, then clone the repo @@ -25,5 +25,78 @@ Please note we have a [coding style guide](/docs/CODE_OF_CONDUCT.md), please fol __Some things that will increase the chance that your pull request is accepted__ -* Follow our [coding style guide](/docs/CODE_OF_CONDUCT.md). +* Follow our [coding style guide](../docs/CODING_STYLE.md). * Write a good commit message. + +# Branch Naming Conventions +The structure and design conventions are based mainly on the “Conventional Branch” concept and the team’s current work process. + +Note: These conventions are recommendations intended to improve readability and consistency of commits within pull requests and are not strictly enforced. Only the release and main branches are required to fully adhere to this naming convention. + +## Purpose +1. Purpose-driven Branch Names: Each branch name clearly indicates its purpose, making it easy for all developers to understand what the branch is for. +2. Integration with CI/CD: By using consistent branch names, it can help automated systems (like Continuous Integration/Continuous Deployment pipelines) to trigger specific actions based on the branch type. +3. Better type and version control: Branches are related to a specific type of change in the code and the version that is being worked on, allowing for a much better backtracking. + +## Basic Rules +- Naming structure: +`/` +- Naming prefixes (Types): + - feature/: For new features (e.g., feature/add-login-page). + - fix/: For general fixes or code correcting. + - update/: For code upgrade or non-breaking code refactoring. + - chore/: For non-code tasks like dependency, docs updates (e.g., chore/update-dependencies). + - release/: For branches preparing a release (e.g., release/v1.2.0). +- Use Lowercase Alphanumeric and Hyphens: Always use lowercase letters (a-z), numbers (0-9), and hyphens to separate words. Avoid special characters, underscores, or spaces. +- No Consecutive or Trailing Hyphens: Ensure that hyphens are used singly, with no consecutive hyphens (feature/new--login) or at the end (feature/new-login-). +- Keep It Clear and Concise: The branch name should be descriptive yet concise, clearly indicating the purpose of the work. +- Include Ticket Numbers: If applicable, include the ticket number from your project management tool to make tracking easier. For example, for a ticket issue-123, the branch name could be feature/issue-123-new-login. + +## General Project Structure +``` +main +├── release/v1.x.x +│ ├── feature/lorem-ipsum +│ └── fix/ipsum-dolor +├── release/v2.x.x +│ └── chore/dolor-sit +└── release/v3.x.x + ├── update/sit-amet + ├── feature/amet-consectetur + └── chore/consectetur-adipiscing +``` +- main: This branch should only contain working versions completely tested and only receive pull requests from finalized release branches. All new release/ branches must come from this one. +- release: The creation of these branches should be done from the last version of main when created. Only this branches can make pull requests to main. +- Other branches: All working branches should come from a release branch. These are the only ones that should receive direct commits from changes made by development staff. These branches should only do PR to the active release branch. + +# Commits Naming Conventions +The structure and design conventions are based mainly on the “Conventional Branch” concept and the team’s current work process. + +## Purpose +1. Automatically generating CHANGELOGs: When the commits are concise, and precise changelogs can be automated or semi-automated from the commit history. +2. Communicating the nature of changes to everyone: Being able to understand the type of changing by just looking at a name and understanding the basics of a commit just by the title is useful in analysis and backtrack situations. +3. Building code habits and good practices: Maintaining structured commits also leads to more precise coding practices and coherent code changes. + +## Basic Rules +- Naming structure: +``` +: + +[optional body] +``` +- Naming prefixes (Types): + - fix: A commit of the type fix patches a bug in your codebase. + - feat: A commit of the type feat introduces a new feature to the codebase + - !: A commit that appends a ! after the type introduces a breaking change. A breaking change can be part of commits of any type. + - update: A commit of type update changes existing code or refactors functions without changing functionality of adding features in your codebase. + - build: A commit of type build changes build process in your codebase. + - docs: A commit of type docs is for creation or updating documentation in your codebase. + - chore: A commit of type chore is for every other minor task in your codebase. +- Commits must be prefixed with a type, which consists of a noun, feat, fix, etc., followed by the optional !, and required terminal colon and space. +- A description must immediately follow the colon and space after the type prefix. The description is a short summary of the code changes, e.g., fix: array parsing issue when multiple spaces were contained in string. +- A longer commit body may be provided after the short description, providing additional contextual information about the code changes. The body must begin one blank line after the description. +- A commit body is free-form and may consist of any number of newline separated paragraphs. + +# Bibliography +[1] “Conventional Branch,” Conventional Branch, 2025. https://conventional-branch.github.io/ (accessed 2025).
+[2] “Conventional Commits,” Conventional Commits. https://www.conventionalcommits.org/en/v1.0.0/ (accessed 2025). diff --git a/docs/CODE_OF_CONDUCT.md b/docs/CODE_OF_CONDUCT.md index 408a57dd..db5068df 100644 --- a/docs/CODE_OF_CONDUCT.md +++ b/docs/CODE_OF_CONDUCT.md @@ -1,133 +1,90 @@ -Coding Style guide for LTFS -============= +# Code of Conduct -Naming conventions -------------- +## Our Pledge -- We don't use capital letters, except on defines and enumerators (see below). -- Public APIs are always prefixed by the name of that module: - * ltfs.c: ltfs_statfs(), ltfs_open(), ltfs_close(), ltfs_read() - * fs.c: fs_resolve_dentry(), fs_set_name(), fs_set_creation_time() +We pledge to make our community welcoming, safe, and equitable for all. +We are committed to fostering an environment that respects and promotes the dignity, rights, and contributions of all individuals, regardless of characteristics including race, ethnicity, caste, color, age, physical characteristics, neurodiversity, disability, sex or gender, gender identity or expression, sexual orientation, language, philosophy or religion, national or social origin, socio-economic position, level of education, or other status. The same privileges of participation are extended to everyone who participates in good faith and in accordance with this Covenant. -Spaces, tabs and commas -------------- +## Encouraged Behaviors -When indenting the code, always use TABs with 4 spaces. Do not replace TABs by spaces. Remove trailing spaces of a line and empty lines at the end of file. +While acknowledging differences in social norms, we all strive to meet our community's expectations for positive behavior. We also understand that our words and actions may be interpreted differently than we intend based on culture, background, or native language. -When writing arguments to a function or defining enums, also use the following comma conventions: +With these considerations in mind, we agree to behave mindfully toward each other and act in ways that center our shared values, including: +1. Respecting the **purpose of our community**, our activities, and our ways of gathering. +2. Engaging **kindly and honestly** with others. +3. Respecting **different viewpoints** and experiences. +4. **Taking responsibility** for our actions and contributions. +5. Gracefully giving and accepting **constructive feedback**. +6. Committing to **repairing harm** when it occurs. +7. Behaving in other ways that promote and sustain the **well-being of our community**. -``` -call_function(arg1, arg2, arg3); -call_another_function( - very_long_argument1, - very_long_argument2, - very_long_argument3 - ); - -enum very_cool_enumerator { - VERY_COOL_1, - VERY_COOL_2, - VERY_COOL_3, -}; -``` - -Macros and defines -------------- - -When defining wrappers around functions using macros do that using lowercase characters. Defines always go in uppercase. - -``` -#define wrapper_around_some_function(x,y) \ - ... - -#define LTFS_MAX_VALUE 2112 -``` - -Functions -------------- - -Return type, function name and its parameters should go all in a single line, except if the parameters are too long. - - -``` -void ltfs_function(void *params) -{ -} - -void ltfs_function_with_many_parameters(void *params1, - void *params2, void *params3) -{ -} -``` - -Conditional tests -------------- - -``` -if (condition) { - line 1; - line 2; -} else - line 3; - -if (another condition) - do this; -else - do that; - -if (yet another condition) { - /* - * It's ok to open brackets when adding comments, - * just to make it clear where the scope ends. - * That can improve readability when comments - * span across multiple lines. - */ - do something else; -} -``` - -Loops -------------- - -``` -for (x=start; x Date: Wed, 29 Jul 2026 19:35:31 +0200 Subject: [PATCH 02/15] fix: fixes and improvements to the ltfs_ordered_copy tool (#586) --- README.md | 1 + src/utils/ltfs_ordered_copy | 114 +++++++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 8d393ba8..fc9ae6d5 100644 --- a/README.md +++ b/README.md @@ -178,6 +178,7 @@ One thing you need to pay attention to here is, that the unmount command continu The [`ltfs_ordered_copy`](https://github.com/LinearTapeFileSystem/ltfs/wiki/ltfs_ordered_copy) is a program to copy files from source to destination with LTFS order optimization. It is written in python and it can work with both python2 and python3 (Python 2.7 or later is strongly recommended). You need to install the `pyxattr` module for both python2 and python3. +For nicer-looking progress bars while copying, it is also recommended you install `tqdm`. # Building the LTFS from this GitHub project diff --git a/src/utils/ltfs_ordered_copy b/src/utils/ltfs_ordered_copy index 5537964e..96f95c6a 100755 --- a/src/utils/ltfs_ordered_copy +++ b/src/utils/ltfs_ordered_copy @@ -44,6 +44,12 @@ import threading from logging import getLogger, basicConfig, NOTSET, CRITICAL, ERROR, WARNING, INFO, DEBUG from collections import deque +try: + from tqdm import tqdm + USE_TQDM = True +except ImportError: + USE_TQDM = False + class CopyItem: """""" def __init__(self, src, dst, vea_pre, cp_attr, cp_xattr, logger): #initialization @@ -77,15 +83,20 @@ class CopyItem: return (self.vuuid, self.part, self.start) - def run(self): + def _run_copy(self, progress): + with open(self.src, 'rb') as srcf, open(self.dst, 'wb') as dstf: + copyfileobj(srcf, dstf, progress.update) + + def run(self, progress): try: if len(self.vuuid): logger.debug('"{0}" ({2}) -> "{1}"'.format(self.src, self.dst, str(self.start))) else: logger.debug('"{0}" -> "{1}"'.format(self.src, self.dst)) - + progress.update_file(self.src) if self.cp_attr: #Copy data and metadata - shutil.copy2(self.src, self.dst) + self._run_copy(progress) + shutil.copystat(self.src, self.dst) if self.cp_xattr: # Capture EAs of the source file src_attributes = {} @@ -96,7 +107,8 @@ class CopyItem: for key in src_attributes: xattr.set(self.dst, key, src_attributes[key]) else: #Only copy data - shutil.copy(self.src, self.dst) + self._run_copy(progress) + shutil.copymode(self.src, self.dst) except Exception as e: self.logger.error('Failed to copy "{0}" to "{1}": {2}'.format(self.src, self.dst, str(str(e)))) return False @@ -116,9 +128,11 @@ class CopyQueue: self.items = 0 self.logger = logger self.sort_files = sort_files + self.total_bytes = 0 def add_copy_item(self, c): (u, p, s) = c.eval() + self.total_bytes += os.path.getsize(c.src) if u == '': # Source is not on LTFS self.direct.append(c) @@ -206,24 +220,83 @@ class CopyQueue: def get_size(self): return self.items +RESULT_LOCK = threading.Lock() + +BUFSIZE = 256 * 1024 * 1024 # 256MiB + +# Based on shutil's code +def copyfileobj(fsrc, fdst, callback, length=BUFSIZE): + try: + # check for optimisation opportunity + if "b" in fsrc.mode and "b" in fdst.mode and fsrc.readinto: + return _copyfileobj_readinto(fsrc, fdst, callback, length) + except AttributeError: + # one or both file objects do not support a .mode or .readinto attribute + pass + + fsrc_read = fsrc.read + fdst_write = fdst.write + + while True: + buf = fsrc_read(length) + if not buf: + break + fdst_write(buf) + callback(len(buf)) + +def _copyfileobj_readinto(fsrc, fdst, callback, length=BUFSIZE): + """readinto()/memoryview() based variant of copyfileobj(). + *fsrc* must support readinto() method and both files must be + open in binary mode. + """ + # Localize variable access to minimize overhead. + fsrc_readinto = fsrc.readinto + fdst_write = fdst.write + with memoryview(bytearray(length)) as mv: + while True: + n = fsrc_readinto(mv) + if not n: + break + elif n < length: + with mv[:n] as smv: + fdst.write(smv) + else: + fdst_write(mv) + callback(n) + class Progress: - def __init__(self, logger, title, num): #initialization + def __init__(self, logger, title, total_files, total_bytes): #initialization self.logger = logger self.title = title - self.num = num - self.cur = 0 + self.total_files = total_files + self.total_bytes = total_bytes + self.current_file = 0 + self.tqdm = None + + def update_file(self, name): + # Delay the initialization of tqdm to prevent console spam + if self.logger.getEffectiveLevel() == INFO and USE_TQDM and self.tqdm is None: + self.tqdm = tqdm(total=self.total_bytes, unit='B', unit_scale=True, unit_divisor=1024) - def update(self, step = 1): + self.current_file += 1 if self.logger.getEffectiveLevel() == INFO: - self.cur = self.cur + 1 - sys.stderr.write('\r{}: {}/{}'.format(self.title, self.cur, self.num)) - sys.stderr.flush() + if self.tqdm is not None: + self.tqdm.set_description(f'{name} [{self.current_file} / {self.total_files}]') + else: + sys.stderr.write('\r{}: {}/{}'.format(self.title, self.current_file, self.total_files)) + sys.stderr.flush() + + def update(self, bytes_add): + if self.tqdm: + self.tqdm.update(bytes_add) def finish(self): - if self.logger.getEffectiveLevel() == INFO: - logger.info("") + if self.tqdm is not None: + self.tqdm.close() + else: + if self.logger.getEffectiveLevel() == INFO: + logger.info("") -RESULT_LOCK = threading.Lock() def writer(logger, prog, q, r): while True: @@ -236,9 +309,7 @@ def writer(logger, prog, q, r): logger.error('writer thread error: ' + str(e)) exit(1) - prog.update() - - result = ci.run() + result = ci.run(prog) with RESULT_LOCK: if result: @@ -363,7 +434,7 @@ direct_write_threads = 8 try: sig = xattr.get(args.DEST, VEA_PREFIX + LTFS_SIG_VEA) - if sig.startswith("LTFS"): + if sig.startswith(b"LTFS"): logger.info("Destination {0} is LTFS".format(args.DEST)) direct_write_threads = 1 else: @@ -425,7 +496,7 @@ success = 0 fail = 0 direct = copyq.pop_direct() -prog_disk = Progress(logger, 'File copy from disk is on going', len(direct)) +prog_disk = Progress(logger, 'File copy from disk is on going', len(direct), copyq.total_bytes) if len(direct): logger.info("Copying on {} disk files with {} threads".format(len(direct), direct_write_threads)) writers = [] @@ -444,7 +515,7 @@ if len(direct): prog_disk.finish() # Copy files on LTFS -prog_tape = Progress(logger, 'File copy from tape is on going', copyq.get_size()) +prog_tape = Progress(logger, 'File copy from tape is on going', copyq.get_size(), copyq.total_bytes) (tape_key, tape) = copyq.pop_tape() while tape != None: logger.log(NOTSET + 1, "Processing {}".format(len(tape))) @@ -461,8 +532,7 @@ while tape != None: for start_block_key in start_block_list: file_ind = partition[start_block_key] for cp in file_ind: - prog_tape.update() - result = cp.run() + result = cp.run(prog_tape) if result: success = success + 1 else: From ba1695effa48af00de4998347f279abfbd237b07 Mon Sep 17 00:00:00 2001 From: Hugo Hurskainen Date: Wed, 29 Jul 2026 20:46:49 +0300 Subject: [PATCH 03/15] fix: resolve ltfs_ordered_copy issue when processing a single file. (#599) --- src/utils/ltfs_ordered_copy | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils/ltfs_ordered_copy b/src/utils/ltfs_ordered_copy index 96f95c6a..80560512 100755 --- a/src/utils/ltfs_ordered_copy +++ b/src/utils/ltfs_ordered_copy @@ -407,6 +407,9 @@ if args.DEST == None: logger.error('No destination is specified') exit(2) +if args.keep_tree is None: + args.keep_tree = '' + # Special case: # Copy source is only one file if args.recursive == False and len(args.SOURCE) == 1: @@ -458,9 +461,6 @@ if len(args.SOURCE) == 0: args.SOURCE.append(line.rstrip('\r\n')) logger.log(NOTSET + 1, 'Source: {}'.format(args.SOURCE)) -if args.keep_tree is None: - args.keep_tree = '' - # Create the list of copy item copyq = CopyQueue(logger, args.sort_files) for s in args.SOURCE: From aa0512555f9c30291acc7bd61d5a0db52a076395 Mon Sep 17 00:00:00 2001 From: Masafumi Horimoto Date: Thu, 30 Jul 2026 02:53:23 +0900 Subject: [PATCH 04/15] feat: introduce support for TANDBERG LTO-6 HH drive. (#605) --- src/tape_drivers/hp_tape.c | 1 + src/tape_drivers/hp_tape.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tape_drivers/hp_tape.c b/src/tape_drivers/hp_tape.c index f94b4aea..23aa7327 100644 --- a/src/tape_drivers/hp_tape.c +++ b/src/tape_drivers/hp_tape.c @@ -68,6 +68,7 @@ struct supported_device *hp_supported_drives[] = { TAPEDRIVE( HP_VENDOR_ID, "Ultrium 7-SCSI", DRIVE_LTO7, "[Ultrium 7-SCSI]" ), /* HP Ultrium Gen 7 */ TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 8-SCSI", DRIVE_LTO8, "[Ultrium 8-SCSI]" ), /* HPE Ultrium Gen 8 */ TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 9-SCSI", DRIVE_LTO9, "[Ultrium 9-SCSI]" ), /* HPE Ultrium Gen 9 */ + TAPEDRIVE( TANDBERG_VENDOR_ID, "LTO-6 HH ", DRIVE_LTO6_HH, "[LTO-6 HH]" ), /* TANDBERG LTO-6 HH */ /* End of supported_devices */ NULL }; diff --git a/src/tape_drivers/hp_tape.h b/src/tape_drivers/hp_tape.h index 5d60dd9a..cc121bfa 100644 --- a/src/tape_drivers/hp_tape.h +++ b/src/tape_drivers/hp_tape.h @@ -67,6 +67,7 @@ extern "C" { #define HP_VENDOR_ID "HP" #define HPE_VENDOR_ID "HPE" +#define TANDBERG_VENDOR_ID "TANDBERG" extern struct error_table hp_tape_errors[]; From 135edb1961db24e7f41dcf65f373ce9564485e2b Mon Sep 17 00:00:00 2001 From: Matej Kenda Date: Wed, 29 Jul 2026 19:55:51 +0200 Subject: [PATCH 05/15] fix: prevent data loss on writes larger than the tape block size. (#607) --- src/iosched/unified.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/iosched/unified.c b/src/iosched/unified.c index f492e12f..71f9dcc1 100644 --- a/src/iosched/unified.c +++ b/src/iosched/unified.c @@ -1790,7 +1790,11 @@ ssize_t _unified_insert_new_request(const char *buf, off_t offset, size_t count, if (new_req->offset + new_req->count > dpr->file_size) dpr->file_size = new_req->offset + new_req->count; - return (ssize_t)count; + /* Only copy_count bytes were stored (one cache block at most); the + * caller's append loop must advance by that, not the full count, or + * everything past the first block of a larger-than-blocksize write is + * silently dropped. */ + return (ssize_t)copy_count; } /** From f5c51b18ec3ab86dff637c60913ba4680f9c5eab Mon Sep 17 00:00:00 2001 From: Matej Kenda Date: Wed, 29 Jul 2026 21:45:17 +0200 Subject: [PATCH 06/15] fix: resolve build and CLI issues. (#608) --- configure.ac | 2 +- src/libltfs/ltfs_thread.h | 8 ++++---- src/main.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configure.ac b/configure.ac index faf4a937..994f68cb 100644 --- a/configure.ac +++ b/configure.ac @@ -377,7 +377,7 @@ if test "x${snmp}" != "xno" then SNMP_ENABLE="-D ENABLE_SNMP" SNMP_MODULE_CFLAGS="`net-snmp-config --cflags 2> /dev/null`"; - SNMP_MODULE_LIBS_A="`net-snmp-config --agent-libs` 2> /dev/null"; + SNMP_MODULE_LIBS_A="`net-snmp-config --agent-libs 2> /dev/null`"; SNMP_MODULE_LIBS="`net-snmp-config --libs 2> /dev/null`"; if test -z "$SNMP_MODULE_LIBS_A" then diff --git a/src/libltfs/ltfs_thread.h b/src/libltfs/ltfs_thread.h index eb80edad..0e5b7f35 100644 --- a/src/libltfs/ltfs_thread.h +++ b/src/libltfs/ltfs_thread.h @@ -67,6 +67,7 @@ extern "C" { #endif #include +#include #include #include #include @@ -208,11 +209,10 @@ static inline ltfs_thread_t ltfs_thread_self(void) static inline int ltfs_thread_yield(void) { -#if defined (__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) + /* sched_yield() is the POSIX standard and is available on every + * supported platform; pthread_yield() is deprecated since glibc 2.34 + * and absent on some libcs (e.g. musl). */ return sched_yield(); -#else - return pthread_yield(); -#endif } #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) diff --git a/src/main.c b/src/main.c index 533ec70d..05696035 100644 --- a/src/main.c +++ b/src/main.c @@ -704,7 +704,7 @@ int main(int argc, char **argv) if (priv->device_list) { ret = show_device_list(priv); ltfs_finish(); - return (ret != 0) ? 0 : 1; + return ret ? 1 : 0; } /* Validate sync option */ From 56baaf9c71bc74505a572f13427f96dfbe65ce74 Mon Sep 17 00:00:00 2001 From: Alexandra Rangel Date: Wed, 29 Jul 2026 14:41:05 -0600 Subject: [PATCH 07/15] fix: correct inverted status checks in the SCSI tape backend. (#627) Authored-by: Matej Kenda --- src/tape_drivers/linux/sg/sg_tape.c | 9 ++++++--- src/tape_drivers/osx/iokit/iokit_tape.c | 16 ++++++---------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 19f2beb8..47b60132 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -4630,7 +4630,9 @@ static bool is_ame(void *device) unsigned char buf[TC_MP_READ_WRITE_CTRL_SIZE] = {0}; const int ret = sg_modesense(device, TC_MP_READ_WRITE_CTRL, TC_MP_PC_CURRENT, 0, buf, sizeof(buf)); - if (ret != 0) { + /* sg_modesense returns the transferred byte count (> 0) on success and a + * negative error code on failure. */ + if (ret < 0) { char message[100] = {0}; sprintf(message, "failed to get MP %02Xh (%d)", TC_MP_READ_WRITE_CTRL, ret); ltfsmsg(LTFS_DEBUG, 30392D, __FUNCTION__, message); @@ -4720,7 +4722,7 @@ int sg_set_key(void *device, const unsigned char *keyalias, const unsigned char unsigned char buf[TC_MP_READ_WRITE_CTRL_SIZE] = {0}; ret = sg_modesense(device, TC_MP_READ_WRITE_CTRL, TC_MP_PC_CURRENT, 0, buf, sizeof(buf)); - if (ret != DEVICE_GOOD) + if (ret < 0) /* sg_modesense returns a byte count (> 0) on success */ goto out; ltfs_u16tobe(buffer + 0, sps); @@ -4767,8 +4769,9 @@ int sg_set_key(void *device, const unsigned char *keyalias, const unsigned char memset(buf, 0, sizeof(buf)); ret = sg_modesense(device, TC_MP_READ_WRITE_CTRL, TC_MP_PC_CURRENT, 0, buf, sizeof(buf)); - if (ret != DEVICE_GOOD) + if (ret < 0) /* sg_modesense returns a byte count (> 0) on success */ goto out; + ret = DEVICE_GOOD; /* normalize the byte count to a success code */ free: free(buffer); diff --git a/src/tape_drivers/osx/iokit/iokit_tape.c b/src/tape_drivers/osx/iokit/iokit_tape.c index 76f14628..ea6b86bd 100644 --- a/src/tape_drivers/osx/iokit/iokit_tape.c +++ b/src/tape_drivers/osx/iokit/iokit_tape.c @@ -285,7 +285,7 @@ static int _get_dump(struct iokit_data *priv, char *fname) long long data_length, buf_offset; int dumpfd = -1; int transfer_size, num_transfers, excess_transfer; - int i, bytes; + int bytes; unsigned char cap_buf[DUMP_HEADER_SIZE]; unsigned char *dump_buf; int buf_id; @@ -331,14 +331,11 @@ static int _get_dump(struct iokit_data *priv, char *fname) /* start to transfer data */ buf_offset = 0; - i = 0; ltfsmsg(LTFS_DEBUG, 30859D); while(num_transfers) { int length; - i++; - /* Allocation Length is transfer_size or excess_transfer*/ if(excess_transfer && num_transfers == 1) length = excess_transfer; @@ -3412,7 +3409,9 @@ int iokit_set_xattr(void *device, const char *name, const char *buf, size_t size free(null_terminated); ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_EXIT(REQ_TC_SETXATTR)); - return -LTFS_NO_XATTR; + /* ret is DEVICE_GOOD when one of the vendor attributes matched above; + * returning the hardcoded failure reported success as an error. */ + return ret; } #define BLOCKLEN_DATA_SIZE 6 @@ -3629,7 +3628,7 @@ static const char *_generate_product_name(const char *product_id) int iokit_get_device_list(struct tc_drive_info *buf, int count) { - int i, ret; + int i; int found = 0; int32_t devs = iokit_get_ssc_device_count(); int drive_type; @@ -3646,10 +3645,7 @@ int iokit_get_device_list(struct tc_drive_info *buf, int count) if( devs > 0 ) { for (i = 0; i < devs; i++) { if(iokit_find_ssc_device(iokit_device, i) != 0) - { - ret = -EDEV_DEVICE_UNOPENABLE; continue; - } drive_type = iokit_get_drive_identifier(iokit_device, &identifier); if (!drive_type) { if (found < count && buf) { @@ -3665,7 +3661,7 @@ int iokit_get_device_list(struct tc_drive_info *buf, int count) } found ++; } - ret = iokit_free_device(iokit_device); + iokit_free_device(iokit_device); } } From 42f5884c88c436c7fbe4537116cd057e923f8645 Mon Sep 17 00:00:00 2001 From: Hugo Hurskainen Date: Fri, 14 Aug 2026 18:39:34 +0300 Subject: [PATCH 08/15] configure: detect ICU via icu-uc/icu-i18n pkg-config modules to easily build on Debian (#597) --- .github/workflows/codeql-analysis.yml | 1 - .github/workflows/icu-config | 12 ------------ README.md | 6 ++---- build.sh | 1 - configure.ac | 10 +++++++++- 5 files changed, 11 insertions(+), 19 deletions(-) delete mode 100755 .github/workflows/icu-config diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index affc7019..6c1b7cf4 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -69,7 +69,6 @@ jobs: sudo apt-get -q -y update sudo apt-get -q -y upgrade sudo apt-get -y install build-essential automake autoconf libtool pkg-config icu-devtools libicu-dev libxml2-dev uuid-dev fuse libfuse-dev libsnmp-dev - sudo cp .github/workflows/icu-config /usr/bin/icu-config ./autogen.sh ./configure make diff --git a/.github/workflows/icu-config b/.github/workflows/icu-config deleted file mode 100755 index d5aed413..00000000 --- a/.github/workflows/icu-config +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh - -opts=$1 - -case $opts in - '--cppflags') - echo '' ;; - '--ldflags') - echo '-licuuc -licudata' ;; - *) - echo '/usr/lib/x86_64-linux-gnu/icu/pkgdata.inc' ;; -esac diff --git a/README.md b/README.md index fc9ae6d5..ca8ef1f9 100644 --- a/README.md +++ b/README.md @@ -290,16 +290,14 @@ You need to add `--enable-lintape` as an argument of ./configure script if you w | Ubuntu 16.04 LTS | ppc64le | OK - Not checked automatically | | Ubuntu 18.04 LTS | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-ubuntu-bionic.yml/badge.svg) | | Ubuntu 18.04 LTS | ppc64le | OK - Not checked automatically | - | Ubuntu 20.04 LTS (Need icu-config) | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-ubuntu-focal.yml/badge.svg) | + | Ubuntu 20.04 LTS | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-ubuntu-focal.yml/badge.svg) | | Debian 9 | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-debian9.yml/badge.svg) | - | Debian 10 (Need icu-config) | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-debian10.yml/badge.svg) | + | Debian 10 | x86\_64 | ![GH Action status](https://github.com/LinearTapeFileSystem/ltfs/actions/workflows/build-debian10.yml/badge.svg) | | ArchLinux 2018.08.01 | x86\_64 | OK - Not checked automatically | | ArchLinux 2018.12.31 (rolling) | x86\_64 | OK - Not checked automatically | Currently, automatic build checking is working on GitHub Actions and Travis CI. -For Ubuntu20.04 and Debian10, dummy `icu-config` is needed in the build machine. See Issue [#153](https://github.com/LinearTapeFileSystem/ltfs/issues/153). - ### Build and install on OSX (macOS) #### Recent Homedrew system setup diff --git a/build.sh b/build.sh index 8875035a..2d1a162b 100755 --- a/build.sh +++ b/build.sh @@ -6,7 +6,6 @@ sudo apt-get -q -y update sudo apt-get -q -y upgrade sudo apt-get -y install build-essential automake autoconf libtool pkg-config libicu66 icu-devtools libicu-dev libxml2-dev uuid-dev fuse libfuse-dev libsnmp-dev -sudo cp .github/workflows/icu-config /usr/bin/icu-config ./autogen.sh ./configure make diff --git a/configure.ac b/configure.ac index 994f68cb..85002c59 100644 --- a/configure.ac +++ b/configure.ac @@ -339,12 +339,16 @@ fi dnl dnl Check for ICU +dnl Prefer icu-config for legacy distros; fall back to pkg-config icu-uc/icu-i18n +dnl (icu-config was removed in ICU 63+ and is absent on modern Debian/Ubuntu). dnl ICU_MODULE_CFLAGS="`icu-config --cppflags 2> /dev/null`"; ICU_MODULE_LIBS="`icu-config --ldflags 2> /dev/null`"; if test -z "$ICU_MODULE_LIBS" then - PKG_CHECK_MODULES([ICU_MODULE], [icu >= 0.21]) + PKG_CHECK_MODULES([ICU_MODULE], [icu-uc >= 0.21 icu-i18n >= 0.21], + [], + [PKG_CHECK_MODULES([ICU_MODULE], [icu >= 0.21])]) fi AC_MSG_CHECKING([use latest ICU]) @@ -359,6 +363,10 @@ if test "x${icu_6x}" = "xyes" then AC_MSG_CHECKING(for ICU version) ICU_MODULE_VERSION="`icu-config --version 2> /dev/null`"; + if test -z "$ICU_MODULE_VERSION" + then + ICU_MODULE_VERSION="`$PKG_CONFIG --modversion icu-uc 2> /dev/null`"; + fi if test "${ICU_MODULE_VERSION%%.*}" -ge "60" then AM_EXTRA_CPPFLAGS="${AM_EXTRA_CPPFLAGS} -D ICU6x" From 413c932c3ad253bfa45d08839731a33150a40f03 Mon Sep 17 00:00:00 2001 From: Rolaxgar97 <44095893+Rolaxgar97@users.noreply.github.com> Date: Fri, 14 Aug 2026 18:57:37 -0600 Subject: [PATCH 09/15] fix: Drive Sense Key error (#625) Co-authored-by: Rolando Garcia Arreguin Co-authored-by: Ivan Orozco --- messages/tape_iokit/root.txt | 4 +- messages/tape_linux_lin_tape/root.txt | 4 +- messages/tape_linux_sg/root.txt | 4 +- src/libltfs/arch/errormap.c | 7 + src/libltfs/ltfs_error.h | 22 ++- src/tape_drivers/ibm_tape.c | 15 ++ .../linux/lin_tape/lin_tape_ibmtape.c | 6 +- src/tape_drivers/linux/sg/sg_scsi_tape.c | 6 +- .../netbsd/scsipi-ibmtape/scsipi_scsi_tape.c | 14 +- src/tape_drivers/osx/iokit/iokit_scsi.c | 6 +- src/tape_drivers/vendor_compat.c | 162 +++++++++++------- 11 files changed, 166 insertions(+), 84 deletions(-) diff --git a/messages/tape_iokit/root.txt b/messages/tape_iokit/root.txt index 20abbabb..595ba357 100644 --- a/messages/tape_iokit/root.txt +++ b/messages/tape_iokit/root.txt @@ -49,8 +49,8 @@ root:table { 30804D:string { "CDB check condition: sense = %06x, %s." } 30805D:string { "CDB %s." } 30806I:string { "Unexpected CDB status: 0x%08x." } - 30807D:string { "%s (0x%02x) expected error %d." } - 30808I:string { "%s (0x%02x) returns %d." } + 30807D:string { "%s (0x%02x) expected error %02x/%02x%02x (%d)." } + 30808I:string { "%s (0x%02x) returns %02x/%02x%02x (%d)." } 30809I:string { "Cannot open device: inquiry failed (%d)." } 30810I:string { "Opening a device through iokit driver (%s)." } 30811I:string { "Cannot open device: failed to convert devname to devnumber (%s)." } diff --git a/messages/tape_linux_lin_tape/root.txt b/messages/tape_linux_lin_tape/root.txt index 780aa3e7..d54b3c8a 100644 --- a/messages/tape_linux_lin_tape/root.txt +++ b/messages/tape_linux_lin_tape/root.txt @@ -52,8 +52,8 @@ root:table { 30407D:string { "IOCTL: pos = 0x%02x%02x%02x%02x %s." } 30408I:string { "IOCTL: %s %d returns %d (generic %d) %s." } 30409D:string { "IOCTL: no sense info." } - 30410D:string { "IOCTL: %s %d expected error %d." } - 30411D:string { "IOCTL: %s %d expected error %d. retry the operation." } + 30410D:string { "IOCTL: %s %d expected error %02x/%02x%02x (%d)." } + 30411D:string { "IOCTL: %s %d expected error %02x/%02x%02x (%d). retry the operation." } 30412I:string { "Cannot get sense (%d)." } 30413I:string { "Error on %s: %s (%d) %s." } 30414E:string { "Error on %s: msg = NULL (%d) %s." } diff --git a/messages/tape_linux_sg/root.txt b/messages/tape_linux_sg/root.txt index 5bfc632b..981fdc1b 100644 --- a/messages/tape_linux_sg/root.txt +++ b/messages/tape_linux_sg/root.txt @@ -43,8 +43,8 @@ root:table { 30201D:string { "CDB check condition: sense = %06x, %s." } 30202D:string { "CDB %s." } 30203I:string { "CDB unexpected status: S = 0x%02x, M = 0x02%x" } - 30204D:string { "%s (0x%02x) expected error %d." } - 30205I:string { "%s (0x%02x) returns %d." } + 30204D:string { "%s (0x%02x) expected error %02x/%02x%02x (%d)." } + 30205I:string { "%s (0x%02x) returns %02x/%02x%02x (%d)." } 30206I:string { "Cannot open device: inquiry failed (%d)." } 30207I:string { "Vendor ID is %s." } 30208I:string { "Product ID is %s." } diff --git a/src/libltfs/arch/errormap.c b/src/libltfs/arch/errormap.c index 8fa6adf5..bc64bc84 100644 --- a/src/libltfs/arch/errormap.c +++ b/src/libltfs/arch/errormap.c @@ -429,6 +429,13 @@ static struct error_map fuse_error_list[] = { { EDEV_TIMEOUT, "D1102E", ETIMEDOUT}, { EDEV_ABORT_WAIT_READY, "D1103E", EIO}, { EDEV_OVERFLOW, "D1300E", EIO}, + { EDEV_THIRD_PARTY_ERROR, "D1000E", EIO}, + { EDEV_UNREACHABLE_TARGET, "D1001E", EIO}, + { EDEV_INCORRECT_TARGET_TYPE, "D1002E", EIO}, + { EDEV_COPY_UNDERRUN, "D1003E", EIO}, + { EDEV_COPY_OVERRUN, "D1004E", EIO}, + { EDEV_INVALID_COPY, "D1005E", EIO}, + { EDEV_COPY_INFORMATION, "D1500E", EIO}, { EDEV_CRYPTO_ERROR, "D1600E", EIO}, { EDEV_KEY_SERVICE_ERROR, "D1601E", EIO}, { EDEV_KEY_CHANGE_DETECTED, "D1602E", EIO}, diff --git a/src/libltfs/ltfs_error.h b/src/libltfs/ltfs_error.h index c762520e..6e7fb341 100644 --- a/src/libltfs/ltfs_error.h +++ b/src/libltfs/ltfs_error.h @@ -345,6 +345,7 @@ #define EDEV_DRIVE_NOT_PRESENT 20013 /* 00/8200 (TS3500) The drive is not present */ #define EDEV_RECORD_NOT_FOUND 20014 /* 00/1400 Record not found (string search) */ #define EDEV_INSUFFICIENT_TIME 20015 /* 00/2E00 Insufficient time for operation (string search) */ +#define EDEV_IDLE 20016 /* 00/5E07 Idle condition activated by timer */ #define EDEV_CLEANING_REQUIRED 20098 /* (IBM LTO 00/8282) Drive requests cleaning */ /* Sense Key 1 Recovered Error */ @@ -361,10 +362,11 @@ #define EDEV_OPERATION_IN_PROGRESS 20205 /* 00/0016 02/0407 Operation in progress */ #define EDEV_OFFLINE 20206 /* 02/0412 Device is off-line */ #define EDEV_DOOR_OPEN 20207 /* 02/0418 Door Open*/ -#define EDEV_OVER_TEMPERATURE 20208 /* 02/0B01 08/0B01 Device is too hot. */ +#define EDEV_OVER_TEMPERATURE 20208 /* 02/0B01 0B/0B01 0B/0B0A 0B/0B0C Device is too hot. */ #define EDEV_NO_MEDIUM 20209 /* 02/3A00 Drive has no medium */ #define EDEV_NOT_SELF_CONFIGURED_YET 20210 /* 02/3E00 Device is not self configured yet */ #define EDEV_PARAMETER_VALUE_REJECTED 20211 /* 02/7411 SA creation parameter value rejected */ +#define EDEV_OVER_HUMIDITY 20212 /* 02/0B0E 0B/0B0E 0B/0B10 Device humidity is too high */ #define EDEV_CLEANING_IN_PROGRESS 20297 /* 02/3003 Cleaning in progress*/ #define EDEV_IE_OPEN 20298 /* 02/0484 (TS3500) IO slot is opened */ @@ -422,6 +424,7 @@ #define EDEV_RESERVATION_PREEMPTED 20610 /* 06/2A03 Reservations preempted */ #define EDEV_RESERVATION_RELEASED 20611 /* 06/2A04 Reservations released */ #define EDEV_REGISTRATION_PREEMPTED 20612 /* 06/2A05 Registrations preempted */ +#define EDEV_PREDICTION_FAILED 20613 /* 06/5D00 Failure prediction threshold exceeded */ #define EDEV_UA_MAX 20699 /* Minimum UA error value */ #define IS_UNIT_ATTENTION(e) ((e>=EDEV_UA_MIN)&&(e<=EDEV_UA_MAX)) @@ -441,15 +444,32 @@ #define EDEV_OVERLAPPED 21101 /* 0B/4E00 Overlapped commands */ #define EDEV_TIMEOUT 21102 /* 0B/4B06 Initiator response timeout */ #define EDEV_ABORT_WAIT_READY 21103 /* 0B/2907 0B/0800 0B/0801 on Library */ +#define EDEV_MISCORRECTED_ERROR 21104 /* 0B/110A Miscorrected error */ +#define EDEV_AUTH_FAILED 21105 /* 0B/7440 Authentication failed */ /* Sense Key D Volume Overflow */ #define EDEV_OVERFLOW 21300 /* 0D/XXXX The medium is overflowed */ +/* Sense Key A Copy Aborted (3592 Only) */ +#define EDEV_THIRD_PARTY_ERROR 21000 /* 0A/0D01 Third party device failure */ +#define EDEV_UNREACHABLE_TARGET 21001 /* 0A/0D02 Copy target device not reachable */ +#define EDEV_INCORRECT_TARGET_TYPE 21002 /* 0A/0D03 Incorrect copy target device type */ +#define EDEV_COPY_UNDERRUN 21003 /* 0A/0D04 Copy target device data underrun */ +#define EDEV_COPY_OVERRUN 21004 /* 0A/0D05 Copy target device data overrun */ +#define EDEV_INVALID_COPY 21005 /* 0A/260C Invalid operation for copy source or destination */ + +/* Sense Key F Completed (3592 Only) */ +#define EDEV_COPY_INFORMATION 21500 /* 0F/0020 Extended copy information available */ + /* Crypto Errors on the tape drive */ #define EDEV_CRYPTO_ERROR 21600 /* XX/EEXX 07/EFXX 07/74XX Other crypto related errors */ #define EDEV_KEY_SERVICE_ERROR 21601 /* 04/EE0E 04/EE0F 07/EE0E 07/EE0F Key service timeout or failure */ #define EDEV_KEY_CHANGE_DETECTED 21602 /* 06/EE12 06/EE18 06/EE19 Detect key change */ #define EDEV_KEY_REQUIRED 21603 /* 07/EF10 Detect key change */ +#define EDEV_KEY_GENERATION 21604 /* 07/EE11 07/EEA1 Detect key generation */ +#define EDEV_KEY_TRANSLATE 21605 /* 07/EE13 Detect key translate */ +#define EDEV_KEY_OPTIONAL 21606 /* 07/EE1A Detect key optional */ +#define EDEV_NO_OPERATION 21607 /* 07/EEC0 Detect no operation */ /* Internal errors */ #define EDEV_INTERNAL_ERROR 21700 /* Internal logic error */ diff --git a/src/tape_drivers/ibm_tape.c b/src/tape_drivers/ibm_tape.c index 21c12e1d..5d1fb566 100644 --- a/src/tape_drivers/ibm_tape.c +++ b/src/tape_drivers/ibm_tape.c @@ -378,20 +378,26 @@ struct supported_device *usb_supported_drives[] = { struct error_table ibm_tape_errors[] = { /* Sense Key 0 (No Sense) */ {0x008282, -EDEV_CLEANING_REQUIRED, "IBM LTO - Cleaning Required"}, + /* Sense Key 1 (Recoverd Error) */ + {0x015DFF, -EDEV_RECOVERED_ERROR, "Failure Prediction Threshold Exceeded (FALSE)"}, {0x018252, -EDEV_DEGRADED_MEDIA, "IBM LTO - Degraded Media"}, {0x018383, -EDEV_RECOVERED_ERROR, "Drive Has Been Cleaned"}, {0x018500, -EDEV_RECOVERED_ERROR, "Search Match List Limit (warning)"}, {0x018501, -EDEV_RECOVERED_ERROR, "Search Snoop Match Found"}, + /* Sense Key 3 (Medium Error) */ {0x038500, -EDEV_DATA_PROTECT, "Write Protected Because of Tape or Drive Failure"}, {0x038501, -EDEV_DATA_PROTECT, "Write Protected Because of Tape Failure"}, {0x038502, -EDEV_DATA_PROTECT, "Write Protected Because of Drive Failure"}, + + /* Sense Key 5 (Illegal Request) */ {0x058000, -EDEV_ILLEGAL_REQUEST, "CU Mode, Vendor-Unique"}, {0x058283, -EDEV_ILLEGAL_REQUEST, "Bad Microcode Detected"}, {0x058503, -EDEV_ILLEGAL_REQUEST, "Write Protected Because of Current Tape Position"}, {0x05A301, -EDEV_ILLEGAL_REQUEST, "OEM Vendor-Specific"}, + /* Sense Key 6 (Unit Attention) */ {0x065DFF, -EDEV_UNIT_ATTENTION, "Failure Prediction False"}, {0x068283, -EDEV_UNIT_ATTENTION, "Drive Has Been Cleaned (older versions of microcode)"}, @@ -409,6 +415,7 @@ struct error_table ibm_tape_errors[] = { {0x044781, -EDEV_HARDWARE_ERROR, "IBM LTO - Write Internal CRC Error"}, {0x04EE0E, -EDEV_KEY_SERVICE_ERROR, "Encryption - Key Service Timeout"}, /* LTO5, Jag4 and earlier */ {0x04EE0F, -EDEV_KEY_SERVICE_ERROR, "Encryption - Key Service Failure"}, /* LTO5, Jag4 and earlier */ + {0x054080, -EDEV_ILLEGAL_REQUEST, "Recovered Diagnostic Failure"}, {0x05EE00, -EDEV_CRYPTO_ERROR, "Encryption - Key Service Not Enabled"}, {0x05EE01, -EDEV_CRYPTO_ERROR, "Encryption - Key Service Not Configured"}, {0x05EE02, -EDEV_CRYPTO_ERROR, "Encryption - Key Service Not Available"}, @@ -453,12 +460,20 @@ struct error_table ibm_tape_errors[] = { {0x06EF1A, -EDEV_CRYPTO_ERROR, "Encryption - Key Optional (i.e., chose encryption enabled/disabled)"}, {0x07EE0E, -EDEV_KEY_SERVICE_ERROR, "Encryption - Key Service Timeout"}, /* LTO6, Jag5 and later */ {0x07EE0F, -EDEV_KEY_SERVICE_ERROR, "Encryption - Key Service Failure"}, /* LTO6, Jag5 and later */ + {0x07EE10, -EDEV_KEY_REQUIRED, "Encryption - Key Required"}, + {0x07EE11, -EDEV_KEY_GENERATION, "Encryption - Key Generation"}, + {0x07EE13, -EDEV_KEY_TRANSLATE, "Encryption - Key Translate"}, + {0x07EE1A, -EDEV_KEY_OPTIONAL, "Encryption - Key Optional"}, + {0x07EEA0, -EDEV_KEY_REQUIRED, "Encryption - Key Required (T10)"}, + {0x07EEA1, -EDEV_KEY_GENERATION, "Encryption - Key Generation (T10)"}, + {0x07EEC0, -EDEV_NO_OPERATION, "Encryption - No Operation"}, {0x07EF10, -EDEV_KEY_REQUIRED, "Encryption - Key Required"}, {0x07EF11, -EDEV_CRYPTO_ERROR, "Encryption - Key Generation"}, {0x07EF13, -EDEV_CRYPTO_ERROR, "Encryption - Key Translate"}, {0x07EF1A, -EDEV_CRYPTO_ERROR, "Encryption - Key Optional"}, {0x07EF31, -EDEV_CRYPTO_ERROR, "Encryption - Key Unknown"}, {0x07EFC0, -EDEV_CRYPTO_ERROR, "Encryption - No Operation"}, + /* NOTE: entries with ASC < 0x80 and ASCQ < 0x80 have been moved to standard_tape_errors */ /* END MARK*/ {0xFFFFFF, -EDEV_UNKNOWN, "Unknown Error code"}, }; diff --git a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c index 97245a8b..f67e54e9 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -503,12 +503,14 @@ static inline int _sioc_stioc_command(void *device, int cmd, char *cmd_name, voi rc = lin_tape_ibmtape_ioctlrc2err(device, fd, &sense_data, msg); if (rc == -EDEV_TIME_STAMP_CHANGED) { - ltfsmsg(LTFS_DEBUG, 30411D, cmd_name, cmd, rc); + ltfsmsg(LTFS_DEBUG, 30411D, cmd_name, cmd, + sense_data.key, sense_data.asc, sense_data.ascq, rc); goto start; } if (is_expected_error(cmd, param, rc)) { - ltfsmsg(LTFS_DEBUG, 30410D, cmd_name, cmd, rc); + ltfsmsg(LTFS_DEBUG, 30410D, cmd_name, cmd, + sense_data.key, sense_data.asc, sense_data.ascq, rc); } else { ltfsmsg(LTFS_INFO, 30408I, cmd_name, cmd, rc, errno, ((struct lin_tape_ibmtape *) device)->drive_serial); diff --git a/src/tape_drivers/linux/sg/sg_scsi_tape.c b/src/tape_drivers/linux/sg/sg_scsi_tape.c index 310c50ae..b2ea8231 100644 --- a/src/tape_drivers/linux/sg/sg_scsi_tape.c +++ b/src/tape_drivers/linux/sg/sg_scsi_tape.c @@ -393,9 +393,11 @@ int sg_issue_cdb_command(struct sg_tape *device, sg_io_hdr_t *req, char **msg) if (ret != DEVICE_GOOD) { if (is_expected_error(device, req->cmdp, ret)) { - ltfsmsg(LTFS_DEBUG, 30204D, (char *)req->usr_ptr, req->cmdp[0], ret); + ltfsmsg(LTFS_DEBUG, 30204D, (char *)req->usr_ptr, req->cmdp[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); } else { - ltfsmsg(LTFS_INFO, 30205I, (char *)req->usr_ptr, req->cmdp[0], ret); + ltfsmsg(LTFS_INFO, 30205I, (char *)req->usr_ptr, req->cmdp[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); } } diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_scsi_tape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_scsi_tape.c index b9aa68f7..4f1d594e 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_scsi_tape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_scsi_tape.c @@ -185,6 +185,7 @@ int scsipi_issue_cdb_command(struct scsipi_tape *device, scsireq_t *req, { int status = 0; int ret = -1; + uint32_t sense = 0; CHECK_ARG_NULL(req, -LTFS_NULL_ARG); CHECK_ARG_NULL(msg, -LTFS_NULL_ARG); @@ -233,7 +234,6 @@ int scsipi_issue_cdb_command(struct scsipi_tape *device, scsireq_t *req, if (req->retsts == SCCMD_SENSE) { if (req->senselen_used) { - uint32_t sense = 0; ret = scsipi_sense2errno(req, &sense, msg); ltfsmsg(LTFS_DEBUG, 30201D, sense, *msg); } else { @@ -242,10 +242,14 @@ int scsipi_issue_cdb_command(struct scsipi_tape *device, scsireq_t *req, } } - if (is_expected_error(device, req->cmd, ret)) { - ltfsmsg(LTFS_DEBUG, 30204D, desc, req->cmd[0], ret); - } else { - ltfsmsg(LTFS_INFO, 30205I, desc, req->cmd[0], ret); + if (ret != DEVICE_GOOD) { + if (is_expected_error(device, req->cmd, ret)) { + ltfsmsg(LTFS_DEBUG, 30204D, desc, req->cmd[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); + } else { + ltfsmsg(LTFS_INFO, 30205I, desc, req->cmd[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); + } } out: diff --git a/src/tape_drivers/osx/iokit/iokit_scsi.c b/src/tape_drivers/osx/iokit/iokit_scsi.c index d806c784..d97c9ee2 100644 --- a/src/tape_drivers/osx/iokit/iokit_scsi.c +++ b/src/tape_drivers/osx/iokit/iokit_scsi.c @@ -257,9 +257,11 @@ int iokit_issue_cdb_command(struct iokit_device *device, free: if (ret != DEVICE_GOOD) { if (is_expected_error(device, req->cmdp, ret)) { - ltfsmsg(LTFS_DEBUG, 30807D, req->desc, req->cmdp[0], ret); + ltfsmsg(LTFS_DEBUG, 30807D, req->desc, req->cmdp[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); } else { - ltfsmsg(LTFS_INFO, 30808I, req->desc, req->cmdp[0], ret); + ltfsmsg(LTFS_INFO, 30808I, req->desc, req->cmdp[0], + (sense >> 16) & 0xFF, (sense >> 8) & 0xFF, sense & 0xFF, ret); } } diff --git a/src/tape_drivers/vendor_compat.c b/src/tape_drivers/vendor_compat.c index 0df8941f..0c3ceb65 100644 --- a/src/tape_drivers/vendor_compat.c +++ b/src/tape_drivers/vendor_compat.c @@ -59,31 +59,31 @@ struct error_table standard_tape_errors[] = { /* Sense Key 0 (No Sense) */ {0x000000, -EDEV_NO_SENSE, "No Additional Sense Information"}, {0x000001, -EDEV_FILEMARK_DETECTED, "Filemark Detected"}, - {0x000002, -EDEV_EARLY_WARNING, "End-of-Partition/Medium Detected (Early Warning)"}, + {0x000002, -EDEV_EARLY_WARNING, "End-of-Partition/Medium Detected, Early Warning"}, {0x000004, -EDEV_BOP_DETECTED, "Beginning-of-Partition/Medium Detected"}, - {0x000007, -EDEV_PROG_EARLY_WARNING, "End-of-Partition/Medium Detected (Programable Early Warning)"}, + {0x000007, -EDEV_PROG_EARLY_WARNING, "Programable Early Warning Detected"}, {0x000016, -EDEV_OPERATION_IN_PROGRESS, "Operation in Progress"}, - {0x000017, -EDEV_CLEANING_REQUIRED, "Cleaning Required"}, {0x000018, -EDEV_OPERATION_IN_PROGRESS, "Erase Operation in Progress"}, + {0x000019, -EDEV_OPERATION_IN_PROGRESS, "Locate Operation in Progress"}, + {0x00001C, -EDEV_OPERATION_IN_PROGRESS, "Verify Operation in Progress"}, + {0x005E00, -EDEV_IDLE, "Always replaced by 5E 07"}, /*Just in case it appears somehow*/ + {0x005E07, -EDEV_IDLE, "Idle_c Condition Activated by Timer (and Low Power Condition ON for any reason)"}, {0x001401, -EDEV_RECORD_NOT_FOUND, "Record Not Found (String Search)"}, {0x002E00, -EDEV_INSUFFICIENT_TIME, "Insufficient Time For Operation (String Search)"}, - {0x003003, -EDEV_CLEANING_CART, "Cleaning tape installed"}, + /* Sense Key 1 (Recovered Error) */ {0x010000, -EDEV_RECOVERED_ERROR, "No Additional Sense Information"}, {0x010017, -EDEV_CLEANING_REQUIRED, "Drive Needs Cleaning"}, - {0x010A00, -EDEV_RECOVERED_ERROR, "Error log overflow"}, - {0x010C00, -EDEV_RECOVERED_ERROR, "Write Error: A write error occurred, but was recovered."}, - {0x011100, -EDEV_RECOVERED_ERROR, "Read Error: A read error occurred, but was recovered."}, + {0x010C00, -EDEV_RECOVERED_ERROR, "Write Error: A write error occurred, but was recovered. Data was successfully written into tape."}, + {0x011100, -EDEV_RECOVERED_ERROR, "Read Error: A read error occurred, but was recovered. Data was successfully read from tape."}, {0x011701, -EDEV_RECOVERED_ERROR, "Recovered Data with Retries"}, {0x011800, -EDEV_RECOVERED_ERROR, "Recovered Data with Error Correction Applied"}, {0x013700, -EDEV_MODE_PARAMETER_ROUNDED, "Mode Parameters Rounded"}, - {0x014700, -EDEV_RECOVERED_ERROR, "SCSI parity error"}, {0x015B02, -EDEV_RECOVERED_ERROR, "Log counter at maximum"}, {0x015D00, -EDEV_RECOVERED_ERROR, "Failure Prediction Threshold Exceeded"}, - {0x015DFF, -EDEV_RECOVERED_ERROR, "Failure Prediction Threshold Exceeded (FALSE)"}, - {0x01EF13, -EDEV_RECOVERED_ERROR, "Encryption - Key Translate"}, + /* Sense Key 2 (Not Ready) */ - {0x020017, -EDEV_CLEANING_IN_PROGRESS, "Drive cleaning requested"}, + {0x020016, -EDEV_OPERATION_IN_PROGRESS, "Operation in Progress"}, {0x020400, -EDEV_NOT_REPORTABLE, "Logical Unit Not Ready, Cause Not Reportable"}, {0x020401, -EDEV_BECOMING_READY, "Logical Unit Is in Process of Becoming Ready"}, {0x020402, -EDEV_NEED_INITIALIZE, "Initializing Command Required"}, @@ -93,19 +93,19 @@ struct error_table standard_tape_errors[] = { {0x020412, -EDEV_OFFLINE, "Logical Unit Not Ready, Offline"}, {0x020413, -EDEV_OPERATION_IN_PROGRESS, "Logical Unit Not Ready, SA Creation in Progress"}, {0x020B01, -EDEV_OVER_TEMPERATURE, "Warning - Specified Temperature Exceeded"}, - {0x023003, -EDEV_CLEANING_IN_PROGRESS, "Cleaning Cartridge Installed"}, + {0x020B0A, -EDEV_OVER_TEMPERATURE, "Warning - High Critical Temperature Limit Exceeded"}, + {0x020B0E, -EDEV_OVER_HUMIDITY, "Warning - High Critical Humidity Limit Exceeded"}, + {0x023003, -EDEV_CLEANING_IN_PROGRESS, "Cleaning In Progress"}, {0x023007, -EDEV_NOT_READY, "Cleaning Failure"}, {0x023A00, -EDEV_NO_MEDIUM, "Medium Not Present"}, - {0x023A02, -EDEV_IE_OPEN, "Medium Not Present - Tray Open"}, {0x023A04, -EDEV_NO_MEDIUM, "Not Ready - Medium Auxiliary Memory Accessible"}, - {0x023B12, -EDEV_DOOR_OPEN, "Magazine removed"}, {0x023E00, -EDEV_NOT_SELF_CONFIGURED_YET, "Logical Unit Has Not Self-configured"}, {0x025300, -EDEV_LOAD_UNLOAD_ERROR, "Media Load or Eject Failed"}, {0x027411, -EDEV_PARAMETER_VALUE_REJECTED, "SA Creation Parameter Value Rejected"}, /* Sense Key 3 (Medium Error) */ {0x030302, -EDEV_WRITE_PERM, "Excessive Write Errors"}, {0x030410, -EDEV_CM_PERM, "Logical Unit Not Ready, Auxiliary Memory Not Accessible"}, - {0x030900, -EDEV_RW_PERM, "Track Following Error (Servo)"}, + {0x030900, -EDEV_RW_PERM, "Track Following Error"}, {0x030C00, -EDEV_WRITE_PERM, "Write Error"}, {0x031100, -EDEV_READ_PERM, "Unrecovered Read Error"}, {0x031101, -EDEV_READ_PERM, "Read Retries Exhausted"}, @@ -115,46 +115,42 @@ struct error_table standard_tape_errors[] = { {0x031401, -EDEV_RW_PERM, "Record Not Found"}, {0x031402, -EDEV_RW_PERM, "Filemark or Setmark Not Found"}, {0x031403, -EDEV_RW_PERM, "End-of-Data Not Found"}, - {0x031404, -EDEV_MEDIUM_ERROR, "Block Sequence Error"}, + {0x031404, -EDEV_RW_PERM, "Block Sequence Error"}, {0x033000, -EDEV_MEDIUM_FORMAT_ERROR, "Incompatible Medium Installed"}, {0x033001, -EDEV_MEDIUM_FORMAT_ERROR, "Cannot Read Medium, Unknown Format"}, {0x033002, -EDEV_MEDIUM_FORMAT_ERROR, "Cannot Read Medium, Incompatible Format"}, - {0x033003, -EDEV_MEDIUM_FORMAT_ERROR, "Cleaning tape installed"}, - {0x033007, -EDEV_CLEANING_FALIURE, "Cleaning failure"}, - {0x03300D, -EDEV_MEDIUM_ERROR, "Medium Error/WORM Medium"}, + {0x03300D, -EDEV_MEDIUM_ERROR, "WORM Medium - Tampering Detected"}, {0x033100, -EDEV_MEDIUM_FORMAT_CORRUPTED, "Medium Format Corrupted"}, {0x033101, -EDEV_MEDIUM_ERROR, "Format Command Failed"}, {0x033300, -EDEV_MEDIUM_ERROR, "Tape Length Error"}, - {0x033B00, -EDEV_RW_PERM, "Sequential Positioning Error"}, + {0x033B00, -EDEV_MEDIUM_ERROR, "Sequential Positioning Error"}, {0x035000, -EDEV_RW_PERM, "Write Append Error"}, {0x035100, -EDEV_MEDIUM_ERROR, "Erase Failure"}, - {0x035200, -EDEV_RW_PERM, "Cartridge Fault"}, + {0x035200, -EDEV_MEDIUM_ERROR, "(LTO)Cartridge Fault/(3592)Media Load or Eject Failed"}, {0x035300, -EDEV_LOAD_UNLOAD_ERROR, "Media Load or Eject Failed"}, {0x035304, -EDEV_LOAD_UNLOAD_ERROR, "Medium Thread or Unthread Failure"}, + /* Sense Key 4 (Hardware or Firmware Error) */ - {0x040302, -EDEV_HARDWARE_ERROR, "Open Writer Failure"}, + {0x040302, -EDEV_WRITE_PERM, "Excessive Write, Errors: The Drive is Fenced. Contact Service."}, {0x040403, -EDEV_HARDWARE_ERROR, "Manual Intervention Required"}, - {0x040801, -EDEV_HARDWARE_ERROR, "Logical Unit Communication Failure"}, {0x040900, -EDEV_HARDWARE_ERROR, "Track Following Error"}, {0x041001, -EDEV_LBP_WRITE_ERROR, "Logical Block Guard Check Failed"}, {0x041004, -EDEV_HARDWARE_ERROR, "Logical Block Protection Error On Recover Buffered Data"}, {0x041501, -EDEV_HARDWARE_ERROR, "Machanical Position Error"}, {0x043B00, -EDEV_HARDWARE_ERROR, "Sequential Positioning Error"}, {0x043B08, -EDEV_HARDWARE_ERROR, "Reposition Error"}, - {0x043B0D, -EDEV_HARDWARE_ERROR, "Medium Destination Element Full"}, - {0x043B0E, -EDEV_HARDWARE_ERROR, "Medium Source Element Empty"}, - {0x043F0F, -EDEV_HARDWARE_ERROR, "Echo buffer overwritten"}, {0x044000, -EDEV_HARDWARE_ERROR, "Diagnostic Failure"}, {0x044100, -EDEV_HARDWARE_ERROR, "Data Path Failure"}, - {0x044400, -EDEV_HARDWARE_ERROR, "Internal Target Failure"}, + {0x044400, -EDEV_HARDWARE_ERROR, "Internal Target Failure, Drive Needs Cleaning/Cleaning Failure"}, {0x044C00, -EDEV_HARDWARE_ERROR, "Logical Unit Failed Self-Configuration"}, {0x045100, -EDEV_HARDWARE_ERROR, "Erase Failure"}, {0x045200, -EDEV_HARDWARE_ERROR, "Cartridge Fault"}, - {0x045300, -EDEV_HARDWARE_ERROR, "Media Load or Eject Failed"}, - {0x045301, -EDEV_HARDWARE_ERROR, "A drive did not unload a cartridge."}, + {0x045300, -EDEV_HARDWARE_ERROR, "Media Load or Eject Failed, Contact Service."}, + {0x045301, -EDEV_HARDWARE_ERROR, "Unload Tape Failure"}, {0x045304, -EDEV_HARDWARE_ERROR, "Medium Thread or Unthread Failure"}, /* Sense Key 5 (Illegal Request) */ - {0x050E03, -EDEV_ILLEGAL_REQUEST, "Invalid Field in Command Information Unit (e.g., FCP_DL error)"}, + {0x050016, -EDEV_OPERATION_IN_PROGRESS, "Operation in Progress"}, + {0x050E03, -EDEV_ILLEGAL_REQUEST, "Invalid Field in Command Information Unit (e.g., FCP_DL error, Likely Device Driver or HBA issue.)"}, {0x051A00, -EDEV_ILLEGAL_REQUEST, "Parameter List Length Error"}, {0x052000, -EDEV_ILLEGAL_REQUEST, "Invalid Command Operation Code"}, {0x05200C, -EDEV_ILLEGAL_REQUEST, "Illegal Command When Not In Append-Only Mode"}, @@ -162,19 +158,21 @@ struct error_table standard_tape_errors[] = { {0x052400, -EDEV_INVALID_FIELD_CDB, "Invalid Field in CDB"}, {0x052500, -EDEV_ILLEGAL_REQUEST, "Logical Unit Not Supported"}, {0x052600, -EDEV_ILLEGAL_REQUEST, "Invalid Field in Parameter List"}, - {0x052601, -EDEV_ILLEGAL_REQUEST, "Parameter list error: parameter not supported"}, - {0x052602, -EDEV_ILLEGAL_REQUEST, "Parameter value invalid"}, + {0x052601, -EDEV_ILLEGAL_REQUEST, "Parameter not Supported"}, + {0x052602, -EDEV_ILLEGAL_REQUEST, "Parameter Value Invalid"}, {0x052603, -EDEV_ILLEGAL_REQUEST, "Threshold Parameters Not Supported"}, - {0x052604, -EDEV_ILLEGAL_REQUEST, "Invalid release of persistent reservation"}, + {0x052604, -EDEV_ILLEGAL_REQUEST, "Invalid Release of Persistent Reservation"}, + {0x052606, -EDEV_ILLEGAL_REQUEST, "Too Many Target Descriptors"}, + {0x052607, -EDEV_ILLEGAL_REQUEST, "Unsupported Target Descriptor Type Code"}, + {0x052608, -EDEV_ILLEGAL_REQUEST, "Too Many Segment Descriptors"}, + {0x052609, -EDEV_ILLEGAL_REQUEST, "Unsupported Segment Descriptor Type Code"}, + {0x05260C, -EDEV_ILLEGAL_REQUEST, "Invalid Operation for Copy Source or Destination"}, {0x052611, -EDEV_ILLEGAL_REQUEST, "Encryption - Incomplete Key-Associate Data Set"}, {0x052612, -EDEV_ILLEGAL_REQUEST, "Vendor Specific Key Reference Not Found"}, - {0x052690, -EDEV_ILLEGAL_REQUEST, "Wrong firmware image, does not fit boot code"}, - {0x052691, -EDEV_ILLEGAL_REQUEST, "Wrong personality firmware image"}, - {0x052693, -EDEV_ILLEGAL_REQUEST, "Wrong firmware image, checksum error"}, {0x052904, -EDEV_ILLEGAL_REQUEST, "Device Internal Reset"}, + {0x052A0B, -EDEV_ILLEGAL_REQUEST, "Error History Snapshot Released"}, {0x052C00, -EDEV_ILLEGAL_REQUEST, "Command Sequence Error"}, {0x052C0B, -EDEV_ILLEGAL_REQUEST, "Not Reserved"}, - {0x053000, -EDEV_ILLEGAL_REQUEST, "Incompatible Medium Installed"}, {0x053005, -EDEV_ILLEGAL_REQUEST, "Cannot Write Medium - Incompatible Format"}, {0x053900, -EDEV_ILLEGAL_REQUEST, "Saving Parameters Not Supported"}, {0x053B00, -EDEV_ILLEGAL_REQUEST, "Sequential Positioning Error"}, @@ -182,85 +180,108 @@ struct error_table standard_tape_errors[] = { {0x053B0D, -EDEV_DEST_FULL, "Medium Destination Element Full"}, {0x053B0E, -EDEV_SRC_EMPTY, "Medium Source Element Empty"}, {0x053B11, -EDEV_MAGAZINE_INACCESSIBLE, "Medium magazine not accessible"}, - {0x053B12, -EDEV_MAGAZINE_INACCESSIBLE, "Media magazine not installed."}, {0x053D00, -EDEV_ILLEGAL_REQUEST, "Invalid Bits in Identify Message"}, {0x054900, -EDEV_ILLEGAL_REQUEST, "Invalid Message Error"}, - {0x055301, -EDEV_MEDIUM_LOCKED, "A drive did not unload a cartridge."}, {0x055302, -EDEV_MEDIUM_LOCKED, "Medium Removal Prevented"}, - {0x055303, -EDEV_MEDIUM_LOCKED, "Drive media removal prevented state set"}, + {0x055303, -EDEV_MEDIUM_LOCKED, "Insufficient Resources"}, + {0x055306, -EDEV_ILLEGAL_REQUEST, "Auxiliary Memory Out of Space"},/*LTO*/ + {0x055503, -EDEV_ILLEGAL_REQUEST, "Insufficient Resources"}, + {0x055506, -EDEV_ILLEGAL_REQUEST, "Auxiliary Memory Out of Space"},/*3592*/ {0x055508, -EDEV_ILLEGAL_REQUEST, "Maximum Number of Supplemental Decryption Keys Exceeded"}, {0x055B03, -EDEV_ILLEGAL_REQUEST, "Log List Codes Exhausted"}, {0x057408, -EDEV_ILLEGAL_REQUEST, "Digital Signature Validation Failure"}, {0x05740C, -EDEV_ILLEGAL_REQUEST, "Unable to Decrypt Parameter List"}, + {0x05740D, -EDEV_ILLEGAL_REQUEST, "Crypto Algorithm Disabled"}, {0x057410, -EDEV_ILLEGAL_REQUEST, "SA Creation Parameter Value Invalid"}, {0x057411, -EDEV_ILLEGAL_REQUEST, "SA Creation Parameter Value Rejected"}, {0x057412, -EDEV_ILLEGAL_REQUEST, "Invalid SA Usage"}, + {0x057421, -EDEV_ILLEGAL_REQUEST, "Crypto Configuration Prevented"}, {0x057430, -EDEV_ILLEGAL_REQUEST, "SA Creation Parameter not Supported"}, + /* Sense Key 6 (Unit Attention) */ {0x060002, -EDEV_EARLY_WARNING, "End-of-Partition/Medium Detected, Early Warning"}, {0x062800, -EDEV_MEDIUM_MAY_BE_CHANGED, "Not Ready to Ready Transition, Medium May Have Changed"}, - {0x062801, -EDEV_IE_ACCESSED, "Import or Export Element Accessed"}, + {0x062801, -EDEV_IE_ACCESSED, "LUN 1-Import or Export Element Accessed"}, {0x062900, -EDEV_POR_OR_BUS_RESET, "Power On, Reset, or Bus Device Reset Occurred"}, {0x062901, -EDEV_POR_OR_BUS_RESET, "Power on occurred"}, - {0x062902, -EDEV_POR_OR_BUS_RESET, "SCSI Bus reset occurred"}, - {0x062903, -EDEV_POR_OR_BUS_RESET, "Internal reset occurred"}, - {0x062904, -EDEV_POR_OR_BUS_RESET, "Internal reset occurred"}, + {0x062903, -EDEV_POR_OR_BUS_RESET, "Bus Device Reset Function Occurred"}, + {0x062904, -EDEV_POR_OR_BUS_RESET, "LUN 0-Device Internal Reset/LUN 1-Library Reset Occurred on Path to This Drive"}, {0x062905, -EDEV_UNIT_ATTENTION, "Transceiver Mode Changed To Single-ended"}, {0x062906, -EDEV_UNIT_ATTENTION, "Transceiver Mode Changed To LVD"}, + {0x062A00, -EDEV_CONFIGURE_CHANGED, "Parameters Changed"}, {0x062A01, -EDEV_CONFIGURE_CHANGED, "Mode Parameters Changed"}, - {0x062A02, -EDEV_CONFIGURE_CHANGED, "Mode Parameters Changed"}, - {0x062A03, -EDEV_RESERVATION_PREEMPTED, "Reservations preempted"}, - {0x062A04, -EDEV_RESERVATION_RELEASED, "Reservations released"}, - {0x062A05, -EDEV_REGISTRATION_PREEMPTED, "Registrations preempted"}, + {0x062A02, -EDEV_CONFIGURE_CHANGED, "Log Parameters Changed"}, + {0x062A03, -EDEV_UNIT_ATTENTION, "Reservations preempted"}, + {0x062A04, -EDEV_UNIT_ATTENTION, "Reservations released"}, + {0x062A05, -EDEV_UNIT_ATTENTION, "Registrations preempted"}, + {0x062A0A, -EDEV_UNIT_ATTENTION, "Error History I_T Nexus Cleared"}, + {0x062A0B, -EDEV_UNIT_ATTENTION, "Crypto Capabilities Changed"},/*LTO*/ + {0x062A0D, -EDEV_UNIT_ATTENTION, "Data Encryption Capabilities Changed"},/*3592*/ {0x062A10, -EDEV_TIME_STAMP_CHANGED, "Time stamp changed"}, {0x062A11, -EDEV_CRYPTO_ERROR, "Encryption - Data Encryption Parameters Changed by Another I_T Nexus"}, {0x062A12, -EDEV_CRYPTO_ERROR, "Encryption - Data Encryption Parameters Changed by Vendor Specific Event"}, {0x062A14, -EDEV_UNIT_ATTENTION, "SA Creation Capabilities Data Has Changed"}, {0x062F00, -EDEV_COMMAND_CLEARED, "Commands Cleared by Another Initiator"}, {0x063000, -EDEV_MEDIUM_ERROR, "Incompatible Medium Installed"}, - {0x063B12, -EDEV_DOOR_CLOSED, "Medium magazine removed"}, - {0x063B13, -EDEV_DOOR_CLOSED, "Medium magazine inserted"}, + {0x063B12, -EDEV_DOOR_CLOSED, "LUN 1-Medium Magazine Removed"}, + {0x063B13, -EDEV_DOOR_CLOSED, "LUN 1-Medium Magazine Inserted"}, + {0x063B14, -EDEV_DOOR_CLOSED, "Medium Magazine Locked"}, + {0x063B15, -EDEV_DOOR_CLOSED, "Medium Magazine Unlocked"}, + {0x063B1A, -EDEV_UNIT_ATTENTION, "LUN 1-Drive Removed"}, + {0x063B1B, -EDEV_UNIT_ATTENTION, "LUN 1-Drive Inserted"}, {0x063F01, -EDEV_CONFIGURE_CHANGED, "Microcode Has Been Changed"}, {0x063F02, -EDEV_CONFIGURE_CHANGED, "Changed Operating Definition"}, {0x063F03, -EDEV_CONFIGURE_CHANGED, "Inquiry Data Has Changed"}, - {0x063F05, -EDEV_CONFIGURE_CHANGED, "Device Identifier Changed"}, + {0x063F05, -EDEV_CONFIGURE_CHANGED, "LUN 1-Device Identifier Changed"}, {0x063F0E, -EDEV_CONFIGURE_CHANGED, "Reported LUNs Data Has Changed"}, - {0x065302, -EDEV_MEDIA_REMOVAL_PREV, "Media removal prevented"}, {0x065A01, -EDEV_MEDIUM_REMOVAL_REQ, "Operator Medium Removal Request"}, + {0x065D00, -EDEV_PREDICTION_FAILED, "Failure Prediction Thershold Exceeded"}, + /* Sense Key 7 (Data Protect) */ {0x072610, -EDEV_CRYPTO_ERROR, "Encryption - Data Decryption Key Fail Limit"}, {0x072700, -EDEV_WRITE_PROTECTED, "Write Protected"}, {0x072A13, -EDEV_CRYPTO_ERROR, "Encryption - Data Encryption Key Instance Counter Has Changed"}, - {0x073005, -EDEV_DATA_PROTECT, "Cannot Write Medium, Incompatible Format"}, - {0x073000, -EDEV_WRITE_PROTECTED_WORM, "Data Protect/WORM Medium"}, + {0x073005, -EDEV_DATA_PROTECT, "Cannot Write Medium - Incompatible Format"}, + {0x073006, -EDEV_DATA_PROTECT, "Cannot Format Medium - Incompatible Format"}, {0x07300C, -EDEV_WRITE_PROTECTED_WORM, "Data Protect/WORM Medium - Overwrite Attempted"}, {0x07300D, -EDEV_WRITE_PROTECTED_WORM, "Data Protect/WORM Medium - Integrity Check"}, {0x075001, -EDEV_WRITE_PROTECTED_WORM, "Write Append Position Error (WORM)"}, {0x075200, -EDEV_DATA_PROTECT, "Cartridge Fault"}, - {0x075A02, -EDEV_WRITE_PROTECTED_OPERATOR, "Data Protect/Operator - Overwrite Attempted"}, + {0x075A02, -EDEV_WRITE_PROTECTED_OPERATOR, "Operator Selected Write Protect"}, {0x077400, -EDEV_WRITE_PROTECTED_WORM, "Security Error"}, {0x077401, -EDEV_CRYPTO_ERROR, "Encryption - Unable to Decrypt Data"}, {0x077402, -EDEV_CRYPTO_ERROR, "Encryption - Unencrypted Data Encountered While Decrypting"}, {0x077403, -EDEV_CRYPTO_ERROR, "Encryption - Incorrect Data Encryption Key"}, {0x077404, -EDEV_CRYPTO_ERROR, "Encryption - Cryptographic Integrity Validation Failed"}, {0x077405, -EDEV_CRYPTO_ERROR, "Encryption - Error Decrypting Data"}, + {0x077406, -EDEV_CRYPTO_ERROR, "Unkown Signature Verification Key"}, + {0x077407, -EDEV_CRYPTO_ERROR, "Encryption Parameters Not Useable"}, + {0x077409, -EDEV_CRYPTO_ERROR, "Encryption Mode Mismatch on Read"}, + {0x07740A, -EDEV_CRYPTO_ERROR, "Encryption Block Not Raw Read Enabled"}, + {0x07740B, -EDEV_CRYPTO_ERROR, "Incorrect Encryption Parameters"}, + {0x07746F, -EDEV_CRYPTO_ERROR, "External Data Encryption Control Error"}, + /* Sense Key 8 (Blank Check) */ - {0x080005, -EDEV_EOD_DETECTED, "End-of-Data (EOD) Detected"}, - {0x081401, -EDEV_RECORD_NOT_FOUND, "Record Not Found, Void Tape"}, - {0x081403, -EDEV_EOD_NOT_FOUND, "End-of-Data (EOD) not found"}, - {0x080B01, -EDEV_OVER_TEMPERATURE, "The drive detected an overtemperature condition."}, + {0x080005, -EDEV_EOD_DETECTED, "End-of-Data Detected"}, + {0x081401, -EDEV_RECORD_NOT_FOUND, "Record Not Found, Void Tape"}, /* Sense Key B (Aborted Command) */ - {0x0B0E01, -EDEV_ABORTED_COMMAND, "Information Unit Too Short"}, + {0x0B001E, -EDEV_ABORTED_COMMAND, "Conflicting SA Creation Request"}, + {0x0B0B01, -EDEV_OVER_TEMPERATURE, "Warning - Specified Temperature Exceeded"}, + {0x0B0B0A, -EDEV_OVER_TEMPERATURE, "Warning - High Critical Temperature Limit Exceeded"}, + {0x0B0B0C, -EDEV_OVER_TEMPERATURE, "Warning - High Operating Temperature Limit Exceeded"}, + {0x0B0B0E, -EDEV_OVER_HUMIDITY, "Warning - High Critical Humidity Limit Exceeded"}, + {0x0B0B10, -EDEV_OVER_HUMIDITY, "Warning - High Operating Humidity Limit Exceeded"}, + {0x0B110A, -EDEV_MISCORRECTED_ERROR, "Miscorrected Error"}, {0x0B1400, -EDEV_ABORTED_COMMAND, "Recorded Entity Not Found"}, {0x0B1401, -EDEV_ABORTED_COMMAND, "Record Not Found"}, {0x0B1402, -EDEV_ABORTED_COMMAND, "Filemark or Setmark Not Found"}, {0x0B1B00, -EDEV_ABORTED_COMMAND, "Synchronous Data Transfer Error"}, + {0x0B2C00, -EDEV_ABORTED_COMMAND, "Command Sequence Error"}, {0x0B3D00, -EDEV_ABORTED_COMMAND, "Invalid Bits in Identify Message"}, {0x0B3F0F, -EDEV_ABORTED_COMMAND, "Echo Buffer Overwritten"}, - {0x0B4100, -EDEV_ABORTED_COMMAND, "LDI command Failure"}, {0x0B4300, -EDEV_ABORTED_COMMAND, "Message Error"}, - {0x0B4400, -EDEV_ABORTED_COMMAND, "Internal Target Failure"}, - {0x0B4500, -EDEV_ABORTED_COMMAND, "Select/Reselect Failure"}, + {0x0B4400, -EDEV_ABORTED_COMMAND, "Internal Target Failure-Hardware or Firmware Problem"}, + {0x0B4500, -EDEV_ABORTED_COMMAND, "Select or Reselect Failure"}, {0x0B4700, -EDEV_ABORTED_COMMAND, "SCSI Parity Error"}, {0x0B4703, -EDEV_ABORTED_COMMAND, "Information Unit iuCRC Error Detected"}, {0x0B4800, -EDEV_ABORTED_COMMAND, "Initiator Detected Error Message Received"}, @@ -272,11 +293,20 @@ struct error_table standard_tape_errors[] = { {0x0B4B04, -EDEV_ABORTED_COMMAND, "NAK Received"}, {0x0B4B05, -EDEV_ABORTED_COMMAND, "Data Offset Error"}, {0x0B4B06, -EDEV_TIMEOUT, "Initiator Response Timeout"}, - {0x0B4E00, -EDEV_OVERLAPPED, "Overlapped Commands"}, - {0x0B0801, -EDEV_ABORTED_COMMAND, "LU Communication - Timeout"}, - + {0x0B4E00, -EDEV_OVERLAPPED, "Overlapped Commands Attempted"}, + {0x0B7440, -EDEV_AUTH_FAILED, "Authentication Failed"}, + /* Sense Key A (Copy Aborted) */ + {0x0A0D01, -EDEV_THIRD_PARTY_ERROR, "Third Party Device Failure"}, + {0x0A0D02, -EDEV_UNREACHABLE_TARGET, "Copy Target Device Not Reachable"}, + {0x0A0D03, -EDEV_INCORRECT_TARGET_TYPE, "Incorrect Copy Target Device Type"}, + {0x0A0D04, -EDEV_COPY_UNDERRUN, "Copy Target Device Data Underrun"}, + {0x0A0D05, -EDEV_COPY_OVERRUN, "Copy Target Device Data Overrun"}, + {0x0A260C, -EDEV_INVALID_COPY, "Invalid Operation for Copy Source or Destination"}, + {0x0A2F02, -EDEV_COMMAND_CLEARED, "Commands Cleared by Device Server"}, /* Sense Key D (Volume Overflow) */ {0x0D0002, -EDEV_OVERFLOW, "End-of-Partition/Medium Detected"}, + /* Sense Key F (Completed) */ + {0x0F0020, -EDEV_COPY_INFORMATION, "Extended Copy Information Available"}, /* END MARK*/ {0xFFFFFF, -EDEV_UNKNOWN, "Unknown Error code"}, }; From f60d45b304216cc978a38821558d19eaa953488f Mon Sep 17 00:00:00 2001 From: Ivan Orozco <47061294+vandelvan@users.noreply.github.com> Date: Mon, 17 Aug 2026 10:28:44 -0600 Subject: [PATCH 10/15] update: release version from 2.4.8.4 to 2.4.9.0 (#632) --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 85002c59..e07c5e66 100644 --- a/configure.ac +++ b/configure.ac @@ -36,7 +36,7 @@ dnl dnl LTFS configure.ac. dnl -AC_INIT([LTFS], [2.4.8.4 (Prelim)], IBM corporation.) +AC_INIT([LTFS], [2.4.9.0 (Prelim)], IBM corporation.) AC_CONFIG_SRCDIR([src/main.c]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_MACRO_DIRS([m4]) From 30fad324598dcc8a7056417064a0b52429898d58 Mon Sep 17 00:00:00 2001 From: Mauricio <68037616+madjesc@users.noreply.github.com> Date: Mon, 17 Aug 2026 16:07:31 -0600 Subject: [PATCH 11/15] fix: rhel10 netsnmp faulty flags (#633) --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index e07c5e66..75c7a535 100644 --- a/configure.ac +++ b/configure.ac @@ -589,6 +589,8 @@ fi AM_CFLAGS=`echo ${AM_CFLAGS} | ${SED} 's|-D_FORTIFY_SOURCE=. ||g'` AM_LDFLAGS="${AM_LDFLAGS} ${MODULE_CHECK_LD} ${FUSE_MODULE_LIBS} ${UUID_MODULE_LIBS} ${LIBXML2_MODULE_LIBS} ${ICU_MODULE_LIBS} ${SNMP_MODULE_LIBS_A} ${SNMP_MODULE_LIBS}" CFLAGS="${CFLAGS} ${OPT_FLAGS}" +CFLAGS=$(echo "$CFLAGS" | sed 's/,-Wp/-Wp/g') +AM_CFLAGS=$(echo "$AM_CFLAGS" | sed 's/,-Wp/-Wp/g') dnl dnl Define options From 2a13b53d4b5a5b3f941a5285656462ff01b85fda Mon Sep 17 00:00:00 2001 From: Ivan Orozco <47061294+vandelvan@users.noreply.github.com> Date: Fri, 21 Aug 2026 12:15:19 -0600 Subject: [PATCH 12/15] fix: HP LTO 6 remaining capacity (#634) --- src/tape_drivers/freebsd/cam/cam_tc.c | 3 ++- src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c | 3 ++- src/tape_drivers/linux/sg/sg_tape.c | 3 ++- src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c | 3 ++- src/tape_drivers/osx/iokit/iokit_tape.c | 3 ++- 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/tape_drivers/freebsd/cam/cam_tc.c b/src/tape_drivers/freebsd/cam/cam_tc.c index 576ae1b3..7c7f82bd 100644 --- a/src/tape_drivers/freebsd/cam/cam_tc.c +++ b/src/tape_drivers/freebsd/cam/cam_tc.c @@ -1781,7 +1781,8 @@ int camtape_remaining_capacity(void *device, struct tc_remaining_cap *cap) int rc; ltfs_profiler_add_entry(softc->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_REMAINCAP)); - if (IS_LTO(softc->drive_type) && (DRIVE_GEN(softc->drive_type) == 0x05)) { + if ((IS_LTO(softc->drive_type) && (DRIVE_GEN(softc->drive_type) == 0x05)) || + (softc->vendor == VENDOR_HP && IS_LTO(softc->drive_type) && (DRIVE_GEN(softc->drive_type) == 0x06))) { /* Issue LogPage 0x31 */ rc = camtape_logsense(device, LOG_TAPECAPACITY, (uint8_t)0, logdata, LOGSENSEPAGE); if (rc < 0) { diff --git a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c index f67e54e9..0726e22a 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -2268,7 +2268,8 @@ int lin_tape_ibmtape_remaining_capacity(void *device, struct tc_remaining_cap *c struct lin_tape_ibmtape *priv = (struct lin_tape_ibmtape *) device; ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_REMAINCAP)); - if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { + if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || + (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { /* Issue LogPage 0x31 */ rc = lin_tape_ibmtape_logsense(device, LOG_TAPECAPACITY, (uint8_t)0, logdata, LOGSENSEPAGE); if (rc) { diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 47b60132..8a13493e 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -3031,7 +3031,8 @@ int sg_remaining_capacity(void *device, struct tc_remaining_cap *cap) memset(buffer, 0, LOGSENSEPAGE); - if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { + if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || + (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { /* Use LogPage 0x31 */ ret = sg_logsense(device, (uint8_t)LOG_TAPECAPACITY, (uint8_t)0, (void *)buffer, LOGSENSEPAGE); if(ret < 0) diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c index 0ea8df55..1fd56d8e 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c @@ -2575,7 +2575,8 @@ int scsipi_ibmtape_remaining_capacity(void *device, struct tc_remaining_cap *cap memset(buffer, 0, LOGSENSEPAGE); - if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { + if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || + (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { /* Use LogPage 0x31 */ ret = scsipi_ibmtape_logsense(device, (uint8_t)LOG_TAPECAPACITY, (uint8_t)0, (void *)buffer, LOGSENSEPAGE); if(ret < 0) diff --git a/src/tape_drivers/osx/iokit/iokit_tape.c b/src/tape_drivers/osx/iokit/iokit_tape.c index ea6b86bd..7b72d2ff 100644 --- a/src/tape_drivers/osx/iokit/iokit_tape.c +++ b/src/tape_drivers/osx/iokit/iokit_tape.c @@ -2299,7 +2299,8 @@ int iokit_remaining_capacity(void *device, struct tc_remaining_cap *cap) memset(&buffer, 0, LOGSENSEPAGE); - if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { + if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || + (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { /* Use LogPage 0x31 */ ret = iokit_logsense(device, (uint8_t)LOG_TAPECAPACITY, (uint8_t)0, (void *)buffer, LOGSENSEPAGE); if(ret < 0) From 5e84c193023042859d713dab6a732947aa89ea9a Mon Sep 17 00:00:00 2001 From: Ivan Orozco <47061294+vandelvan@users.noreply.github.com> Date: Fri, 4 Sep 2026 13:47:26 -0600 Subject: [PATCH 13/15] fix: remove vendor condition from lintape (#642) --- src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c | 3 +-- src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c index 0726e22a..f67e54e9 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -2268,8 +2268,7 @@ int lin_tape_ibmtape_remaining_capacity(void *device, struct tc_remaining_cap *c struct lin_tape_ibmtape *priv = (struct lin_tape_ibmtape *) device; ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_REMAINCAP)); - if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || - (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { + if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { /* Issue LogPage 0x31 */ rc = lin_tape_ibmtape_logsense(device, LOG_TAPECAPACITY, (uint8_t)0, logdata, LOGSENSEPAGE); if (rc) { diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c index 1fd56d8e..0ea8df55 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c @@ -2575,8 +2575,7 @@ int scsipi_ibmtape_remaining_capacity(void *device, struct tc_remaining_cap *cap memset(buffer, 0, LOGSENSEPAGE); - if ((IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) || - (priv->vendor == VENDOR_HP && IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x06))) { + if (IS_LTO(priv->drive_type) && (DRIVE_GEN(priv->drive_type) == 0x05)) { /* Use LogPage 0x31 */ ret = scsipi_ibmtape_logsense(device, (uint8_t)LOG_TAPECAPACITY, (uint8_t)0, (void *)buffer, LOGSENSEPAGE); if(ret < 0) From dea5496c849109eedbdaed78ba98b2b3145820f3 Mon Sep 17 00:00:00 2001 From: Simon Waid Date: Fri, 11 Sep 2026 16:19:03 +0200 Subject: [PATCH 14/15] Fixes issues with Tandberg LTO 6 drive documented in #645 --- src/tape_drivers/hp_tape.c | 12 ++++++------ src/tape_drivers/linux/sg/sg_tape.c | 2 +- src/tape_drivers/vendor_compat.c | 3 +++ 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/tape_drivers/hp_tape.c b/src/tape_drivers/hp_tape.c index 23aa7327..e01b2368 100644 --- a/src/tape_drivers/hp_tape.c +++ b/src/tape_drivers/hp_tape.c @@ -63,12 +63,12 @@ #include "libltfs/ltfs_endian.h" struct supported_device *hp_supported_drives[] = { - TAPEDRIVE( HP_VENDOR_ID, "Ultrium 5-SCSI", DRIVE_LTO5, "[Ultrium 5-SCSI]" ), /* HP Ultrium Gen 5 */ - TAPEDRIVE( HP_VENDOR_ID, "Ultrium 6-SCSI", DRIVE_LTO6, "[Ultrium 6-SCSI]" ), /* HP Ultrium Gen 6 */ - TAPEDRIVE( HP_VENDOR_ID, "Ultrium 7-SCSI", DRIVE_LTO7, "[Ultrium 7-SCSI]" ), /* HP Ultrium Gen 7 */ - TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 8-SCSI", DRIVE_LTO8, "[Ultrium 8-SCSI]" ), /* HPE Ultrium Gen 8 */ - TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 9-SCSI", DRIVE_LTO9, "[Ultrium 9-SCSI]" ), /* HPE Ultrium Gen 9 */ - TAPEDRIVE( TANDBERG_VENDOR_ID, "LTO-6 HH ", DRIVE_LTO6_HH, "[LTO-6 HH]" ), /* TANDBERG LTO-6 HH */ + TAPEDRIVE( HP_VENDOR_ID, "Ultrium 5-SCSI", DRIVE_LTO5, "[Ultrium 5-SCSI]" ), /* HP Ultrium Gen 5 */ + TAPEDRIVE( HP_VENDOR_ID, "Ultrium 6-SCSI", DRIVE_LTO6, "[Ultrium 6-SCSI]" ), /* HP Ultrium Gen 6 */ + TAPEDRIVE( HP_VENDOR_ID, "Ultrium 7-SCSI", DRIVE_LTO7, "[Ultrium 7-SCSI]" ), /* HP Ultrium Gen 7 */ + TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 8-SCSI", DRIVE_LTO8, "[Ultrium 8-SCSI]" ), /* HPE Ultrium Gen 8 */ + TAPEDRIVE( HPE_VENDOR_ID, "Ultrium 9-SCSI", DRIVE_LTO9, "[Ultrium 9-SCSI]" ), /* HPE Ultrium Gen 9 */ + TAPEDRIVE( TANDBERG_VENDOR_ID, "LTO-6 HH ", DRIVE_LTO6_HH, "[LTO-6 HH]" ), /* TANDBERG LTO-6 HH */ /* End of supported_devices */ NULL }; diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 8a13493e..b840418c 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -2393,7 +2393,7 @@ int sg_locate(void *device, struct tc_position dest, struct tc_position *pos) ret = sg_issue_cdb_command(&priv->dev, &req, &msg); if (ret < 0){ - if (dest.block == TAPE_BLOCK_MAX && ret == -EDEV_EOD_DETECTED) { + if (dest.block == TAPE_BLOCK_MAX && ret == -EDEV_EOD_DETECTED || ret == -EDEV_EOD_NOT_FOUND) { ltfsmsg(LTFS_DEBUG, 30224D, "Locate"); ret = DEVICE_GOOD; } else { diff --git a/src/tape_drivers/vendor_compat.c b/src/tape_drivers/vendor_compat.c index 0c3ceb65..4761a4ce 100644 --- a/src/tape_drivers/vendor_compat.c +++ b/src/tape_drivers/vendor_compat.c @@ -264,6 +264,7 @@ struct error_table standard_tape_errors[] = { /* Sense Key 8 (Blank Check) */ {0x080005, -EDEV_EOD_DETECTED, "End-of-Data Detected"}, {0x081401, -EDEV_RECORD_NOT_FOUND, "Record Not Found, Void Tape"}, + {0x081403, -EDEV_EOD_NOT_FOUND, "End-of-Data (EOD) not found"}, /* Sense Key B (Aborted Command) */ {0x0B001E, -EDEV_ABORTED_COMMAND, "Conflicting SA Creation Request"}, {0x0B0B01, -EDEV_OVER_TEMPERATURE, "Warning - Specified Temperature Exceeded"}, @@ -319,6 +320,8 @@ int get_vendor_id(char* vendor) return VENDOR_HP; else if (!strncmp(vendor, HPE_VENDOR_ID, strlen(HPE_VENDOR_ID))) return VENDOR_HP; + else if (!strncmp(vendor, TANDBERG_VENDOR_ID, strlen(TANDBERG_VENDOR_ID))) + return VENDOR_HP; else if (!strncmp(vendor, QUANTUM_VENDOR_ID, strlen(QUANTUM_VENDOR_ID))) return VENDOR_QUANTUM; else From 52d131862a98ef350e9a3a77e03f2973a7072b59 Mon Sep 17 00:00:00 2001 From: Simon Waid Date: Sun, 13 Sep 2026 09:13:34 +0200 Subject: [PATCH 15/15] Add missing parenthesis --- src/tape_drivers/linux/sg/sg_tape.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index b840418c..cef7be97 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -2393,7 +2393,7 @@ int sg_locate(void *device, struct tc_position dest, struct tc_position *pos) ret = sg_issue_cdb_command(&priv->dev, &req, &msg); if (ret < 0){ - if (dest.block == TAPE_BLOCK_MAX && ret == -EDEV_EOD_DETECTED || ret == -EDEV_EOD_NOT_FOUND) { + if (dest.block == TAPE_BLOCK_MAX && (ret == -EDEV_EOD_DETECTED || ret == -EDEV_EOD_NOT_FOUND)) { ltfsmsg(LTFS_DEBUG, 30224D, "Locate"); ret = DEVICE_GOOD; } else {