Re: [PATCH] 3/6 Avoid overflow in calculation of resvd blocks in resized fs

Theodore Tso <[email protected]> Wed, 30 Aug 2006 03:10:22 -0400
Newsgroups gmane.comp.file-systems.ext2.devel
Message-ID <[email protected]>
On Wed, Aug 16, 2006 at 03:51:50PM -0500, Eric Sandeen wrote:
> The way the new reserved blocks count was calculated at resize time could
> overflow pretty easily.
> 
> The new calculation changes the rounding slightly, so fix up the expected
> output for the resize tests as well.

I created a new function, e2p_percent, which won't overflow and which
calculates the percentages as accurately as possible, so it doesn't
need to adjust the expected output of the test suite.

						- Ted

# HG changeset patch
# User [email protected]
# Date 1156921693 14400
# Node ID 4a2b0d6c55fc3bea9e5bed4faa82845676f3be2b
# Parent  14e45223b10be14cc318f10b804a3fd535a86ad5
Fix potential 2**32-1 overflow by using e2p_percent()

Add a new functiom, e2p_percent(), which correct calculates the percentage
of a number based on a given percentage, without worrying about overflow
issues.  This is used where we calculate the number of reserved blocks using
a percentage of the total number of blocks in a filesystem.

Based on patches from Eric Sandeen, but generalized to use this new function.

Signed-off-by: "Theodore Ts'o" <[email protected]>
Signed-off-by: Eric Sandeen <[email protected]>

diff -r 14e45223b10b -r 4a2b0d6c55fc lib/e2p/ChangeLog
--- a/lib/e2p/ChangeLog	Wed Aug 30 02:16:55 2006 -0400
+++ b/lib/e2p/ChangeLog	Wed Aug 30 03:08:13 2006 -0400
@@ -1,3 +1,9 @@ 2006-08-05  Theodore Tso  <[email protected]
+2006-08-30  Theodore Tso  <[email protected]>
+
+	* percent.c (e2p_percent): Add a new function which accurate and
+		without risk of overflow calculates a percentage of a base
+		number.
+
 2006-08-05  Theodore Tso  <[email protected]>
 
 	* pf.c: Add support for EXT4_EXTENTS_FL flag.
diff -r 14e45223b10b -r 4a2b0d6c55fc lib/e2p/Makefile.in
--- a/lib/e2p/Makefile.in	Wed Aug 30 02:16:55 2006 -0400
+++ b/lib/e2p/Makefile.in	Wed Aug 30 03:08:13 2006 -0400
@@ -19,7 +19,7 @@ OBJS=		feature.o fgetflags.o fsetflags.o
 OBJS=		feature.o fgetflags.o fsetflags.o fgetversion.o fsetversion.o \
 		getflags.o getversion.o hashstr.o iod.o ls.o mntopts.o \
 		parse_num.o pe.o pf.o ps.o setflags.o setversion.o uuid.o \
-		ostype.o 
+		ostype.o percent.o
 
 SRCS=		$(srcdir)/feature.c $(srcdir)/fgetflags.c \
 		$(srcdir)/fsetflags.c $(srcdir)/fgetversion.c \
@@ -28,7 +28,7 @@ SRCS=		$(srcdir)/feature.c $(srcdir)/fge
 		$(srcdir)/ls.c $(srcdir)/mntopts.c $(srcdir)/parse_num.c \
 		$(srcdir)/pe.c $(srcdir)/pf.c $(srcdir)/ps.c \
 		$(srcdir)/setflags.c $(srcdir)/setversion.c $(srcdir)/uuid.c \
-		$(srcdir)/ostype.c
+		$(srcdir)/ostype.c $(srcdir)/percent.o
 HFILES= e2p.h
 
 LIBRARY= libe2p
