From nobody@FreeBSD.org  Tue May  4 00:24:16 2010
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52])
	by hub.freebsd.org (Postfix) with ESMTP id DE29F106564A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  4 May 2010 00:24:16 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [69.147.83.33])
	by mx1.freebsd.org (Postfix) with ESMTP id CE3B38FC12
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  4 May 2010 00:24:16 +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 o440OGKG028307
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 4 May 2010 00:24:16 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id o440OGVW028300;
	Tue, 4 May 2010 00:24:16 GMT
	(envelope-from nobody)
Message-Id: <201005040024.o440OGVW028300@www.freebsd.org>
Date: Tue, 4 May 2010 00:24:16 GMT
From: Jeremy Faulkner <gldisater@gmail.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: gpart add -s 128M creates 1GB partition on 4k sectorsize disk
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         146277
>Category:       bin
>Synopsis:       gpart(8): gpart add -s 128M creates 1GB partition on 4k sectorsize disk
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    ae
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue May 04 00:30:00 UTC 2010
>Closed-Date:    Wed Jul 21 08:49:46 UTC 2010
>Last-Modified:  Wed Jul 21 08:50:03 UTC 2010
>Originator:     Jeremy Faulkner
>Release:        9-current
>Organization:
>Environment:
FreeBSD planet 9.0-CURRENT FreeBSD 9.0-CURRENT #1: Sun May 2 20:31:09 EDT 2010 gldisater@planet:/usr/obj/usr/src/sys/GENERIC i386
>Description:
When using gpart to create a GPT partition on a device that has a sector size of 4k it will create a partition that is much larger than requested. It appears to be using 512 sector size to calculate the number of sectors to allocate even when the sector size is not 512.
>How-To-Repeat:
gnop create -S 4k <disk or partition>
gpart create -s GPT <gnop'd disk or partition>
gpart add -s 512M -t freebsd-swap <gnop'd disk or partition>

gpart will create a 4GB partition instead of a 512M partition
>Fix:


>Release-Note:
>Audit-Trail:

From: "Andrey V. Elsukov" <bu7cher@yandex.ru>
To: Jeremy Faulkner <gldisater@gmail.com>
Cc: freebsd-gnats-submit@FreeBSD.org, 
 Marcel Moolenaar <marcel@FreeBSD.org>
Subject: Re: misc/146277: gpart add -s 128M creates 1GB partition on 4k	sectorsize
 disk
Date: Tue, 04 May 2010 08:59:13 +0400

 On 04.05.2010 4:24, Jeremy Faulkner wrote:
 >> Description:
 > When using gpart to create a GPT partition on a device that has a sector size of 4k it will
 > create a partition that is much larger than requested. It appears to be using 512 sector size to
 > calculate the number of sectors to allocate even when the sector size is not 512.
 >> How-To-Repeat:
 > gnop create -S 4k<disk or partition> gpart create -s GPT<gnop'd disk or partition> gpart add -s
 > 512M -t freebsd-swap<gnop'd disk or partition>
 >
 > gpart will create a 4GB partition instead of a 512M partition
 
 This is known issue. When gpart(8) parses arguments it doesn't know about medium's sector size.
 
 -- 
 WBR, Andrey V. Elsukov
State-Changed-From-To: open->suspended 
State-Changed-By: linimon 
State-Changed-When: Tue May 4 16:37:54 UTC 2010 
State-Changed-Why:  
Mark this suspended as being a known issue. 


