Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions src/tape_drivers/linux/lin_tape/lin_tape_ibmtape.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
ltfsmsg(LTFS_WARN, 30440W, ++retry);
sleep(3); // Wait for kernel GC

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using nanosleep? This does not use signals, such as SIGALRM.

rc = _handle_block_write_failure(device, pos);
if (rc == WRITE_RETRY) {
errno = 0;
goto write_start;
Expand All @@ -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;
Expand Down
46 changes: 29 additions & 17 deletions src/tape_drivers/linux/sg/sg_tape.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
#include <dirent.h>
#include <sys/ioctl.h>

#include "libltfs/ltfs_error.h"
#include "ltfs_copyright.h"
#include "libltfs/ltfslogging.h"
#include "libltfs/fs.h"
Expand Down Expand Up @@ -104,6 +105,7 @@ struct sg_global_data global_data;
#define MAX_RETRY (100)

#define MAX_TAKE_DUMP_ATTEMPTS (10)
#define POR_MAX_RETRIES (3)

/* Forward references (For keep function order to struct tape_ops) */
int sg_readpos(void *device, struct tc_position *pos);
Expand Down Expand Up @@ -604,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;

Expand All @@ -624,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)
Expand Down Expand Up @@ -1861,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) {
Expand Down Expand Up @@ -1984,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");
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;
}
Expand Down Expand Up @@ -2093,12 +2093,12 @@ 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;
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));

Expand Down Expand Up @@ -2128,32 +2128,44 @@ 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
&& pos->block + 1 == cur_pos.block) {
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;
}
} else if (ret == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) {
ret = _handle_block_allocation_failure(device, pos, &retry_count, "write");
} else if (ret_write == -EDEV_BUFFER_ALLOCATE_ERROR && retry_count < MAX_RETRY) {
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;
} else if (ret_write == -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_write_failure(device, pos, "write");
if (ret == -EDEV_RETRY)
goto start_write;
ret_write = DEVICE_GOOD;
}
}

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)
Expand Down
30 changes: 20 additions & 10 deletions src/tape_drivers/netbsd/scsipi-ibmtape/scsipi_ibmtape.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -569,7 +570,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;

Expand All @@ -589,6 +590,7 @@ void _clear_por_raw(const int fd)
}
i++;
}
return ret;
}

/* Forward reference */
Expand Down Expand Up @@ -1425,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) {
Expand Down Expand Up @@ -1548,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;
}
Expand Down Expand Up @@ -1656,7 +1655,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));

Expand Down Expand Up @@ -1704,9 +1703,20 @@ 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_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));
Expand Down
Loading