gpart: various improvements

Add patch to fix crash non-disk device
Add patch to avoid superfluous seek calls
Add patches to increase reading speed
Add patch for LVM2 and btrfs to list of supported modules

Signed-off-by: Nathan Owens <ndowens04@gmail.com>
This commit is contained in:
Nathan Owens 2019-11-22 18:50:32 -06:00 committed by Helmut Pozimski
parent 70a12196fa
commit 7dc6bce189
6 changed files with 390 additions and 9 deletions

View file

@ -0,0 +1,152 @@
From 42c45995fdee50f135f1ac42d0ab496dd0d01f60 Mon Sep 17 00:00:00 2001
From: Baruch Even <baruch@ev-en.org>
Date: Wed, 25 Nov 2015 23:02:38 +0200
Subject: [PATCH 1/5] Fix crash on a non-disk device
Closes #9
---
src/disku.c | 115 +++++++++++++++++++++++++++-------------------------
1 file changed, 59 insertions(+), 56 deletions(-)
diff --git src/disku.c src/disku.c
index b918147..b33ba91 100644
--- src/disku.c
+++ src/disku.c
@@ -36,66 +36,33 @@
#include <unistd.h>
-
-/*
- * get disk geometry. The medium is opened for reading,
- * descriptor in d_fd.
- */
-
-struct disk_geom *disk_geometry(disk_desc *d)
-{
- static struct disk_geom g;
- uint64_t nsects;
-
- memset(&g, 0, sizeof(g));
-
#if defined(__linux__)
- struct hd_geometry hg;
-#endif
-#if defined(__FreeBSD__)
- struct disklabel dl;
-#endif
-
- struct stat st;
- int ret;
- uint64_t lba;
- ret = stat(d->d_dev, &st);
- if (ret == 0)
- {
- if (S_ISREG(st.st_mode))
- {
- nsects = st.st_size / 512;
- if (nsects == 0)
- pr(FATAL, EM_FATALERROR, "Not a block device image file");
- lba = nsects - 1;
- g.d_h = (lba / 63) % 255;
- g.d_s = lba % 63 + 1;
- g.d_c = lba / (255 * 63);
- g.d_nsecs = nsects;
- return (&g);
- }
+static void os_disk_geometry(disk_desc *d, struct disk_geom *g)
+{
+ struct hd_geometry hg;
+ uint64_t nsects;
+
+ if (ioctl(d->d_fd, HDIO_GETGEO, &hg) == -1)
+ pr(FATAL, EM_IOCTLFAILED, "HDIO_GETGEO", strerror(errno));
+ else {
+ g->d_h = hg.heads;
+ g->d_s = hg.sectors;
+ g->d_c = hg.cylinders;
}
-
-#if defined(__linux__)
- if (ioctl(d->d_fd,HDIO_GETGEO,&hg) == -1)
- pr(FATAL,EM_IOCTLFAILED,"HDIO_GETGEO",strerror(errno));
#ifdef BLKGETSIZE
- if (ioctl(d->d_fd,BLKGETSIZE,&nsects) == -1)
- pr(FATAL,EM_IOCTLFAILED,"BLKGETSIZE",strerror(errno));
- g.d_nsecs = nsects;
- g.d_c = nsects / (hg.heads * hg.sectors);
-#else
- g.d_c = hg.cylinders;
-#endif
- g.d_h = hg.heads;
- g.d_s = hg.sectors;
-
+ if (ioctl(d->d_fd, BLKGETSIZE, &nsects) == -1)
+ pr(FATAL, EM_IOCTLFAILED, "BLKGETSIZE", strerror(errno));
+ else
+ g->d_c = nsects / (hg.heads * hg.sectors);
#endif
-
-#if defined(__FreeBSD__)
- struct disklabel loclab;
- u_int u;
- off_t o; /* total disk size */
+}
+#elif defined(__FreeBSD__)
+static void os_disk_geometry(disk_desc *d, struct disk_geom *g)
+{
+ struct disklabel dl;
+ struct disklabel loclab;
+ u_int u;
+ off_t o; /* total disk size */
if (ioctl(d->d_fd, DIOCGFWSECTORS, &u) == 0)
g.d_s = u;
@@ -114,8 +81,44 @@ struct disk_geom *disk_geometry(disk_desc *d)
g.d_nsecs = o / u;
g.d_c = g.d_nsecs / g.d_h / g.d_s;
+}
+#else
+#error Only Linux and FreeBSD supported
#endif
+/*
+ * get disk geometry. The medium is opened for reading,
+ * descriptor in d_fd.
+ */
+
+struct disk_geom *disk_geometry(disk_desc *d)
+{
+ static struct disk_geom g;
+ uint64_t nsects;
+
+ memset(&g, 0, sizeof(g));
+
+ struct stat st;
+ int ret;
+ uint64_t lba;
+ ret = stat(d->d_dev, &st);
+ if (ret == 0) {
+ // We have something, we'll use it for a first fill of the data
+ nsects = st.st_size / 512;
+ if (nsects == 0)
+ pr(FATAL, EM_FATALERROR, "Not a block device image file");
+ lba = nsects - 1;
+ g.d_h = (lba / 63) % 255;
+ g.d_s = lba % 63 + 1;
+ g.d_c = lba / (255 * 63);
+ g.d_nsecs = nsects;
+
+ // If it is a regular file there is no reason to try anything else
+ if (S_ISREG(st.st_mode))
+ return (&g);
+ }
+
+ os_disk_geometry(d, &g);
return (&g);
}
--
2.24.0

View file

@ -0,0 +1,113 @@
From bba08ed9c64e8e8dad239b19e6ca8128adcaac64 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@arcor.de>
Date: Fri, 20 Nov 2015 00:17:13 +0100
Subject: [PATCH 2/5] gpart: avoid superfluous seek calls
The l64opush() logic would cause 2 lseek() syscalls per guess loop.
By simply seeking back after every probing call, we do with a single
seek() call.
---
src/gpart.c | 42 ++++++++++++++++++++++--------------------
1 file changed, 22 insertions(+), 20 deletions(-)
diff --git src/gpart.c src/gpart.c
index 8555f66..bd3806a 100644
--- src/gpart.c
+++ src/gpart.c
@@ -13,7 +13,7 @@
* Modified: 11.06.1999 <mb@ichabod.han.de>
* Handle disk read errors.
* Minor fixes.
- *
+ *
* 29.06.1999 <mb@ichabod.han.de>
* Made every disk read/write buffer aligned to pagesize.
*
@@ -21,7 +21,7 @@
* Default scan increment now 's'.
* Extended ptbl boundary condition now depends on scan
* increment.
- *
+ *
* 26.02.2000 <mb@ichabod.han.de>
* Default scan increment 'h' again.
* Fixed faulty head boundary condition.
@@ -871,7 +871,7 @@ static void add_guessed_p(disk_desc *d,dos_part_entry *p,int cnt)
gpt = d->d_gl = (dos_guessed_pt *)alloc(sizeof(dos_guessed_pt));
else
{
- for (gpt = d->d_gl; gpt->g_next; gpt = gpt->g_next)
+ for (gpt = d->d_gl; gpt->g_next; gpt = gpt->g_next)
;
gpt->g_next = (dos_guessed_pt *)alloc(sizeof(dos_guessed_pt));
gpt = gpt->g_next;
@@ -999,15 +999,18 @@ static void do_guess_loop(disk_desc *d)
pr(MSG,DM_STARTSCAN);
scanloop:
- while ((rd = bread(d->d_fd,d->d_sbuf,d->d_ssize,nsecs)) == bsize)
- {
- int mod, have_ext = 0;
- g_module *bg;
- s64_t sz, ofs;
-
- d->d_nsb += incr; noffset = 0;
- ofs = d->d_nsb; s2mb(d,ofs);
- if (maxsec && (d->d_nsb > maxsec)) break;
+ while ((rd = bread(d->d_fd, d->d_sbuf, d->d_ssize, nsecs)) == bsize) {
+ int mod, have_ext = 0;
+ g_module *bg;
+ s64_t sz, ofs, fpos;
+
+ d->d_nsb += incr;
+ noffset = 0;
+ ofs = d->d_nsb;
+ s2mb(d, ofs);
+ fpos = d->d_nsb * d->d_ssize + bsize;
+ if (maxsec && (d->d_nsb > maxsec))
+ break;
/*
* reset modules
@@ -1026,15 +1029,14 @@ guessit:
/*
* because a gmodule is allowed to seek on
* d->d_fd the current file position must be
- * saved.
+ * restored after calling it.
*/
- memset(&m->m_part,0,sizeof(dos_part_entry));
- m->m_guess = GM_NO; l64opush(d->d_fd);
- if ((*m->m_gfun)(d,m) && (m->m_guess * m->m_weight >= GM_PERHAPS))
+ memset(&m->m_part, 0, sizeof(dos_part_entry));
+ m->m_guess = GM_NO;
+ if ((*m->m_gfun)(d, m) && (m->m_guess * m->m_weight >= GM_PERHAPS))
guesses[mod++] = m;
- if ((sz = l64opop(d->d_fd)) != l64tell(d->d_fd))
- l64seek(d->d_fd,sz,SEEK_SET);
+ l64seek(d->d_fd, fpos, SEEK_SET);
}
/*
@@ -1288,7 +1290,7 @@ static void write_primary_ptbl(disk_desc *d,char *dev)
{
if ((n = number_or_quit(DM_ACTWHICHPART,1,NDOSPARTS)) < 0)
break;
- if ((n >= 1) && (n <= NDOSPARTS) &&
+ if ((n >= 1) && (n <= NDOSPARTS) &&
get_part_type(d->d_gpt.t_parts[n].p_typ))
{
d->d_gpt.t_parts[n - 1].p_flag = DOSPARTACTIVE;
@@ -1571,7 +1573,7 @@ static int check_partition_list(disk_desc *d)
if (gp->g_orph) pr(MSG,PM_G_ORPHANED);
if (gp->g_prim) pr(MSG,PM_G_PRIMARY);
if (gp->g_log) pr(MSG,PM_G_LOGICAL);
- pr(MSG,"\n");
+ pr(MSG,"\n");
if (f_verbose > 1)
print_partition(d,p,gp->g_log ? 1 : 0,0);
}
--
2.24.0

View file

@ -0,0 +1,42 @@
From b01b124b36f81a76d38eb0169e6d279a777646c9 Mon Sep 17 00:00:00 2001
From: Martin Wilck <mwilck@arcor.de>
Date: Thu, 19 Nov 2015 23:24:43 +0100
Subject: [PATCH 3/5] gpart: use posix_fadvise to increase reading speed
Use fadvise to tell the OS to try readahead.
---
configure.ac | 2 +-
src/gpart.c | 4 ++++
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git configure.ac configure.ac
index 6eca1de..21dfc00 100644
--- configure.ac
+++ configure.ac
@@ -26,7 +26,7 @@ AC_TYPE_UINT8_T
# Checks for library functions.
AC_FUNC_MALLOC
-AC_CHECK_FUNCS([getpagesize memset strchr strdup strerror strtoul])
+AC_CHECK_FUNCS([getpagesize memset strchr strdup strerror strtoul posix_fadvise])
# Configure system services.
AC_SYS_LARGEFILE
diff --git src/gpart.c src/gpart.c
index bd3806a..63b36a5 100644
--- src/gpart.c
+++ src/gpart.c
@@ -949,6 +949,10 @@ static void do_guess_loop(disk_desc *d)
if ((d->d_fd = open(d->d_dev,O_RDONLY)) == -1)
pr(FATAL,EM_OPENFAIL,d->d_dev,strerror(errno));
+#if HAVE_POSIX_FADVISE
+ posix_fadvise(d->d_fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ posix_fadvise(d->d_fd, 0, 0, POSIX_FADV_WILLNEED);
+#endif /* HAVE_POSIX_FADVISE */
/*
* initialize modules. Each should return the minimum
* size in bytes it wants to receive for a test.
--
2.24.0

View file

@ -0,0 +1,54 @@
From d56778515e88e8fd5821b49850006962fe81b18d Mon Sep 17 00:00:00 2001
From: Baruch Even <baruch@ev-en.org>
Date: Wed, 25 Nov 2015 08:58:10 +0200
Subject: [PATCH 4/5] Speed up by reading larger chunks
Based on work initiated by mwilck
---
src/gpart.c | 27 ++++++++++++++++-----------
1 file changed, 16 insertions(+), 11 deletions(-)
diff --git src/gpart.c src/gpart.c
index 63b36a5..d530547 100644
--- src/gpart.c
+++ src/gpart.c
@@ -163,20 +163,25 @@ byte_t *alloc(ssize_t s)
ssize_t bread(int fd,byte_t *buf,size_t ssize,size_t nsecs)
{
- ssize_t cs = 0, nr = 0;
-
- for ( ; nsecs > 0; nsecs--)
- {
- if ((nr = read(fd,buf,ssize)) == -1)
- {
+ const size_t total = ssize * nsecs;
+ size_t read_bytes = 0;
+
+ while (read_bytes < total) {
+ ssize_t ret = read(fd, buf + read_bytes, total - read_bytes);
+ if (ret > 0)
+ read_bytes += ret;
+ else if (ret == 0) {
+ return read_bytes;
+ } else {
+ // ret < 0, an error case
+ if (errno == EINTR)
+ continue; // Rogue signal interruption, retry
berrno = errno;
- return ((cs == 0) ? -1 : cs);
- }
- cs += nr; buf += nr;
- if (nr < ssize)
break;
+ }
}
- return (cs);
+
+ return read_bytes ? read_bytes : -1;
}
--
2.24.0

View file

@ -0,0 +1,26 @@
From 1bf2faf1340d4ae946a1f0d1aecc2ddc4b79c4bc Mon Sep 17 00:00:00 2001
From: Baruch Even <baruch@ev-en.org>
Date: Wed, 25 Nov 2015 08:17:17 +0200
Subject: [PATCH 5/5] Add LVM2 and btrfs to list of supported modules
---
README.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git README.md README.md
index 7cd3e2d..330821b 100644
--- README.md
+++ README.md
@@ -41,7 +41,8 @@ See file *INSTALL*.
qnx4 | 0x4F | QNX 4.x
beos | 0xEB | BeOS fs
xfs | 0x83 | SGI XFS filesystem
-
+ btrfs | 0x83 | BtrFS
+ LVM2 | 0x8E | LVM2
## Guessing modules
--
2.24.0

View file

@ -1,21 +1,15 @@
# Template file for 'gpart'
pkgname=gpart
version=0.3
revision=3
revision=4
build_style=gnu-configure
hostmakedepends="automake"
short_desc="Partition table rescue/guessing tool"
maintainer="Orphaned <orphan@voidlinux.org>"
license="GPL-2.0-or-later"
homepage="https://github.com/baruch/gpart"
distfiles="https://github.com/baruch/gpart/archive/${version}.tar.gz
https://github.com/ndowens/voidpatches/archive/gpart-patches.tar.gz"
checksum="ec56d12ec9ffdb9877c12692ea6e51620b1ae44473d3d253b27fc31ed9ebb4dd
ac68a5275d878623add392fc6a68913735e6cfbed5a6c49fcbe48105f88b97eb"
post_extract() {
patch -p0 < ../voidpatches-gpart-patches/0004-Real-fix-for-crash.patch
}
distfiles="https://github.com/baruch/gpart/archive/${version}.tar.gz"
checksum=ec56d12ec9ffdb9877c12692ea6e51620b1ae44473d3d253b27fc31ed9ebb4dd
pre_configure() {
autoreconf -fi