From cjk32@cam.ac.uk  Tue Jun  7 17:23:16 2011
Return-Path: <cjk32@cam.ac.uk>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id AF746106566B
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  7 Jun 2011 17:23:16 +0000 (UTC)
	(envelope-from cjk32@cam.ac.uk)
Received: from chacal.cjkey.org.uk (chacal.cjkey.org.uk [88.97.163.217])
	by mx1.freebsd.org (Postfix) with ESMTP id 34D8D8FC14
	for <FreeBSD-gnats-submit@freebsd.org>; Tue,  7 Jun 2011 17:23:15 +0000 (UTC)
Received: from chacal.wzl33 (localhost [127.0.0.1])
	by chacal.cjkey.org.uk (8.14.4/8.14.4) with ESMTP id p57GjFDr018047
	for <FreeBSD-gnats-submit@freebsd.org>; Tue, 7 Jun 2011 17:45:15 +0100 (BST)
	(envelope-from chris@chacal.wzl33)
Received: (from chris@localhost)
	by chacal.wzl33 (8.14.4/8.14.4/Submit) id p57GjFUL018046;
	Tue, 7 Jun 2011 17:45:15 +0100 (BST)
	(envelope-from chris)
Message-Id: <201106071645.p57GjFUL018046@chacal.wzl33>
Date: Tue, 7 Jun 2011 17:45:15 +0100 (BST)
From: Christopher Key <cjk32@cam.ac.uk>
Reply-To: Christopher Key <cjk32@cam.ac.uk>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [zfs] [patch] zpool import -d broken
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         157691
>Category:       bin
>Synopsis:       [zfs] [patch] zpool import -d broken
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    delphij
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Jun 07 17:30:09 UTC 2011
>Closed-Date:    Thu Jun 09 22:58:49 UTC 2011
>Last-Modified:  Thu Jun 09 22:58:49 UTC 2011
>Originator:     Christopher Key
>Release:        FreeBSD 8.2-RC3 amd64
>Organization:
>Environment:
System: FreeBSD chacal.wzl33 8.2-RC3 FreeBSD 8.2-RC3 #6: Mon Feb 14 00:36:21 GMT 2011 root@chacal.wzl33:/usr/obj/usr/src/sys/CHACAL amd64


>Description:
zfs import -d <dir> is supposed to enumerate the contents of dir, opening and statting each item within before possible further processing.  However, the way in which the path to be opened and statted is built is broken.  The fundamental problem is repeated usage of,

snprintf(path, sizeof (path), "%s/%s", rdsk, dp->d_name)

where,

rdsk == path

>How-To-Repeat:
Without patch:

chris@chacal:~> ls -al /dev/mirror
total 1
dr-xr-xr-x   2 root  wheel          512  6 Jun 19:20 .
dr-xr-xr-x  11 root  wheel          512  6 Jun 19:20 ..
crw-r-----   1 root  operator    0, 108  6 Jun 19:20 gm0
crw-r-----   1 root  operator    0, 112  6 Jun 19:20 gm0p1
crw-r-----   1 root  operator    0, 113  6 Jun 19:20 gm0p2
crw-r-----   1 root  operator    0, 114  6 Jun 19:20 gm0p3
crw-r-----   1 root  operator    0, 115  6 Jun 19:20 gm0p4
crw-r-----   1 root  operator    0, 116  6 Jun 19:20 gm0p5
crw-r-----   1 root  operator    0, 117  6 Jun 19:20 gm0p6
crw-r-----   1 root  operator    0, 143  6 Jun 19:20 gm1
crw-r-----   1 root  operator    0, 189  6 Jun 19:20 gm1s1
crw-r-----   1 root  operator    0, 190  6 Jun 19:20 gm1s2
crw-r-----   1 root  operator    0, 191  6 Jun 19:20 gm1s3
chris@chacal:~> sudo truss zpool import -d /dev/mirror 2>&1 | grep /dev
open("/dev/zfs",O_RDWR,00) 	 	 = 3 (0x3)
open("/dev/zero",O_RDONLY,0666)		      = 4 (0x4)
lstat("/dev",{ mode=dr-xr-xr-x ,inode=2,size=512,blksize=4096 }) = 0 (0x0)
lstat("/dev/mirror",{ mode=dr-xr-xr-x ,inode=215,size=512,blksize=4096 }) = 0 (0x0)
stat("/dev/mirror/",{ mode=dr-xr-xr-x ,inode=215,size=512,blksize=4096 }) = 0 (0x0)
open("/dev/mirror/",O_NONBLOCK,01)    				        = 6 (0x6)
open("/dev/mirror//gm0",O_RDONLY,00)					   = 7 (0x7)
open("/dev/mirror//gm0/gm0p1",O_RDONLY,00)				    ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5/gm0p6",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5/gm0p6/gm1",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5/gm0p6/gm1/gm1s1",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5/gm0p6/gm1/gm1s1/gm1s2",O_RDONLY,00) ERR#20 'Not a directory'
open("/dev/mirror//gm0/gm0p1/gm0p2/gm0p3/gm0p4/gm0p5/gm0p6/gm1/gm1s1/gm1s2/gm1s3",O_RDONLY,00) ERR#20 'Not a directory'


With patch:

chris@chacal:~> ls -al /dev/mirror
total 1
dr-xr-xr-x   2 root  wheel          512  6 Jun 19:20 .
dr-xr-xr-x  11 root  wheel          512  6 Jun 19:20 ..
crw-r-----   1 root  operator    0, 108  6 Jun 19:20 gm0
crw-r-----   1 root  operator    0, 112  6 Jun 19:20 gm0p1
crw-r-----   1 root  operator    0, 113  6 Jun 19:20 gm0p2
crw-r-----   1 root  operator    0, 114  6 Jun 19:20 gm0p3
crw-r-----   1 root  operator    0, 115  6 Jun 19:20 gm0p4
crw-r-----   1 root  operator    0, 116  6 Jun 19:20 gm0p5
crw-r-----   1 root  operator    0, 117  6 Jun 19:20 gm0p6
crw-r-----   1 root  operator    0, 143  6 Jun 19:20 gm1
crw-r-----   1 root  operator    0, 189  6 Jun 19:20 gm1s1
crw-r-----   1 root  operator    0, 190  6 Jun 19:20 gm1s2
crw-r-----   1 root  operator    0, 191  6 Jun 19:20 gm1s3
chris@chacal:~> sudo truss zpool import -d /dev/mirror 2>&1 | grep /dev
open("/dev/zfs",O_RDWR,00) 	 	 = 3 (0x3)
open("/dev/zero",O_RDONLY,0666)		      = 4 (0x4)
lstat("/dev",{ mode=dr-xr-xr-x ,inode=2,size=512,blksize=4096 }) = 0 (0x0)
lstat("/dev/mirror",{ mode=dr-xr-xr-x ,inode=215,size=512,blksize=4096 }) = 0 (0x0)
stat("/dev/mirror/",{ mode=dr-xr-xr-x ,inode=215,size=512,blksize=4096 }) = 0 (0x0)
open("/dev/mirror/",O_NONBLOCK,0144)  				        = 6 (0x6)
open("/dev/mirror/gm0",O_RDONLY,01760)					   = 7 (0x7)
open("/dev/mirror/gm0p1",O_RDONLY,01756)				    = 7 (0x7)
open("/dev/mirror/gm0p2",O_RDONLY,01756)				     = 7 (0x7)
open("/dev/mirror/gm0p3",O_RDONLY,01756)				      = 7 (0x7)
open("/dev/mirror/gm0p4",O_RDONLY,01756)				       = 7 (0x7)
open("/dev/mirror/gm0p5",O_RDONLY,01756)				        = 7 (0x7)
open("/dev/mirror/gm0p6",O_RDONLY,01756)					 = 7 (0x7)
open("/dev/mirror/gm1",O_RDONLY,01760)						    = 7 (0x7)
open("/dev/mirror/gm1s1",O_RDONLY,01756)					     = 7 (0x7)
open("/dev/mirror/gm1s2",O_RDONLY,01756)					      = 7 (0x7)
open("/dev/mirror/gm1s3",O_RDONLY,01756)					       = 7 (0x7)


>Fix:

	

--- zpool-import-d-patch begins here ---
Index: cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c
===================================================================
--- cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c	(revision 218622)
+++ cddl/contrib/opensolaris/lib/libzfs/common/libzfs_import.c	(working copy)
@@ -869,7 +869,6 @@
 	 * and toplevel GUID.
 	 */
 	for (i = 0; i < argc; i++) {
-		char *rdsk;
 		int dfd;
 
 		/* use realpath to normalize the path */
@@ -889,21 +888,11 @@
 			continue;
 		}
 
-		/*
-		 * Using raw devices instead of block devices when we're
-		 * reading the labels skips a bunch of slow operations during
-		 * close(2) processing, so we replace /dev/dsk with /dev/rdsk.
-		 */
-		if (strcmp(path, "/dev/dsk/") == 0)
-			rdsk = "/dev/rdsk/";
-		else
-			rdsk = path;
-
-		if ((dirp = opendir(rdsk)) == NULL) {
+		if ((dirp = opendir(path)) == NULL) {
 			zfs_error_aux(hdl, strerror(errno));
 			(void) zfs_error_fmt(hdl, EZFS_BADPATH,
 			    dgettext(TEXT_DOMAIN, "cannot open '%s'"),
-			    rdsk);
+			    path);
 			goto error;
 		}
 
@@ -916,8 +905,7 @@
 			    (name[1] == 0 || (name[1] == '.' && name[2] == 0)))
 				continue;
 
-			(void) snprintf(path, sizeof (path), "%s/%s", rdsk,
-			    dp->d_name);
+			(void) strlcpy(end, name, pathleft);
 
 			if ((fd = open64(path, O_RDONLY)) < 0)
 				continue;
@@ -965,8 +953,7 @@
 					config = NULL;
 					continue;
 				}
-				/* use the non-raw path for the config */
-				(void) strlcpy(end, name, pathleft);
+
 				if (add_config(hdl, &pools, path, config) != 0)
 					goto error;
 			}
--- zpool-import-d-patch ends here ---


>Release-Note:
>Audit-Trail:

From: Christopher Key <cjk32@cam.ac.uk>
To: bug-followup@FreeBSD.org, cjk32@cam.ac.uk
Cc:  
Subject: Re: bin/157691: [zfs] [patch] zpool import -d broken
Date: Wed, 08 Jun 2011 15:32:53 +0100

 Forgot to mention that this has apparently been fixed in 9-CURRENT by
 the newer version of ZFS.
 
 Subsequent investigation has shown that the new version of ZFS has also
 been MFCed to 8-STABLE, so 8.2 is the last release affected by this
 bug.  It can therefore probably be closed.
 
Responsible-Changed-From-To: freebsd-bugs->freebsd-fs 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Thu Jun 9 21:28:54 UTC 2011 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=157691 
State-Changed-From-To: open->closed 
State-Changed-By: delphij 
State-Changed-When: Thu Jun 9 22:58:07 UTC 2011 
State-Changed-Why:  
This should have been fixed in a newer 8-STABLE snapshot, per 
submitter. 


Responsible-Changed-From-To: freebsd-fs->delphij 
Responsible-Changed-By: delphij 
Responsible-Changed-When: Thu Jun 9 22:58:07 UTC 2011 
Responsible-Changed-Why:  
Take just in case. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=157691 
>Unformatted:
