View | Details | Raw Unified | Return to bug 197841
Collapse All | Expand All

(-)diskcheckd-2015-0214/files/diskcheckd.8 (-3 / +12 lines)
Lines 199-207 Link Here
199
.An Ben Smithurst Aq ben@FreeBSD.org ,
199
.An Ben Smithurst Aq ben@FreeBSD.org ,
200
with input from
200
with input from
201
.An Poul-Henning Kamp Aq phk@FreeBSD.org .
201
.An Poul-Henning Kamp Aq phk@FreeBSD.org .
202
The geom-aware version of the sector->partition translation code was added by
203
.An Perry Hutchison Aq perryh@pluto.rain.com ,
204
based on a mechanism suggested by
205
.An Warner Losh Aq imp@bsdimp.com .
202
.Sh BUGS
206
.Sh BUGS
203
.Nm
207
.Nm
204
assumes all disks have 512 byte sectors.
208
Too much of the code assumes all disks have 512 byte sectors.
205
.Pp
209
.Pp
206
The code that attempts to identify and report which slice and partition
210
There are two versions of the code that attempts to identify
207
contain a detected error does not understand GPT partitions.
211
and report which slice and/or partition contain a detected error.
212
The older version, used when the DIOCGDINFO ioctl is available
213
(i.e. prior to
214
.Fx 11.0 ),
215
does not understand either GPT partitions or dedicated BSD disks
216
(having the BSD disklabel in place of an MBR).
(-)diskcheckd-2015-0214/files/diskcheckd.c (-17 / +141 lines)
Lines 22-27 Link Here
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
 * SUCH DAMAGE.
24
 * SUCH DAMAGE.
25
 *
26
 * geom-aware portions of logreaderror() Copyright (c) 2015 Perry Hutchison
27
 * <perryh@pluto.rain.com>, licensed on the same terms as above.
25
 */
28
 */
26
29
27
static const char rcsid[] =
30
static const char rcsid[] =
Lines 58-63 Link Here
58
61
59
#define	READ_SIZE (64 << 10)
62
#define	READ_SIZE (64 << 10)
60
63
64
/*
65
 * Customize format strings according to what printf et al. want for a quad_t.
66
 *
67
 * This should not be necessary -- the whole point of %qd is to match a quad_t
68
 * -- but in LP64 a quad_t is the same size as a long and yet %qd is treated as
69
 * equivalent to %lld (which is correct only if a long is 32 bits, as in ILP32).
70
 */
71
#ifdef	LP64
72
#define QD "%ld"
73
#else
74
#define	QD "%qd"
75
#endif
76
61
struct disk {
77
struct disk {
62
	int fd;
78
	int fd;
63
	char *device;
79
	char *device;
Lines 125-134 Link Here
125
141
126
	initial_debug = debug;
142
	initial_debug = debug;
127
143
128
	openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0), LOG_DAEMON);
144
	openlog("diskcheckd", LOG_CONS|LOG_PID|(debug?LOG_PERROR:0),
145
		LOG_DAEMON);
129
146
130
	if (!debug && daemon(0, 0) < 0) {
147
	if (!debug && daemon(0, 0) < 0) {
131
		syslog(LOG_NOTICE, "daemon failure: %m");
148
		syslog(LOG_NOTICE, "daemon() failure: %m");
132
		exit(EXIT_FAILURE);
149
		exit(EXIT_FAILURE);
133
	}
150
	}
