[parted-devel] [PATCH] mkpartfs ext2 2 10 would erroneously report "file system too small"

Jim Meyering jim at meyering.net
Fri May 18 13:56:02 UTC 2007


        mkpartfs ext2 2 10 would erroneously report "file system too small"
        for some small (single-group) partitions.  It would also fail to
        report "file system too small" in some cases, and instead continue
        on to into inode-allocation code where it'd report "File system full!"
        * libparted/fs/ext2/ext2_mkfs.c (compute_block_counts): New function,
        factored out of...
        (ext2_mkfs): ...here.  Call compute_block_counts rather than
        open-coded it.  When decrementing numblocks, call compute_block_counts
        again, to recompute all of the derived values.
        Require at least 14 free blocks in a 16-inode-per-group partition.
        * tests/t1500-small-ext2.sh: New file.  Test for the above.
        * tests/Makefile.am (TESTS): Add t1500-small-ext2.sh.

Signed-off-by: Jim Meyering <jim at meyering.net>
---
 libparted/fs/ext2/ext2_mkfs.c |   81 ++++++++++++++++++++++++++++-------------
 tests/Makefile.am             |    1 +
 tests/t1500-small-ext2.sh     |   63 ++++++++++++++++++++++++++++++++
 3 files changed, 120 insertions(+), 25 deletions(-)
 create mode 100755 tests/t1500-small-ext2.sh

diff --git a/libparted/fs/ext2/ext2_mkfs.c b/libparted/fs/ext2/ext2_mkfs.c
index 86175a8..8f74a45 100644
--- a/libparted/fs/ext2/ext2_mkfs.c
+++ b/libparted/fs/ext2/ext2_mkfs.c
@@ -480,6 +480,32 @@ static int ext2_mkfs_init_sb (struct ext2_super_block *sb, blk_t numblocks,
 	return 1;
 }
 
+/* Given these five inputs, compute the three outputs.  */
+static void
+compute_block_counts (blk_t numblocks, int numgroups, int log_block_size,
+                      int sparse_sb, blk_t blocks_per_group,
+                      int *last_group_blocks,
+                      int *last_group_admin,
+                      int *inodes_per_group)
+{
+        int first_block = (log_block_size == 10) ? 1 : 0;
+        size_t block_size = 1 << log_block_size;
+
+        *last_group_blocks = ((numblocks - first_block) % blocks_per_group);
+        if (!*last_group_blocks)
+                *last_group_blocks = blocks_per_group;
+        *inodes_per_group = ped_round_up_to (numblocks / numgroups / 2,
+                                             (block_size
+                                              / sizeof(struct ext2_inode)));
+        *last_group_admin = (2 + *inodes_per_group * sizeof(struct ext2_inode)
+                             / block_size);
+        if (is_group_sparse(sparse_sb, numgroups - 1)) {
+                *last_group_admin +=
+                  (ped_div_round_up (numgroups * sizeof(struct ext2_group_desc),
+                                     block_size));
+        }
+}
+
 struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 			  blk_t numblocks,
 			  int log_block_size,
@@ -494,8 +520,6 @@ struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 	struct ext2_group_desc *gd;
 	int numgroups;
 	int first_block;
-	int non_sparse_admin;
-	int sparse_admin;
 	int last_group_blocks;
 	int last_group_admin;
         
@@ -518,6 +542,7 @@ struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 
 	if (numblocks == 0)
 		numblocks = handle->ops->get_size(handle->cookie);
+        PED_ASSERT(numblocks != 0, return NULL);
 
 	if (blocks_per_group == (unsigned int) 0)
 		blocks_per_group = 8 << log_block_size;
@@ -527,11 +552,6 @@ struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 	numgroups = ped_div_round_up (numblocks
                         - first_block, blocks_per_group);
 
-	if (inodes_per_group == 0)
-		inodes_per_group = ped_round_up_to (
-			numblocks / numgroups / 2,
-			(1 << log_block_size) / sizeof(struct ext2_inode));
-
 	if (sparse_sb == -1)
 		sparse_sb = 1;
 