Responsible-Changed-From-To: freebsd-bugs->freebsd-geom 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Tue May 4 16:37:54 UTC 2010 
Responsible-Changed-Why:  
Reclassify and reassign. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/146277: commit references a PR
Date: Mon, 21 Jun 2010 08:25:11 +0000 (UTC)

 Author: ae
 Date: Mon Jun 21 08:24:50 2010
 New Revision: 209388
 URL: http://svn.freebsd.org/changeset/base/209388
 
 Log:
   Remove G_TYPE_ASCLBA type and replace it with G_TYPE_STRING in gpart.
   Move code that converts params from humanized numbers to sectors count
   to subr.c and adjust comment.
   Add post-processing for "size" and "start offset" params in gpart,
   now they are properly converted to sectors count with known sector size
   that can be greater that 512 bytes.
   Also replace "unsigned long long" type to "off_t" for unify code since
   it used for medium size in libgeom(3) and DIOCGMEDIASIZE ioctl.
   
   PR:		bin/146277
   Reviewed by:	marcel (previous version)
   Approved by:	kib (mentor)
   MFC after:	1 month
 
 Modified:
   head/sbin/geom/class/part/geom_part.c
   head/sbin/geom/core/geom.c
   head/sbin/geom/core/geom.h
   head/sbin/geom/misc/subr.c
   head/sbin/geom/misc/subr.h
 
 Modified: head/sbin/geom/class/part/geom_part.c
 ==============================================================================
 --- head/sbin/geom/class/part/geom_part.c	Mon Jun 21 07:17:48 2010	(r209387)
 +++ head/sbin/geom/class/part/geom_part.c	Mon Jun 21 08:24:50 2010	(r209388)
 @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
  #include <stdint.h>
  #include <stdio.h>
  #include <stdlib.h>
 +#include <limits.h>
 +#include <inttypes.h>
  #include <string.h>
  #include <strings.h>
  #include <unistd.h>
 @@ -60,6 +62,9 @@ static char autofill[] = "*";
  static char optional[] = "";
  static char flags[] = "C";
  
 +static char sstart[32];
 +static char ssize[32];
 +
  static const char const bootcode_param[] = "bootcode";
  static const char const index_param[] = "index";
  static const char const partcode_param[] = "partcode";
 @@ -68,8 +73,7 @@ static struct gclass *find_class(struct 
  static struct ggeom * find_geom(struct gclass *, const char *);
  static const char *find_geomcfg(struct ggeom *, const char *);
  static const char *find_provcfg(struct gprovider *, const char *);
 -static struct gprovider *find_provider(struct ggeom *,
 -    unsigned long long);
 +static struct gprovider *find_provider(struct ggeom *, off_t);
  static const char *fmtsize(int64_t);
  static int gpart_autofill(struct gctl_req *);
  static int gpart_autofill_resize(struct gctl_req *);
 @@ -84,8 +88,8 @@ static void gpart_write_partcode_vtoc8(s
  
  struct g_command PUBSYM(class_commands)[] = {
  	{ "add", 0, gpart_issue, {
 -		{ 'b', "start", autofill, G_TYPE_ASCLBA },
 -		{ 's', "size", autofill, G_TYPE_ASCLBA },
 +		{ 'b', "start", autofill, G_TYPE_STRING },
 +		{ 's', "size", autofill, G_TYPE_STRING },
  		{ 't', "type", NULL, G_TYPE_STRING },
  		{ 'i', index_param, optional, G_TYPE_ASCNUM },
  		{ 'l', "label", optional, G_TYPE_STRING },
 @@ -149,7 +153,7 @@ struct g_command PUBSYM(class_commands)[
  	  "geom", NULL
  	},
  	{ "resize", 0, gpart_issue, {
 -		{ 's', "size", autofill, G_TYPE_ASCLBA },
 +		{ 's', "size", autofill, G_TYPE_STRING },
  		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
  		{ 'f', "flags", flags, G_TYPE_STRING },
  		G_OPT_SENTINEL },
 @@ -207,11 +211,11 @@ find_provcfg(struct gprovider *pp, const
  }
  
  static struct gprovider *
 -find_provider(struct ggeom *gp, unsigned long long minsector)
 +find_provider(struct ggeom *gp, off_t minsector)
  {
  	struct gprovider *pp, *bestpp;
  	const char *s;
 -	unsigned long long sector, bestsector;
 +	off_t sector, bestsector;
  
  	bestpp = NULL;
  	bestsector = 0;
 @@ -219,9 +223,10 @@ find_provider(struct ggeom *gp, unsigned
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			sector = atoll(s) / pp->lg_sectorsize;
 +			sector =
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			sector = atoll(s);
 +			sector = (off_t)strtoimax(s, NULL, 0);
  
  		if (sector < minsector)
  			continue;
 @@ -271,18 +276,12 @@ gpart_autofill_resize(struct gctl_req *r
  	struct gclass *cp;
  	struct ggeom *gp;
  	struct gprovider *pp;
 -	unsigned long long last, size, start, new_size;
 -	unsigned long long lba, new_lba;
 +	off_t last, size, start, new_size;
 +	off_t lba, new_lba;
  	const char *s;
  	char *val;
  	int error, idx;
  
 -	s = gctl_get_ascii(req, "size");
 -	if (*s == '*')
 -		new_size = (unsigned long long)atoll(s);
 -	else
 -		return (0);
 -
  	s = gctl_get_ascii(req, index_param);
  	idx = strtol(s, &val, 10);
  	if (idx < 1 || *s == '\0' || *val != '\0')
 @@ -303,8 +302,22 @@ gpart_autofill_resize(struct gctl_req *r
  	gp = find_geom(cp, s);
  	if (gp == NULL)
  		errx(EXIT_FAILURE, "No such geom: %s.", s);
 -	last = atoll(find_geomcfg(gp, "last"));
 +	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
 +	if (pp == NULL)
 +		errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
 +
 +	s = gctl_get_ascii(req, "size");
 +	if (*s == '*')
 +		new_size = 0;
 +	else {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &new_size);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid size param");
 +		/* no autofill necessary. */
 +		goto done;
 +	}
  
 +	last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
  	LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
  		s = find_provcfg(pp, "index");
  		if (s == NULL)
 @@ -318,18 +331,21 @@ gpart_autofill_resize(struct gctl_req *r
  	s = find_provcfg(pp, "start");
  	if (s == NULL) {
  		s = find_provcfg(pp, "offset");
 -		start = atoll(s) / pp->lg_sectorsize;
 +		start = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  	} else
 -		start = atoll(s);
 +		start = (off_t)strtoimax(s, NULL, 0);
  	s = find_provcfg(pp, "end");
  	if (s == NULL) {
  		s = find_provcfg(pp, "length");
 -		lba = start + atoll(s) / pp->lg_sectorsize;
 +		lba = start +
 +		    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  	} else
 -		lba = atoll(s) + 1;
 +		lba = (off_t)strtoimax(s, NULL, 0) + 1;
  
 -	if (lba > last)
 +	if (lba > last) {
 +		geom_deletetree(&mesh);
  		return (ENOSPC);
 +	}
  	size = lba - start;
  	pp = find_provider(gp, lba);
  	if (pp == NULL)
 @@ -338,22 +354,25 @@ gpart_autofill_resize(struct gctl_req *r
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			new_lba = atoll(s) / pp->lg_sectorsize;
 +			new_lba =
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			new_lba = atoll(s);
 -		/* Is there any free space between current and
 +			new_lba = (off_t)strtoimax(s, NULL, 0);
 +		/*
 +		 * Is there any free space between current and
  		 * next providers?
  		 */
  		if (new_lba > lba)
  			new_size = new_lba - start;
 -		else
 +		else {
 +			geom_deletetree(&mesh);
  			return (ENOSPC);
 +		}
  	}
 -	asprintf(&val, "%llu", new_size);
 -	if (val == NULL)
 -		return (ENOMEM);
 -	gctl_change_param(req, "size", -1, val);
 -
 +done:
 +	snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)new_size);
 +	gctl_change_param(req, "size", -1, ssize);
 +	geom_deletetree(&mesh);
  	return (0);
  }
  
 @@ -364,11 +383,11 @@ gpart_autofill(struct gctl_req *req)
  	struct gclass *cp;
  	struct ggeom *gp;
  	struct gprovider *pp;
 -	unsigned long long first, last;
 -	unsigned long long size, start;
 -	unsigned long long lba, len, grade;
 +	off_t first, last;
 +	off_t size, start;
 +	off_t lba, len;
 +	uintmax_t grade;
  	const char *s;
 -	char *val;
  	int error, has_size, has_start;
  
  	s = gctl_get_ascii(req, "verb");
 @@ -377,18 +396,6 @@ gpart_autofill(struct gctl_req *req)
  	if (strcmp(s, "add") != 0)
  		return (0);
  
 -	s = gctl_get_ascii(req, "size");
 -	has_size = (*s == '*') ? 0 : 1;
 -	size = (has_size) ? (unsigned long long)atoll(s) : 0ULL;
 -
 -	s = gctl_get_ascii(req, "start");
 -	has_start = (*s == '*') ? 0 : 1;
 -	start = (has_start) ? (unsigned long long)atoll(s) : ~0ULL;
 -
 -	/* No autofill necessary. */
 -	if (has_size && has_start)
 -		return (0);
 -
  	error = geom_gettree(&mesh);
  	if (error)
  		return (error);
 @@ -404,22 +411,49 @@ gpart_autofill(struct gctl_req *req)
  	gp = find_geom(cp, s);
  	if (gp == NULL)
  		errx(EXIT_FAILURE, "No such geom: %s.", s);
 -	first = atoll(find_geomcfg(gp, "first"));
 -	last = atoll(find_geomcfg(gp, "last"));
 +	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
 +	if (pp == NULL)
 +		errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
 +
 +	s = gctl_get_ascii(req, "size");
 +	has_size = (*s == '*') ? 0 : 1;
 +	size = 0;
 +	if (has_size) {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &size);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid size param");
 +	}
 +
 +	s = gctl_get_ascii(req, "start");
 +	has_start = (*s == '*') ? 0 : 1;
 +	start = 0ULL;
 +	if (has_start) {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &start);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid start param");
 +	}
 +
 +	/* No autofill necessary. */
 +	if (has_size && has_start)
 +		goto done;
 +
 +	first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0);
 +	last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
  	grade = ~0ULL;
  	while ((pp = find_provider(gp, first)) != NULL) {
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			lba = atoll(s) / pp->lg_sectorsize;
 +			lba = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			lba = atoll(s);
 +			lba = (off_t)strtoimax(s, NULL, 0);
  
  		if (first < lba) {
  			/* Free space [first, lba> */
  			len = lba - first;
  			if (has_size) {
 -				if (len >= size && len - size < grade) {
 +				if (len >= size &&
 +				    (uintmax_t)(len - size) < grade) {
  					start = first;
  					grade = len - size;
  				}
 @@ -440,15 +474,17 @@ gpart_autofill(struct gctl_req *req)
  		s = find_provcfg(pp, "end");
  		if (s == NULL) {
  			s = find_provcfg(pp, "length");
 -			first = lba + atoll(s) / pp->lg_sectorsize;
 +			first = lba +
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			first = atoll(s) + 1;
 +			first = (off_t)strtoimax(s, NULL, 0) + 1;
  	}
  	if (first <= last) {
  		/* Free space [first-last] */
  		len = last - first + 1;
  		if (has_size) {
 -			if (len >= size && len - size < grade) {
 +			if (len >= size &&
 +			    (uintmax_t)(len - size) < grade) {
  				start = first;
  				grade = len - size;
  			}
 @@ -466,21 +502,17 @@ gpart_autofill(struct gctl_req *req)
  		}
  	}
  
 -	if (grade == ~0ULL)
 +	if (grade == ~0ULL) {
 +		geom_deletetree(&mesh);
  		return (ENOSPC);
 -
 -	if (!has_size) {
 -		asprintf(&val, "%llu", size);
 -		if (val == NULL)
 -			return (ENOMEM);
 -		gctl_change_param(req, "size", -1, val);
 -	}
 -	if (!has_start) {
 -		asprintf(&val, "%llu", start);
 -		if (val == NULL)
 -			return (ENOMEM);
 -		gctl_change_param(req, "start", -1, val);
  	}
 +
 +done:
 +	snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)size);
 +	gctl_change_param(req, "size", -1, ssize);
 +	snprintf(sstart, sizeof(sstart), "%jd", (intmax_t)start);
 +	gctl_change_param(req, "start", -1, sstart);
 +	geom_deletetree(&mesh);
  	return (0);
  }
  
 @@ -489,21 +521,21 @@ gpart_show_geom(struct ggeom *gp, const 
  {
  	struct gprovider *pp;
  	const char *s, *scheme;
 -	unsigned long long first, last, sector, end;
 -	unsigned long long length, secsz;
 +	off_t first, last, sector, end;
 +	off_t length, secsz;
  	int idx, wblocks, wname;
  
  	scheme = find_geomcfg(gp, "scheme");
  	s = find_geomcfg(gp, "first");
 -	first = atoll(s);
 +	first = (off_t)strtoimax(s, NULL, 0);
  	s = find_geomcfg(gp, "last");
 -	last = atoll(s);
 +	last = (off_t)strtoimax(s, NULL, 0);
  	wblocks = strlen(s);
  	wname = strlen(gp->lg_name);
  	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
  	secsz = pp->lg_sectorsize;
 -	printf("=>%*llu  %*llu  %*s  %s  (%s)\n",
 -	    wblocks, first, wblocks, (last - first + 1),
 +	printf("=>%*jd  %*jd  %*s  %s  (%s)\n",
 +	    wblocks, (intmax_t)first, wblocks, (intmax_t)(last - first + 1),
  	    wname, gp->lg_name,
  	    scheme, fmtsize(pp->lg_mediasize));
  
 @@ -511,37 +543,37 @@ gpart_show_geom(struct ggeom *gp, const 
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			sector = atoll(s) / secsz;
 +			sector = (off_t)strtoimax(s, NULL, 0) / secsz;
  		} else
 -			sector = atoll(s);
 +			sector = (off_t)strtoimax(s, NULL, 0);
  
  		s = find_provcfg(pp, "end");
  		if (s == NULL) {
  			s = find_provcfg(pp, "length");
 -			length = atoll(s) / secsz;
 +			length = (off_t)strtoimax(s, NULL, 0) / secsz;
  			end = sector + length - 1;
  		} else {
 -			end = atoll(s);
 +			end = (off_t)strtoimax(s, NULL, 0);
  			length = end - sector + 1;
  		}
  		s = find_provcfg(pp, "index");
  		idx = atoi(s);
  		if (first < sector) {
 -			printf("  %*llu  %*llu  %*s  - free -  (%s)\n",
 -			    wblocks, first, wblocks, sector - first,
 -			    wname, "",
 +			printf("  %*jd  %*jd  %*s  - free -  (%s)\n",
 +			    wblocks, (intmax_t)first, wblocks,
 +			    (intmax_t)(sector - first), wname, "",
  			    fmtsize((sector - first) * secsz));
  		}
 -		printf("  %*llu  %*llu  %*d  %s %s (%s)\n",
 -		    wblocks, sector, wblocks, length,
 +		printf("  %*jd  %*jd  %*d  %s %s (%s)\n",
 +		    wblocks, (intmax_t)sector, wblocks, (intmax_t)length,
  		    wname, idx, find_provcfg(pp, element),
  		    fmtattrib(pp), fmtsize(pp->lg_mediasize));
  		first = end + 1;
  	}
  	if (first <= last) {
  		length = last - first + 1;
 -		printf("  %*llu  %*llu  %*s  - free -  (%s)\n",
 -		    wblocks, first, wblocks, length,
 +		printf("  %*jd  %*jd  %*s  - free -  (%s)\n",
 +		    wblocks, (intmax_t)first, wblocks, (intmax_t)length,
  		    wname, "",
  		    fmtsize(length * secsz));
  	}
 
 Modified: head/sbin/geom/core/geom.c
 ==============================================================================
 --- head/sbin/geom/core/geom.c	Mon Jun 21 07:17:48 2010	(r209387)
 +++ head/sbin/geom/core/geom.c	Mon Jun 21 08:24:50 2010	(r209388)
 @@ -259,94 +259,6 @@ set_option(struct gctl_req *req, struct 
  			    opt->go_val);
  		} else
  			gctl_ro_param(req, opt->go_name, -1, opt->go_val);
 -	} else if (G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
 -		/*
 -		 * LBAs are ugly. The argument is a sector. The size of a
 -		 * sector is context specific (i.e. determined by the media),
 -		 * which we don't know here. But when users enter a value
 -		 * with a SI unit, they really mean the byte-size or byte-
 -		 * offset and not the size or offset in sectors.
 -		 * So how can we map the byte-oriented value into a sector-
 -		 * oriented value if we don't know the sector size in bytes?
 -		 * The approach taken here is:
 -		 * o  Sectors are 512 bytes in size. Mostly the case anyway.
 -		 * o  When no SI unit is specified the value is in sectors.
 -		 * o  With an SI unit the value is in bytes.
 -		 * o  The 'b' suffix forces byte interpretation and the 's'
 -		 *    suffix forces sector interpretation.
 -		 *
 -		 * Thus:
 -		 * o  2 and 2s mean 2 sectors, and 2b means 2 bytes.
 -		 * o  4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
 -		 *
 -		 * "This seemed like a good idea at the time"
 -		 */
 -		intmax_t mult, unit;
 -
 -		number = strtoimax(val, &s, 0);
 -		if (s == val)
 -			errc(EXIT_FAILURE, EINVAL, "argument '%c'",
 -			    opt->go_char);
 -		mult = 1;
 -		unit = 512;	/* sector */
 -		if (*s == '\0')
 -			goto done;
 -		switch (*s) {
 -		case 'e': case 'E':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'p': case 'P':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 't': case 'T':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'g': case 'G':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'm': case 'M':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'k': case 'K':
 -			mult *= 1024;
 -			break;
 -		default:
 -			goto sfx;
 -		}
 -		unit = 1;	/* bytes */
 -		s++;
 -		if (*s == '\0')
 -			goto done;
 -sfx:
 -		switch (*s) {
 -		case 's': case 'S':
 -			unit = 512;	/* sector */
 -			break;
 -		case 'b': case 'B':
 -			unit = 1;	/* bytes */
 -			break;
 -		default:
 -			errc(EXIT_FAILURE, EINVAL, "argument '%c': suffix '%c'",
 -			    opt->go_char, *s);
 -		}
 -		s++;
 -		if (*s != '\0')
 -			errx(EXIT_FAILURE, "argument '%c': junk at end (%s)",
 -			    opt->go_char, s);
 -done:
 -		if (mult * unit < mult || number * mult * unit < number)
 -			errc(EXIT_FAILURE, ERANGE, "argument '%c'",
 -			    opt->go_char);
 -		number *= mult * unit;
 -		if (number % 512)
 -			errx(EXIT_FAILURE, "argument '%c': "
 -			    "not a valid block address", opt->go_char);
 -		number /= 512;
 -		asprintf(&s, "%jd", number);
 -		if (s == NULL)
 -			err(EXIT_FAILURE, NULL);
 -		opt->go_val = s;
 -		gctl_ro_param(req, opt->go_name, -1, s);
  	} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
  		gctl_ro_param(req, opt->go_name, -1, val);
  	} else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
 @@ -439,8 +351,7 @@ parse_arguments(struct g_command *cmd, s
  					gctl_ro_param(req, opt->go_name,
  					    sizeof(intmax_t), opt->go_val);
  				} else if (G_OPT_TYPE(opt) == G_TYPE_STRING ||
 -				    G_OPT_TYPE(opt) == G_TYPE_ASCNUM ||
 -				    G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
 +				    G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
  					if (cmd->gc_argname == NULL ||
  					    opt->go_val == NULL ||
  					    *(char *)opt->go_val != '\0')
 
 Modified: head/sbin/geom/core/geom.h
 ==============================================================================
 --- head/sbin/geom/core/geom.h	Mon Jun 21 07:17:48 2010	(r209387)
 +++ head/sbin/geom/core/geom.h	Mon Jun 21 08:24:50 2010	(r209388)
 @@ -39,7 +39,6 @@
  #define	G_TYPE_STRING	0x02
  #define	G_TYPE_NUMBER	0x03
  #define	G_TYPE_ASCNUM	0x04
 -#define	G_TYPE_ASCLBA	0x05
  #define	G_TYPE_MASK	0x0f
  #define	G_TYPE_DONE	0x10
  
 
 Modified: head/sbin/geom/misc/subr.c
 ==============================================================================
 --- head/sbin/geom/misc/subr.c	Mon Jun 21 07:17:48 2010	(r209387)
 +++ head/sbin/geom/misc/subr.c	Mon Jun 21 08:24:50 2010	(r209388)
 @@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
  #include <paths.h>
  #include <stdio.h>
  #include <stdlib.h>
 +#include <limits.h>
 +#include <inttypes.h>
  #include <stdarg.h>
  #include <string.h>
  #include <strings.h>
 @@ -107,6 +109,94 @@ bitcount32(uint32_t x)
  	return (x);
  }
  
 +/*
 + * The size of a sector is context specific (i.e. determined by the
 + * media). But when users enter a value with a SI unit, they really
 + * mean the byte-size or byte-offset and not the size or offset in
 + * sectors. We should map the byte-oriented value into a sector-oriented
 + * value when we already know the sector size in bytes. At this time
 + * we can use g_parse_lba() function. It converts user specified
 + * value into sectors with following conditions:
 + * o  Sectors size taken as argument from caller.
 + * o  When no SI unit is specified the value is in sectors.
 + * o  With an SI unit the value is in bytes.
 + * o  The 'b' suffix forces byte interpretation and the 's'
 + *    suffix forces sector interpretation.
 + *
 + * Thus:
 + * o  2 and 2s mean 2 sectors, and 2b means 2 bytes.
 + * o  4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
 + *
 + */
 +int
 +g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors)
 +{
 +	off_t number, mult, unit;
 +	char *s;
 +
 +	assert(lbastr != NULL);
 +	assert(sectorsize > 0);
 +	assert(sectors != NULL);
 +
 +	number = (off_t)strtoimax(lbastr, &s, 0);
 +	if (s == lbastr)
 +		return (EINVAL);
 +
 +	mult = 1;
 +	unit = sectorsize;
 +	if (*s == '\0')
 +		goto done;
 +	switch (*s) {
 +	case 'e': case 'E':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'p': case 'P':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 't': case 'T':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'g': case 'G':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'm': case 'M':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'k': case 'K':
 +		mult *= 1024;
 +		break;
 +	default:
 +		goto sfx;
 +	}
 +	unit = 1;	/* bytes */
 +	s++;
 +	if (*s == '\0')
 +		goto done;
 +sfx:
 +	switch (*s) {
 +	case 's': case 'S':
 +		unit = sectorsize;	/* sector */
 +		break;
 +	case 'b': case 'B':
 +		unit = 1;		/* bytes */
 +		break;
 +	default:
 +		return (EINVAL);
 +	}
 +	s++;
 +	if (*s != '\0')
 +		return (EINVAL);
 +done:
 +	if (mult * unit < mult || number * mult * unit < number)
 +		return (ERANGE);
 +	number *= mult * unit;
 +	if (number % sectorsize)
 +		return (EINVAL);
 +	number /= sectorsize;
 +	*sectors = number;
 +	return (0);
 +}
 +
  off_t
  g_get_mediasize(const char *name)
  {
 
 Modified: head/sbin/geom/misc/subr.h
 ==============================================================================
 --- head/sbin/geom/misc/subr.h	Mon Jun 21 07:17:48 2010	(r209387)
 +++ head/sbin/geom/misc/subr.h	Mon Jun 21 08:24:50 2010	(r209388)
 @@ -32,6 +32,7 @@
  
  unsigned g_lcm(unsigned a, unsigned b);
  uint32_t bitcount32(uint32_t x);
 +int g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors);
  
  off_t g_get_mediasize(const char *name);
  unsigned g_get_sectorsize(const char *name);
 _______________________________________________
 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: suspended->patched 
State-Changed-By: ae 
State-Changed-When: Sat Jul 10 16:53:26 UTC 2010 
State-Changed-Why:  
Patched in HEAD. 


Responsible-Changed-From-To: freebsd-geom->ae 
Responsible-Changed-By: ae 
Responsible-Changed-When: Sat Jul 10 16:53:26 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=146277 
State-Changed-From-To: patched->closed 
State-Changed-By: ae 
State-Changed-When: Wed Jul 21 08:49:10 UTC 2010 
State-Changed-Why:  
Merged to stable/8. 

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

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/146277: commit references a PR
Date: Wed, 21 Jul 2010 08:49:06 +0000 (UTC)

 Author: ae
 Date: Wed Jul 21 08:48:45 2010
 New Revision: 210322
 URL: http://svn.freebsd.org/changeset/base/210322
 
 Log:
   MFC r209388:
     Remove G_TYPE_ASCLBA type and replace it with G_TYPE_STRING in gpart.
     Move code that converts params from humanized numbers to sectors count
     to subr.c and adjust comment.
     Add post-processing for "size" and "start offset" params in gpart,
     now they are properly converted to sectors count with known sector size
     that can be greater that 512 bytes.
     Also replace "unsigned long long" type to "off_t" for unify code since
     it used for medium size in libgeom(3) and DIOCGMEDIASIZE ioctl.
   
     PR:		bin/146277
   
   MFC r209392:
     Check for overflow before it occurs. Also add check for
     negative numbers.
   
     Suggested by:	ache
   
   Approved by:	mav (mentor)
 
 Modified:
   stable/8/sbin/geom/class/part/geom_part.c
   stable/8/sbin/geom/core/geom.c
   stable/8/sbin/geom/core/geom.h
   stable/8/sbin/geom/misc/subr.c
   stable/8/sbin/geom/misc/subr.h
 Directory Properties:
   stable/8/sbin/geom/   (props changed)
   stable/8/sbin/geom/class/part/   (props changed)
   stable/8/sbin/geom/class/stripe/   (props changed)
 
 Modified: stable/8/sbin/geom/class/part/geom_part.c
 ==============================================================================
 --- stable/8/sbin/geom/class/part/geom_part.c	Wed Jul 21 08:43:48 2010	(r210321)
 +++ stable/8/sbin/geom/class/part/geom_part.c	Wed Jul 21 08:48:45 2010	(r210322)
 @@ -40,6 +40,8 @@ __FBSDID("$FreeBSD$");
  #include <stdint.h>
  #include <stdio.h>
  #include <stdlib.h>
 +#include <limits.h>
 +#include <inttypes.h>
  #include <string.h>
  #include <strings.h>
  #include <unistd.h>
 @@ -60,6 +62,9 @@ static char autofill[] = "*";
  static char optional[] = "";
  static char flags[] = "C";
  
 +static char sstart[32];
 +static char ssize[32];
 +
  static const char const bootcode_param[] = "bootcode";
  static const char const index_param[] = "index";
  static const char const partcode_param[] = "partcode";
 @@ -68,8 +73,7 @@ static struct gclass *find_class(struct 
  static struct ggeom * find_geom(struct gclass *, const char *);
  static const char *find_geomcfg(struct ggeom *, const char *);
  static const char *find_provcfg(struct gprovider *, const char *);
 -static struct gprovider *find_provider(struct ggeom *,
 -    unsigned long long);
 +static struct gprovider *find_provider(struct ggeom *, off_t);
  static const char *fmtsize(int64_t);
  static int gpart_autofill(struct gctl_req *);
  static void gpart_bootcode(struct gctl_req *, unsigned int);
 @@ -83,8 +87,8 @@ static void gpart_write_partcode_vtoc8(s
  
  struct g_command PUBSYM(class_commands)[] = {
  	{ "add", 0, gpart_issue, {
 -		{ 'b', "start", autofill, G_TYPE_ASCLBA },
 -		{ 's', "size", autofill, G_TYPE_ASCLBA },
 +		{ 'b', "start", autofill, G_TYPE_STRING },
 +		{ 's', "size", autofill, G_TYPE_STRING },
  		{ 't', "type", NULL, G_TYPE_STRING },
  		{ 'i', index_param, optional, G_TYPE_ASCNUM },
  		{ 'l', "label", optional, G_TYPE_STRING },
 @@ -148,7 +152,7 @@ struct g_command PUBSYM(class_commands)[
  	  "geom", NULL
  	},
  	{ "resize", 0, gpart_issue, {
 -		{ 's', "size", autofill, G_TYPE_ASCLBA },
 +		{ 's', "size", autofill, G_TYPE_STRING },
  		{ 'i', index_param, NULL, G_TYPE_ASCNUM },
  		{ 'f', "flags", flags, G_TYPE_STRING },
  		G_OPT_SENTINEL },
 @@ -206,11 +210,11 @@ find_provcfg(struct gprovider *pp, const
  }
  
  static struct gprovider *
 -find_provider(struct ggeom *gp, unsigned long long minsector)
 +find_provider(struct ggeom *gp, off_t minsector)
  {
  	struct gprovider *pp, *bestpp;
  	const char *s;
 -	unsigned long long sector, bestsector;
 +	off_t sector, bestsector;
  
  	bestpp = NULL;
  	bestsector = 0;
 @@ -218,9 +222,10 @@ find_provider(struct ggeom *gp, unsigned
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			sector = atoll(s) / pp->lg_sectorsize;
 +			sector =
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			sector = atoll(s);
 +			sector = (off_t)strtoimax(s, NULL, 0);
  
  		if (sector < minsector)
  			continue;
 @@ -270,18 +275,12 @@ gpart_autofill_resize(struct gctl_req *r
  	struct gclass *cp;
  	struct ggeom *gp;
  	struct gprovider *pp;
 -	unsigned long long last, size, start, new_size;
 -	unsigned long long lba, new_lba;
 +	off_t last, size, start, new_size;
 +	off_t lba, new_lba;
  	const char *s;
  	char *val;
  	int error, idx;
  
 -	s = gctl_get_ascii(req, "size");
 -	if (*s == '*')
 -		new_size = (unsigned long long)atoll(s);
 -	else
 -		return (0);
 -
  	s = gctl_get_ascii(req, index_param);
  	idx = strtol(s, &val, 10);
  	if (idx < 1 || *s == '\0' || *val != '\0')
 @@ -302,8 +301,22 @@ gpart_autofill_resize(struct gctl_req *r
  	gp = find_geom(cp, s);
  	if (gp == NULL)
  		errx(EXIT_FAILURE, "No such geom: %s.", s);
 -	last = atoll(find_geomcfg(gp, "last"));
 +	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
 +	if (pp == NULL)
 +		errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
 +
 +	s = gctl_get_ascii(req, "size");
 +	if (*s == '*')
 +		new_size = 0;
 +	else {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &new_size);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid size param");
 +		/* no autofill necessary. */
 +		goto done;
 +	}
  
 +	last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
  	LIST_FOREACH(pp, &gp->lg_provider, lg_provider) {
  		s = find_provcfg(pp, "index");
  		if (s == NULL)
 @@ -317,18 +330,21 @@ gpart_autofill_resize(struct gctl_req *r
  	s = find_provcfg(pp, "start");
  	if (s == NULL) {
  		s = find_provcfg(pp, "offset");
 -		start = atoll(s) / pp->lg_sectorsize;
 +		start = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  	} else
 -		start = atoll(s);
 +		start = (off_t)strtoimax(s, NULL, 0);
  	s = find_provcfg(pp, "end");
  	if (s == NULL) {
  		s = find_provcfg(pp, "length");
 -		lba = start + atoll(s) / pp->lg_sectorsize;
 +		lba = start +
 +		    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  	} else
 -		lba = atoll(s) + 1;
 +		lba = (off_t)strtoimax(s, NULL, 0) + 1;
  
 -	if (lba > last)
 +	if (lba > last) {
 +		geom_deletetree(&mesh);
  		return (ENOSPC);
 +	}
  	size = lba - start;
  	pp = find_provider(gp, lba);
  	if (pp == NULL)
 @@ -337,22 +353,25 @@ gpart_autofill_resize(struct gctl_req *r
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			new_lba = atoll(s) / pp->lg_sectorsize;
 +			new_lba =
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			new_lba = atoll(s);
 -		/* Is there any free space between current and
 +			new_lba = (off_t)strtoimax(s, NULL, 0);
 +		/*
 +		 * Is there any free space between current and
  		 * next providers?
  		 */
  		if (new_lba > lba)
  			new_size = new_lba - start;
 -		else
 +		else {
 +			geom_deletetree(&mesh);
  			return (ENOSPC);
 +		}
  	}
 -	asprintf(&val, "%llu", new_size);
 -	if (val == NULL)
 -		return (ENOMEM);
 -	gctl_change_param(req, "size", -1, val);
 -
 +done:
 +	snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)new_size);
 +	gctl_change_param(req, "size", -1, ssize);
 +	geom_deletetree(&mesh);
  	return (0);
  }
  
 @@ -363,11 +382,11 @@ gpart_autofill(struct gctl_req *req)
  	struct gclass *cp;
  	struct ggeom *gp;
  	struct gprovider *pp;
 -	unsigned long long first, last;
 -	unsigned long long size, start;
 -	unsigned long long lba, len, grade;
 +	off_t first, last;
 +	off_t size, start;
 +	off_t lba, len;
 +	uintmax_t grade;
  	const char *s;
 -	char *val;
  	int error, has_size, has_start;
  
  	s = gctl_get_ascii(req, "verb");
 @@ -376,18 +395,6 @@ gpart_autofill(struct gctl_req *req)
  	if (strcmp(s, "add") != 0)
  		return (0);
  
 -	s = gctl_get_ascii(req, "size");
 -	has_size = (*s == '*') ? 0 : 1;
 -	size = (has_size) ? (unsigned long long)atoll(s) : 0ULL;
 -
 -	s = gctl_get_ascii(req, "start");
 -	has_start = (*s == '*') ? 0 : 1;
 -	start = (has_start) ? (unsigned long long)atoll(s) : ~0ULL;
 -
 -	/* No autofill necessary. */
 -	if (has_size && has_start)
 -		return (0);
 -
  	error = geom_gettree(&mesh);
  	if (error)
  		return (error);
 @@ -403,22 +410,49 @@ gpart_autofill(struct gctl_req *req)
  	gp = find_geom(cp, s);
  	if (gp == NULL)
  		errx(EXIT_FAILURE, "No such geom: %s.", s);
 -	first = atoll(find_geomcfg(gp, "first"));
 -	last = atoll(find_geomcfg(gp, "last"));
 +	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
 +	if (pp == NULL)
 +		errx(EXIT_FAILURE, "Provider for geom %s not found.", s);
 +
 +	s = gctl_get_ascii(req, "size");
 +	has_size = (*s == '*') ? 0 : 1;
 +	size = 0;
 +	if (has_size) {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &size);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid size param");
 +	}
 +
 +	s = gctl_get_ascii(req, "start");
 +	has_start = (*s == '*') ? 0 : 1;
 +	start = 0ULL;
 +	if (has_start) {
 +		error = g_parse_lba(s, pp->lg_sectorsize, &start);
 +		if (error)
 +			errc(EXIT_FAILURE, error, "Invalid start param");
 +	}
 +
 +	/* No autofill necessary. */
 +	if (has_size && has_start)
 +		goto done;
 +
 +	first = (off_t)strtoimax(find_geomcfg(gp, "first"), NULL, 0);
 +	last = (off_t)strtoimax(find_geomcfg(gp, "last"), NULL, 0);
  	grade = ~0ULL;
  	while ((pp = find_provider(gp, first)) != NULL) {
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			lba = atoll(s) / pp->lg_sectorsize;
 +			lba = (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			lba = atoll(s);
 +			lba = (off_t)strtoimax(s, NULL, 0);
  
  		if (first < lba) {
  			/* Free space [first, lba> */
  			len = lba - first;
  			if (has_size) {
 -				if (len >= size && len - size < grade) {
 +				if (len >= size &&
 +				    (uintmax_t)(len - size) < grade) {
  					start = first;
  					grade = len - size;
  				}
 @@ -439,15 +473,17 @@ gpart_autofill(struct gctl_req *req)
  		s = find_provcfg(pp, "end");
  		if (s == NULL) {
  			s = find_provcfg(pp, "length");
 -			first = lba + atoll(s) / pp->lg_sectorsize;
 +			first = lba +
 +			    (off_t)strtoimax(s, NULL, 0) / pp->lg_sectorsize;
  		} else
 -			first = atoll(s) + 1;
 +			first = (off_t)strtoimax(s, NULL, 0) + 1;
  	}
  	if (first <= last) {
  		/* Free space [first-last] */
  		len = last - first + 1;
  		if (has_size) {
 -			if (len >= size && len - size < grade) {
 +			if (len >= size &&
 +			    (uintmax_t)(len - size) < grade) {
  				start = first;
  				grade = len - size;
  			}
 @@ -465,21 +501,17 @@ gpart_autofill(struct gctl_req *req)
  		}
  	}
  
 -	if (grade == ~0ULL)
 +	if (grade == ~0ULL) {
 +		geom_deletetree(&mesh);
  		return (ENOSPC);
 -
 -	if (!has_size) {
 -		asprintf(&val, "%llu", size);
 -		if (val == NULL)
 -			return (ENOMEM);
 -		gctl_change_param(req, "size", -1, val);
 -	}
 -	if (!has_start) {
 -		asprintf(&val, "%llu", start);
 -		if (val == NULL)
 -			return (ENOMEM);
 -		gctl_change_param(req, "start", -1, val);
  	}
 +
 +done:
 +	snprintf(ssize, sizeof(ssize), "%jd", (intmax_t)size);
 +	gctl_change_param(req, "size", -1, ssize);
 +	snprintf(sstart, sizeof(sstart), "%jd", (intmax_t)start);
 +	gctl_change_param(req, "start", -1, sstart);
 +	geom_deletetree(&mesh);
  	return (0);
  }
  
 @@ -488,21 +520,21 @@ gpart_show_geom(struct ggeom *gp, const 
  {
  	struct gprovider *pp;
  	const char *s, *scheme;
 -	unsigned long long first, last, sector, end;
 -	unsigned long long length, secsz;
 +	off_t first, last, sector, end;
 +	off_t length, secsz;
  	int idx, wblocks, wname;
  
  	scheme = find_geomcfg(gp, "scheme");
  	s = find_geomcfg(gp, "first");
 -	first = atoll(s);
 +	first = (off_t)strtoimax(s, NULL, 0);
  	s = find_geomcfg(gp, "last");
 -	last = atoll(s);
 +	last = (off_t)strtoimax(s, NULL, 0);
  	wblocks = strlen(s);
  	wname = strlen(gp->lg_name);
  	pp = LIST_FIRST(&gp->lg_consumer)->lg_provider;
  	secsz = pp->lg_sectorsize;
 -	printf("=>%*llu  %*llu  %*s  %s  (%s)\n",
 -	    wblocks, first, wblocks, (last - first + 1),
 +	printf("=>%*jd  %*jd  %*s  %s  (%s)\n",
 +	    wblocks, (intmax_t)first, wblocks, (intmax_t)(last - first + 1),
  	    wname, gp->lg_name,
  	    scheme, fmtsize(pp->lg_mediasize));
  
 @@ -510,37 +542,37 @@ gpart_show_geom(struct ggeom *gp, const 
  		s = find_provcfg(pp, "start");
  		if (s == NULL) {
  			s = find_provcfg(pp, "offset");
 -			sector = atoll(s) / secsz;
 +			sector = (off_t)strtoimax(s, NULL, 0) / secsz;
  		} else
 -			sector = atoll(s);
 +			sector = (off_t)strtoimax(s, NULL, 0);
  
  		s = find_provcfg(pp, "end");
  		if (s == NULL) {
  			s = find_provcfg(pp, "length");
 -			length = atoll(s) / secsz;
 +			length = (off_t)strtoimax(s, NULL, 0) / secsz;
  			end = sector + length - 1;
  		} else {
 -			end = atoll(s);
 +			end = (off_t)strtoimax(s, NULL, 0);
  			length = end - sector + 1;
  		}
  		s = find_provcfg(pp, "index");
  		idx = atoi(s);
  		if (first < sector) {
 -			printf("  %*llu  %*llu  %*s  - free -  (%s)\n",
 -			    wblocks, first, wblocks, sector - first,
 -			    wname, "",
 +			printf("  %*jd  %*jd  %*s  - free -  (%s)\n",
 +			    wblocks, (intmax_t)first, wblocks,
 +			    (intmax_t)(sector - first), wname, "",
  			    fmtsize((sector - first) * secsz));
  		}
 -		printf("  %*llu  %*llu  %*d  %s %s (%s)\n",
 -		    wblocks, sector, wblocks, length,
 +		printf("  %*jd  %*jd  %*d  %s %s (%s)\n",
 +		    wblocks, (intmax_t)sector, wblocks, (intmax_t)length,
  		    wname, idx, find_provcfg(pp, element),
  		    fmtattrib(pp), fmtsize(pp->lg_mediasize));
  		first = end + 1;
  	}
  	if (first <= last) {
  		length = last - first + 1;
 -		printf("  %*llu  %*llu  %*s  - free -  (%s)\n",
 -		    wblocks, first, wblocks, length,
 +		printf("  %*jd  %*jd  %*s  - free -  (%s)\n",
 +		    wblocks, (intmax_t)first, wblocks, (intmax_t)length,
  		    wname, "",
  		    fmtsize(length * secsz));
  	}
 
 Modified: stable/8/sbin/geom/core/geom.c
 ==============================================================================
 --- stable/8/sbin/geom/core/geom.c	Wed Jul 21 08:43:48 2010	(r210321)
 +++ stable/8/sbin/geom/core/geom.c	Wed Jul 21 08:48:45 2010	(r210322)
 @@ -249,94 +249,6 @@ set_option(struct gctl_req *req, struct 
  			    opt->go_val);
  		} else
  			gctl_ro_param(req, opt->go_name, -1, opt->go_val);
 -	} else if (G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
 -		/*
 -		 * LBAs are ugly. The argument is a sector. The size of a
 -		 * sector is context specific (i.e. determined by the media),
 -		 * which we don't know here. But when users enter a value
 -		 * with a SI unit, they really mean the byte-size or byte-
 -		 * offset and not the size or offset in sectors.
 -		 * So how can we map the byte-oriented value into a sector-
 -		 * oriented value if we don't know the sector size in bytes?
 -		 * The approach taken here is:
 -		 * o  Sectors are 512 bytes in size. Mostly the case anyway.
 -		 * o  When no SI unit is specified the value is in sectors.
 -		 * o  With an SI unit the value is in bytes.
 -		 * o  The 'b' suffix forces byte interpretation and the 's'
 -		 *    suffix forces sector interpretation.
 -		 *
 -		 * Thus:
 -		 * o  2 and 2s mean 2 sectors, and 2b means 2 bytes.
 -		 * o  4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
 -		 *
 -		 * "This seemed like a good idea at the time"
 -		 */
 -		intmax_t mult, unit;
 -
 -		number = strtoimax(val, &s, 0);
 -		if (s == val)
 -			errc(EXIT_FAILURE, EINVAL, "argument '%c'",
 -			    opt->go_char);
 -		mult = 1;
 -		unit = 512;	/* sector */
 -		if (*s == '\0')
 -			goto done;
 -		switch (*s) {
 -		case 'e': case 'E':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'p': case 'P':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 't': case 'T':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'g': case 'G':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'm': case 'M':
 -			mult *= 1024;
 -			/*FALLTHROUGH*/
 -		case 'k': case 'K':
 -			mult *= 1024;
 -			break;
 -		default:
 -			goto sfx;
 -		}
 -		unit = 1;	/* bytes */
 -		s++;
 -		if (*s == '\0')
 -			goto done;
 -sfx:
 -		switch (*s) {
 -		case 's': case 'S':
 -			unit = 512;	/* sector */
 -			break;
 -		case 'b': case 'B':
 -			unit = 1;	/* bytes */
 -			break;
 -		default:
 -			errc(EXIT_FAILURE, EINVAL, "argument '%c': suffix '%c'",
 -			    opt->go_char, *s);
 -		}
 -		s++;
 -		if (*s != '\0')
 -			errx(EXIT_FAILURE, "argument '%c': junk at end (%s)",
 -			    opt->go_char, s);
 -done:
 -		if (mult * unit < mult || number * mult * unit < number)
 -			errc(EXIT_FAILURE, ERANGE, "argument '%c'",
 -			    opt->go_char);
 -		number *= mult * unit;
 -		if (number % 512)
 -			errx(EXIT_FAILURE, "argument '%c': "
 -			    "not a valid block address", opt->go_char);
 -		number /= 512;
 -		asprintf(&s, "%jd", number);
 -		if (s == NULL)
 -			err(EXIT_FAILURE, NULL);
 -		opt->go_val = s;
 -		gctl_ro_param(req, opt->go_name, -1, s);
  	} else if (G_OPT_TYPE(opt) == G_TYPE_STRING) {
  		gctl_ro_param(req, opt->go_name, -1, val);
  	} else if (G_OPT_TYPE(opt) == G_TYPE_BOOL) {
 @@ -429,8 +341,7 @@ parse_arguments(struct g_command *cmd, s
  					gctl_ro_param(req, opt->go_name,
  					    sizeof(intmax_t), opt->go_val);
  				} else if (G_OPT_TYPE(opt) == G_TYPE_STRING ||
 -				    G_OPT_TYPE(opt) == G_TYPE_ASCNUM ||
 -				    G_OPT_TYPE(opt) == G_TYPE_ASCLBA) {
 +				    G_OPT_TYPE(opt) == G_TYPE_ASCNUM) {
  					if (cmd->gc_argname == NULL ||
  					    opt->go_val == NULL ||
  					    *(char *)opt->go_val != '\0')
 
 Modified: stable/8/sbin/geom/core/geom.h
 ==============================================================================
 --- stable/8/sbin/geom/core/geom.h	Wed Jul 21 08:43:48 2010	(r210321)
 +++ stable/8/sbin/geom/core/geom.h	Wed Jul 21 08:48:45 2010	(r210322)
 @@ -39,7 +39,6 @@
  #define	G_TYPE_STRING	0x02
  #define	G_TYPE_NUMBER	0x03
  #define	G_TYPE_ASCNUM	0x04
 -#define	G_TYPE_ASCLBA	0x05
  #define	G_TYPE_MASK	0x0f
  #define	G_TYPE_DONE	0x10
  
 
 Modified: stable/8/sbin/geom/misc/subr.c
 ==============================================================================
 --- stable/8/sbin/geom/misc/subr.c	Wed Jul 21 08:43:48 2010	(r210321)
 +++ stable/8/sbin/geom/misc/subr.c	Wed Jul 21 08:48:45 2010	(r210322)
 @@ -36,6 +36,8 @@ __FBSDID("$FreeBSD$");
  #include <paths.h>
  #include <stdio.h>
  #include <stdlib.h>
 +#include <limits.h>
 +#include <inttypes.h>
  #include <stdarg.h>
  #include <string.h>
  #include <strings.h>
 @@ -107,6 +109,94 @@ bitcount32(uint32_t x)
  	return (x);
  }
  
 +/*
 + * The size of a sector is context specific (i.e. determined by the
 + * media). But when users enter a value with a SI unit, they really
 + * mean the byte-size or byte-offset and not the size or offset in
 + * sectors. We should map the byte-oriented value into a sector-oriented
 + * value when we already know the sector size in bytes. At this time
 + * we can use g_parse_lba() function. It converts user specified
 + * value into sectors with following conditions:
 + * o  Sectors size taken as argument from caller.
 + * o  When no SI unit is specified the value is in sectors.
 + * o  With an SI unit the value is in bytes.
 + * o  The 'b' suffix forces byte interpretation and the 's'
 + *    suffix forces sector interpretation.
 + *
 + * Thus:
 + * o  2 and 2s mean 2 sectors, and 2b means 2 bytes.
 + * o  4k and 4kb mean 4096 bytes, and 4ks means 4096 sectors.
 + *
 + */
 +int
 +g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors)
 +{
 +	off_t number, mult, unit;
 +	char *s;
 +
 +	assert(lbastr != NULL);
 +	assert(sectorsize > 0);
 +	assert(sectors != NULL);
 +
 +	number = (off_t)strtoimax(lbastr, &s, 0);
 +	if (s == lbastr || number < 0)
 +		return (EINVAL);
 +
 +	mult = 1;
 +	unit = sectorsize;
 +	if (*s == '\0')
 +		goto done;
 +	switch (*s) {
 +	case 'e': case 'E':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'p': case 'P':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 't': case 'T':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'g': case 'G':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'm': case 'M':
 +		mult *= 1024;
 +		/* FALLTHROUGH */
 +	case 'k': case 'K':
 +		mult *= 1024;
 +		break;
 +	default:
 +		goto sfx;
 +	}
 +	unit = 1;	/* bytes */
 +	s++;
 +	if (*s == '\0')
 +		goto done;
 +sfx:
 +	switch (*s) {
 +	case 's': case 'S':
 +		unit = sectorsize;	/* sector */
 +		break;
 +	case 'b': case 'B':
 +		unit = 1;		/* bytes */
 +		break;
 +	default:
 +		return (EINVAL);
 +	}
 +	s++;
 +	if (*s != '\0')
 +		return (EINVAL);
 +done:
 +	if ((OFF_MAX / unit) < mult || (OFF_MAX / mult / unit) < number)
 +		return (ERANGE);
 +	number *= mult * unit;
 +	if (number % sectorsize)
 +		return (EINVAL);
 +	number /= sectorsize;
 +	*sectors = number;
 +	return (0);
 +}
 +
  off_t
  g_get_mediasize(const char *name)
  {
 
 Modified: stable/8/sbin/geom/misc/subr.h
 ==============================================================================
 --- stable/8/sbin/geom/misc/subr.h	Wed Jul 21 08:43:48 2010	(r210321)
 +++ stable/8/sbin/geom/misc/subr.h	Wed Jul 21 08:48:45 2010	(r210322)
 @@ -32,6 +32,7 @@
  
  unsigned g_lcm(unsigned a, unsigned b);
  uint32_t bitcount32(uint32_t x);
 +int g_parse_lba(const char *lbastr, unsigned sectorsize, off_t *sectors);
  
  off_t g_get_mediasize(const char *name);
  unsigned g_get_sectorsize(const char *name);
 _______________________________________________
 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"
 
>Unformatted:
