Skip to contentSkip to conversation

reiserfsprogs: enforce 2^32-1 block limit

PATCH In review Jeff Mahoney 2 participants 5 messages Aug 13, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 reiserfsprogs: enforce 2^32-1 block limit

Currently, mkreiserfs on a block device >= 16 TiB will fail with this error:
reiserfs_create_journal: cannot create a journal of 8193 blocks with 18 offset on 0 blocks

The message doesn't adequately describe that the problem is that reiserfs supports file system sizes up to 2^32-1 blocks, and it silently overflows.

This patch treats the block device size, as well as the <blocks> command line parameter as __u64's, so that they can be safely compared to UINT_MAX.

If the block device is too large, we warn the user, offer to truncate the file system to 2^32-1 blocks, and confirm. This is overridable by the -f option, which will elect to truncate automatically.

If the user has specified a block count that is too large, we fail always since the user has provided invalid input.

Please apply.

utils/mkfs/mkreiserfs.c +39 -2
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
@@ -438,6 +439,21 @@
     return val;
 }
 
+static __u64 str2u64 (char *str)
+{
+    __u64 val;
+    char *tmp;
+
+    val = (__u64)strtoll(str, &tmp, 0);
+
+    if (*tmp) {
+	reiserfs_exit (1, "%s: strtoll is unable to make an integer of %s\n",
+		       program_name, str);
+    }
+
+    return val;
+}
+
 
 static void set_block_size (char * str, int *b_size)
 {
@@ -575,7 +591,7 @@
     int force = 0;
     char * device_name = NULL;
     char * jdevice_name = NULL;
-    unsigned long fs_size = 0;
+    __u64 fs_size = 0;
     int c;
     static int flag;
 
@@ -710,7 +726,7 @@
     
     if (optind == argc - 2) {
         /* number of blocks for filesystem is specified */
-        fs_size = str2int (argv[optind + 1]);
+        fs_size = str2u64 (argv[optind + 1]);
     } else if (optind == argc - 1) {
         /* number of blocks is not specified */
         if (!(fs_size = misc_device_count_blocks (device_name, Block_size)))
@@ -719,6 +735,27 @@
         print_usage_and_exit ();
     }
 
+    if (fs_size >= UINT_MAX) {
+	fprintf(stderr, ">>> ReiserFS supports file systems of up to %u "
+	        "blocks.\n>>> The maximum size with a block size of %u bytes "
+		"is about %Lu MiB.\n>>> This file system would occupy %Lu "
+		"blocks. ", UINT_MAX, Block_size,
+		((__u64)UINT_MAX * Block_size) / (1024 * 1024), fs_size);
+
+	if (optind == argc - 1) {
+	    if (!force &&
+		!util_user_confirmed (stderr, "Truncate? (y/N): ", "y\n")) {
+		fprintf(stderr, "\nExiting.\n\n");
+		exit(1);
+	    }
+	    fprintf(stderr, "Truncating.\n\n");
+	    fs_size = UINT_MAX;
+	} else {
+	    fprintf(stderr, "Exiting.\n\n");
+	    exit(1);
+	}
+    }
+
     if (is_journal_default (device_name, jdevice_name, Block_size))
         Create_default_journal = 1;
     
Signature · 2 lines
Jeff Mahoney
SUSE Labs
#1 lore raw

Hello

utils/mkfs/mkreiserfs.c

Quoted 23 lines · Jeff Mahoney

Currently, mkreiserfs on a block device >= 16 TiB will fail with this error:
reiserfs_create_journal: cannot create a journal of 8193 blocks with 18 offset on 0 blocks

The message doesn't adequately describe that the problem is that reiserfs supports file system sizes up to 2^32-1 blocks, and it silently overflows.

This patch treats the block device size, as well as the <blocks> command line parameter as __u64's, so that they can be safely compared to UINT_MAX.

If the block device is too large, we warn the user, offer to truncate the file system to 2^32-1 blocks, and confirm. This is overridable by the -f option, which will elect to truncate automatically.

If the user has specified a block count that is too large, we fail always since the user has provided invalid input.

Please apply.

utils/mkfs/mkreiserfs.c +0 -0

What did you diff against?

Quoted 77 lines
utils/mkfs/mkreiserfs.c +39 -2
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
@@ -438,6 +439,21 @@
     return val;
 }
 
