summaryrefslogtreecommitdiff
path: root/cmds-scrub.c
diff options
context:
space:
mode:
authorEric Sandeen <sandeen@redhat.com>2013-03-04 16:45:37 -0600
committerDavid Sterba <dsterba@suse.cz>2013-03-10 16:06:37 +0100
commitb79d4a217fe8501431dcc0d956ed58a93b05565f (patch)
tree40af8f2443d7331b80dff78f4bb785e68408aadd /cmds-scrub.c
parent6626354fdf00ce8d61edc69c0d65d283ef99c69c (diff)
btrfs-progs: Error handling in scrub_progress_cycle() thread
consolidate error handling to ensure that peer_fd is closed on error paths. Add a couple comments to the error handling after the thread is complete. Note that scrub_progress_cycle returns negative errnos on any error. Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Diffstat (limited to 'cmds-scrub.c')
-rw-r--r--cmds-scrub.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/cmds-scrub.c b/cmds-scrub.c
index 6fcff8b4..91ace9ce 100644
--- a/cmds-scrub.c
+++ b/cmds-scrub.c
@@ -840,9 +840,11 @@ static void *progress_one_dev(void *ctx)
return NULL;
}
+/* nb: returns a negative errno via ERR_PTR */
static void *scrub_progress_cycle(void *ctx)
{
int ret;
+ int perr = 0; /* positive / pthread error returns */
int old;
int i;
char fsid[37];
@@ -867,9 +869,9 @@ static void *scrub_progress_cycle(void *ctx)
struct sockaddr_un peer;
socklen_t peer_size = sizeof(peer);
- ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
- if (ret)
- return ERR_PTR(-ret);
+ perr = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
+ if (perr)
+ goto out;
uuid_unparse(spc->fi->fsid, fsid);
@@ -890,8 +892,10 @@ static void *scrub_progress_cycle(void *ctx)
while (1) {
ret = poll(&accept_poll_fd, 1, 5 * 1000);
- if (ret == -1)
- return ERR_PTR(-errno);
+ if (ret == -1) {
+ ret = -errno;
+ goto out;
+ }
if (ret)
peer_fd = accept(spc->prg_fd, (struct sockaddr *)&peer,
&peer_size);
@@ -909,42 +913,46 @@ static void *scrub_progress_cycle(void *ctx)
if (!sp->ret)
continue;
if (sp->ioctl_errno != ENOTCONN &&
- sp->ioctl_errno != ENODEV)
- return ERR_PTR(-sp->ioctl_errno);
+ sp->ioctl_errno != ENODEV) {
+ ret = -sp->ioctl_errno;
+ goto out;
+ }
/*
* scrub finished or device removed, check the
* finished flag. if unset, just use the last
* result we got for the current write and go
* on. flag should be set on next cycle, then.
*/
- ret = pthread_mutex_lock(&sp_shared->progress_mutex);
- if (ret)
- return ERR_PTR(-ret);
+ perr = pthread_mutex_lock(&sp_shared->progress_mutex);
+ if (perr)
+ goto out;
if (!sp_shared->stats.finished) {
- ret = pthread_mutex_unlock(
+ perr = pthread_mutex_unlock(
&sp_shared->progress_mutex);
- if (ret)
- return ERR_PTR(-ret);
+ if (perr)
+ goto out;
memcpy(sp, sp_last, sizeof(*sp));
continue;
}
- ret = pthread_mutex_unlock(&sp_shared->progress_mutex);
- if (ret)
- return ERR_PTR(-ret);
+ perr = pthread_mutex_unlock(&sp_shared->progress_mutex);
+ if (perr)
+ goto out;
memcpy(sp, sp_shared, sizeof(*sp));
memcpy(sp_last, sp_shared, sizeof(*sp));
}
if (peer_fd != -1) {
write_poll_fd.fd = peer_fd;
ret = poll(&write_poll_fd, 1, 0);
- if (ret == -1)
- return ERR_PTR(-errno);
+ if (ret == -1) {
+ ret = -errno;
+ goto out;
+ }
if (ret) {
ret = scrub_write_file(
peer_fd, fsid,
&spc->progress[this * ndev], ndev);
if (ret)
- return ERR_PTR(ret);
+ goto out;
}
close(peer_fd);
peer_fd = -1;
@@ -954,8 +962,14 @@ static void *scrub_progress_cycle(void *ctx)
ret = scrub_write_progress(spc->write_mutex, fsid,
&spc->progress[this * ndev], ndev);
if (ret)
- return ERR_PTR(ret);
+ goto out;
}
+out:
+ if (peer_fd != -1)
+ close(peer_fd);
+ if (perr)
+ ret = -perr;
+ return ERR_PTR(ret);
}
static struct scrub_file_record *last_dev_scrub(
@@ -1373,11 +1387,14 @@ static int scrub_start(int argc, char **argv, int resume)
ret = pthread_cancel(t_prog);
if (!ret)
ret = pthread_join(t_prog, &terr);
+
+ /* check for errors from the handling of the progress thread */
if (do_print && ret) {
- fprintf(stderr, "ERROR: progress thead handling failed: %s\n",
+ fprintf(stderr, "ERROR: progress thread handling failed: %s\n",
strerror(ret));
}
+ /* check for errors returned from the progress thread itself */
if (do_print && terr && terr != PTHREAD_CANCELED) {
fprintf(stderr, "ERROR: recording progress "
"failed: %s\n", strerror(-PTR_ERR(terr)));