Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 1 Mar 2015 20:08:58 +0000 (UTC)
From:      Kurt Jaeger <pi@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r380226 - in head/sysutils/diskcheckd: . files
Message-ID:  <201503012008.t21K8wF2047797@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pi
Date: Sun Mar  1 20:08:57 2015
New Revision: 380226
URL: https://svnweb.freebsd.org/changeset/ports/380226
QAT: https://qat.redports.org/buildarchive/r380226/

Log:
  sysutils/diskcheckd: 20110729 -> 20150220
  
  adapt to missing DIOCGDINFO on 11-current and fix some printf warnings
  
  PR:		197841
  Submitted by:	Perry Hutchison <perryh_bsd_bugs@pluto.rain.com> (maintainer)

Modified:
  head/sysutils/diskcheckd/Makefile
  head/sysutils/diskcheckd/files/diskcheckd.8
  head/sysutils/diskcheckd/files/diskcheckd.c

Modified: head/sysutils/diskcheckd/Makefile
==============================================================================
--- head/sysutils/diskcheckd/Makefile	Sun Mar  1 19:45:49 2015	(r380225)
+++ head/sysutils/diskcheckd/Makefile	Sun Mar  1 20:08:57 2015	(r380226)
@@ -2,7 +2,7 @@
 # $FreeBSD$
 
 PORTNAME=	diskcheckd
-PORTVERSION=	20110729
+PORTVERSION=	20150220
 CATEGORIES=	sysutils
 MASTER_SITES=	# part of port
 DISTFILES=	# part of port

Modified: head/sysutils/diskcheckd/files/diskcheckd.8
==============================================================================
--- head/sysutils/diskcheckd/files/diskcheckd.8	Sun Mar  1 19:45:49 2015	(r380225)
+++ head/sysutils/diskcheckd/files/diskcheckd.8	Sun Mar  1 20:08:57 2015	(r380226)
@@ -199,9 +199,18 @@ and this manual page were written by
 .An Ben Smithurst Aq ben@FreeBSD.org ,
 with input from
 .An Poul-Henning Kamp Aq phk@FreeBSD.org .
+The geom-aware version of the sector->partition translation code was added by
+.An Perry Hutchison Aq perryh@pluto.rain.com ,
+based on a mechanism suggested by
+.An Warner Losh Aq imp@bsdimp.com .
 .Sh BUGS
 .Nm
-assumes all disks have 512 byte sectors.
+Too much of the code assumes all disks have 512 byte sectors.
 .Pp
-The code that attempts to identify and report which slice and partition
-contain a detected error does not understand GPT partitions.
+There are two versions of the code that attempts to identify
+and report which slice and/or partition contain a detected error.
+The older version, used when the DIOCGDINFO ioctl is available
+(i.e. prior to
+.Fx 11.0 ),
+does not understand either GPT partitions or dedicated BSD disks
+(having the BSD disklabel in place of an MBR).

Modified: head/sysutils/diskcheckd/files/diskcheckd.c
==============================================================================
--- head/sysutils/diskcheckd/files/diskcheckd.c	Sun Mar  1 19:45:49 2015	(r380225)
+++ head/sysutils/diskcheckd/files/diskcheckd.c	Sun Mar  1 20:08:57 2015	(r380226)
@@ -22,6 +22,9 @@
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
+ *
+ * geom-aware portions of logreaderror() Copyright (c) 2015 Perry Hutchison
+ * <perryh@pluto.rain.com>, licensed on the same terms as above.
  */
 
 static const char rcsid[] =
@@ -58,6 +61,19 @@ static const char rcsid[] =
 
 #define	READ_SIZE (64 << 10)
 
+/*
+ * Customize format strings according to what printf et al. want for a quad_t.
+ *
+ * This should not be necessary -- the whole point of %qd is to match a quad_t
+ * -- but in LP64 a quad_t is the same size as a long and yet %qd is treated as
+ * equivalent to %lld (which is correct only if a long is 32 bits, as in ILP32).
+ */
+#ifdef	LP64
+#define QD "%ld"
+#else
+#define	QD "%qd"
+#endif
+
 struct disk {
 	int fd;
 	char *device;
@@ -125,10 +141,11 @@ main(int argc, char *argv[]) {
 
 	initial_debug = debug;
 
-	openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0), LOG_DAEMON);
+	openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0),
+		LOG_DAEMON);
 
 	if (!debug && daemon(0, 0) < 0) {
-		syslog(LOG_NOTICE, "daemon failure: %m");
+		syslog(LOG_NOTICE, "daemon() failure: %m");
 		exit(EXIT_FAILURE);
 	}
 