+static __u64 str2u64 (char *str)
+{
+    __u64 val;
+    char *tmp;
+
+    val = (__u64)strtoll(str, &tmp, 0);
+
+    if (*tmp) {
+	reiserfs_exit (1, "%s: strtoll is unable to make an integer of %s\n",
+		       program_name, str);
+    }
+
+    return val;
+}
+
 
 static void set_block_size (char * str, int *b_size)
 {
@@ -575,7 +591,7 @@
     int force = 0;
     char * device_name = NULL;
     char * jdevice_name = NULL;
-    unsigned long fs_size = 0;
+    __u64 fs_size = 0;
     int c;
     static int flag;
 
@@ -710,7 +726,7 @@
 
     if (optind == argc - 2) {
         /* number of blocks for filesystem is specified */
-        fs_size = str2int (argv[optind + 1]);
+        fs_size = str2u64 (argv[optind + 1]);
     } else if (optind == argc - 1) {
         /* number of blocks is not specified */
         if (!(fs_size = misc_device_count_blocks (device_name, Block_size)))
@@ -719,6 +735,27 @@
         print_usage_and_exit ();
     }
 
+    if (fs_size >= UINT_MAX) {
+	fprintf(stderr, ">>> ReiserFS supports file systems of up to %u "
+	        "blocks.\n>>> The maximum size with a block size of %u bytes "
+		"is about %Lu MiB.\n>>> This file system would occupy %Lu "
+		"blocks. ", UINT_MAX, Block_size,
+		((__u64)UINT_MAX * Block_size) / (1024 * 1024), fs_size);
+
+	if (optind == argc - 1) {
+	    if (!force &&
+		!util_user_confirmed (stderr, "Truncate? (y/N): ", "y\n")) {
+		fprintf(stderr, "\nExiting.\n\n");
+		exit(1);
+	    }
+	    fprintf(stderr, "Truncating.\n\n");
+	    fs_size = UINT_MAX;
+	} else {
+	    fprintf(stderr, "Exiting.\n\n");
+	    exit(1);
+	}
+    }
+
     if (is_journal_default (device_name, jdevice_name, Block_size))
         Create_default_journal = 1;
 
#2 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 20 lines · Vladimir V. Saveliev

Hello

Quoted 17 lines · Jeff Mahoney

Currently, mkreiserfs on a block device >= 16 TiB will fail with this error:
reiserfs_create_journal: cannot create a journal of 8193 blocks with 18 offset on 0 blocks

The message doesn't adequately describe that the problem is that reiserfs supports file system sizes up to 2^32-1 blocks, and it silently overflows.

This patch treats the block device size, as well as the <blocks> command line parameter as __u64's, so that they can be safely compared to UINT_MAX.

If the block device is too large, we warn the user, offer to truncate the file system to 2^32-1 blocks, and confirm. This is overridable by the -f option, which will elect to truncate automatically.

If the user has specified a block count that is too large, we fail always since the user has provided invalid input.

Quoted 8 lines

utils/mkfs/mkreiserfs.c

Quoted 6 lines

Please apply.

utils/mkfs/mkreiserfs.c +0 -0

What did you diff against?

reiserfsprogs 3.6.20, though I think it was my development tree since a patch to a fresh tree comes up with offset -2, but otherwise applies.

- -Jeff

Quoted 69 lines
Quoted 69 lines
utils/mkfs/mkreiserfs.c +35 -2
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
@@ -438,6 +439,21 @@
     return val;
 }
 
