2026-04-02 16:00:27 +02:00
// SPDX-License-Identifier: GPL-3.0-or-later
2026-04-02 16:25:49 +02:00
// Copyright (C) 2011 Andrea Mazzoleni
2011-04-08 22:32:40 +02:00
2026-06-24 00:15:15 +02:00
# include "os/portable.h"
2011-04-08 22:32:40 +02:00
# include "util.h"
# include "elem.h"
# include "state.h"
# include "parity.h"
# include "handle.h"
2016-01-05 15:35:57 +01:00
# include "io.h"
2016-01-20 21:30:00 +01:00
# include "raid/raid.h"
2011-04-08 22:32:40 +02:00
/****************************************************************************/
/* dry */
2026-01-24 19:19:11 +01:00
static const char * es ( int err )
{
2026-02-22 14:58:06 +01:00
if ( is_hw ( err ) )
2026-01-24 19:19:11 +01:00
return " error_io " ;
else
return " error " ;
}
2016-01-05 15:35:57 +01:00
static void dry_data_reader ( struct snapraid_worker * worker , struct snapraid_task * task )
{
struct snapraid_io * io = worker - > io ;
struct snapraid_state * state = io - > state ;
struct snapraid_handle * handle = worker - > handle ;
struct snapraid_disk * disk = handle - > disk ;
block_off_t blockcur = task - > position ;
unsigned char * buffer = task - > buffer ;
int ret ;
/* if the disk position is not used */
if ( ! disk ) {
/* use an empty block */
memset ( buffer , 0 , state - > block_size ) ;
task - > state = TASK_STATE_DONE ;
return ;
}
/* get the block */
2016-01-16 14:26:05 +01:00
task - > block = fs_par2block_find ( disk , blockcur ) ;
2016-01-05 15:35:57 +01:00
/* if the block is not used */
if ( ! block_has_file ( task - > block ) ) {
/* use an empty block */
memset ( buffer , 0 , state - > block_size ) ;
task - > state = TASK_STATE_DONE ;
return ;
}
/* get the file of this block */
task - > file = fs_par2file_get ( disk , blockcur , & task - > file_pos ) ;
/* if the file is different than the current one, close it */
if ( handle - > file ! = 0 & & handle - > file ! = task - > file ) {
/* keep a pointer at the file we are going to close for error reporting */
struct snapraid_file * report = handle - > file ;
ret = handle_close ( handle ) ;
if ( ret = = - 1 ) {
/* LCOV_EXCL_START */
2026-07-06 22:31:11 +02:00
2026-04-27 15:43:06 +02:00
/*
* This one is really an unexpected error , because we are only reading
* and closing a descriptor should never fail
*/
2026-09-23 16:25:32 +02:00
log_tag ( " %s::%s:%s: Close error. %s. \n " , es ( errno ) , disk - > name , esc_tag ( report - > sub ) , strerror ( errno ) ) ;
2026-01-24 19:19:11 +01:00
log_fatal_errno ( errno , disk - > name ) ;
2026-06-03 23:06:27 +02:00
log_fatal ( errno , " Stopping at block % " PRIu64 " \n " , blockcur ) ;
2026-01-24 19:19:11 +01:00
2026-02-22 14:58:06 +01:00
if ( is_hw ( errno ) ) {
2016-01-05 15:35:57 +01:00
task - > state = TASK_STATE_IOERROR ;
2026-01-24 19:19:11 +01:00
} else {
task - > state = TASK_STATE_ERROR ;
2016-01-05 15:35:57 +01:00
}
return ;
/* LCOV_EXCL_STOP */
}
}
2026-06-03 20:49:36 +02:00
ret = handle_open ( handle , task - > file , state - > file_mode , 0 ) ;
2016-01-05 15:35:57 +01:00
if ( ret = = - 1 ) {
2026-06-03 23:06:27 +02:00
log_tag ( " %s:% " PRIu64 " :%s:%s: Open error. %s. \n " , es ( errno ) , blockcur , disk - > name , esc_tag ( task - > file - > sub ) , strerror ( errno ) ) ;
2026-02-22 14:58:06 +01:00
if ( is_hw ( errno ) ) {
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_START */
log_fatal_errno ( errno , disk - > name ) ;
2026-06-03 23:06:27 +02:00
log_fatal ( errno , " Stopping at block % " PRIu64 " \n " , blockcur ) ;
2016-01-05 15:35:57 +01:00
task - > state = TASK_STATE_IOERROR ;
return ;
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
task - > state = TASK_STATE_ERROR_CONTINUE ;
return ;
}
2026-06-03 20:49:36 +02:00
task - > read_size = handle_read ( handle , task - > file_pos , buffer , state - > block_size , 0 ) ;
2016-01-05 15:35:57 +01:00
if ( task - > read_size = = - 1 ) {
2026-06-03 23:06:27 +02:00
log_tag ( " %s:% " PRIu64 " :%s:%s: Read error at position % " PRIu64 " . %s. \n " , es ( errno ) , blockcur , disk - > name , esc_tag ( task - > file - > sub ) , task - > file_pos , strerror ( errno ) ) ;
2026-02-22 14:58:06 +01:00
if ( is_hw ( errno ) ) {
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_START */
2026-05-30 17:54:31 +02:00
log_fatal_errno ( errno , disk - > name ) ;
2016-01-05 15:35:57 +01:00
task - > state = TASK_STATE_IOERROR_CONTINUE ;
return ;
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
task - > state = TASK_STATE_ERROR_CONTINUE ;
return ;
}
/* store the path of the opened file */
pathcpy ( task - > path , sizeof ( task - > path ) , handle - > path ) ;
task - > state = TASK_STATE_DONE ;
}
static void dry_parity_reader ( struct snapraid_worker * worker , struct snapraid_task * task )
{
struct snapraid_io * io = worker - > io ;
struct snapraid_state * state = io - > state ;
struct snapraid_parity_handle * parity_handle = worker - > parity_handle ;
unsigned level = parity_handle - > level ;
block_off_t blockcur = task - > position ;
unsigned char * buffer = task - > buffer ;
int ret ;
/* read the parity */
2026-06-03 20:49:36 +02:00
ret = parity_read ( parity_handle , blockcur , buffer , state - > block_size ) ;
2016-01-05 15:35:57 +01:00
if ( ret = = - 1 ) {
2026-06-03 23:06:27 +02:00
log_tag ( " parity_%s:% " PRIu64 " :%s: Read error. %s. \n " , es ( errno ) , blockcur , lev_config_name ( level ) , strerror ( errno ) ) ;
2026-02-22 14:58:06 +01:00
if ( is_hw ( errno ) ) {
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_START */
2026-05-30 17:54:31 +02:00
log_fatal_errno ( errno , lev_config_name ( level ) ) ;
2016-01-05 15:35:57 +01:00
task - > state = TASK_STATE_IOERROR_CONTINUE ;
return ;
2026-01-24 19:19:11 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
task - > state = TASK_STATE_ERROR_CONTINUE ;
return ;
}
task - > state = TASK_STATE_DONE ;
}
2016-01-05 15:06:46 +01:00
static int state_dry_process ( struct snapraid_state * state , struct snapraid_parity_handle * parity_handle , block_off_t blockstart , block_off_t blockmax )
2011-04-08 22:32:40 +02:00
{
2016-01-05 15:35:57 +01:00
struct snapraid_io io ;
2011-04-08 22:32:40 +02:00
struct snapraid_handle * handle ;
2011-09-23 21:48:50 +02:00
unsigned diskmax ;
2016-01-05 15:35:57 +01:00
block_off_t blockcur ;
2011-04-08 22:32:40 +02:00
unsigned j ;
2016-01-05 15:35:57 +01:00
unsigned buffermax ;
2011-04-08 22:32:40 +02:00
int ret ;
data_off_t countsize ;
block_off_t countpos ;
block_off_t countmax ;
2026-01-25 21:25:03 +01:00
unsigned soft_error ;
2016-01-05 15:35:57 +01:00
unsigned io_error ;
2013-09-15 21:12:41 +02:00
unsigned l ;
2016-01-20 21:30:00 +01:00
unsigned * waiting_map ;
unsigned waiting_mac ;
2016-01-18 22:38:01 +01:00
handle = handle_mapping ( state , & diskmax ) ;
2011-09-23 21:48:50 +02:00
2016-01-05 15:35:57 +01:00
/* we need 1 * data + 2 * parity */
buffermax = diskmax + 2 * state - > level ;
/* initialize the io threads */
2026-05-21 16:59:57 +02:00
io_init ( & io , state , state - > opt . io_cache , buffermax , handle , diskmax , 0 , dry_data_reader , 0 , parity_handle , state - > level , 0 , dry_parity_reader , 0 ) ;
2011-04-08 22:32:40 +02:00
2016-01-21 18:52:45 +01:00
/* possibly waiting disks */
waiting_mac = diskmax > RAID_PARITY_MAX ? diskmax : RAID_PARITY_MAX ;
2026-07-06 18:38:50 +02:00
waiting_map = nalloc_nofail ( waiting_mac , sizeof ( unsigned ) ) ;
2016-01-20 21:30:00 +01:00
2026-01-25 21:25:03 +01:00
soft_error = 0 ;
2016-01-05 15:35:57 +01:00
io_error = 0 ;
2011-04-08 22:32:40 +02:00
2014-09-08 21:24:11 +02:00
/* drop until now */
state_usage_waste ( state ) ;
2011-04-08 22:32:40 +02:00
countmax = blockmax - blockstart ;
countsize = 0 ;
countpos = 0 ;
2026-05-21 12:49:47 +02:00
blockcur = blockstart ;
2016-01-05 15:35:57 +01:00
2026-02-09 23:49:02 +01:00
int alert = state_progress_begin ( state , blockstart , blockmax , countmax ) ;
if ( alert > 0 )
2025-09-24 11:32:10 +02:00
goto end ;
2026-02-09 23:49:02 +01:00
if ( alert < 0 )
goto bail ;
2025-09-24 11:32:10 +02:00
2026-09-07 10:15:13 +02:00
/* start all the worker threads */
io_start ( & io , blockstart , blockmax , 0 ) ;
2016-01-05 15:35:57 +01:00
while ( 1 ) {
void * * buffer ;
2016-04-10 22:44:40 +02:00
2016-01-05 15:35:57 +01:00
/* go to the next block */
blockcur = io_read_next ( & io , & buffer ) ;
if ( blockcur > = blockmax )
break ;
2016-01-31 16:38:29 +01:00
/* until now is scheduling */
state_usage_sched ( state ) ;
2011-04-08 22:32:40 +02:00
/* for each disk, process the block */
2014-09-27 00:32:39 +02:00
for ( j = 0 ; j < diskmax ; + + j ) {
2016-01-05 15:35:57 +01:00
struct snapraid_task * task ;
2026-06-04 00:34:51 +02:00
ssize_t read_size ;
2015-10-03 10:43:02 +02:00
struct snapraid_block * block ;
2016-01-05 15:35:57 +01:00
struct snapraid_disk * disk ;
unsigned diskcur ;
2011-04-08 22:32:40 +02:00
2016-01-26 23:25:01 +01:00
/* until now is misc */
state_usage_misc ( state ) ;
2014-11-01 18:00:56 +01:00
2016-01-05 15:35:57 +01:00
/* get the next task */
2016-01-20 21:30:00 +01:00
task = io_data_read ( & io , & diskcur , waiting_map , & waiting_mac ) ;
/* until now is disk */
state_usage_disk ( state , handle , waiting_map , waiting_mac ) ;
2013-02-24 19:02:53 +01:00
2016-01-05 15:35:57 +01:00
/* get the task results */
disk = task - > disk ;
block = task - > block ;
read_size = task - > read_size ;
2011-04-08 22:32:40 +02:00
2016-01-05 15:35:57 +01:00
/* if the disk position is not used */
if ( ! disk )
continue ;
2015-09-02 19:44:48 +02:00
2017-11-19 19:33:47 +01:00
state_usage_file ( state , disk , task - > file ) ;
2016-01-05 15:35:57 +01:00
/* if the block is not used */
if ( ! block_has_file ( block ) )
continue ;
2011-04-08 22:32:40 +02:00
2016-01-05 15:35:57 +01:00
/* handle error conditions */
if ( task - > state = = TASK_STATE_IOERROR ) {
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_START */
2016-01-05 15:35:57 +01:00
+ + io_error ;
goto bail ;
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
if ( task - > state = = TASK_STATE_ERROR ) {
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_START */
2026-01-25 21:25:03 +01:00
+ + soft_error ;
2016-01-05 15:35:57 +01:00
goto bail ;
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
if ( task - > state = = TASK_STATE_ERROR_CONTINUE ) {
2026-01-25 21:25:03 +01:00
+ + soft_error ;
2016-01-05 15:35:57 +01:00
continue ;
}
if ( task - > state = = TASK_STATE_IOERROR_CONTINUE ) {
+ + io_error ;
if ( io_error > = state - > opt . io_error_limit ) {
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_START */
2026-02-01 20:21:28 +01:00
log_fatal ( EIO , " DANGER! Too many input/output errors in the %s disk. It isn't possible to continue. \n " , disk - > dir ) ;
2026-06-03 23:06:27 +02:00
log_fatal ( EIO , " Stopping at block % " PRIu64 " \n " , blockcur ) ;
2013-06-15 23:40:58 +02:00
goto bail ;
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_STOP */
2013-06-15 23:40:58 +02:00
}
2011-04-08 22:32:40 +02:00
2016-01-05 15:35:57 +01:00
/* otherwise continue */
2011-04-08 22:32:40 +02:00
continue ;
}
2016-01-05 15:35:57 +01:00
if ( task - > state ! = TASK_STATE_DONE ) {
/* LCOV_EXCL_START */
2026-02-01 20:21:28 +01:00
log_fatal ( EINTERNAL , " Internal inconsistency in task state \n " ) ;
2016-01-05 15:35:57 +01:00
os_abort ( ) ;
/* LCOV_EXCL_STOP */
}
2014-09-08 21:24:11 +02:00
2011-04-08 22:32:40 +02:00
countsize + = read_size ;
}
2016-01-26 23:25:01 +01:00
/* until now is misc */
state_usage_misc ( state ) ;
2016-01-05 15:35:57 +01:00
2011-04-08 22:32:40 +02:00
/* read the parity */
2014-09-27 00:32:39 +02:00
for ( l = 0 ; l < state - > level ; + + l ) {
2016-01-05 15:35:57 +01:00
struct snapraid_task * task ;
unsigned levcur ;
2014-09-08 21:24:11 +02:00
2016-01-20 21:30:00 +01:00
task = io_parity_read ( & io , & levcur , waiting_map , & waiting_mac ) ;
2016-01-05 15:06:46 +01:00
/* until now is parity */
2016-01-20 21:30:00 +01:00
state_usage_parity ( state , waiting_map , waiting_mac ) ;
2016-01-05 15:35:57 +01:00
/* handle error conditions */
if ( task - > state = = TASK_STATE_IOERROR ) {
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_START */
2016-01-05 15:35:57 +01:00
+ + io_error ;
goto bail ;
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
if ( task - > state = = TASK_STATE_ERROR ) {
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_START */
2026-01-25 21:25:03 +01:00
+ + soft_error ;
2016-01-05 15:35:57 +01:00
goto bail ;
2016-11-06 18:27:44 +01:00
/* LCOV_EXCL_STOP */
2016-01-05 15:35:57 +01:00
}
if ( task - > state = = TASK_STATE_ERROR_CONTINUE ) {
2026-01-25 21:25:03 +01:00
+ + soft_error ;
2016-01-05 15:35:57 +01:00
continue ;
}
if ( task - > state = = TASK_STATE_IOERROR_CONTINUE ) {
+ + io_error ;
if ( io_error > = state - > opt . io_error_limit ) {
/* LCOV_EXCL_START */
2026-02-01 20:21:28 +01:00
log_fatal ( EIO , " DANGER! Too many input/output errors in the %s disk. It isn't possible to continue. \n " , lev_name ( levcur ) ) ;
2026-06-03 23:06:27 +02:00
log_fatal ( EIO , " Stopping at block % " PRIu64 " \n " , blockcur ) ;
2016-01-05 15:35:57 +01:00
goto bail ;
/* LCOV_EXCL_STOP */
}
continue ;
}
if ( task - > state ! = TASK_STATE_DONE ) {
/* LCOV_EXCL_START */
2026-02-01 20:21:28 +01:00
log_fatal ( EINTERNAL , " Internal inconsistency in task state \n " ) ;
2016-01-05 15:35:57 +01:00
os_abort ( ) ;
/* LCOV_EXCL_STOP */
}
2013-09-11 23:30:32 +02:00
}
2011-04-08 22:32:40 +02:00
/* count the number of processed block */
+ + countpos ;
/* progress */
2016-01-27 20:37:31 +01:00
if ( state_progress ( state , & io , blockcur , countpos , countmax , countsize ) ) {
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_START */
2011-04-08 22:32:40 +02:00
break ;
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_STOP */
2011-04-08 22:32:40 +02:00
}
2025-09-21 19:54:10 +02:00
/* thermal control */
if ( state_thermal_alarm ( state ) ) {
/* until now is misc */
state_usage_misc ( state ) ;
state_progress_stop ( state ) ;
2026-08-26 19:07:28 +02:00
/* complete all read-ahead without consuming the results */
io_quiesce ( & io ) ;
2025-09-21 19:54:10 +02:00
state_thermal_cooldown ( state ) ;
state_progress_restart ( state ) ;
/* drop until now */
state_usage_waste ( state ) ;
2026-09-06 23:20:21 +02:00
if ( os_signal_interrupt ( ) )
break ;
2025-09-21 19:54:10 +02:00
}
2011-04-08 22:32:40 +02:00
}
2025-09-24 11:32:10 +02:00
end :
2025-10-13 11:46:36 +02:00
state_progress_end ( state , countpos , countmax , countsize , " Nothing to dry. \n " ) ;
2011-04-08 22:32:40 +02:00
2014-09-08 21:24:11 +02:00
state_usage_print ( state ) ;
2011-04-08 22:32:40 +02:00
bail :
2016-01-05 15:35:57 +01:00
/* stop all the worker threads */
io_stop ( & io ) ;
2014-09-27 00:32:39 +02:00
for ( j = 0 ; j < diskmax ; + + j ) {
2015-02-03 18:12:52 +01:00
struct snapraid_file * file = handle [ j ] . file ;
struct snapraid_disk * disk = handle [ j ] . disk ;
2011-04-08 22:32:40 +02:00
ret = handle_close ( & handle [ j ] ) ;
if ( ret = = - 1 ) {
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_START */
2026-07-06 22:31:11 +02:00
/*
* If handle_close fails , the handle was open ( f ! = - 1 ) , which
* guarantees that both file and disk pointers are valid .
*/
2026-09-23 16:25:32 +02:00
log_tag ( " %s::%s:%s: Close error. %s. \n " , es ( errno ) , disk - > name , esc_tag ( file - > sub ) , strerror ( errno ) ) ;
2026-01-24 19:19:11 +01:00
log_fatal_errno ( errno , disk - > name ) ;
2026-02-22 14:58:06 +01:00
if ( is_hw ( errno ) ) {
2026-01-24 19:19:11 +01:00
+ + io_error ;
} else {
2026-01-25 21:25:03 +01:00
+ + soft_error ;
2026-01-24 19:19:11 +01:00
}
2013-06-15 23:40:58 +02:00
/* continue, as we are already exiting */
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_STOP */
2011-04-08 22:32:40 +02:00
}
}
2026-01-25 21:25:03 +01:00
if ( soft_error | | io_error ) {
2015-02-22 14:31:03 +01:00
msg_status ( " \n " ) ;
2026-01-25 21:25:03 +01:00
msg_status ( " %8u soft errors \n " , soft_error ) ;
2016-01-05 15:35:57 +01:00
msg_status ( " %8u io errors \n " , io_error ) ;
2011-04-08 22:32:40 +02:00
}
2026-01-25 21:25:03 +01:00
if ( soft_error )
2026-02-01 20:21:28 +01:00
log_fatal ( ESOFT , " DANGER! Unexpected errors! \n " ) ;
2016-01-05 15:35:57 +01:00
if ( io_error )
2026-02-01 20:21:28 +01:00
log_fatal ( EIO , " DANGER! Unexpected input/output errors! \n " ) ;
2015-02-22 14:31:03 +01:00
2026-01-25 21:25:03 +01:00
log_tag ( " summary:error_soft:%u \n " , soft_error ) ;
2026-01-24 19:19:11 +01:00
log_tag ( " summary:error_io:%u \n " , io_error ) ;
2026-01-25 21:25:03 +01:00
if ( soft_error + io_error = = 0 )
2026-01-24 19:19:11 +01:00
log_tag ( " summary:exit:ok \n " ) ;
else
log_tag ( " summary:exit:error \n " ) ;
log_flush ( ) ;
2011-04-08 22:32:40 +02:00
free ( handle ) ;
2016-01-20 21:30:00 +01:00
free ( waiting_map ) ;
2016-01-05 15:35:57 +01:00
io_done ( & io ) ;
2011-04-08 22:32:40 +02:00
2026-01-25 21:25:03 +01:00
if ( soft_error + io_error ! = 0 )
2011-04-08 22:32:40 +02:00
return - 1 ;
2026-02-09 23:49:02 +01:00
if ( alert < 0 )
return - 1 ;
2011-04-08 22:32:40 +02:00
return 0 ;
}
2025-10-17 08:49:11 +02:00
int state_dry ( struct snapraid_state * state , block_off_t blockstart , block_off_t blockcount )
2011-04-08 22:32:40 +02:00
{
block_off_t blockmax ;
int ret ;
2016-01-05 15:06:46 +01:00
struct snapraid_parity_handle parity_handle [ LEV_MAX ] ;
2026-01-25 21:25:03 +01:00
unsigned process_error ;
2013-09-15 21:12:41 +02:00
unsigned l ;
2011-04-08 22:32:40 +02:00
2015-02-22 14:31:03 +01:00
msg_progress ( " Drying... \n " ) ;
2011-04-08 22:32:40 +02:00
2015-02-01 18:48:50 +01:00
blockmax = parity_allocated_size ( state ) ;
2011-04-08 22:32:40 +02:00
if ( blockstart > blockmax ) {
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_START */
2026-06-03 23:06:27 +02:00
log_fatal ( EUSER , " Error in the specified starting block % " PRIu64 " . It's larger than the parity size % " PRIu64 " . \n " , blockstart , blockmax ) ;
2011-04-08 22:32:40 +02:00
exit ( EXIT_FAILURE ) ;
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_STOP */
2011-04-08 22:32:40 +02:00
}
/* adjust the number of block to process */
2026-06-03 19:00:24 +02:00
if ( blockcount ! = 0 & & blockcount < blockmax - blockstart ) {
2011-04-08 22:32:40 +02:00
blockmax = blockstart + blockcount ;
}
2026-04-27 15:43:06 +02:00
/*
* Open the file for reading
* it may fail if the file doesn ' t exist , in this case we continue to dry the files
*/
2014-09-27 00:32:39 +02:00
for ( l = 0 ; l < state - > level ; + + l ) {
2016-09-28 20:32:50 +02:00
ret = parity_open ( & parity_handle [ l ] , & state - > parity [ l ] , l , state - > file_mode , state - > block_size , state - > opt . parity_limit_size ) ;
2011-10-09 07:51:25 +02:00
if ( ret = = - 1 ) {
2016-01-05 15:06:46 +01:00
/* LCOV_EXCL_START */
2026-09-23 16:25:32 +02:00
log_tag ( " parity_%s:%u:%s: Open error. %s. \n " , es ( errno ) , 0 , lev_config_name ( l ) , strerror ( errno ) ) ;
2026-01-24 19:19:11 +01:00
log_fatal_errno ( errno , lev_config_name ( l ) ) ;
2016-01-05 15:06:46 +01:00
exit ( EXIT_FAILURE ) ;
/* LCOV_EXCL_STOP */
2011-04-23 21:38:26 +02:00
}
2013-09-11 23:30:32 +02:00
}
2026-01-25 21:25:03 +01:00
process_error = 0 ;
2011-04-08 22:32:40 +02:00
/* skip degenerated cases of empty parity, or skipping all */
if ( blockstart < blockmax ) {
2016-01-05 15:06:46 +01:00
ret = state_dry_process ( state , parity_handle , blockstart , blockmax ) ;
2011-04-08 22:32:40 +02:00
if ( ret = = - 1 ) {
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_START */
2026-01-25 21:25:03 +01:00
+ + process_error ;
2011-04-08 22:32:40 +02:00
/* continue, as we are already exiting */
2014-02-03 22:40:51 +01:00
/* LCOV_EXCL_STOP */
2011-04-08 22:32:40 +02:00
}
}
/* try to close only if opened */
2014-09-27 00:32:39 +02:00
for ( l = 0 ; l < state - > level ; + + l ) {
2016-01-05 15:06:46 +01:00
ret = parity_close ( & parity_handle [ l ] ) ;
if ( ret = = - 1 ) {
/* LCOV_EXCL_START */
2026-09-23 16:25:32 +02:00
log_tag ( " parity_%s::%s: Close error. %s. \n " , es ( errno ) , lev_config_name ( l ) , strerror ( errno ) ) ;
2026-01-24 19:19:11 +01:00
log_fatal_errno ( errno , lev_config_name ( l ) ) ;
2026-01-25 21:25:03 +01:00
+ + process_error ;
2016-01-05 15:06:46 +01:00
/* continue, as we are already exiting */
/* LCOV_EXCL_STOP */
2013-09-11 23:30:32 +02:00
}
}
2026-01-25 21:25:03 +01:00
if ( process_error ! = 0 )
2025-10-17 08:49:11 +02:00
return - 1 ;
2026-08-14 01:18:03 +02:00
2026-09-20 15:56:14 +02:00
if ( log_hardware_errors ( ) ! = 0 ) {
msg_status ( " Everything done, but hardware errors were encountered in the process \n " ) ;
return - 1 ;
}
2026-08-14 01:18:03 +02:00
msg_status ( " Everything OK \n " ) ;
2025-10-17 08:49:11 +02:00
return 0 ;
2011-04-08 22:32:40 +02:00
}