134
151
Lines 309-334 Link Here
309
logreaderror(struct disk *dp, int nbytes) {
326
logreaderror(struct disk *dp, int nbytes) {
310
	quad_t secno;
327
	quad_t secno;
311
	off_t saved_offset;
328
	off_t saved_offset;
329
	char newdev[512];
330
331
#ifdef	DIOCGDINFO
312
	int fd, slice, part;
332
	int fd, slice, part;
313
	struct dos_partition *dos;
333
	struct dos_partition *dos;
314
	struct disklabel label;
334
	struct disklabel label;
315
	char buf[512];
335
	char buf[512];
316
	char newdev[512];
336
#else	/* DIOCGDINFO */
337
	static size_t geomSize = 0;
338
	static char * geomConf = NULL;
339
	char * cp;
340
	static size_t partLen = 31;
341
	static char *part = NULL;
342
	quad_t relsec = -1;
343
	char *typefld = NULL;
344
#endif	/* DIOCGDINFO */
317
345
318
	saved_offset = dseek(dp, 0, SEEK_CUR);
346
	saved_offset = dseek(dp, 0, SEEK_CUR);
319
	secno = (quad_t)saved_offset / dp->secsize;
347
	secno = (quad_t)saved_offset / dp->secsize;
320
	dp->errors++;
348
	dp->errors++;
321
349
322
	syslog(LOG_NOTICE, "error reading %d bytes from sector %qd on %s",
350
	syslog(LOG_NOTICE, "error reading %d bytes from sector " QD " on %s",
323
	    nbytes, secno, dp->device);
351
	    nbytes, secno, dp->device);
324
352
353
#ifdef	DIOCGDINFO
325
	/*
354
	/*
326
	 * First, find out which slice it's in.  To do this, we seek to the
355
	 * First, find out which slice it's in.  To do this, we seek to the
327
	 * start of the disk, read the first sector, and go through the DOS
356
	 * start of the disk, read the first sector, and go through the DOS
328
	 * slice table.
357
	 * slice table.
329
	 */
358
	 */
330
	if (dseek(dp, 0, SEEK_SET) == -1)
359
	if (dseek(dp, 0, SEEK_SET) == -1) {
360
		syslog(LOG_NOTICE, "could not seek to start of disk: %m");
331
		exit(EXIT_FAILURE);
361
		exit(EXIT_FAILURE);
362
	}
332
363
333
	if (read(dp->fd, buf, sizeof buf) != sizeof buf) {
364
	if (read(dp->fd, buf, sizeof buf) != sizeof buf) {
334
		dseek(dp, saved_offset, SEEK_SET);
365
		dseek(dp, saved_offset, SEEK_SET);
Lines 336-344 Link Here
336
	}
367
	}
337
368
338
	/* seek back to where we were */
369
	/* seek back to where we were */
339
	if (dseek(dp, saved_offset, SEEK_SET) == -1)
370
	if (dseek(dp, saved_offset, SEEK_SET) == -1) {
371
		syslog(LOG_NOTICE,
372
		       "could not seek to previous position"
373
		       "after reading first sector: %m");
340
		exit(EXIT_FAILURE);
374
		exit(EXIT_FAILURE);
375
	}
341
376
377
	// TODO:  should validate DOS partition table (vs GPT or dedicated)
342
	dos = (struct dos_partition *)&buf[DOSPARTOFF];
378
	dos = (struct dos_partition *)&buf[DOSPARTOFF];
343
	for (slice = 0; slice < NDOSPART; slice++)
379
	for (slice = 0; slice < NDOSPART; slice++)
344
		if (dos[slice].dp_start <= secno &&
380
		if (dos[slice].dp_start <= secno &&
Lines 347-353 Link Here
347
383
348
	if (slice == NDOSPART) {
384
	if (slice == NDOSPART) {
349
		syslog(LOG_NOTICE,
385
		syslog(LOG_NOTICE,
350
		  "sector %qd on %s doesn't appear "
386
		  "sector " QD " on %s doesn't appear "
351
		  "to be within any DOS slice", secno, dp->device);
387
		  "to be within any DOS slice", secno, dp->device);
352
		return;
388
		return;
353
	}
389
	}
Lines 361-368 Link Here
361
	/* Check the type of that partition. */
397
	/* Check the type of that partition. */
362
	if (dos[slice].dp_typ != DOSPTYP_386BSD) {
398
	if (dos[slice].dp_typ != DOSPTYP_386BSD) {
363
		/* If not a BSD slice, we can't do much more. */
399
		/* If not a BSD slice, we can't do much more. */
364
		syslog(LOG_NOTICE, "last bad sector is sector %qd "
400
		syslog(LOG_NOTICE, "last bad sector is sector " QD
365
		    "on device %s, type %02x", secno, newdev,
401
		    " on device %s, type %02x", secno, newdev,
366
		    dos[slice].dp_typ);
402
		    dos[slice].dp_typ);
367
		return;
403
		return;
368
	}
404
	}
Lines 389-395 Link Here
389
425
390
	if (part == MAXPARTITIONS) {
426
	if (part == MAXPARTITIONS) {
391
		syslog(LOG_NOTICE,
427
		syslog(LOG_NOTICE,
392
		  "sector %qd on %s doesn't appear "
428
		  "sector " QD " on %s doesn't appear "
393
		  "to be within any BSD partition", secno, newdev);
429
		  "to be within any BSD partition", secno, newdev);
394
		return;
430
		return;
395
	}
431
	}
Lines 400-413 Link Here
400
	syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev);
436
	syslog(LOG_DEBUG, "bad sector seems to be within %s", newdev);
401
	if (label.d_partitions[part].p_fstype != FS_BSDFFS) {
437
	if (label.d_partitions[part].p_fstype != FS_BSDFFS) {
402
		/* Again, if not a BSD partition, can't do much. */
438
		/* Again, if not a BSD partition, can't do much. */
403
		syslog(LOG_NOTICE, "last bad sector is sector %qd "
439
		syslog(LOG_NOTICE, "last bad sector is sector " QD
404
		    "on device %s, type %s", secno, newdev,
440
		    " on device %s, type %s", secno, newdev,
405
		    fstypename(label.d_partitions[part].p_fstype));
441
		    fstypename(label.d_partitions[part].p_fstype));
406
		return;
442
		return;
407
	}
443
	}
444
#else	/* DIOCGDINFO */
445
	if (geomSize == 0) {
446
		sysctlbyname("kern.geom.conftxt", NULL, &geomSize, NULL, 0);
447
		if (geomSize <= 0) {
448
			printf("sysctlbyname() returned size = %d\n", geomSize);
449
			geomSize = 0;
450
			exit(EXIT_FAILURE);
451
		}
452
		geomConf = malloc(geomSize);
453
		if (geomConf == NULL) {
454
			printf("malloc(%d) returned NULL\n", geomSize);
455
			geomSize = 0;
456
			exit(EXIT_FAILURE);
457
		}
458
		if (sysctlbyname("kern.geom.conftxt", geomConf, &geomSize,
459
				 NULL, 0) != 0) {
460
			perror("sysctlbyname()");
461
			geomSize = 0;
462
			free(geomConf);
463
			geomConf = NULL;
464
			exit(EXIT_FAILURE);
465
		}
466
	}
467
	if (part == NULL)
468
		part = malloc(partLen + 1);
469
470
	for ( cp = geomConf ; *cp ; ++cp ) {
471
		// find line "0 DISK " matching current disk, using
472
		// strncmp because where cp points is not null-terminated
473
		// (All DISK lines, and only DISK lines, are at level 0.)
474
		// Magic numbers:  7 == strlen("0 DISK "); 5 == strlen("/dev/")
475
		if (strncmp(cp, "0 DISK ", 7) == 0
476
		 && strncmp(&cp[7], &dp->device[5], strlen(dp->device) - 5) == 0
477
		 && cp[7 + strlen(dp->device) - 5] == ' ') {
478
			for (;;) {
479
				// scan to end of line
480
				while (cp[1] && *cp != '\n')
481
					++cp;
482
				++cp;	// start of next line
483
				// Find PART line containing the failed sector;
484
				// must be on same disk => stop upon finding
485
				// another DISK line.  If more than one matching
486
				// PART -- due to nested geoms -- use the last
487
				// (innermost).
488
				if (*cp == '\0' || *cp == '0')
489
					break;	// end of current DISK's entries
490
				// scan to end of level number
491
				while (cp[1] && *cp != ' ')
492
					++cp;
493
				if (strncmp(cp, " PART ", 6) == 0) {
494
					char *pp = &cp[6];
495
					int pl = strchr(pp, ' ') - pp;
496
					quad_t mediasize, offset;
497
					long secsize;
498
499
					cp = pp + pl;	// cp -> mediasize
500
					mediasize = strtoq(cp, &cp, 10);
501
					secsize = strtol(cp, &cp, 10);
502
					mediasize /= secsize;
503
					cp = strchr(cp, 'o') + 1;
504
					offset = strtoq(cp, &cp, 10) / secsize;
505
					if (secno >= offset
506
					 && (secno - offset) < mediasize) {
507
						if (pl > partLen) {
508
							part = realloc(part,
509
									pl+1);
510
							partLen = pl;
511
						}
512
						strncpy(part, pp, pl);
513
						part[pl] = '\0';
514
						relsec = secno - offset;
515
						typefld = cp + 1;
516
					}
517
				}
518
			}
519
		}
520
		// scan to end of line
521
		while (cp[1] && *cp != '\n')
522
			++cp;
523
	}
524
////	printf("part %s, relsec %qd, typefld %p: %.27s\n",
525
////		part, relsec, typefld, typefld);
526
	secno = relsec;
527
	strncpy(newdev, part, sizeof(newdev) - 1);
528
	newdev[sizeof(newdev) - 1] = '\0';		// paranoia
529
#endif	/* DIOCGDINFO */
408
530
409
	syslog(LOG_NOTICE, "last bad sector is sector %qd "
531
	syslog(LOG_NOTICE, "last bad sector is sector " QD
410
	  "on 4.2BSD filesystem %s", secno, newdev);
532
	  " on 4.2BSD filesystem %s", secno, newdev);
411
533
412
	/*
534
	/*
413
	 * XXX: todo: find out which file on the BSD filesystem uses this
535
	 * XXX: todo: find out which file on the BSD filesystem uses this
Lines 472-483 Link Here
472
			"#\tposition/size\tdays\trate\terrors\tintvl\tnext\n");
594
			"#\tposition/size\tdays\trate\terrors\tintvl\tnext\n");
473
	for (dp = disks; dp->device != NULL; dp++)
595
	for (dp = disks; dp->device != NULL; dp++)
474
		if (strcmp(dp->device, "*") != 0) {
596
		if (strcmp(dp->device, "*") != 0) {
475
			fprintf(fp, "%s %qd\n", dp->device,
597
			fprintf(fp, "%s " QD "\n", dp->device,
476
			    (quad_t)dseek(dp, 0, SEEK_CUR));
598
			    (quad_t)dseek(dp, 0, SEEK_CUR));
477
			if (debug) {
599
			if (debug) {
478
				fprintf(stderr, "%s %qd\n", dp->device,
600
				fprintf(stderr, "%s " QD "\n", dp->device,
479
					(quad_t)dseek(dp, 0, SEEK_CUR));
601
					(quad_t)dseek(dp, 0, SEEK_CUR));
480
				fprintf(stderr, "#\t%qd\t%d\t%d\t%d\t%qd\t%qd\n",
602
				fprintf(stderr,
603
					"#\t" QD "\t%d\t%d\t%d\t" QD "\t" QD
604
					"\n",
481
					(quad_t)dp->size, dp->days, dp->rate,
605
					(quad_t)dp->size, dp->days, dp->rate,
482
					dp->errors, dp->interval, dp->next);
606
					dp->errors, dp->interval, dp->next);
483
			}
607
			}

Return to bug 197841