btrfs-progs: scrub: improve output of status

Prievous patch added throughput and time left calculatios, but with more
information it becomes less clear. Switch to the output format used in
several other commands that prints header, followed by colon, whitespace
and the value. Grouped values are indented by 2 spaces.

This patch uses the space info that is more accurate than the total
size. The used space is what scrub will check, however the multiplicity
is not yet taken into account, so this works only for the 'single'
profile.

Sample output:

  UUID:             bf8720e0-606b-4065-8320-b48df2e8e669
  Scrub started:    Fri Jun 14 12:00:00 2019
  Status:           running
  Duration:         0:14:11
  Time left:        0:04:04
  ETA:              Fri Jun 14 12:18:15 2019
  Total to scrub:   182.55GiB
  Bytes scrubbed:   141.80GiB
  Rate:             170.63MiB/s
  Error summary:    csum=7
    Corrected:      0
    Uncorrectable:  7
    Unverified:     0

For the reference, this is 'fi df':

  Data, single: total=261.00GiB, used=179.91GiB
  System, single: total=32.00MiB, used=48.00KiB
  Metadata, single: total=5.00GiB, used=2.64GiB
  GlobalReserve, single: total=375.23MiB, used=0.00B

Several repeated runs of scrub showed that the time estimate is very
close to the final time (within tens of seconds).

Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
David Sterba 2019-06-14 20:09:31 +02:00
parent eb37e8212d
commit 0323a6c777

View File

@ -141,6 +141,7 @@ static void print_scrub_summary(struct btrfs_scrub_progress *p, struct scrub_sta
u64 bytes_scrubbed;
u64 bytes_per_sec = 0;
u64 sec_left = 0;
time_t sec_eta;
bytes_scrubbed = p->data_bytes_scrubbed + p->tree_bytes_scrubbed;
if (s->duration > 0)
@ -160,30 +161,41 @@ static void print_scrub_summary(struct btrfs_scrub_progress *p, struct scrub_sta
"results may be inaccurate\n");
if (s->in_progress) {
printf(
"\ttotal %s scrubbed at rate %s/s, time left: %llu:%02llu:%02llu\n",
pretty_size(bytes_scrubbed),
pretty_size(bytes_per_sec),
char t[4096];
struct tm tm;
if (s->t_resumed)
sec_eta = s->t_resumed;
else
sec_eta = s->t_start;
sec_eta += sec_left;
localtime_r(&sec_eta, &tm);
t[sizeof(t) - 1] = '\0';
strftime(t, sizeof(t), "%c", &tm);
printf("Time left: %llu:%02llu:%02llu\n",
sec_left / 3600, (sec_left / 60) % 60, sec_left % 60);
printf("ETA: %s\n", t);
printf("Total to scrub: %s\n", pretty_size(bytes_total));
printf("Bytes scrubbed: %s\n", pretty_size(bytes_scrubbed));
printf("Rate: %s/s\n", pretty_size(bytes_per_sec));
} else {
printf("\ttotal %s scrubbed at rate %s/s\n",
pretty_size(bytes_scrubbed),
pretty_size(bytes_per_sec));
printf("Total to scrub: %s\n", pretty_size(bytes_total));
printf("Rate: %s/s\n", pretty_size(bytes_per_sec));
}
printf("Error summary: ");
if (err_cnt || err_cnt2) {
printf("\terror details:");
PRINT_SCRUB_ERROR(p->read_errors, "read");
PRINT_SCRUB_ERROR(p->super_errors, "super");
PRINT_SCRUB_ERROR(p->verify_errors, "verify");
PRINT_SCRUB_ERROR(p->csum_errors, "csum");
printf("\n");
printf("\tcorrected errors: %llu, uncorrectable errors: %llu, "
"unverified errors: %llu\n", p->corrected_errors,
p->uncorrectable_errors, p->unverified_errors);
printf(" Corrected: %llu\n", p->corrected_errors);
printf(" Uncorrectable: %llu\n", p->uncorrectable_errors);
printf(" Unverified: %llu\n", p->unverified_errors);
} else {
printf("\tno errors found\n");
printf(" no errors found\n");
}
}
@ -258,27 +270,23 @@ static void _print_scrub_ss(struct scrub_stats *ss)
localtime_r(&ss->t_resumed, &tm);
strftime(t, sizeof(t), "%c", &tm);
t[sizeof(t) - 1] = '\0';
printf("\tscrub resumed at %s", t);
printf("Scrub resumed: %s\n", t);
} else {
localtime_r(&ss->t_start, &tm);
strftime(t, sizeof(t), "%c", &tm);
t[sizeof(t) - 1] = '\0';
printf("\tscrub started at %s", t);
printf("Scrub started: %s\n", t);
}
seconds = ss->duration;
hours = ss->duration / (60 * 60);
gmtime_r(&seconds, &tm);
strftime(t, sizeof(t), "%M:%S", &tm);
if (ss->in_progress)
printf(", running for %u:%s\n", hours, t);
else if (ss->canceled)
printf(" and was aborted after %u:%s\n", hours, t);
else if (ss->finished)
printf(" and finished after %u:%s\n", hours, t);
else
printf(", interrupted after %u:%s, not running\n",
hours, t);
printf("Status: %s\n",
(ss->in_progress ? "running" :
(ss->canceled ? "aborted" :
(ss->finished ? "finished" : "interrupted"))));
printf("Duration: %u:%s\n", hours, t);
}
static void print_scrub_dev(struct btrfs_ioctl_dev_info_args *di,
@ -1690,6 +1698,7 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
char *path;
struct btrfs_ioctl_fs_info_args fi_args;
struct btrfs_ioctl_dev_info_args *di_args = NULL;
struct btrfs_ioctl_space_args *si_args = NULL;
struct scrub_file_record **past_scrubs = NULL;
struct scrub_file_record *last_scrub;
struct scrub_fs_stat fs_stat;
@ -1742,6 +1751,13 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
err = 1;
goto out;
}
ret = get_df(fdmnt, &si_args);
if (ret) {
errno = -ret;
error("cannot get space info: %m");
err = 1;
goto out;
}
uuid_unparse(fi_args.fsid, fsid);
@ -1776,7 +1792,7 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
}
in_progress = is_scrub_running_in_kernel(fdmnt, di_args, fi_args.num_devices);
printf("scrub status for %s\n", fsid);
printf("UUID: %s\n", fsid);
if (do_stats_per_dev) {
for (i = 0; i < fi_args.num_devices; ++i) {
@ -1795,6 +1811,7 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
}
} else {
u64 total_bytes_used = 0;
struct btrfs_ioctl_space_info *sp = si_args->spaces;
init_fs_stat(&fs_stat);
fs_stat.s.in_progress = in_progress;
@ -1805,7 +1822,13 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
continue;
add_to_fs_stat(&last_scrub->p, &last_scrub->stats,
&fs_stat);
total_bytes_used += di_args[i].bytes_used;
}
for (i = 0; i < si_args->total_spaces; i++, sp++) {
const int index = btrfs_bg_flags_to_raid_index(sp->flags);
const int factor = btrfs_raid_array[index].ncopies;
/* This is still slightly off for RAID56 */
total_bytes_used += sp->used_bytes * factor;
}
print_fs_stat(&fs_stat, print_raw, total_bytes_used);
}
@ -1813,6 +1836,7 @@ static int cmd_scrub_status(const struct cmd_struct *cmd, int argc, char **argv)
out:
free_history(past_scrubs);
free(di_args);
free(si_args);
if (fdres > -1)
close(fdres);
close_file_or_dir(fdmnt, dirstream);