From nobody@FreeBSD.org  Mon Mar 22 18:41:15 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 207B5106566B
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 22 Mar 2010 18:41:15 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 0EEEF8FC0A
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 22 Mar 2010 18:41:15 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o2MIfElC090245
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 22 Mar 2010 18:41:14 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o2MIfEO0090207;
	Mon, 22 Mar 2010 18:41:14 GMT
	(envelope-from nobody)
Message-Id: <201003221841.o2MIfEO0090207@www.freebsd.org>
Date: Mon, 22 Mar 2010 18:41:14 GMT
From: Bruce Cran <bruce@cran.org.uk>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [geom] panic when accessing GPT disk with a large number of entries
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         144962
>Category:       kern
>Synopsis:       [geom] panic when accessing GPT disk with a large number of entries
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    ae
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 22 18:50:02 UTC 2010
>Closed-Date:    Sat Feb 05 14:36:43 UTC 2011
>Last-Modified:  Sat Feb 05 14:36:43 UTC 2011
>Originator:     Bruce Cran
>Release:        9.0-CURRENT
>Organization:
>Environment:
FreeBSD core.draftnet 9.0-CURRENT FreeBSD 9.0-CURRENT #3 r205344M: Sat Mar 20 21:31:35 GMT 2010     brucec@core.draftnet:/usr/obj/usr/src/head/sys/CORE  amd64
>Description:
After creating a GPT with an excessively large number of entries, FreeBSD then is unable to access the disk without running out of kernel virtual memory.

For example, after running "gpart create -s gpt -n 1000000 da0" then accessing the disk, the system will the panic with "kmem_map too small".
>How-To-Repeat:
Run "gpart create -s gpt -n 1000000 da0" then reboot
>Fix:


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-geom 
Responsible-Changed-By: brucec 
Responsible-Changed-When: Mon Mar 22 19:02:27 UTC 2010 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144962 

From: Alexander Best <alexbestms@wwu.de>
To: <bug-followup@FreeBSD.org>
Cc: Bruce Cran <bruce@cran.org.uk>
Subject: Re: kern/144962: [geom] panic when accessing GPT disk with a large
 number of entries
Date: Tue, 23 Mar 2010 01:09:01 +0100 (CET)

 tried this too under HEAD (r205390):
 
 `gpart create -s gpt -n 1000000 /dev/da0` gave me "gpart: provider: No space
 left on device" so i did `gpart create -s gpt -n 1000000 /dev/da0` instead
 which worked. reattaching the device caused no problem.
 
 when i tried to create a label with `glabel label usb da0` i got:
 
 GEOM: da0: the secondary GPT table is corrupt or invalid.
 GEOM: da0: using the primary only -- recovery suggested.
 GEOM: da0: the secondary GPT table is corrupt or invalid.
 GEOM: da0: using the primary only -- recovery suggested.
 GEOM: label/usb: the secondary GPT table is corrupt or invalid.
 GEOM: label/usb: using the primary only -- recovery suggested.
 
 seems -n 1000000 is not enough to fill up kernel virtual memory in my case.
 
 -- 
 Alexander Best

From: Alexander Best <alexbestms@wwu.de>
To: <bug-followup@FreeBSD.org>
Cc: Bruce Cran <bruce@cran.org.uk>
Subject: Re: kern/144962: [geom] panic when accessing GPT disk with a large
 number of entries
Date: Tue, 23 Mar 2010 01:19:20 +0100 (CET)

 sorry. the command i used was `gpart create -s gpt -n 100000 /dev/da0`.
 
 -- 
 Alexander Best

From: Bruce Cran <brucec@muon.cran.org.uk>
To: Alexander Best <alexbestms@wwu.de>
Cc: bug-followup@FreeBSD.org, Bruce Cran <bruce@cran.org.uk>
Subject: Re: kern/144962: [geom] panic when accessing GPT disk with a large
	number of entries
Date: Tue, 23 Mar 2010 07:46:22 +0000

 I've just recreated the panic - it seems 10,000,000 entries are 
 required to fill virtual memory, not 1,000,000. It takes a very long 
 time for gpart to create them, but on reboot after the disk is detected 
 the system will wait for a couple of minutes before panicing.
 
 -- 
 Bruce Cran
