From 79ef974a68d4e70b1ad69a18d70d8a04c9d00bd5 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 22 Apr 2020 14:57:33 +0200 Subject: [PATCH] sfdisk: only report I/O errors on --move-data Now sfdisk stops everything on I/O error when moving data. It seems better to report the error to user and continue as it's better to have one bad sector in the partition than inconsistent all partition. Addresses: https://github.com/karelzak/util-linux/issues/984 Signed-off-by: Karel Zak --- disk-utils/sfdisk.c | 58 ++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index 24d1f729c..07e8b2341 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -376,9 +376,9 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa FILE *f = NULL; int ok = 0, fd, backward = 0; fdisk_sector_t nsectors, from, to, step, i, prev; - size_t io, ss, step_bytes, cc; + size_t io, ss, step_bytes, cc, ioerr = 0; uintmax_t src, dst, nbytes; - int errsv, progress = 0; + int progress = 0, rc = 0; struct timeval prev_time; uint64_t bytes_per_sec = 0; @@ -474,8 +474,9 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa if (typescript) { f = fopen(typescript, "w"); if (!f) { + rc = -errno; fdisk_warn(sf->cxt, _("cannot open %s"), typescript); - goto fail; + goto done; } /* don't translate */ @@ -506,8 +507,6 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa prev = 0; for (cc = 1, i = 0; i < nsectors && nbytes > 0; i += step, cc++) { - ssize_t rc; - if (backward) src -= step_bytes, dst -= step_bytes; @@ -522,18 +521,26 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa if (!sf->noact) { /* read source */ - if (lseek(fd, src, SEEK_SET) == (off_t) -1) - goto fail; - rc = read(fd, buf, step_bytes); - if (rc < 0 || rc != (ssize_t) step_bytes) - goto fail; + if (lseek(fd, src, SEEK_SET) == (off_t) -1 || + read_all(fd, buf, step_bytes) != (ssize_t) step_bytes) { + if (f) + fprintf(f, "%05zu: read error %12ju %12ju\n", cc, src, dst); + fdisk_warn(sf->cxt, + _("cannot read at offset: %zu; continue"), src); + ioerr++; + goto next; + } /* write target */ - if (lseek(fd, dst, SEEK_SET) == (off_t) -1) - goto fail; - rc = write(fd, buf, step_bytes); - if (rc < 0 || rc != (ssize_t) step_bytes) - goto fail; + if (lseek(fd, dst, SEEK_SET) == (off_t) -1 || + write_all(fd, buf, step_bytes) != 0) { + if (f) + fprintf(f, "%05zu: write error %12ju %12ju\n", cc, src, dst); + fdisk_warn(sf->cxt, + _("cannot write at offset: %zu; continue"), dst); + ioerr++; + goto next; + } if (sf->movefsync) fsync(fd); } @@ -571,7 +578,7 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa fputc('\r', stdout); } - +next: if (!backward) src += step_bytes, dst += step_bytes; } @@ -587,6 +594,8 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa 100.0 / ((double) nsectors/(i+1))); fputc('\n', stdout); } + rc = 0; +done: if (f) fclose(f); free(buf); @@ -595,18 +604,13 @@ static int move_partition_data(struct sfdisk *sf, size_t partno, struct fdisk_pa if (sf->noact) fdisk_info(sf->cxt, _("Your data has not been moved (--no-act).")); + if (ioerr) { + fdisk_info(sf->cxt, _("%zu I/O errors detected!"), ioerr); + rc = -EIO; + } else if (rc) + warn(_("%s: failed to move data"), devname); - return 0; -fail: - errsv = -errno; - warn(_("%s: failed to move data"), devname); - if (f) - fclose(f); - free(buf); - free(devname); - free(typescript); - - return errsv; + return rc; } static int write_changes(struct sfdisk *sf)