@@ -539,25 +559,36 @@ struct ext2_fs *ext2_mkfs(struct ext2_dev_handle *handle,
 	if (reserved_block_percentage == -1)
 		reserved_block_percentage = 5;
 
-	last_group_blocks = (numblocks - first_block) % blocks_per_group;
-	if (!last_group_blocks) last_group_blocks = blocks_per_group;
-	non_sparse_admin = 2
-			   + inodes_per_group * sizeof(struct ext2_inode)
-			   	/ (1 << log_block_size);
-	sparse_admin = non_sparse_admin
-		       + ped_div_round_up (numgroups
-                                       * sizeof(struct ext2_group_desc),
-				  1 << log_block_size);
-	last_group_admin = is_group_sparse(sparse_sb, numgroups - 1)
-			   ? sparse_admin : non_sparse_admin;
-	if (last_group_admin >= last_group_blocks) {
-		numgroups--;
+        compute_block_counts (numblocks, numgroups, log_block_size, sparse_sb,
+                              blocks_per_group, &last_group_blocks,
+                              &last_group_admin, &inodes_per_group);
+
+	int fs_too_small = 0;
+	if (last_group_admin >= last_group_blocks)
+          {
+            numgroups--;
+            if (numgroups == 0)
+              fs_too_small = 1;
+            else if (numgroups == 1)
+              {
 		numblocks -= last_group_blocks;
-	}
-	if (!numgroups
-	    || (numgroups == 1
-		    && (last_group_blocks - last_group_admin < 8
-	    		|| inodes_per_group < 16))) {
+                compute_block_counts (numblocks, numgroups, log_block_size,
+                                      sparse_sb, blocks_per_group,
+                                      &last_group_blocks, &last_group_admin,
+                                      &inodes_per_group);
+              }
+          }
+
+        if (numgroups == 1
+            && (last_group_blocks - last_group_admin < 8
+                || inodes_per_group < 16
+                /* This final term ensures that we detect
+                   mkpartfs primary ext2 10KB 27650B as invalid.  */
+                || (inodes_per_group == 16
+                    && last_group_blocks - last_group_admin < 14)))
+          fs_too_small = 1;
+
+	if (fs_too_small) {
 		ped_exception_throw (
 			PED_EXCEPTION_ERROR,
 			PED_EXCEPTION_CANCEL,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index df18eb4..55e44e2 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -2,6 +2,7 @@ TESTS = \
   t0000-basic.sh \
   t1000-mkpartfs.sh \
   t1100-busy-label.sh \
+  t1500-small-ext2.sh \
   t2000-mkfs.sh
 
 TESTS_ENVIRONMENT = \
diff --git a/tests/t1500-small-ext2.sh b/tests/t1500-small-ext2.sh
new file mode 100755
index 0000000..887a5f5
--- /dev/null
+++ b/tests/t1500-small-ext2.sh
@@ -0,0 +1,63 @@
+#!/bin/sh
+
+# Copyright (C) 2007 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+test_description='Create very small ext2 file systems.'
+
+. ./init.sh
+
+dev=loop-file
+test_expect_success \
+    'setup' '
+    dd if=/dev/zero of=$dev bs=10M count=1 2> /dev/null &&
+    parted -s $dev mklabel msdos'
+
+test_expect_failure \
+    'try to create an ext2 partition that is one byte too small' '
+    parted -s $dev mkpartfs primary ext2 10KB 29695B > out 2>&1'
+
+test_expect_success \
+    'check for expected diagnostic' '
+    echo Error: File system too small for ext2. > exp &&
+    $compare out exp'
+
+test_expect_success \
+    'create the smallest ext2 partition' '
+    parted -s $dev mkpartfs primary ext2 10KB 29696B > out 2>&1
+    $compare out /dev/null'
+
+# Restore $dev to initial state by writing 1KB of zeroes at the beginning.
+# Then relabel.
+test_expect_success \
+    'setup' '
+    dd if=/dev/zero of=$dev bs=1K count=1 conv=notrunc 2> /dev/null &&
+    parted -s $dev mklabel msdos'
+
+test_expect_success \
+    'create another ext2 file system (this would fail for parted-1.8.7)' '
+    parted -s $dev mkpartfs primary ext2 2 10 > out 2>&1'
+test_expect_success 'expect no output' '$compare out /dev/null'
+
+test_expect_success \
+    'create a smaller one; this would succeed for parted-1.8.7' '
+    dd if=/dev/zero of=$dev bs=1K count=1 conv=notrunc 2> /dev/null &&
+    parted -s $dev mklabel msdos &&
+    parted -s $dev mkpartfs primary ext2 2 9 > out 2>&1'
+test_expect_success 'expect no output' '$compare out /dev/null'
+
+test_done
-- 
1.5.2.rc3.50.gfdcb7



More information about the parted-devel mailing list