From 9a24577ab27c9f3c0f67ee2e663ee16c4a52fe92 Mon Sep 17 00:00:00 2001 From: syaoraang Date: Wed, 29 Jul 2026 09:55:27 -0600 Subject: [PATCH 1/8] fix: Retrying write operations only after repositioning the drive --- src/tape_drivers/linux/sg/sg_tape.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 19f2beb8..c78a1367 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -104,6 +104,7 @@ struct sg_global_data global_data; #define MAX_RETRY (100) #define MAX_TAKE_DUMP_ATTEMPTS (10) +#define SOFT_ERROR_MAX_RETRIES (3) /* Forward references (For keep function order to struct tape_ops) */ int sg_readpos(void *device, struct tc_position *pos); @@ -2098,7 +2099,8 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po struct sg_data *priv = (struct sg_data*)device; struct tc_position cur_pos; size_t datacount = count; - int retry_count = 0; + int reconnect_retry_count = 0, soft_error_retry_count = 0; + int TBL_SLEEP_SECS[SOFT_ERROR_MAX_RETRIES] = {45, 60, 75}; // Hardcoded exponentially increasing sleep time ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_WRITE)); @@ -2145,7 +2147,12 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po } else ret = -EDEV_POR_OR_BUS_RESET; } - } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { + } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && reconnect_retry_count < MAX_RETRY) { + ret = _handle_block_allocation_failure(device, pos, &reconnect_retry_count, "write"); + if (ret == -EDEV_RETRY) + goto start_write; + } else if (ret == -EDEV_HOST_ERROR && soft_error_retry_count < SOFT_ERROR_MAX_RETRIES) { + sleep(TBL_SLEEP_SECS[soft_error_retry_count]); ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; From ce7dba36f64f23ca1f6426d39a4160d67073641f Mon Sep 17 00:00:00 2001 From: mcardenas Date: Wed, 29 Jul 2026 16:16:11 -0600 Subject: [PATCH 2/8] fix: retry operations _clear_por changes - clear the previous power on reset status and retry - retry in both ibmtape netbsd driver and the sg one - make _clear_por return an int --- src/tape_drivers/linux/sg/sg_tape.c | 22 +++++++++++-------- .../netbsd/scsipi-ibmtape/scsipi_ibmtape.c | 11 +++++++++- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index c78a1367..15385566 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -54,6 +54,7 @@ #include #include +#include "libltfs/ltfs_error.h" #include "ltfs_copyright.h" #include "libltfs/ltfslogging.h" #include "libltfs/fs.h" @@ -605,7 +606,7 @@ int _raw_tur(const int fd) #define _clear_por(p) _clear_por_raw((p)->dev.fd); -void _clear_por_raw(const int fd) +int _clear_por_raw(const int fd) { int i = 0, ret = -1; @@ -625,6 +626,7 @@ void _clear_por_raw(const int fd) } i++; } + return ret; } #define _get_stable_tur_response(p) _get_stable_tur_response_raw((p)->dev.fd) @@ -2099,8 +2101,7 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po struct sg_data *priv = (struct sg_data*)device; struct tc_position cur_pos; size_t datacount = count; - int reconnect_retry_count = 0, soft_error_retry_count = 0; - int TBL_SLEEP_SECS[SOFT_ERROR_MAX_RETRIES] = {45, 60, 75}; // Hardcoded exponentially increasing sleep time + int retry_count = 0; ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_WRITE)); @@ -2147,15 +2148,18 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po } else ret = -EDEV_POR_OR_BUS_RESET; } - } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && reconnect_retry_count < MAX_RETRY) { - ret = _handle_block_allocation_failure(device, pos, &reconnect_retry_count, "write"); - if (ret == -EDEV_RETRY) - goto start_write; - } else if (ret == -EDEV_HOST_ERROR && soft_error_retry_count < SOFT_ERROR_MAX_RETRIES) { - sleep(TBL_SLEEP_SECS[soft_error_retry_count]); + } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; + } else if (ret == -EDEV_HOST_ERROR && retry_count < SOFT_ERROR_MAX_RETRIES) { + sleep(5); + ret = _clear_por(priv); + if (ret == DEVICE_GOOD) { + ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + if (ret == -EDEV_RETRY) + goto start_write; + } } ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_EXIT(REQ_TC_WRITE)); diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c index 0ea8df55..a3caf1f9 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c @@ -569,7 +569,7 @@ int _raw_tur(const int fd) #define _clear_por(p) _clear_por_raw((p)->dev.fd); -void _clear_por_raw(const int fd) +int _clear_por_raw(const int fd) { int i = 0, ret = -1; @@ -589,6 +589,7 @@ void _clear_por_raw(const int fd) } i++; } + return ret; } /* Forward reference */ @@ -1707,6 +1708,14 @@ int scsipi_ibmtape_write(void *device, const char *buf, size_t count, struct tc_ ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; + } else if (ret == -EDEV_HOST_ERROR && retry_count < SOFT_ERROR_MAX_RETRIES) { + sleep(5); + ret = _clear_por(priv); + if (ret == DEVICE_GOOD) { + ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + if (ret == -EDEV_RETRY) + goto start_write; + } } ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_EXIT(REQ_TC_WRITE)); From 6d40e0554e742fdc1b308118f6c283825856d729 Mon Sep 17 00:00:00 2001 From: mcardenas Date: Wed, 29 Jul 2026 16:27:48 -0600 Subject: [PATCH 3/8] fix: minor changes chore: revert separation of por and allocation issues --- src/tape_drivers/linux/sg/sg_tape.c | 8 ++++---- src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 15385566..92ac961b 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -105,7 +105,7 @@ struct sg_global_data global_data; #define MAX_RETRY (100) #define MAX_TAKE_DUMP_ATTEMPTS (10) -#define SOFT_ERROR_MAX_RETRIES (3) +#define POR_MAX_RETRIES (3) /* Forward references (For keep function order to struct tape_ops) */ int sg_readpos(void *device, struct tc_position *pos); @@ -2101,7 +2101,7 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po struct sg_data *priv = (struct sg_data*)device; struct tc_position cur_pos; size_t datacount = count; - int retry_count = 0; + int retry_count = 0, por_retry_count = 0; ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_WRITE)); @@ -2152,11 +2152,11 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; - } else if (ret == -EDEV_HOST_ERROR && retry_count < SOFT_ERROR_MAX_RETRIES) { + } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + ret = _handle_block_allocation_failure(device, pos, &por_retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; } diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c index a3caf1f9..153c2f14 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c @@ -96,6 +96,7 @@ struct scsipi_ibmtape_global_data global_data; #define TU_DEFAULT_TIMEOUT (60) #define MAX_RETRY (100) +#define POR_MAX_RETRIES (3) /* Forward references (For keep function order to struct tape_ops) */ int scsipi_ibmtape_readpos(void *device, struct tc_position *pos); @@ -1657,7 +1658,7 @@ int scsipi_ibmtape_write(void *device, const char *buf, size_t count, struct tc_ struct scsipi_ibmtape_data *priv = (struct scsipi_ibmtape_data*)device; struct tc_position cur_pos; size_t datacount = count; - int retry_count = 0; + int retry_count = 0, por_retry_count = 0; ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_ENTER(REQ_TC_WRITE)); @@ -1708,11 +1709,11 @@ int scsipi_ibmtape_write(void *device, const char *buf, size_t count, struct tc_ ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; - } else if (ret == -EDEV_HOST_ERROR && retry_count < SOFT_ERROR_MAX_RETRIES) { + } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + ret = _handle_block_allocation_failure(device, pos, &por_retry_count, "write"); if (ret == -EDEV_RETRY) goto start_write; } From a0d49e6a9ca1e81fbb8b61d2f6bea5ea0027ad3e Mon Sep 17 00:00:00 2001 From: mcardenas Date: Fri, 31 Jul 2026 13:02:15 -0600 Subject: [PATCH 4/8] feat: make block failure generic --- .../linux/lin_tape/lin_tape_ibmtape.c | 13 ++++++------- src/tape_drivers/linux/sg/sg_tape.c | 18 +++++++++--------- 2 files changed, 15 insertions(+), 16 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 97245a8b..205e0163 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -1437,15 +1437,11 @@ int lin_tape_ibmtape_read(void *device, char *buf, size_t count, struct tc_posit #define WRITE_RETRY (-LINUX_MAX_BLOCK_SIZE) -static inline int _handle_block_allocation_failure(void *device, struct tc_position *pos, int *retry) +static inline int _handle_block_write_failure(void *device, struct tc_position *pos) { int ret = 0; struct tc_position tmp_pos = {0, 0}; - /* Sleep 3 secs to wait garbage correction in kernel side and retry */ - ltfsmsg(LTFS_WARN, 30440W, ++(*retry)); - sleep(3); - ret = lin_tape_ibmtape_readpos(device, &tmp_pos); if (ret == DEVICE_GOOD && pos->partition == tmp_pos.partition) { if (pos->block == tmp_pos.block) { @@ -1545,7 +1541,9 @@ int lin_tape_ibmtape_write(void *device, const char *buf, size_t count, struct t rc = DEVICE_GOOD; } } else if (errno == ENOMEM && retry < MAX_WRITE_RETRY) { - rc = _handle_block_allocation_failure(device, pos, &retry); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30440W, ++retry); + rc = _handle_block_write_failure(device, pos); if (rc == WRITE_RETRY) { errno = 0; goto write_start; @@ -1571,7 +1569,8 @@ int lin_tape_ibmtape_write(void *device, const char *buf, size_t count, struct t if (retry < MAX_WRITE_RETRY && ((current_errno == EIO && rc == -EDEV_NO_SENSE ) || (rc == -EDEV_CONFIGURE_CHANGED) || (rc == -EDEV_TIME_STAMP_CHANGED))) { - rc = _handle_block_allocation_failure(device, pos, &retry); + sleep(5); + rc = _handle_block_write_failure(device, pos); if (rc == WRITE_RETRY) { errno = 0; goto write_start; diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 92ac961b..5ef05d90 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -1864,16 +1864,11 @@ static int _cdb_read(void *device, char *buf, size_t size, bool sili) return length; } -static inline int _handle_block_allocation_failure(void *device, struct tc_position *pos, - int *retry, char *op) +static inline int _handle_block_write_failure(void *device, struct tc_position *pos, char *op) { int ret = 0; struct tc_position tmp_pos = {0, 0}; - /* Sleep 3 secs to wait garbage correction in kernel side and retry */ - ltfsmsg(LTFS_WARN, 30277W, ++(*retry)); - sleep(3); - ret = sg_readpos(device, &tmp_pos); if (ret == DEVICE_GOOD && pos->partition == tmp_pos.partition) { if (pos->block == tmp_pos.block) { @@ -1987,7 +1982,9 @@ int sg_read(void *device, char *buf, size_t size, priv->use_sili = false; ret = _cdb_read(device, buf, datacount, unusual_size); } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "read"); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + ret = _handle_block_write_failure(device, pos, "read"); if (ret == -EDEV_RETRY) goto start_read; } @@ -2149,14 +2146,17 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po ret = -EDEV_POR_OR_BUS_RESET; } } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { + por_retry_count++; sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_allocation_failure(device, pos, &por_retry_count, "write"); + ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; } From 21fb327efd8850e95920ff56218bebe4b9134443 Mon Sep 17 00:00:00 2001 From: syaoraang Date: Fri, 31 Jul 2026 13:49:05 -0600 Subject: [PATCH 5/8] chore: Fixing identation --- src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c | 6 +++--- src/tape_drivers/linux/sg/sg_tape.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 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 205e0163..c3c691b0 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -1541,8 +1541,8 @@ int lin_tape_ibmtape_write(void *device, const char *buf, size_t count, struct t rc = DEVICE_GOOD; } } else if (errno == ENOMEM && retry < MAX_WRITE_RETRY) { - sleep(3); // Wait for kernel GC - ltfsmsg(LTFS_WARN, 30440W, ++retry); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30440W, ++retry); rc = _handle_block_write_failure(device, pos); if (rc == WRITE_RETRY) { errno = 0; @@ -1569,7 +1569,7 @@ int lin_tape_ibmtape_write(void *device, const char *buf, size_t count, struct t if (retry < MAX_WRITE_RETRY && ((current_errno == EIO && rc == -EDEV_NO_SENSE ) || (rc == -EDEV_CONFIGURE_CHANGED) || (rc == -EDEV_TIME_STAMP_CHANGED))) { - sleep(5); + sleep(5); rc = _handle_block_write_failure(device, pos); if (rc == WRITE_RETRY) { errno = 0; diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 5ef05d90..e5e520b1 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -1982,8 +1982,8 @@ int sg_read(void *device, char *buf, size_t size, priv->use_sili = false; ret = _cdb_read(device, buf, datacount, unusual_size); } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - sleep(3); // Wait for kernel GC - ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30277W, ++retry_count); ret = _handle_block_write_failure(device, pos, "read"); if (ret == -EDEV_RETRY) goto start_read; @@ -2146,13 +2146,13 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po ret = -EDEV_POR_OR_BUS_RESET; } } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - sleep(3); // Wait for kernel GC - ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + sleep(3); // Wait for kernel GC + ltfsmsg(LTFS_WARN, 30277W, ++retry_count); ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { - por_retry_count++; + por_retry_count++; sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { From 6a5a0a11a30a9021cce5bc109df23162d4eff33f Mon Sep 17 00:00:00 2001 From: syaoraang Date: Fri, 31 Jul 2026 14:26:28 -0600 Subject: [PATCH 6/8] fix: Avoiding hidding cdb_write return code --- src/tape_drivers/linux/sg/sg_tape.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index e5e520b1..6747d736 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -2093,7 +2093,7 @@ static int _cdb_write(void *device, uint8_t *buf, size_t size, bool *ew, bool *p int sg_write(void *device, const char *buf, size_t count, struct tc_position *pos) { - int ret, ret_fo; + int ret, ret_fo, ret_write = -1; bool ew = false, pew = false; struct sg_data *priv = (struct sg_data*)device; struct tc_position cur_pos; @@ -2128,12 +2128,12 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po } start_write: - ret = _cdb_write(device, (uint8_t *)buf, datacount, &ew, &pew); - if (ret == DEVICE_GOOD) { + ret_write = _cdb_write(device, (uint8_t *)buf, datacount, &ew, &pew); + if (ret_write == DEVICE_GOOD) { pos->block++; pos->early_warning = ew; pos->programmable_early_warning = pew; - } else if (ret == -EDEV_NEED_FAILOVER) { + } else if (ret_write == -EDEV_NEED_FAILOVER) { ret_fo = sg_readpos(device, &cur_pos); if (!ret_fo) { if (pos->partition == cur_pos.partition @@ -2141,7 +2141,7 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po pos->block++; pos->early_warning = cur_pos.early_warning; pos->programmable_early_warning = cur_pos.programmable_early_warning; - ret = DEVICE_GOOD; + ret = ret_write = DEVICE_GOOD; } else ret = -EDEV_POR_OR_BUS_RESET; } @@ -2156,15 +2156,15 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_write_failure(device, pos, "write"); - if (ret == -EDEV_RETRY) - goto start_write; + ret = _handle_block_write_failure(device, pos, "write"); + if (ret == -EDEV_RETRY) + goto start_write; } } ltfs_profiler_add_entry(priv->profiler, NULL, TAPEBEND_REQ_EXIT(REQ_TC_WRITE)); - return ret; + return ret_write; } int sg_writefm(void *device, size_t count, struct tc_position *pos, bool immed) From 0287d35bec841d4111c4096faef8f5b33d413227 Mon Sep 17 00:00:00 2001 From: syaoraang Date: Mon, 3 Aug 2026 17:38:07 -0600 Subject: [PATCH 7/8] fix: Using correct return value to check write output --- src/tape_drivers/linux/sg/sg_tape.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 6747d736..75128ff9 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -2145,13 +2145,13 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po } else ret = -EDEV_POR_OR_BUS_RESET; } - } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { + } else if (ret_write == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { sleep(3); // Wait for kernel GC ltfsmsg(LTFS_WARN, 30277W, ++retry_count); ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; - } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { + } else if (ret_write == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { por_retry_count++; sleep(5); ret = _clear_por(priv); From fd83052b8eec95c14a7bc04110d61d6170ac27eb Mon Sep 17 00:00:00 2001 From: mcardenas Date: Wed, 5 Aug 2026 11:18:43 -0600 Subject: [PATCH 8/8] fix: ret and netbsd driver --- .../linux/lin_tape/lin_tape_ibmtape.c | 2 +- src/tape_drivers/linux/sg/sg_tape.c | 11 +++++----- .../netbsd/scsipi-ibmtape/scsipi_ibmtape.c | 20 +++++++++---------- 3 files changed, 17 insertions(+), 16 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 c3c691b0..1916fa62 100644 --- a/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c +++ b/src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c @@ -1541,8 +1541,8 @@ int lin_tape_ibmtape_write(void *device, const char *buf, size_t count, struct t rc = DEVICE_GOOD; } } else if (errno == ENOMEM && retry < MAX_WRITE_RETRY) { - sleep(3); // Wait for kernel GC ltfsmsg(LTFS_WARN, 30440W, ++retry); + sleep(3); // Wait for kernel GC rc = _handle_block_write_failure(device, pos); if (rc == WRITE_RETRY) { errno = 0; diff --git a/src/tape_drivers/linux/sg/sg_tape.c b/src/tape_drivers/linux/sg/sg_tape.c index 75128ff9..6ba88f35 100644 --- a/src/tape_drivers/linux/sg/sg_tape.c +++ b/src/tape_drivers/linux/sg/sg_tape.c @@ -1982,8 +1982,8 @@ int sg_read(void *device, char *buf, size_t size, priv->use_sili = false; ret = _cdb_read(device, buf, datacount, unusual_size); } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - sleep(3); // Wait for kernel GC ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + sleep(3); // Wait for kernel GC ret = _handle_block_write_failure(device, pos, "read"); if (ret == -EDEV_RETRY) goto start_read; @@ -2146,8 +2146,8 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po ret = -EDEV_POR_OR_BUS_RESET; } } else if (ret_write == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - sleep(3); // Wait for kernel GC ltfsmsg(LTFS_WARN, 30277W, ++retry_count); + sleep(3); // Wait for kernel GC ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; @@ -2156,9 +2156,10 @@ int sg_write(void *device, const char *buf, size_t count, struct tc_position *po sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_write_failure(device, pos, "write"); - if (ret == -EDEV_RETRY) - goto start_write; + ret = _handle_block_write_failure(device, pos, "write"); + if (ret == -EDEV_RETRY) + goto start_write; + ret_write = DEVICE_GOOD; } } diff --git a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c index 153c2f14..8dfe162d 100644 --- a/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c +++ b/src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c @@ -1427,16 +1427,11 @@ static int _cdb_read(void *device, char *buf, size_t size, bool sili) return length; } -static inline int _handle_block_allocation_failure(void *device, struct tc_position *pos, - int *retry, char *op) +static inline int _handle_block_write_failure(void *device, struct tc_position *pos, char *op) { int ret = 0; struct tc_position tmp_pos = {0, 0}; - /* Sleep 3 secs to wait garbage correction in kernel side and retry */ - ltfsmsg(LTFS_WARN, 30277W, ++(*retry)); - sleep(3); - ret = scsipi_ibmtape_readpos(device, &tmp_pos); if (ret == DEVICE_GOOD && pos->partition == tmp_pos.partition) { if (pos->block == tmp_pos.block) { @@ -1550,7 +1545,9 @@ int scsipi_ibmtape_read(void *device, char *buf, size_t size, priv->use_sili = false; ret = _cdb_read(device, buf, datacount, unusual_size); } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "read"); + ltfsmsg(LTFS_WARN, 30277W, ++(*retry)); + sleep(3); // Wait for kernel GC + ret = _handle_block_write_failure(device, pos, "read"); if (ret == -EDEV_RETRY) goto start_read; } @@ -1706,15 +1703,18 @@ int scsipi_ibmtape_write(void *device, const char *buf, size_t count, struct tc_ ret = -EDEV_POR_OR_BUS_RESET; } } else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) { - ret = _handle_block_allocation_failure(device, pos, &retry_count, "write"); + ltfsmsg(LTFS_WARN, 30277W, ++(*retry)); + sleep(3); // Wait for kernel GC + ret = _handle_block_write_failure(device, pos, "write"); if (ret == -EDEV_RETRY) goto start_write; } else if (ret == -EDEV_HOST_ERROR && por_retry_count < POR_MAX_RETRIES) { + por_retry_count++; sleep(5); ret = _clear_por(priv); if (ret == DEVICE_GOOD) { - ret = _handle_block_allocation_failure(device, pos, &por_retry_count, "write"); - if (ret == -EDEV_RETRY) + ret = _handle_block_write_failure(device, pos, "write"); + if (ret == -EDEV_RETRY) goto start_write; } }