From 2e53604e6db35f727f417326642a793b0b346938 Mon Sep 17 00:00:00 2001 From: Zhao Lei Date: Wed, 2 Sep 2015 20:22:31 +0800 Subject: btrfs-progs: stat info for btrfs rescue chunk-recover chunk-recover need to use many many time in scan_devices(), and no output in screen: # btrfs rescue chunk-recover /dev/sda6 (no output here, but need long time) To notice user that "the command is not hang", this patch add dynamic updated stat information in above period: # btrfs rescue chunk-recover /dev/sda6 Scanning: DONE in dev[0], 19998441472 in dev[1], DONE in dev[2] (until) Scanning: DONE in dev0, DONE in dev1, DONE in dev2 Check chunks successfully with no orphans Recover the chunk tree successfully. Signed-off-by: Zhao Lei Signed-off-by: David Sterba --- chunk-recover.c | 72 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 18 deletions(-) diff --git a/chunk-recover.c b/chunk-recover.c index 576a2a68..7c20b716 100644 --- a/chunk-recover.c +++ b/chunk-recover.c @@ -78,6 +78,7 @@ struct device_scan { struct recover_control *rc; struct btrfs_device *dev; int fd; + u64 bytenr; }; static struct extent_record *btrfs_new_extent_record(struct extent_buffer *eb) @@ -768,6 +769,8 @@ static int scan_one_device(void *dev_scan_struct) bytenr = 0; while (1) { + dev_scan->bytenr = bytenr; + if (is_super_block_address(bytenr)) bytenr += rc->sectorsize; @@ -834,9 +837,8 @@ static int scan_devices(struct recover_control *rc) long *t_rets; int devnr = 0; int devidx = 0; - int cancel_from = 0; - int cancel_to = 0; int i; + int all_done; list_for_each_entry(dev, &rc->fs_devices->devices, dev_list) devnr++; @@ -862,30 +864,64 @@ static int scan_devices(struct recover_control *rc) dev_scans[devidx].rc = rc; dev_scans[devidx].dev = dev; dev_scans[devidx].fd = fd; - ret = pthread_create(&t_scans[devidx], NULL, - (void *)scan_one_device, - (void *)&dev_scans[devidx]); - if (ret) { - cancel_from = 0; - cancel_to = devidx - 1; - goto out1; - } + dev_scans[devidx].bytenr = -1; devidx++; } for (i = 0; i < devidx; i++) { - ret = pthread_join(t_scans[i], (void **)&t_rets[i]); - if (ret || t_rets[i]) { - ret = 1; - cancel_from = i + 1; - cancel_to = devnr - 1; + ret = pthread_create(&t_scans[i], NULL, + (void *)scan_one_device, + (void *)&dev_scans[i]); + if (ret) goto out1; + + dev_scans[i].bytenr = 0; + } + + while (1) { + all_done = 1; + for (i = 0; i < devidx; i++) { + if (dev_scans[i].bytenr == -1) + continue; + ret = pthread_tryjoin_np(t_scans[i], + (void **)&t_rets[i]); + if (ret == EBUSY) { + all_done = 0; + continue; + } + if (ret || t_rets[i]) { + ret = 1; + goto out1; + } + dev_scans[i].bytenr = -1; + } + + printf("\rScanning: "); + for (i = 0; i < devidx; i++) { + if (dev_scans[i].bytenr == -1) + printf("%sDONE in dev%d", + i ? ", " : "", i); + else + printf("%s%llu in dev%d", + i ? ", " : "", dev_scans[i].bytenr, i); } + /* clear chars if exist in tail */ + printf(" "); + printf("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b"); + fflush(stdout); + + if (all_done) { + printf("\n"); + break; + } + + sleep(1); } out1: - while (ret && (cancel_from <= cancel_to)) { - pthread_cancel(t_scans[cancel_from]); - cancel_from++; + for (i = 0; i < devidx; i++) { + if (dev_scans[i].bytenr == -1) + continue; + pthread_cancel(t_scans[i]); } out2: free(dev_scans); -- cgit v1.2.3