Hello,

Here's take 3.  I've moved the blocks >= 1 << 31 check after the instantiation
of the ext2_filsys so I can use the io manager stuff directly.  Also made a few
tweaks and such based on Andreas' comments.  Let me know if this works.  Thank
you,

Josef


Index: e2fsprogs/lib/ext2fs/getsize.c
===================================================================
--- e2fsprogs.orig/lib/ext2fs/getsize.c
+++ e2fsprogs/lib/ext2fs/getsize.c
@@ -135,6 +135,21 @@ static int valid_offset (int fd, ext2_lo
        return 1;
 }
 
+static int valid_size(unsigned long long *size64, int blocksize)
+{
+       /* see if we are above 16tb */
+       if ((*size64 / blocksize) > 0xFFFFFFFF) {
+               /* if we are just at 2^32 blocks adjust the size slightly */
+               if ((*size64 / blocksize) == 0x100000000) {
+                       (*size64)--;
+                       return 1;
+               } else
+                       return 0;
+       }
+
+       return 1;
+}
+
 /*
  * Returns the number of blocks in a partition
  */
@@ -189,7 +204,7 @@ errcode_t ext2fs_get_device_size(const c
        if (valid_blkgetsize64 &&
            ioctl(fd, BLKGETSIZE64, &size64) >= 0) {
                if ((sizeof(*retblocks) < sizeof(unsigned long long)) &&
-                   ((size64 / blocksize) > 0xFFFFFFFF)) {
+                   !valid_size(&size64, blocksize)) {
                        rc = EFBIG;
                        goto out;
                }
@@ -252,13 +267,14 @@ errcode_t ext2fs_get_device_size(const c
                struct stat     st;
                if (fstat(fd, &st) == 0)
 #endif
+                       size64 = st.st_size;
                        if (S_ISREG(st.st_mode)) {
                                if ((sizeof(*retblocks) < sizeof(unsigned long 
long)) &&
-                                   ((st.st_size / blocksize) > 0xFFFFFFFF)) {
+                                   !valid_size(&size64, blocksize)) {
                                        rc = EFBIG;
                                        goto out;
                                }
-                               *retblocks = st.st_size / blocksize;
+                               *retblocks = size64 / blocksize;
                                goto out;
                        }
        }
@@ -283,7 +299,7 @@ errcode_t ext2fs_get_device_size(const c
        valid_offset (fd, 0);
        size64 = low + 1;
        if ((sizeof(*retblocks) < sizeof(unsigned long long))
-           && ((size64 / blocksize) > 0xFFFFFFFF)) {
+           && !valid_size(&size64, blocksize)) {
                rc = EFBIG;
                goto out;
        }
Index: e2fsprogs/misc/mke2fs.c
===================================================================
--- e2fsprogs.orig/misc/mke2fs.c
+++ e2fsprogs/misc/mke2fs.c
@@ -916,6 +916,54 @@ static void edit_feature(const char *str
        }
 }
 
+static errcode_t check_for_wrap(ext2_filsys fs)
+{
+       char *buf, *orig;
+       errcode_t retval;
+
+       buf = malloc(fs->blocksize);
+       if (!buf) {
+               com_err(program_name, retval, "trying to allocate buffer\n");
+               exit(1);
+       }
+
+       orig = malloc(fs->blocksize);
+       if (!orig) {
+               com_err(program_name, retval, "trying to allocate buffer\n");
+               free(buf);
+               exit(1);
+       }
+
+       memset(buf, 0, fs->blocksize);
+       memset(orig, 0, fs->blocksize);
+
+       retval = io_channel_write_blk(fs->io, 1, 1, buf);
+       if (retval)
+               goto out;
+
+       memset(buf, 0xdead, fs->blocksize);
+       retval = io_channel_write_blk(fs->io, (1UL << 31)+1, 1, buf);
+       if (retval)
+               goto out;
+
+       retval = io_channel_flush(fs->io);
+       if (retval)
+               goto out;
+
+       retval = io_channel_read_blk(fs->io, 1, 1, buf);
+       if (retval)
+               goto out;
+
+       if (memcmp(buf, orig, fs->blocksize))
+               retval = -1;
+
+out:
+       free(buf);
+       free(orig);
+
+       return retval;
+}
+
 extern const char *mke2fs_default_profile;
 static const char *default_files[] = { "<default>", 0 };
 
@@ -1455,13 +1503,6 @@ static void PRS(int argc, char *argv[])
                }
        }
 
-       if (!force && fs_param.s_blocks_count >= ((unsigned) 1 << 31)) {
-               com_err(program_name, 0,
-                       _("Filesystem too large.  No more than 2**31-1 blocks\n"
-                         "\t (8TB using a blocksize of 4k) are currently 
supported."));
-             exit(1);
-       }
-
        if ((blocksize > 4096) &&
            (fs_param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
                fprintf(stderr, _("\nWarning: some 2.4 kernels do not support "
@@ -1572,6 +1613,23 @@ int main (int argc, char *argv[])
                exit(1);
        }
 
+       if (fs->super->s_blocks_count >= ((unsigned) 1 << 31)) {
+               if (!noaction) {
+                       retval = check_for_wrap(fs);
+                       if (retval) {
+                               com_err(program_name, retval, "Write wrapped,"
+                                       "filesystem is too large for the disk"
+                                       "to handle %d\n", (signed)retval);
+                               exit(1);
+                       }
+               }
+
+               com_err(program_name, 0, "\nWarning: older 2.6 kernels "
+                      "(2.6.18 and older) may have problems with such a \n\t"
+                      "large filesystem.  If you have problems try a newer "
+                      "kernel\n");
+       }
+
        /*
         * Wipe out the old on-disk superblock
         */
-
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to