+static __u64 str2u64 (char *str)
+{
+    __u64 val;
+    char *tmp;
+
+    val = (__u64)strtoll(str, &tmp, 0);
+
+    if (*tmp) {
+	reiserfs_exit (1, "%s: strtoll is unable to make an integer of %s\n",
+		       program_name, str);
+    }
+
+    return val;
+}
+
 
 static void set_block_size (char * str, int *b_size)
 {
@@ -575,7 +591,7 @@
     int force = 0;
     char * device_name = NULL;
     char * jdevice_name = NULL;
-    unsigned long fs_size = 0;
+    __u64 fs_size = 0;
     int c;
     static int flag;
 
@@ -710,7 +726,7 @@
 
     if (optind == argc - 2) {
         /* number of blocks for filesystem is specified */
-        fs_size = str2int (argv[optind + 1]);
+        fs_size = str2u64 (argv[optind + 1]);
     } else if (optind == argc - 1) {
         /* number of blocks is not specified */
         if (!(fs_size = misc_device_count_blocks (device_name, Block_size)))
@@ -719,6 +735,27 @@
         print_usage_and_exit ();
     }
 
+    if (fs_size >= UINT_MAX) {
+	fprintf(stderr, ">>> ReiserFS supports file systems of up to %u "
+	        "blocks.\n>>> The maximum size with a block size of %u bytes "
+		"is about %Lu MiB.\n>>> This file system would occupy %Lu "
+		"blocks. ", UINT_MAX, Block_size,
+		((__u64)UINT_MAX * Block_size) / (1024 * 1024), fs_size);
+
+	if (optind == argc - 1) {
+	    if (!force &&
+		!util_user_confirmed (stderr, "Truncate? (y/N): ", "y\n")) {
+		fprintf(stderr, "\nExiting.\n\n");
+		exit(1);
+	    }
+	    fprintf(stderr, "Truncating.\n\n");
+	    fs_size = UINT_MAX;
+	} else {
+	    fprintf(stderr, "Exiting.\n\n");
Quoted 9 lines

utils/mkfs/mkreiserfs.c line 761

Quoted 8 lines
utils/mkfs/mkreiserfs.c +4 -0
+	    exit(1);
+	}
+    }
+
     if (is_journal_default (device_name, jdevice_name, Block_size))
         Create_default_journal = 1;
 

- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFGwLegLPWxlyuTD7IRAsDFAJ9QQ4OKUcyTeoW5b0DdS7+1vG7EzwCfUz1+ XARDrvF4WzwYY2T58F9FEwk=
=me8b
-----END PGP SIGNATURE-----

#3 lore raw
Quoted 8 lines · Jeff Mahoney
Quoted 7 lines · Vladimir V. Saveliev
Quoted 7 lines

Hello

Quoted 4 lines · Jeff Mahoney

Currently, mkreiserfs on a block device >= 16 TiB will fail with this error:
reiserfs_create_journal: cannot create a journal of 8193 blocks with 18 offset on 0 blocks

Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines

The message doesn't adequately describe that the problem is that reiserfs supports file system sizes up to 2^32-1 blocks, and it silently overflows.

This patch treats the block device size, as well as the <blocks> command line parameter as __u64's, so that they can be safely compared to UINT_MAX.

If the block device is too large,

You probably should also fix misc_device_count_blocks to return device size in 64 bits. Currently it returns unsigned long.

we warn the user, offer to truncate the

Quoted 102 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

file system to 2^32-1 blocks, and confirm. This is overridable by the -f option, which will elect to truncate automatically.

If the user has specified a block count that is too large, we fail always since the user has provided invalid input.

Quoted 7 lines
Quoted 7 lines

utils/mkfs/mkreiserfs.c

Quoted 6 lines

Please apply.

utils/mkfs/mkreiserfs.c +0 -0

What did you diff against?

reiserfsprogs 3.6.20, though I think it was my development tree since a patch to a fresh tree comes up with offset -2, but otherwise applies.

-Jeff

Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
utils/mkfs/mkreiserfs.c +35 -2
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
@@ -438,6 +439,21 @@
     return val;
 }
 
+static __u64 str2u64 (char *str)
+{
+    __u64 val;
+    char *tmp;
+
+    val = (__u64)strtoll(str, &tmp, 0);
+
+    if (*tmp) {
+	reiserfs_exit (1, "%s: strtoll is unable to make an integer of %s\n",
+		       program_name, str);
+    }
+
+    return val;
+}
+
 
 static void set_block_size (char * str, int *b_size)
 {
@@ -575,7 +591,7 @@
     int force = 0;
     char * device_name = NULL;
     char * jdevice_name = NULL;
-    unsigned long fs_size = 0;
+    __u64 fs_size = 0;
     int c;
     static int flag;
 
@@ -710,7 +726,7 @@
 
     if (optind == argc - 2) {
         /* number of blocks for filesystem is specified */
-        fs_size = str2int (argv[optind + 1]);
+        fs_size = str2u64 (argv[optind + 1]);
     } else if (optind == argc - 1) {
         /* number of blocks is not specified */
         if (!(fs_size = misc_device_count_blocks (device_name, Block_size)))
@@ -719,6 +735,27 @@
         print_usage_and_exit ();
     }
 
+    if (fs_size >= UINT_MAX) {
+	fprintf(stderr, ">>> ReiserFS supports file systems of up to %u "
+	        "blocks.\n>>> The maximum size with a block size of %u bytes "
+		"is about %Lu MiB.\n>>> This file system would occupy %Lu "
+		"blocks. ", UINT_MAX, Block_size,
+		((__u64)UINT_MAX * Block_size) / (1024 * 1024), fs_size);
+
+	if (optind == argc - 1) {
+	    if (!force &&
+		!util_user_confirmed (stderr, "Truncate? (y/N): ", "y\n")) {
+		fprintf(stderr, "\nExiting.\n\n");
+		exit(1);
+	    }
+	    fprintf(stderr, "Truncating.\n\n");
+	    fs_size = UINT_MAX;
+	} else {
+	    fprintf(stderr, "Exiting.\n\n");
Quoted 8 lines
Quoted 8 lines

utils/mkfs/mkreiserfs.c line 761

Quoted 8 lines
utils/mkfs/mkreiserfs.c +4 -0
+	    exit(1);
+	}
+    }
+
     if (is_journal_default (device_name, jdevice_name, Block_size))
         Create_default_journal = 1;
 

--
Jeff Mahoney
SUSE Labs

#4 lore raw

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Quoted 12 lines · Vladimir V. Saveliev
Quoted 11 lines · Jeff Mahoney
Quoted 10 lines · Vladimir V. Saveliev
Quoted 10 lines

Hello

Quoted 7 lines · Jeff Mahoney

Currently, mkreiserfs on a block device >= 16 TiB will fail with this error:
reiserfs_create_journal: cannot create a journal of 8193 blocks with 18 offset on 0 blocks

The message doesn't adequately describe that the problem is that reiserfs supports file system sizes up to 2^32-1 blocks, and it silently overflows.

Quoted 8 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines
Quoted 4 lines

This patch treats the block device size, as well as the <blocks> command line parameter as __u64's, so that they can be safely compared to UINT_MAX.

If the block device is too large,

You probably should also fix misc_device_count_blocks to return device size in 64 bits. Currently it returns unsigned long.

Ok, I'll check that. I initially developed the patch against 3.6.19, since that's what we ship still.

- -Jeff

Quoted 101 lines

we warn the user, offer to truncate the

Quoted 100 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines

file system to 2^32-1 blocks, and confirm. This is overridable by the -f option, which will elect to truncate automatically.

If the user has specified a block count that is too large, we fail always since the user has provided invalid input.

Quoted 7 lines
Quoted 7 lines

utils/mkfs/mkreiserfs.c

Quoted 6 lines

Please apply.

utils/mkfs/mkreiserfs.c +0 -0

What did you diff against?

reiserfsprogs 3.6.20, though I think it was my development tree since a patch to a fresh tree comes up with offset -2, but otherwise applies.

-Jeff

Quoted 69 lines
Quoted 69 lines
Quoted 69 lines
utils/mkfs/mkreiserfs.c +35 -2
@@ -29,6 +29,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <errno.h>
+#include <limits.h>
 
 #ifdef HAVE_UNAME
 # include <sys/utsname.h>
@@ -438,6 +439,21 @@
     return val;
 }
 
+static __u64 str2u64 (char *str)
+{
+    __u64 val;
+    char *tmp;
+
+    val = (__u64)strtoll(str, &tmp, 0);
+
+    if (*tmp) {
+	reiserfs_exit (1, "%s: strtoll is unable to make an integer of %s\n",
+		       program_name, str);
+    }
+
+    return val;
+}
+
 
 static void set_block_size (char * str, int *b_size)
 {
@@ -575,7 +591,7 @@
     int force = 0;
     char * device_name = NULL;
     char * jdevice_name = NULL;
-    unsigned long fs_size = 0;
+    __u64 fs_size = 0;
     int c;
     static int flag;
 
@@ -710,7 +726,7 @@
 
     if (optind == argc - 2) {
         /* number of blocks for filesystem is specified */
-        fs_size = str2int (argv[optind + 1]);
+        fs_size = str2u64 (argv[optind + 1]);
     } else if (optind == argc - 1) {
         /* number of blocks is not specified */
         if (!(fs_size = misc_device_count_blocks (device_name, Block_size)))
@@ -719,6 +735,27 @@
         print_usage_and_exit ();
     }
 
+    if (fs_size >= UINT_MAX) {
+	fprintf(stderr, ">>> ReiserFS supports file systems of up to %u "
+	        "blocks.\n>>> The maximum size with a block size of %u bytes "
+		"is about %Lu MiB.\n>>> This file system would occupy %Lu "
+		"blocks. ", UINT_MAX, Block_size,
+		((__u64)UINT_MAX * Block_size) / (1024 * 1024), fs_size);
+
+	if (optind == argc - 1) {
+	    if (!force &&
+		!util_user_confirmed (stderr, "Truncate? (y/N): ", "y\n")) {
+		fprintf(stderr, "\nExiting.\n\n");
+		exit(1);
+	    }
+	    fprintf(stderr, "Truncating.\n\n");
+	    fs_size = UINT_MAX;
+	} else {
+	    fprintf(stderr, "Exiting.\n\n");
Quoted 8 lines
Quoted 8 lines

utils/mkfs/mkreiserfs.c line 761

Quoted 8 lines
utils/mkfs/mkreiserfs.c +4 -0
+	    exit(1);
+	}
+    }
+
     if (is_journal_default (device_name, jdevice_name, Block_size))
         Create_default_journal = 1;
 

--
Jeff Mahoney
SUSE Labs

- --
Jeff Mahoney
SUSE Labs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.4-svn0 (GNU/Linux)
Comment: Using GnuPG with SUSE - http://enigmail.mozdev.org

iD8DBQFGwLrGLPWxlyuTD7IRAm42AJ9pbhp7lI4yMegFS8RgKFh502RuugCfYrKy fR0APgjMHMV9UywsISPMjPE=
=844X
-----END PGP SIGNATURE-----