Responsible-Changed-From-To: freebsd-geom->ae 
Responsible-Changed-By: ae 
Responsible-Changed-When: Tue Jan 18 07:32:31 UTC 2011 
Responsible-Changed-Why:  
Take it. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144962 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/144962: commit references a PR
Date: Tue, 18 Jan 2011 09:53:00 +0000 (UTC)

 Author: ae
 Date: Tue Jan 18 09:52:53 2011
 New Revision: 217531
 URL: http://svn.freebsd.org/changeset/base/217531
 
 Log:
   Limit maximum number of GPT entries to 4k. It is most realistic value
   and can prevent kernel memory exhausting when big value is specified
   from command line.
   
   Split reading and writing operation to several iteration to do not
   trigger KASSERT when data length is greater than MAXPHYS.
   
   PR:             kern/144962, kern/147851
   MFC after:      2 weeks
 
 Modified:
   head/sys/geom/part/g_part_gpt.c
 
 Modified: head/sys/geom/part/g_part_gpt.c
 ==============================================================================
 --- head/sys/geom/part/g_part_gpt.c	Tue Jan 18 06:24:52 2011	(r217530)
 +++ head/sys/geom/part/g_part_gpt.c	Tue Jan 18 09:52:53 2011	(r217531)
 @@ -134,7 +134,7 @@ static struct g_part_scheme g_part_gpt_s
  	sizeof(struct g_part_gpt_table),
  	.gps_entrysz = sizeof(struct g_part_gpt_entry),
  	.gps_minent = 128,
 -	.gps_maxent = INT_MAX,
 +	.gps_maxent = 4096,
  	.gps_bootcodesz = MBRSIZE,
  };
  G_PART_SCHEME_DECLARE(g_part_gpt);
 @@ -317,7 +317,7 @@ gpt_read_tbl(struct g_part_gpt_table *ta
  	struct g_provider *pp;
  	struct gpt_ent *ent, *tbl;
  	char *buf, *p;
 -	unsigned int idx, sectors, tblsz;
 +	unsigned int idx, sectors, tblsz, size;
  	int error;
  
  	if (hdr == NULL)
 @@ -329,11 +329,19 @@ gpt_read_tbl(struct g_part_gpt_table *ta
  	table->state[elt] = GPT_STATE_MISSING;
  	tblsz = hdr->hdr_entries * hdr->hdr_entsz;
  	sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize;
 -	buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, 
 -	    sectors * pp->sectorsize, &error);
 -	if (buf == NULL)
 -		return (NULL);
 -
 +	buf = g_malloc(sectors * pp->sectorsize, M_WAITOK | M_ZERO);
 +	for (idx = 0; idx < sectors; idx += MAXPHYS / pp->sectorsize) {
 +		size = (sectors - idx > MAXPHYS / pp->sectorsize) ?  MAXPHYS:
 +		    (sectors - idx) * pp->sectorsize;
 +		p = g_read_data(cp, (table->lba[elt] + idx) * pp->sectorsize,
 +		    size, &error);
 +		if (p == NULL) {
 +			g_free(buf);
 +			return (NULL);
 +		}
 +		bcopy(p, buf + idx * pp->sectorsize, size);
 +		g_free(p);
 +	}
  	table->state[elt] = GPT_STATE_CORRUPT;
  	if (crc32(buf, tblsz) != hdr->hdr_crc_table) {
  		g_free(buf);
 @@ -986,10 +994,15 @@ g_part_gpt_write(struct g_part_table *ba
  	crc = crc32(buf, table->hdr->hdr_size);
  	le32enc(buf + 16, crc);
  
 -	error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize,
 -	    buf + pp->sectorsize, tblsz * pp->sectorsize);
 -	if (error)
 -		goto out;
 +	for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) {
 +		error = g_write_data(cp,
 +		    (table->lba[GPT_ELT_PRITBL] + index) * pp->sectorsize,
 +		    buf + (index + 1) * pp->sectorsize,
 +		    (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS:
 +		    (tblsz - index) * pp->sectorsize);
 +		if (error)
 +			goto out;
 +	}
  	error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize,
  	    buf, pp->sectorsize);
  	if (error)
 @@ -1003,10 +1016,15 @@ g_part_gpt_write(struct g_part_table *ba
  	crc = crc32(buf, table->hdr->hdr_size);
  	le32enc(buf + 16, crc);
  
 -	error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize,
 -	    buf + pp->sectorsize, tblsz * pp->sectorsize);
 -	if (error)
 -		goto out;
 +	for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) {
 +		error = g_write_data(cp,
 +		    (table->lba[GPT_ELT_SECTBL] + index) * pp->sectorsize,
 +		    buf + (index + 1) * pp->sectorsize,
 +		    (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS:
 +		    (tblsz - index) * pp->sectorsize);
 +		if (error)
 +			goto out;
 +	}
  	error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize,
  	    buf, pp->sectorsize);
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: ae 
State-Changed-When: Tue Jan 18 10:10:37 UTC 2011 
State-Changed-Why:  
Patched in head/. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=144962 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: kern/144962: commit references a PR
Date: Tue,  1 Feb 2011 09:27:38 +0000 (UTC)

 Author: ae
 Date: Tue Feb  1 09:27:28 2011
 New Revision: 218162
 URL: http://svn.freebsd.org/changeset/base/218162
 
 Log:
   MFC r217531:
     Limit maximum number of GPT entries to 4k. It is most realistic value
     and can prevent kernel memory exhausting when big value is specified
     from command line.
   
     Split reading and writing operation to several iterations to do not
     trigger KASSERT when data length is greater than MAXPHYS.
   
     PR:             kern/144962, kern/147851
 
 Modified:
   stable/8/sys/geom/part/g_part_gpt.c
 Directory Properties:
   stable/8/sys/   (props changed)
   stable/8/sys/amd64/include/xen/   (props changed)
   stable/8/sys/cddl/contrib/opensolaris/   (props changed)
   stable/8/sys/contrib/dev/acpica/   (props changed)
   stable/8/sys/contrib/pf/   (props changed)
 
 Modified: stable/8/sys/geom/part/g_part_gpt.c
 ==============================================================================
 --- stable/8/sys/geom/part/g_part_gpt.c	Tue Feb  1 09:27:24 2011	(r218161)
 +++ stable/8/sys/geom/part/g_part_gpt.c	Tue Feb  1 09:27:28 2011	(r218162)
 @@ -134,7 +134,7 @@ static struct g_part_scheme g_part_gpt_s
  	sizeof(struct g_part_gpt_table),
  	.gps_entrysz = sizeof(struct g_part_gpt_entry),
  	.gps_minent = 128,
 -	.gps_maxent = INT_MAX,
 +	.gps_maxent = 4096,
  	.gps_bootcodesz = MBRSIZE,
  };
  G_PART_SCHEME_DECLARE(g_part_gpt);
 @@ -317,7 +317,7 @@ gpt_read_tbl(struct g_part_gpt_table *ta
  	struct g_provider *pp;
  	struct gpt_ent *ent, *tbl;
  	char *buf, *p;
 -	unsigned int idx, sectors, tblsz;
 +	unsigned int idx, sectors, tblsz, size;
  	int error;
  
  	if (hdr == NULL)
 @@ -329,11 +329,19 @@ gpt_read_tbl(struct g_part_gpt_table *ta
  	table->state[elt] = GPT_STATE_MISSING;
  	tblsz = hdr->hdr_entries * hdr->hdr_entsz;
  	sectors = (tblsz + pp->sectorsize - 1) / pp->sectorsize;
 -	buf = g_read_data(cp, table->lba[elt] * pp->sectorsize, 
 -	    sectors * pp->sectorsize, &error);
 -	if (buf == NULL)
 -		return (NULL);
 -
 +	buf = g_malloc(sectors * pp->sectorsize, M_WAITOK | M_ZERO);
 +	for (idx = 0; idx < sectors; idx += MAXPHYS / pp->sectorsize) {
 +		size = (sectors - idx > MAXPHYS / pp->sectorsize) ?  MAXPHYS:
 +		    (sectors - idx) * pp->sectorsize;
 +		p = g_read_data(cp, (table->lba[elt] + idx) * pp->sectorsize,
 +		    size, &error);
 +		if (p == NULL) {
 +			g_free(buf);
 +			return (NULL);
 +		}
 +		bcopy(p, buf + idx * pp->sectorsize, size);
 +		g_free(p);
 +	}
  	table->state[elt] = GPT_STATE_CORRUPT;
  	if (crc32(buf, tblsz) != hdr->hdr_crc_table) {
  		g_free(buf);
 @@ -986,10 +994,15 @@ g_part_gpt_write(struct g_part_table *ba
  	crc = crc32(buf, table->hdr->hdr_size);
  	le32enc(buf + 16, crc);
  
 -	error = g_write_data(cp, table->lba[GPT_ELT_PRITBL] * pp->sectorsize,
 -	    buf + pp->sectorsize, tblsz * pp->sectorsize);
 -	if (error)
 -		goto out;
 +	for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) {
 +		error = g_write_data(cp,
 +		    (table->lba[GPT_ELT_PRITBL] + index) * pp->sectorsize,
 +		    buf + (index + 1) * pp->sectorsize,
 +		    (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS:
 +		    (tblsz - index) * pp->sectorsize);
 +		if (error)
 +			goto out;
 +	}
  	error = g_write_data(cp, table->lba[GPT_ELT_PRIHDR] * pp->sectorsize,
  	    buf, pp->sectorsize);
  	if (error)
 @@ -1003,10 +1016,15 @@ g_part_gpt_write(struct g_part_table *ba
  	crc = crc32(buf, table->hdr->hdr_size);
  	le32enc(buf + 16, crc);
  
 -	error = g_write_data(cp, table->lba[GPT_ELT_SECTBL] * pp->sectorsize,
 -	    buf + pp->sectorsize, tblsz * pp->sectorsize);
 -	if (error)
 -		goto out;
 +	for (index = 0; index < tblsz; index += MAXPHYS / pp->sectorsize) {
 +		error = g_write_data(cp,
 +		    (table->lba[GPT_ELT_SECTBL] + index) * pp->sectorsize,
 +		    buf + (index + 1) * pp->sectorsize,
 +		    (tblsz - index > MAXPHYS / pp->sectorsize) ? MAXPHYS:
 +		    (tblsz - index) * pp->sectorsize);
 +		if (error)
 +			goto out;
 +	}
  	error = g_write_data(cp, table->lba[GPT_ELT_SECHDR] * pp->sectorsize,
  	    buf, pp->sectorsize);
  
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: ae 
State-Changed-When: Sat Feb 5 14:36:16 UTC 2011 
State-Changed-Why:  
Fixed in head/ and stable/8. 

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