New "--error-skip-block" option.

This commit is contained in:
Andrew Wood
2023-09-02 01:21:18 +01:00
parent f7ccb79147
commit 14ce832249
13 changed files with 72 additions and 8 deletions
+1
View File
@@ -42,6 +42,7 @@ struct opts_s { /* structure describing run-time options */
unsigned long long size; /* total size of data */
bool no_splice; /* flag set if never to use splice */
unsigned int skip_errors; /* skip read errors counter */
unsigned long long error_skip_block; /* skip block size, 0 for adaptive */
bool stop_at_size; /* set if we stop at "size" bytes */
bool sync_after_write; /* set if we sync after every write */
bool direct_io; /* set if O_DIRECT is to be used */
+1
View File
@@ -93,6 +93,7 @@ struct pvstate_s {
bool null_terminated_lines; /* lines are null-terminated */
bool no_display; /* do nothing other than pipe data */
unsigned int skip_errors; /* skip read errors counter */
unsigned long long error_skip_block; /* skip block size, 0 for adaptive */
bool stop_at_size; /* set if we stop at "size" bytes */
bool sync_after_write; /* set if we sync after every write */
bool direct_io; /* set if O_DIRECT is to be used */
+1
View File
@@ -148,6 +148,7 @@ extern void pv_state_bits_set(pvstate_t, bool);
extern void pv_state_null_terminated_lines_set(pvstate_t, bool);
extern void pv_state_no_display_set(pvstate_t, bool);
extern void pv_state_skip_errors_set(pvstate_t, unsigned int);
extern void pv_state_error_skip_block_set(pvstate_t, unsigned long long);
extern void pv_state_stop_at_size_set(pvstate_t, bool);
extern void pv_state_sync_after_write_set(pvstate_t, bool);
extern void pv_state_direct_io_set(pvstate_t, bool);
+3
View File
@@ -368,6 +368,9 @@ void display_help(void)
{ "-E", "--skip-errors", NULL,
N_("skip read errors in input"),
{ 0, 0, 0, 0} },
{ "-Z", "--error-skip-block", N_("BYTES"),
N_("skip errors in BYTES blocks at a time"),
{ 0, 0, 0, 0} },
{ "-S", "--stop-at-size", NULL,
N_("stop after --size bytes have been transferred"),
{ 0, 0, 0, 0} },
+1
View File
@@ -271,6 +271,7 @@ int main(int argc, char **argv)
pv_state_bits_set(state, opts->bits);
pv_state_null_terminated_lines_set(state, opts->null_terminated_lines);
pv_state_skip_errors_set(state, opts->skip_errors);
pv_state_error_skip_block_set(state, opts->error_skip_block);
pv_state_stop_at_size_set(state, opts->stop_at_size);
pv_state_sync_after_write_set(state, opts->sync_after_write);
pv_state_direct_io_set(state, opts->direct_io);
+11 -1
View File
@@ -169,6 +169,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
{ "buffer-size", 1, NULL, (int) 'B' },
{ "no-splice", 0, NULL, (int) 'C' },
{ "skip-errors", 0, NULL, (int) 'E' },
{ "error-skip-block", 1, NULL, (int) 'Z' },
{ "stop-at-size", 0, NULL, (int) 'S' },
{ "sync", 0, NULL, (int) 'Y' },
{ "direct-io", 0, NULL, (int) 'K' },
@@ -185,7 +186,7 @@ opts_t opts_parse(unsigned int argc, char **argv)
/*@+nullassign@ */
int option_index = 0;
#endif /* HAVE_GETOPT_LONG */
char *short_options = "hVpteIrab8TA:fnqcWD:s:l0i:w:H:N:F:L:B:CESYKXR:P:d:m:"
char *short_options = "hVpteIrab8TA:fnqcWD:s:l0i:w:H:N:F:L:B:CEZ:SYKXR:P:d:m:"
#ifdef ENABLE_DEBUGGING
"!:"
#endif
@@ -281,6 +282,8 @@ opts_t opts_parse(unsigned int argc, char **argv)
case 'R':
/*@fallthrough@ */
case 'm':
/*@fallthrough@ */
case 'Z':
if (pv_getnum_check(optarg, PV_NUMTYPE_INTEGER) != 0) {
/*@-mustfreefresh@ *//* see above */
fprintf(stderr, "%s: -%c: %s\n", opts->program_name, c, _("integer argument expected"));
@@ -461,6 +464,9 @@ opts_t opts_parse(unsigned int argc, char **argv)
case 'E':
opts->skip_errors++;
break;
case 'Z':
opts->error_skip_block = pv_getnum_ull(optarg);
break;
case 'S':
opts->stop_at_size = true;
break;
@@ -605,6 +611,10 @@ opts_t opts_parse(unsigned int argc, char **argv)
opts->bytes = true;
}
/* If -Z was given but not -E, pretend one -E was given too. */
if (opts->error_skip_block > 0 && 0 == opts->skip_errors)
opts->skip_errors = 1;
/*
* Store remaining command-line arguments.
*/
+5
View File
@@ -207,6 +207,11 @@ void pv_state_skip_errors_set(pvstate_t state, unsigned int val)
state->skip_errors = val;
};
void pv_state_error_skip_block_set(pvstate_t state, unsigned long long val)
{
state->error_skip_block = val;
}
void pv_state_stop_at_size_set(pvstate_t state, bool val)
{
state->stop_at_size = val;
+15 -6
View File
@@ -402,12 +402,21 @@ static int pv__transfer_read(pvstate_t state, int fd, int *eof_in, int *eof_out,
return 1;
}
if (state->read_errors_in_a_row < 10) {
amount_to_skip = state->read_errors_in_a_row < 5 ? 1 : 2;
} else if (state->read_errors_in_a_row < 20) {
amount_to_skip = 1 << (state->read_errors_in_a_row - 10);
} else {
amount_to_skip = 512;
/*
* If a non-zero error skip block size was given, just use that,
* otherwise start small and ramp up based on the number of errors
* in a row.
*/
if (state->error_skip_block > 0) {
amount_to_skip = state->error_skip_block;
} else {
if (state->read_errors_in_a_row < 10) {
amount_to_skip = state->read_errors_in_a_row < 5 ? 1 : 2;
} else if (state->read_errors_in_a_row < 20) {
amount_to_skip = 1 << (state->read_errors_in_a_row - 10);
} else {
amount_to_skip = 512;
}
}
/*