LCOV - code coverage report
Current view: top level - cmdline - status.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 265 275 96.4 %
Date: 2026-04-29 15:04:44 Functions: 2 2 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-3.0-or-later
       2             : // Copyright (C) 2013 Andrea Mazzoleni
       3             : 
       4             : #include "portable.h"
       5             : 
       6             : #include "support.h"
       7             : #include "elem.h"
       8             : #include "state.h"
       9             : #include "parity.h"
      10             : #include "handle.h"
      11             : #include "raid/raid.h"
      12             : 
      13             : /****************************************************************************/
      14             : /* status */
      15             : 
      16          33 : unsigned day_ago(time_t ref, time_t now)
      17             : {
      18             :         /* in case some dates is in the future */
      19          33 :         if (now < ref)
      20           0 :                 return 0;
      21             : 
      22          33 :         return (now - ref) / (24 * 3600);
      23             : }
      24             : 
      25             : #define GRAPH_COLUMN 70
      26             : #define GRAPH_ROW 15
      27             : 
      28             : /**
      29             :  * Bit used to mark unscrubbed time info.
      30             :  */
      31             : #define TIME_NEW 1
      32             : 
      33          17 : int state_status(struct snapraid_state* state)
      34             : {
      35             :         char esc_buffer[ESC_MAX];
      36             :         block_off_t blockmax;
      37             :         block_off_t i;
      38             :         time_t now;
      39             :         block_off_t count;
      40             :         unsigned l;
      41             :         unsigned dayoldest, daymedian, daynewest;
      42             :         unsigned bar_scrubbed[GRAPH_COLUMN];
      43             :         unsigned bar_new[GRAPH_COLUMN];
      44             :         unsigned barmax;
      45             :         time_t oldest, newest, median;
      46             :         unsigned x, y;
      47             :         tommy_node* node_disk;
      48             :         unsigned file_count;
      49             :         unsigned file_fragmented;
      50             :         unsigned extra_fragment;
      51             :         unsigned file_zerosubsecond;
      52             :         uint64_t file_size;
      53             :         uint64_t file_block_count;
      54             :         uint64_t file_block_free;
      55             :         unsigned dealloc_count;
      56             :         block_off_t parity_block_free;
      57             :         uint64_t all_wasted;
      58             :         int free_not_zero;
      59             : 
      60             :         /* get the present time */
      61          17 :         now = time(0);
      62             : 
      63             :         /* keep track if at least a free info is available */
      64          17 :         free_not_zero = 0;
      65             : 
      66          17 :         blockmax = parity_allocated_size(state);
      67             : 
      68          17 :         log_tag("summary:block_size:%u\n", state->block_size);
      69          17 :         log_tag("summary:parity_block_count:%u\n", blockmax);
      70             : 
      71             :         /* get the minimum parity free space */
      72          17 :         parity_block_free = state->parity[0].free_blocks;
      73         109 :         for (l = 0; l < state->level; ++l) {
      74          92 :                 log_tag("summary:parity_block_total:%s:%u\n", lev_config_name(l), state->parity[l].total_blocks);
      75          92 :                 log_tag("summary:parity_block_free:%s:%u\n", lev_config_name(l), state->parity[l].free_blocks);
      76          92 :                 if (state->parity[l].free_blocks < parity_block_free)
      77           1 :                         parity_block_free = state->parity[l].free_blocks;
      78          92 :                 if (state->parity[l].free_blocks != 0)
      79          81 :                         free_not_zero = 1;
      80             :         }
      81          17 :         log_tag("summary:parity_block_free_min:%u\n", parity_block_free);
      82             : 
      83          17 :         printf("SnapRAID status report:\n");
      84          17 :         printf("\n");
      85          17 :         printf("   Files Fragmented Excess  Wasted  Used    Free  Use Name\n");
      86          17 :         printf("            Files  Fragments  GB      GB      GB\n");
      87             : 
      88             :         /* count fragments */
      89          17 :         dealloc_count = 0;
      90          17 :         file_count = 0;
      91          17 :         file_size = 0;
      92          17 :         file_block_count = 0;
      93          17 :         file_block_free = 0;
      94          17 :         file_fragmented = 0;
      95          17 :         extra_fragment = 0;
      96          17 :         file_zerosubsecond = 0;
      97          17 :         all_wasted = 0;
      98         113 :         for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
      99          96 :                 struct snapraid_disk* disk = node_disk->data;
     100             :                 tommy_node* node;
     101             :                 block_off_t j;
     102          96 :                 unsigned disk_file_count = 0;
     103          96 :                 unsigned disk_file_fragmented = 0;
     104          96 :                 unsigned disk_extra_fragment = 0;
     105          96 :                 unsigned disk_file_zerosubsecond = 0;
     106          96 :                 block_off_t disk_block_count = 0;
     107          96 :                 uint64_t disk_file_size = 0;
     108          96 :                 block_off_t disk_block_latest_used = 0;
     109             :                 block_off_t disk_block_max_by_space;
     110             :                 block_off_t disk_block_max_by_parity;
     111             :                 block_off_t disk_block_max;
     112             :                 uint64_t disk_used_bytes;
     113             :                 uint64_t disk_free_bytes;
     114             :                 int64_t wasted;
     115             : 
     116          96 :                 dealloc_count += tommy_list_count(&disk->dealloclist);
     117             : 
     118             :                 /* for each file in the disk */
     119          96 :                 node = disk->filelist;
     120      100637 :                 while (node) {
     121             :                         struct snapraid_file* file;
     122             : 
     123      100541 :                         file = node->data;
     124      100541 :                         node = node->next; /* next node */
     125             : 
     126      100541 :                         if (file->mtime_nsec == STAT_NSEC_INVALID
     127      100541 :                                 || file->mtime_nsec == 0
     128             :                         ) {
     129           0 :                                 ++file_zerosubsecond;
     130           0 :                                 ++disk_file_zerosubsecond;
     131           0 :                                 if (disk_file_zerosubsecond < 50)
     132           0 :                                         log_tag("zerosubsecond:%s:%s: \n", disk->name, file->sub);
     133           0 :                                 if (disk_file_zerosubsecond == 50)
     134           0 :                                         log_tag("zerosubsecond:%s:%s: (more follow)\n", disk->name, file->sub);
     135             :                         }
     136             : 
     137             :                         /* check fragmentation */
     138      100541 :                         if (file->blockmax != 0) {
     139             :                                 block_off_t prev_pos;
     140             :                                 block_off_t last_pos;
     141             :                                 int fragmented;
     142             : 
     143      100398 :                                 fragmented = 0;
     144      100398 :                                 prev_pos = fs_file2par_get(disk, file, 0);
     145      240698 :                                 for (j = 1; j < file->blockmax; ++j) {
     146      140300 :                                         block_off_t parity_pos = fs_file2par_get(disk, file, j);
     147      140300 :                                         if (prev_pos + 1 != parity_pos) {
     148         713 :                                                 fragmented = 1;
     149         713 :                                                 ++extra_fragment;
     150         713 :                                                 ++disk_extra_fragment;
     151             :                                         }
     152      140300 :                                         prev_pos = parity_pos;
     153             :                                 }
     154             : 
     155             :                                 /* keep track of latest block used */
     156      100398 :                                 last_pos = fs_file2par_get(disk, file, file->blockmax - 1);
     157      100398 :                                 if (last_pos > disk_block_latest_used) {
     158       96495 :                                         disk_block_latest_used = last_pos;
     159             :                                 }
     160             : 
     161      100398 :                                 if (fragmented) {
     162         593 :                                         ++file_fragmented;
     163         593 :                                         ++disk_file_fragmented;
     164             :                                 }
     165             : 
     166      100398 :                                 disk_block_count += file->blockmax;
     167             :                         }
     168             : 
     169             :                         /* count files */
     170      100541 :                         ++file_count;
     171      100541 :                         ++disk_file_count;
     172      100541 :                         file_size += file->size;
     173      100541 :                         file_block_count += file->blockmax;
     174      100541 :                         disk_file_size += file->size;
     175             :                 }
     176             : 
     177          96 :                 if (disk->free_blocks != 0)
     178          59 :                         free_not_zero = 1;
     179             : 
     180             :                 /* get the free block info */
     181          96 :                 disk_block_max_by_space = disk_block_count + disk->free_blocks;
     182          96 :                 disk_block_max_by_parity = blockmax + parity_block_free;
     183             : 
     184             :                 /*
     185             :                  * The maximum usable space in a disk is limited by the smallest
     186             :                  * of the disk size and the parity size
     187             :                  * the wasted space is the space that we have to leave
     188             :                  * free on the data disk, when the parity is filled up
     189             :                  */
     190          96 :                 if (disk_block_max_by_space < disk_block_max_by_parity) {
     191          84 :                         disk_block_max = disk_block_max_by_space;
     192             :                 } else {
     193          12 :                         disk_block_max = disk_block_max_by_parity;
     194             :                 }
     195             : 
     196             :                 /*
     197             :                  * Wasted space is the difference of the two maximum size
     198             :                  * if negative, it's extra space available in parity
     199             :                  */
     200          96 :                 wasted = (int64_t)disk_block_max_by_space - (int64_t)disk_block_max_by_parity;
     201          96 :                 wasted *= state->block_size;
     202             : 
     203          96 :                 if (wasted > 0)
     204           6 :                         all_wasted += wasted;
     205          96 :                 file_block_free += disk_block_max - disk_block_count;
     206             : 
     207          96 :                 printf("%8u", disk_file_count);
     208          96 :                 printf("%8u", disk_file_fragmented);
     209          96 :                 printf("%8u", disk_extra_fragment);
     210          96 :                 if (wasted < -100LL * GIGA) {
     211          84 :                         printf("       -");
     212             :                 } else {
     213          12 :                         printf("%8.1f", (double)wasted / GIGA);
     214             :                 }
     215          96 :                 printf("%8" PRIu64, disk_file_size / GIGA);
     216             : 
     217          96 :                 if (disk_block_max == 0 && disk_block_count == 0) {
     218             :                         /* if the disk is empty and we don't have the free space info */
     219          37 :                         printf("       -");
     220          37 :                         printf("   - ");
     221             :                 } else {
     222          59 :                         printf("%8" PRIu64, (disk_block_max - disk_block_count) * (uint64_t)state->block_size / GIGA);
     223          59 :                         printf(" %3u%%", muldiv(disk_block_count, 100, disk_block_max));
     224             :                 }
     225          96 :                 printf(" %s\n", disk->name);
     226             : 
     227          96 :                 log_tag("summary:disk_file_count:%s:%u\n", disk->name, disk_file_count);
     228          96 :                 log_tag("summary:disk_block_count:%s:%u\n", disk->name, disk_block_count);
     229          96 :                 log_tag("summary:disk_fragmented_file_count:%s:%u\n", disk->name, disk_file_fragmented);
     230          96 :                 log_tag("summary:disk_excess_fragment_count:%s:%u\n", disk->name, disk_extra_fragment);
     231          96 :                 log_tag("summary:disk_zerosubsecond_file_count:%s:%u\n", disk->name, disk_file_zerosubsecond);
     232          96 :                 log_tag("summary:disk_file_size:%s:%" PRIu64 "\n", disk->name, disk_file_size);
     233          96 :                 log_tag("summary:disk_block_allocated:%s:%u\n", disk->name, disk_block_latest_used + 1);
     234          96 :                 log_tag("summary:disk_block_total:%s:%u\n", disk->name, disk->total_blocks);
     235          96 :                 log_tag("summary:disk_block_free:%s:%u\n", disk->name, disk->free_blocks);
     236          96 :                 log_tag("summary:disk_block_max_by_space:%s:%u\n", disk->name, disk_block_max_by_space);
     237          96 :                 log_tag("summary:disk_block_max_by_parity:%s:%u\n", disk->name, disk_block_max_by_parity);
     238          96 :                 log_tag("summary:disk_block_max:%s:%u\n", disk->name, disk_block_max);
     239          96 :                 log_tag("summary:disk_space_wasted:%s:%" PRId64 "\n", disk->name, wasted);
     240             : 
     241          96 :                 disk_used_bytes = disk_block_count * (uint64_t)state->block_size;
     242          96 :                 disk_free_bytes = (disk_block_max - disk_block_count) * (uint64_t)state->block_size;
     243          96 :                 log_tag("summary:disk_used:%s:%" PRIu64 "\n", disk->name, disk_used_bytes);
     244          96 :                 log_tag("summary:disk_free:%s:%" PRIu64 "\n", disk->name, disk_free_bytes);
     245          96 :                 log_tag("summary:disk_use_percent:%s:%u\n", disk->name, muldiv(disk_block_count, 100, disk_block_max));
     246             :         }
     247             : 
     248             :         /* totals */
     249          17 :         printf(" --------------------------------------------------------------------------\n");
     250          17 :         printf("%8u", file_count);
     251          17 :         printf("%8u", file_fragmented);
     252          17 :         printf("%8u", extra_fragment);
     253          17 :         printf("%8.1f", (double)all_wasted / GIGA);
     254          17 :         printf("%8" PRIu64, file_size / GIGA);
     255          17 :         printf("%8" PRIu64, file_block_free * state->block_size / GIGA);
     256          17 :         printf(" %3u%%", muldiv(file_block_count, 100, file_block_count + file_block_free));
     257          17 :         printf("\n");
     258             : 
     259             :         /* warn about invalid data free info */
     260          17 :         if (!free_not_zero)
     261           1 :                 printf("\nWARNING! Free space info will be valid after the first sync.\n");
     262             : 
     263          17 :         log_tag("summary:file_count:%u\n", file_count);
     264          17 :         log_tag("summary:file_block_count:%" PRIu64 "\n", file_block_count);
     265          17 :         log_tag("summary:fragmented_file_count:%u\n", file_fragmented);
     266          17 :         log_tag("summary:excess_fragment_count:%u\n", extra_fragment);
     267          17 :         log_tag("summary:zerosubsecond_file_count:%u\n", file_zerosubsecond);
     268          17 :         log_tag("summary:file_size:%" PRIu64 "\n", file_size);
     269          17 :         log_tag("summary:parity_size:%" PRIu64 "\n", blockmax * (uint64_t)state->block_size);
     270          17 :         log_tag("summary:parity_size_max:%" PRIu64 "\n", (blockmax + parity_block_free) * (uint64_t)state->block_size);
     271          17 :         log_tag("summary:hash:%s\n", hash_config_name(state->hash));
     272          17 :         log_tag("summary:prev_hash:%s\n", hash_config_name(state->prevhash));
     273          17 :         log_tag("summary:best_hash:%s\n", hash_config_name(state->besthash));
     274          17 :         log_tag("summary:total_wasted:%" PRIu64 "\n", all_wasted);
     275          17 :         log_tag("summary:total_used:%" PRIu64 "\n", file_size);
     276          17 :         log_tag("summary:total_free:%" PRIu64 "\n", file_block_free * state->block_size);
     277          17 :         log_tag("summary:total_use_percent:%u\n", muldiv(file_block_count, 100, file_block_count + file_block_free));
     278          17 :         log_flush();
     279             : 
     280          17 :         oldest = 0;
     281          17 :         median = 0;
     282          17 :         newest = 0;
     283          17 :         count = 0;
     284          38 :         for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) {
     285          21 :                 struct snapraid_bucket* bucket = j->data;
     286          21 :                 block_off_t bucket_count = bucket->count_scrubbed + bucket->count_justsynced;
     287             : 
     288          21 :                 if (count == 0)
     289          11 :                         oldest = bucket->time_at;
     290          21 :                 if (count < state->bucketcount / 2)
     291          17 :                         median = bucket->time_at;
     292          21 :                 newest = bucket->time_at;
     293             : 
     294          21 :                 count += bucket_count;
     295             :         }
     296             : 
     297          17 :         if (!count) {
     298           6 :                 log_fatal(EUSER, "The array is empty.\n");
     299           6 :                 return 0;
     300             :         }
     301             : 
     302          11 :         dayoldest = day_ago(oldest, now);
     303          11 :         daymedian = day_ago(median, now);
     304          11 :         daynewest = day_ago(newest, now);
     305             : 
     306          11 :         log_tag("summary:scrub_oldest_days:%u\n", dayoldest);
     307          11 :         log_tag("summary:scrub_median_days:%u\n", daymedian);
     308          11 :         log_tag("summary:scrub_newest_days:%u\n", daynewest);
     309             : 
     310             :         /* compute graph limits */
     311          11 :         barmax = 0;
     312          11 :         memset(bar_scrubbed, 0, sizeof(bar_scrubbed));
     313          11 :         memset(bar_new, 0, sizeof(bar_new));
     314          32 :         for (tommy_node* j = tommy_list_head(&state->bucketlist); j != 0; j = j->next) {
     315          21 :                 struct snapraid_bucket* bucket = j->data;
     316             : 
     317          21 :                 unsigned column = muldiv(bucket->time_at - oldest, GRAPH_COLUMN, newest - oldest + 1);
     318             : 
     319          21 :                 bar_scrubbed[column] += bucket->count_scrubbed;
     320          21 :                 bar_new[column] += bucket->count_justsynced;
     321             : 
     322          21 :                 if (bar_scrubbed[column] + bar_new[column] > barmax)
     323          14 :                         barmax = bar_scrubbed[column] + bar_new[column];
     324             :         }
     325             : 
     326             :         /* output scrub history as structured data */
     327          11 :         log_tag("scrub_graph_range:%u:%u\n", GRAPH_COLUMN, barmax);
     328         781 :         for (i = 0; i < GRAPH_COLUMN; ++i) {
     329         770 :                 unsigned days_ago = dayoldest - (dayoldest - daynewest) * i / (GRAPH_COLUMN - 1);
     330         770 :                 log_tag("scrub_graph_bar:%u:%u:%u:%u\n", i, days_ago, bar_scrubbed[i], bar_new[i]);
     331             :         }
     332             : 
     333          11 :         printf("\n\n");
     334             : 
     335             :         /* print the graph */
     336         176 :         for (y = 0; y < GRAPH_ROW; ++y) {
     337         165 :                 if (y == 0)
     338          11 :                         printf("%3u%%|", barmax * 100 / count);
     339         154 :                 else if (y == GRAPH_ROW - 1)
     340          11 :                         printf("  0%%|");
     341         143 :                 else if (y == GRAPH_ROW / 2)
     342          11 :                         printf("%3u%%|", barmax * 50 / count);
     343             :                 else
     344         132 :                         printf("    |");
     345       11715 :                 for (x = 0; x < GRAPH_COLUMN; ++x) {
     346       11550 :                         unsigned pivot_upper = barmax * (GRAPH_ROW - y) / GRAPH_ROW;
     347       11550 :                         unsigned pivot_lower = barmax * (GRAPH_ROW - 1 - y) / GRAPH_ROW;
     348       11550 :                         unsigned both = bar_scrubbed[x] + bar_new[x];
     349       11550 :                         unsigned scrubbed = bar_scrubbed[x];
     350             : 
     351       11550 :                         if (both > pivot_upper) {
     352         178 :                                 if (scrubbed > pivot_lower)
     353          58 :                                         printf("*");
     354             :                                 else
     355         120 :                                         printf("o");
     356       11372 :                         } else if (both > pivot_lower) {
     357          21 :                                 if (scrubbed == both)
     358           5 :                                         printf("*");
     359             :                                 else
     360          16 :                                         printf("o");
     361             :                         } else {
     362       11351 :                                 if (y == GRAPH_ROW - 1)
     363         749 :                                         printf("_");
     364             :                                 else
     365       10602 :                                         printf(" ");
     366             :                         }
     367             :                 }
     368         165 :                 printf("\n");
     369             :         }
     370          11 :         printf("   %3u                    days ago of the last scrub/sync               %3u\n", dayoldest, daynewest);
     371             : 
     372          11 :         printf("\n");
     373             : 
     374          11 :         printf("The oldest block was scrubbed %u days ago, the median %u, the newest %u.\n", dayoldest, daymedian, daynewest);
     375             : 
     376          11 :         printf("\n");
     377             : 
     378          11 :         if (newest > now) {
     379           0 :                 printf("WARNING! You have scrub dates in the future! The next sync/scrub will truncate them!\n");
     380             :         }
     381             : 
     382          11 :         if (state->unsynced_blocks) {
     383           3 :                 printf("WARNING! The array is NOT fully synced.\n");
     384           3 :                 printf("You have a sync in progress at %u%%.\n", muldiv(blockmax - state->unsynced_blocks, 100, blockmax));
     385           3 :                 if (dealloc_count) {
     386           3 :                         printf("WARNING! There are %u files updated or deleted from the array that may reduce the recovery probability until the next sync.\n", dealloc_count);
     387          15 :                         for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
     388          12 :                                 struct snapraid_disk* disk = node_disk->data;
     389        1645 :                                 for (tommy_node* node = tommy_list_head(&disk->dealloclist); node != 0; node = node->next) {
     390        1633 :                                         struct snapraid_dealloc* dealloc = node->data;
     391        1633 :                                         msg_verbose("\t%s\n", fmt_term(disk, dealloc->sub, esc_buffer));
     392             :                                 }
     393             :                         }
     394             :                 }
     395             :         } else {
     396           8 :                 printf("No sync is in progress.\n");
     397             :         }
     398             : 
     399          11 :         if (state->unscrubbed_blocks) {
     400           9 :                 printf("%u%% of the array is not scrubbed.\n", muldiv_upper(state->unscrubbed_blocks, 100, blockmax));
     401             :         } else {
     402           2 :                 printf("The full array was scrubbed at least one time.\n");
     403             :         }
     404             : 
     405          11 :         if (file_zerosubsecond) {
     406           0 :                 printf("You have %u files with a zero sub-second timestamp.\n", file_zerosubsecond);
     407           0 :                 printf("Run 'snapraid touch' to set their sub-second timestamps to a non-zero value.\n");
     408             :         } else {
     409          11 :                 printf("No file has a zero sub-second timestamp.\n");
     410             :         }
     411             : 
     412          11 :         if (state->rehash_blocks) {
     413           1 :                 printf("You have a rehash in progress at %u%%.\n", muldiv(count - state->rehash_blocks, 100, count));
     414             :         } else {
     415          10 :                 if (state->besthash != state->hash) {
     416           7 :                         printf("No rehash is in progress, but for optimal performance one is recommended.\n");
     417             :                 } else {
     418           3 :                         printf("No rehash is in progress or needed.\n");
     419             :                 }
     420             :         }
     421             : 
     422          11 :         if (state->bad_blocks) {
     423           2 :                 printf("DANGER! In the array there are %u errors!\n\n", state->bad_blocks);
     424             : 
     425             :                 block_off_t bad_range;
     426             :                 block_off_t bad_count;
     427             :                 block_off_t range_start;
     428             :                 block_off_t range_count;
     429             : 
     430           2 :                 printf("They are at blocks:");
     431             : 
     432             :                 /* print some of the errors */
     433           2 :                 bad_range = 0;
     434           2 :                 bad_count = 0;
     435           2 :                 range_start = 0;
     436           2 :                 range_count = 0;
     437         870 :                 for (i = 0; i <= blockmax; ++i) { /* one extra iteration to print the final range */
     438         870 :                         snapraid_info info = 0;
     439         870 :                         int is_bad = 0;
     440             : 
     441         870 :                         if (i < blockmax) {
     442         870 :                                 info = info_get(&state->infoarr, i);
     443         870 :                                 if (info != 0) /* unused blocks are never bad */
     444         870 :                                         is_bad = info_get_bad(info);
     445             :                         }
     446         870 :                         if (is_bad) {
     447             :                                 /* create or extend the range */
     448         252 :                                 if (!range_count)
     449         202 :                                         range_start = i;
     450         252 :                                 ++range_count;
     451             :                         } else {
     452             :                                 /* break the range */
     453         618 :                                 if (range_count) {
     454         202 :                                         if (range_count == 1) {
     455         161 :                                                 printf(" %u", range_start);
     456             :                                         } else {
     457          41 :                                                 printf(" %u-%u", range_start, range_start + range_count - 1);
     458             :                                         }
     459         202 :                                         bad_count += range_count;
     460         202 :                                         ++bad_range;
     461         202 :                                         range_count = 0;
     462             :                                 }
     463             :                         }
     464             : 
     465         870 :                         if (bad_range > 100) {
     466           2 :                                 printf(" and %u more...", state->bad_blocks - bad_count);
     467           2 :                                 break;
     468             :                         }
     469             :                 }
     470             : 
     471           2 :                 printf("\n");
     472             : 
     473           2 :                 printf("To fix them use the command 'snapraid -e fix'.\n");
     474           2 :                 printf("The errors will disappear from the 'status' at the next 'scrub' command.\n");
     475             :         } else {
     476           9 :                 printf("No error detected.\n");
     477             :         }
     478             : 
     479          11 :         if (state->bad_blocks)
     480           2 :                 log_tag("summary:exit:bad\n");
     481           9 :         else if (state->unsynced_blocks != 0)
     482           3 :                 log_tag("summary:exit:unsynced\n");
     483             :         else
     484           6 :                 log_tag("summary:exit:ok\n");
     485             : 
     486          11 :         return 0;
     487             : }
     488             : 

Generated by: LCOV version 1.0