summaryrefslogtreecommitdiff
path: root/chunk-recover.c
diff options
context:
space:
mode:
authorRakesh Pandit <rakesh@tuxera.com>2014-03-26 21:34:30 +0200
committerDavid Sterba <dsterba@suse.cz>2014-04-22 14:33:44 +0200
commit30156b749bd7ceeec3f75f676c07aedafd26799c (patch)
tree80749e1b893c850364cad0de01604f41f86e606b /chunk-recover.c
parent5d889503552d9cccc8a7df8fac8804a1b0d773a4 (diff)
Btrfs-progs: chunk_recovery: fix mem leak and pthread_cancel call
Free memory if open call fails. Prevent pthread_cancel on threads which have already finished successfully. If all calls to pthread_create and pthread_join are successful, we mistakenly call pthread_cancel because cancel_from and cancel_to are both zero. Make POSIX.1-2001 happy by supplying a non-NULL second argument to pthread_setcanceltype. Signed-off-by: Rakesh Pandit <rakesh@tuxera.com> Signed-off-by: David Sterba <dsterba@suse.cz>
Diffstat (limited to 'chunk-recover.c')
-rw-r--r--chunk-recover.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/chunk-recover.c b/chunk-recover.c
index a05e6447..613d7152 100644
--- a/chunk-recover.c
+++ b/chunk-recover.c
@@ -745,8 +745,9 @@ static int scan_one_device(void *dev_scan_struct)
struct recover_control *rc = dev_scan->rc;
struct btrfs_device *device = dev_scan->dev;
int fd = dev_scan->fd;
+ int oldtype;
- ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+ ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
if (ret)
return 1;
@@ -845,7 +846,8 @@ static int scan_devices(struct recover_control *rc)
if (fd < 0) {
fprintf(stderr, "Failed to open device %s\n",
dev->name);
- return -1;
+ ret = 1;
+ goto out2;
}
dev_scans[devidx].rc = rc;
dev_scans[devidx].dev = dev;
@@ -856,7 +858,7 @@ static int scan_devices(struct recover_control *rc)
if (ret) {
cancel_from = 0;
cancel_to = devidx - 1;
- goto out;
+ goto out1;
}
devidx++;
}
@@ -868,15 +870,16 @@ static int scan_devices(struct recover_control *rc)
ret = 1;
cancel_from = i + 1;
cancel_to = devnr - 1;
- break;
+ goto out1;
}
i++;
}
-out:
- while (cancel_from <= cancel_to) {
+out1:
+ while (ret && (cancel_from <= cancel_to)) {
pthread_cancel(t_scans[cancel_from]);
cancel_from++;
}
+out2:
free(dev_scans);
free(t_scans);
free(t_rets);