]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
sfdisk: only report I/O errors on --move-data
authorKarel Zak <kzak@redhat.com>
Wed, 22 Apr 2020 12:57:33 +0000 (14:57 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 15 May 2020 10:19:47 +0000 (12:19 +0200)
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 <kzak@redhat.com>
disk-utils/sfdisk.c

index 6049b9c724d5a193d8dc81b10d0d02efe9d08d44..8d3a9ad1b8f97eeed99d6626bb123b9cad215c69 100644 (file)
@@ -373,9 +373,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;
 
@@ -471,8 +471,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 */
@@ -503,8 +504,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;
 
@@ -519,18 +518,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);
                }
@@ -568,7 +575,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;
        }
@@ -584,6 +591,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);
@@ -592,18 +601,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)