bin/148296: [zfs] [loader] Very slow probe in /usr/src/sys/boot/zfs/zfs.c

Jimmy Olgeni olgeni at FreeBSD.org
Thu Jul 1 16:10:07 UTC 2010


>Number:         148296
>Category:       bin
>Synopsis:       [zfs] [loader] Very slow probe in /usr/src/sys/boot/zfs/zfs.c
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 01 16:10:06 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Jimmy Olgeni
>Release:        FreeBSD 8.1-RC1 i386
>Organization:
>Environment:
System: FreeBSD backoffice 8.1-RC1 FreeBSD 8.1-RC1 #0: Fri Jun 25 21:42:58 CEST 2010 root at backoffice:/usr/obj/usr/src/sys/RELENG_8.i386 i386
>Description:

Code in /usr/src/sys/boot/zfs/zfs.c (zfs_dev_init) probes all
possible disks/partitions to reconstruct ZFS pools.

Until rev 198420 it used to probe 4 partitions, which caused no
harm. However, with rev 198420 it started to probe all 128 possible
GPT partitions, causing very long boot times.

The problem is that for each possible GPT partition (diskNpM) the
code tries to fall back to a MBR slice (diskNsM).

When the code falls back to probing slices it actually ignores the
fact that the diskNpM partition could not be opened, and keeps
probing missing partitions up to index 128 (which takes a while).

If the partition index is > 4, the code tries to probe slices that
cannot possibly exist (diskNs5, ...), thus doubling the already
long processing time.

>How-To-Repeat:
>Fix:

Since we are looking for boot partitions, I think it should be safe
to assume that there are no empty partitions before them.

I moved slice probing into a separate loop to avoid any issues with
fallback code.

With the attached patch my 8.1-RC1 zfs-only server got back its old
boot time.

*** zfs.c.orig	Thu Jul  1 17:14:42 2010
--- zfs.c	Thu Jul  1 17:40:03 2010
***************
*** 413,427 ****
  		if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  			close(fd);
  
  		for (slice = 1; slice <= 128; slice++) {
  			sprintf(devname, "disk%dp%d:", unit, slice);
  			fd = open(devname, O_RDONLY);
! 			if (fd == -1) {
! 				sprintf(devname, "disk%ds%d:", unit, slice);
! 				fd = open(devname, O_RDONLY);
! 				if (fd == -1)
! 					continue;
! 			}
  			if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  				close(fd);
  		}
--- 413,432 ----
  		if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  			close(fd);
  
+ 		for (slice = 1; slice <= 4; slice++) {
+ 			sprintf(devname, "disk%ds%d:", unit, slice);
+ 			fd = open(devname, O_RDONLY);
+ 			if (fd == -1)
+ 				continue;
+ 			if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
+ 				close(fd);
+ 		}
+ 
  		for (slice = 1; slice <= 128; slice++) {
  			sprintf(devname, "disk%dp%d:", unit, slice);
  			fd = open(devname, O_RDONLY);
! 			if (fd == -1)
! 				break;
  			if (vdev_probe(vdev_read, (void*) (uintptr_t) fd, 0))
  				close(fd);
  		}
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list