@@ -309,26 +326,40 @@ void
 logreaderror(struct disk *dp, int nbytes) {
 	quad_t secno;
 	off_t saved_offset;
+	char newdev[512];
+
+#ifdef	DIOCGDINFO
 	int fd, slice, part;
 	struct dos_partition *dos;
 	struct disklabel label;
 	char buf[512];
-	char newdev[512];
+#else	/* DIOCGDINFO */
+	static size_t geomSize = 0;
+	static char * geomConf = NULL;
+	char * cp;
+	static size_t partLen = 31;
+	static char *part = NULL;
+	quad_t relsec = -1;
+	char *typefld = NULL;
+#endif	/* DIOCGDINFO */
 
 	saved_offset = dseek(dp, 0, SEEK_CUR);
 	secno = (quad_t)saved_offset / dp->secsize;
 	dp->errors++;
 
-	syslog(LOG_NOTICE, "error reading %d bytes from sector %qd on %s",
+	syslog(LOG_NOTICE, "error reading %d bytes from sector " QD " on %s",
 	    nbytes, secno, dp->device);
 
+#ifdef	DIOCGDINFO
 	/*
 	 * First, find out which slice it's in.  To do this, we seek to the
 	 * start of the disk, read the first sector, and go through the DOS
 	 * slice table.
 	 */
-	if (dseek(dp, 0, SEEK_SET) == -1)
+	if (dseek(dp, 0, SEEK_SET) == -1) {
+		syslog(LOG_NOTICE, "could not seek to start of disk: %m");
 		exit(EXIT_FAILURE);
+	}
 
 	if (read(dp->fd, buf, sizeof buf) != sizeof buf) {
 		dseek(dp, saved_offset, SEEK_SET);
@@ -336,9 +367,14 @@ logreaderror(struct disk *dp, int nbytes
 	}
 
 	/* seek back to where we were */
-	if (dseek(dp, saved_offset, SEEK_SET) == -1)
+	if (dseek(dp, saved_offset, SEEK_SET) == -1) {
+		syslog(LOG_NOTICE,
+		       "could not seek to previous position"
+		       "after reading first sector: %m");
 		exit(EXIT_FAILURE);
+	}
 
+	// TODO:  should validate DOS partition table (vs GPT or dedicated)
 	dos = (struct dos_partition *)&buf[DOSPARTOFF];
 	for (slice = 0; slice < NDOSPART; slice++)
 		if (dos[slice].dp_start <= secno &&
@@ -347,7 +383,7 @@ logreaderror(struct disk *dp, int nbytes
 
 	if (slice == NDOSPART) {
 		syslog(LOG_NOTICE,
-		  "sector %qd on %s doesn't appear "
+		  "sector " QD " on %s doesn't appear "
 		  "to be within any DOS slice", secno, dp->device);
 		return;
 	}
@@ -361,8 +397,8 @@ logreaderror(struct disk *dp, int nbytes
 	/* Check the type of that partition. */
 	if (dos[slice].dp_typ != DOSPTYP_386BSD) {
 		/* If not a BSD slice, we can't do much more. */
-		syslog(LOG_NOTICE, "last bad sector is sector %qd "
-		    "on device %s, type %02x", secno, newdev,
+		syslog(LOG_NOTICE, "last bad sector is sector " QD
+		    " on device %s, type %02x", secno, newdev,
 		    dos[slice].dp_typ);
 		return;
 	}
@@ -389,7 +425,7 @@ logreaderror(struct disk *dp, int nbytes
 
 	if (part == MAXPARTITIONS) {
 		syslog(LOG_NOTICE,
-		  "sector %qd on %s doesn't appear "
+		  "sector " QD " on %s doesn't appear "
 		  "to be within any BSD partition", secno, newdev);
 		return;
 	}
@@ -400,14 +436,100 @@ logreaderror(struct disk *dp, int nbytes
 	syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev);
 	if (label.d_partitions[part].p_fstype != FS_BSDFFS) {
 		/* Again, if not a BSD partition, can't do much. */
-		syslog(LOG_NOTICE, "last bad sector is sector %qd "
-		    "on device %s, type %s", secno, newdev,
+		syslog(LOG_NOTICE, "last bad sector is sector " QD
+		    " on device %s, type %s", secno, newdev,
 		    fstypename(label.d_partitions[part].p_fstype));
 		return;
 	}
+#else	/* DIOCGDINFO */
+	if (geomSize == 0) {
+		sysctlbyname("kern.geom.conftxt", NULL, &geomSize, NULL, 0);
+		if (geomSize <= 0) {
+			printf("sysctlbyname() returned size = %d\n", geomSize);
+			geomSize = 0;
+			exit(EXIT_FAILURE);
+		}
+		geomConf = malloc(geomSize);
+		if (geomConf == NULL) {
+			printf("malloc(%d) returned NULL\n", geomSize);
+			geomSize = 0;
+			exit(EXIT_FAILURE);
+		}
+		if (sysctlbyname("kern.geom.conftxt", geomConf, &geomSize,
+				 NULL, 0) != 0) {
+			perror("sysctlbyname()");
+			geomSize = 0;
+			free(geomConf);
+			geomConf = NULL;
+			exit(EXIT_FAILURE);
+		}
+	}
+	if (part == NULL)
+		part = malloc(partLen + 1);
+
+	for ( cp = geomConf ; *cp ; ++cp ) {
+		// find line "0 DISK " matching current disk, using
+		// strncmp because where cp points is not null-terminated
+		// (All DISK lines, and only DISK lines, are at level 0.)
+		// Magic numbers:  7 == strlen("0 DISK "); 5 == strlen("/dev/")
+		if (strncmp(cp, "0 DISK ", 7) == 0
+		 && strncmp(&cp[7], &dp->device[5], strlen(dp->device) - 5) == 0
+		 && cp[7 + strlen(dp->device) - 5] == ' ') {
+			for (;;) {
+				// scan to end of line
+				while (cp[1] && *cp != '\n')
+					++cp;
+				++cp;	// start of next line
+				// Find PART line containing the failed sector;
+				// must be on same disk => stop upon finding
+				// another DISK line.  If more than one matching
+				// PART -- due to nested geoms -- use the last
+				// (innermost).
+				if (*cp == '\0' || *cp == '0')
+					break;	// end of current DISK's entries
+				// scan to end of level number
+				while (cp[1] && *cp != ' ')
+					++cp;
+				if (strncmp(cp, " PART ", 6) == 0) {
+					char *pp = &cp[6];
+					int pl = strchr(pp, ' ') - pp;
+					quad_t mediasize, offset;
+					long secsize;
+
+					cp = pp + pl;	// cp -> mediasize
+					mediasize = strtoq(cp, &cp, 10);
+					secsize = strtol(cp, &cp, 10);
+					mediasize /= secsize;
+					cp = strchr(cp, 'o') + 1;
+					offset = strtoq(cp, &cp, 10) / secsize;
+					if (secno >= offset
+					 && (secno - offset) < mediasize) {
+						if (pl > partLen) {
+							part = realloc(part,
+									pl+1);
+							partLen = pl;
+						}
+						strncpy(part, pp, pl);
+						part[pl] = '\0';
+						relsec = secno - offset;
+						typefld = cp + 1;
+					}
+				}
+			}
+		}
+		// scan to end of line
+		while (cp[1] && *cp != '\n')
+			++cp;
+	}
+////	printf("part %s, relsec %qd, typefld %p: %.27s\n",
+////		part, relsec, typefld, typefld);
+	secno = relsec;
+	strncpy(newdev, part, sizeof(newdev) - 1);
+	newdev[sizeof(newdev) - 1] = '\0';		// paranoia
+#endif	/* DIOCGDINFO */
 
-	syslog(LOG_NOTICE, "last bad sector is sector %qd "
-	  "on 4.2BSD filesystem %s", secno, newdev);
+	syslog(LOG_NOTICE, "last bad sector is sector " QD
+	  " on 4.2BSD filesystem %s", secno, newdev);
 
 	/*
 	 * XXX: todo: find out which file on the BSD filesystem uses this
@@ -472,12 +594,14 @@ writeoffsets(struct disk *disks, const c
 			"#\tposition/size\tdays\trate\terrors\tintvl\tnext\n");
 	for (dp = disks; dp->device != NULL; dp++)
 		if (strcmp(dp->device, "*") != 0) {
-			fprintf(fp, "%s %qd\n", dp->device,
+			fprintf(fp, "%s " QD "\n", dp->device,
 			    (quad_t)dseek(dp, 0, SEEK_CUR));
 			if (debug) {
-				fprintf(stderr, "%s %qd\n", dp->device,
+				fprintf(stderr, "%s " QD "\n", dp->device,
 					(quad_t)dseek(dp, 0, SEEK_CUR));
-				fprintf(stderr, "#\t%qd\t%d\t%d\t%d\t%qd\t%qd\n",
+				fprintf(stderr,
+					"#\t" QD "\t%d\t%d\t%d\t" QD "\t" QD
+					"\n",
 					(quad_t)dp->size, dp->days, dp->rate,
 					dp->errors, dp->interval, dp->next);
 			}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201503012008.t21K8wF2047797>