diff -r 14e45223b10b -r 4a2b0d6c55fc lib/e2p/e2p.h
--- a/lib/e2p/e2p.h	Wed Aug 30 02:16:55 2006 -0400
+++ b/lib/e2p/e2p.h	Wed Aug 30 03:08:13 2006 -0400
@@ -50,3 +50,5 @@ unsigned long parse_num_blocks(const cha
 
 char *e2p_os2string(int os_type);
 int e2p_string2os(char *str);
+
+unsigned int e2p_percent(int percent, unsigned int base);
diff -r 14e45223b10b -r 4a2b0d6c55fc lib/e2p/percent.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/e2p/percent.c	Wed Aug 30 03:08:13 2006 -0400
@@ -0,0 +1,62 @@
+/*
+ * percent.c		- Take percentage of a number
+ *
+ * Copyright (C) 2006  Theodore Ts'o <[email protected]>
+ * 
+ * This file can be redistributed under the terms of the GNU Library General
+ * Public License
+ */
+
+#include "e2p.h"
+
+#include <stdlib.h>
+
+/*
+ * We work really hard to calculate this accurately, while avoiding
+ * an overflow.  "Is there a hyphen in anal-retentive?"  :-)
+ */
+unsigned int e2p_percent(int percent, unsigned int base)
+{
+	unsigned int mask = ~((1 << (sizeof(unsigned int) - 1) * 8) - 1);
+
+	if (100 % percent == 0)
+		return base / (100 / percent);
+	if (mask & base) 
+		return (base / 100) * percent;
+	return base * percent / 100;
+}
+
+#ifdef DEBUG
+#include <unistd.h>
+#include <stdio.h>
+
+main(int argc, char **argv)
+{
+	unsigned int base;
+	int percent;
+	char *p;
+	int log_block_size = 0;
+
+	if (argc != 3) {
+		fprintf(stderr, "Usage: %s percent base\n", argv[0]);
+		exit(1);
+	}
+
+	percent = strtoul(argv[1], &p, 0);
+	if (p[0] && p[1]) {
+		fprintf(stderr, "Bad percent: %s\n", argv[1]);
+		exit(1);
+	}
+	
+	base = strtoul(argv[2], &p, 0);
+	if (p[0] && p[1]) {
+		fprintf(stderr, "Bad base: %s\n", argv[2]);
+		exit(1);
+	}
+
+	printf("%d percent of %u is %u.\n", percent, base,
+	       e2p_percent(percent, base));
+
+	exit(0);
+}
+#endif
diff -r 14e45223b10b -r 4a2b0d6c55fc misc/ChangeLog
--- a/misc/ChangeLog	Wed Aug 30 02:16:55 2006 -0400
+++ b/misc/ChangeLog	Wed Aug 30 03:08:13 2006 -0400
@@ -1,4 +1,8 @@ 2006-08-30  Theodore Tso  <[email protected]
 2006-08-30  Theodore Tso  <[email protected]>
+
+	* tune2fs.c (main), mke2fs.c (PRS): Use e2p_percent to properly
+		calculate the number of reserved blocks without worrying
+		about overflow.
 
 	* Makefile.in (resize2fs): Remove unused (and bogus) resize2fs
 		rule, which shouldn't be in misc/Makefile.in
diff -r 14e45223b10b -r 4a2b0d6c55fc misc/mke2fs.c
--- a/misc/mke2fs.c	Wed Aug 30 02:16:55 2006 -0400
+++ b/misc/mke2fs.c	Wed Aug 30 03:08:13 2006 -0400
@@ -1447,8 +1447,8 @@ static void PRS(int argc, char *argv[])
 	/*
 	 * Calculate number of blocks to reserve
 	 */
-	fs_param.s_r_blocks_count = (fs_param.s_blocks_count * reserved_ratio)
-		/ 100;
+	fs_param.s_r_blocks_count = e2p_percent(reserved_ratio, 
+						fs_param.s_blocks_count);
 }
 
 int main (int argc, char *argv[])
diff -r 14e45223b10b -r 4a2b0d6c55fc misc/tune2fs.c
--- a/misc/tune2fs.c	Wed Aug 30 02:16:55 2006 -0400
+++ b/misc/tune2fs.c	Wed Aug 30 03:08:13 2006 -0400
@@ -823,7 +823,8 @@ int main (int argc, char ** argv)
 		printf (_("Setting interval between checks to %lu seconds\n"), interval);
 	}
 	if (m_flag) {
-		sb->s_r_blocks_count = sb->s_blocks_count * reserved_ratio /100;
+		sb->s_r_blocks_count = e2p_percent(reserved_ratio,
+						   sb->s_blocks_count);
 		ext2fs_mark_super_dirty(fs);
 		printf (_("Setting reserved blocks percentage to %g%% (%u blocks)\n"),
 			reserved_ratio, sb->s_r_blocks_count);
diff -r 14e45223b10b -r 4a2b0d6c55fc resize/ChangeLog
--- a/resize/ChangeLog	Wed Aug 30 02:16:55 2006 -0400
+++ b/resize/ChangeLog	Wed Aug 30 03:08:13 2006 -0400
@@ -1,4 +1,8 @@ 2006-08-30  Theodore Tso  <[email protected]
 2006-08-30  Theodore Tso  <[email protected]>
+
+	* resize2fs.c (adjust_fs_info), online.c (online_resize_fs): Use
+		e2p_percent to properly calculate the number of reserved
+		blocks without worrying about overflow.
 
 	* resize2fs.c (ext2fs_calculate_summary_stats): Fix potential
 		overflow problems when the number of blocks is close to
diff -r 14e45223b10b -r 4a2b0d6c55fc resize/online.c
--- a/resize/online.c	Wed Aug 30 02:16:55 2006 -0400
+++ b/resize/online.c	Wed Aug 30 03:08:13 2006 -0400
@@ -107,7 +107,8 @@ errcode_t online_resize_fs(ext2_filsys f
 				sb->s_first_data_block - 
 				(i * sb->s_blocks_per_group);
 		}
-		input.reserved_blocks = input.blocks_count * r_frac / 100;
+		input.reserved_blocks = e2p_percent(r_frac, 
+						    input.blocks_count);
 
 #if 0
 		printf("new block bitmap is at 0x%04x\n", input.block_bitmap);
diff -r 14e45223b10b -r 4a2b0d6c55fc resize/resize2fs.c
--- a/resize/resize2fs.c	Wed Aug 30 02:16:55 2006 -0400
+++ b/resize/resize2fs.c	Wed Aug 30 03:08:13 2006 -0400
@@ -245,8 +245,8 @@ retry:
 	 */
 	blk = old_fs->super->s_r_blocks_count * 100 /
 		old_fs->super->s_blocks_count;
-	fs->super->s_r_blocks_count = ((fs->super->s_blocks_count * blk)
-				       / 100);
+	fs->super->s_r_blocks_count = e2p_percent(blk, 
+						  fs->super->s_blocks_count);
 
 	/*
 	 * Adjust the bitmaps for size

-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642