forked from Mirrors/btrfs-progs
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>master
parent
6626354fdf
commit
b79d4a217f
59
cmds-scrub.c
59
cmds-scrub.c
|
@ -840,9 +840,11 @@ static void *progress_one_dev(void *ctx)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* nb: returns a negative errno via ERR_PTR */
|
||||||
static void *scrub_progress_cycle(void *ctx)
|
static void *scrub_progress_cycle(void *ctx)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
int perr = 0; /* positive / pthread error returns */
|
||||||
int old;
|
int old;
|
||||||
int i;
|
int i;
|
||||||
char fsid[37];
|
char fsid[37];
|
||||||
|
@ -867,9 +869,9 @@ static void *scrub_progress_cycle(void *ctx)
|
||||||
struct sockaddr_un peer;
|
struct sockaddr_un peer;
|
||||||
socklen_t peer_size = sizeof(peer);
|
socklen_t peer_size = sizeof(peer);
|
||||||
|
|
||||||
ret = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
perr = pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||||
if (ret)
|
if (perr)
|
||||||
return ERR_PTR(-ret);
|
goto out;
|
||||||
|
|
||||||
uuid_unparse(spc->fi->fsid, fsid);
|
uuid_unparse(spc->fi->fsid, fsid);
|
||||||
|
|
||||||
|
@ -890,8 +892,10 @@ static void *scrub_progress_cycle(void *ctx)
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = poll(&accept_poll_fd, 1, 5 * 1000);
|
ret = poll(&accept_poll_fd, 1, 5 * 1000);
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
return ERR_PTR(-errno);
|
ret = -errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (ret)
|
if (ret)
|
||||||
peer_fd = accept(spc->prg_fd, (struct sockaddr *)&peer,
|
peer_fd = accept(spc->prg_fd, (struct sockaddr *)&peer,
|
||||||
&peer_size);
|
&peer_size);
|
||||||
|
@ -909,42 +913,46 @@ static void *scrub_progress_cycle(void *ctx)
|
||||||
if (!sp->ret)
|
if (!sp->ret)
|
||||||
continue;
|
continue;
|
||||||
if (sp->ioctl_errno != ENOTCONN &&
|
if (sp->ioctl_errno != ENOTCONN &&
|
||||||
sp->ioctl_errno != ENODEV)
|
sp->ioctl_errno != ENODEV) {
|
||||||
return ERR_PTR(-sp->ioctl_errno);
|
ret = -sp->ioctl_errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* scrub finished or device removed, check the
|
* scrub finished or device removed, check the
|
||||||
* finished flag. if unset, just use the last
|
* finished flag. if unset, just use the last
|
||||||
* result we got for the current write and go
|
* result we got for the current write and go
|
||||||
* on. flag should be set on next cycle, then.
|
* on. flag should be set on next cycle, then.
|
||||||
*/
|
*/
|
||||||
ret = pthread_mutex_lock(&sp_shared->progress_mutex);
|
perr = pthread_mutex_lock(&sp_shared->progress_mutex);
|
||||||
if (ret)
|
if (perr)
|
||||||
return ERR_PTR(-ret);
|
goto out;
|
||||||
if (!sp_shared->stats.finished) {
|
if (!sp_shared->stats.finished) {
|
||||||
ret = pthread_mutex_unlock(
|
perr = pthread_mutex_unlock(
|
||||||
&sp_shared->progress_mutex);
|
&sp_shared->progress_mutex);
|
||||||
if (ret)
|
if (perr)
|
||||||
return ERR_PTR(-ret);
|
goto out;
|
||||||
memcpy(sp, sp_last, sizeof(*sp));
|
memcpy(sp, sp_last, sizeof(*sp));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = pthread_mutex_unlock(&sp_shared->progress_mutex);
|
perr = pthread_mutex_unlock(&sp_shared->progress_mutex);
|
||||||
if (ret)
|
if (perr)
|
||||||
return ERR_PTR(-ret);
|
goto out;
|
||||||
memcpy(sp, sp_shared, sizeof(*sp));
|
memcpy(sp, sp_shared, sizeof(*sp));
|
||||||
memcpy(sp_last, sp_shared, sizeof(*sp));
|
memcpy(sp_last, sp_shared, sizeof(*sp));
|
||||||
}
|
}
|
||||||
if (peer_fd != -1) {
|
if (peer_fd != -1) {
|
||||||
write_poll_fd.fd = peer_fd;
|
write_poll_fd.fd = peer_fd;
|
||||||
ret = poll(&write_poll_fd, 1, 0);
|
ret = poll(&write_poll_fd, 1, 0);
|
||||||
if (ret == -1)
|
if (ret == -1) {
|
||||||
return ERR_PTR(-errno);
|
ret = -errno;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ret = scrub_write_file(
|
ret = scrub_write_file(
|
||||||
peer_fd, fsid,
|
peer_fd, fsid,
|
||||||
&spc->progress[this * ndev], ndev);
|
&spc->progress[this * ndev], ndev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ERR_PTR(ret);
|
goto out;
|
||||||
}
|
}
|
||||||
close(peer_fd);
|
close(peer_fd);
|
||||||
peer_fd = -1;
|
peer_fd = -1;
|
||||||
|
@ -954,8 +962,14 @@ static void *scrub_progress_cycle(void *ctx)
|
||||||
ret = scrub_write_progress(spc->write_mutex, fsid,
|
ret = scrub_write_progress(spc->write_mutex, fsid,
|
||||||
&spc->progress[this * ndev], ndev);
|
&spc->progress[this * ndev], ndev);
|
||||||
if (ret)
|
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(
|
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);
|
ret = pthread_cancel(t_prog);
|
||||||
if (!ret)
|
if (!ret)
|
||||||
ret = pthread_join(t_prog, &terr);
|
ret = pthread_join(t_prog, &terr);
|
||||||
|
|
||||||
|
/* check for errors from the handling of the progress thread */
|
||||||
if (do_print && ret) {
|
if (do_print && ret) {
|
||||||
fprintf(stderr, "ERROR: progress thead handling failed: %s\n",
|
fprintf(stderr, "ERROR: progress thread handling failed: %s\n",
|
||||||
strerror(ret));
|
strerror(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check for errors returned from the progress thread itself */
|
||||||
if (do_print && terr && terr != PTHREAD_CANCELED) {
|
if (do_print && terr && terr != PTHREAD_CANCELED) {
|
||||||
fprintf(stderr, "ERROR: recording progress "
|
fprintf(stderr, "ERROR: recording progress "
|
||||||
"failed: %s\n", strerror(-PTR_ERR(terr)));
|
"failed: %s\n", strerror(-PTR_ERR(terr)));
|
||||||
|
|
Loading…
Reference in New Issue