|
|
Subscribe / Log in / New account

Breaking ext2 file size limit of 2TB

From:  "Goldwyn Rodrigues" <goldwyn_r@myrealbox.com>
To:  linux-kernel@vger.kernel.org
Subject:  [PATCH] Breaking ext2 file size limit of 2TB
Date:  Fri, 25 Jun 2004 18:34:06 +0530

Hi,

I have made a patch to enable file creation greater than 2TB. I tested it using sparse files and it works good.

Working:
The file size limit of the ext3 filesystem is limited to 2TB because of i_blocks, a variable which stores the number of 512 blocks in the inode. i_blocks is a 32 which limits the number it can hold. The patch makes use of l_i_reserved1 field to keep the higher order bits of i_blocks.

This has been developed and tested on kernel version 2.6.5 using sparse files.

Advantages: 
1. Patch is compatible with the existing filesystem and does not need re-formatting of the device.

Disadvantages: 

1. The patch uses l_i_reserved1 field to keep higher order 32-bits of i_blocks. This means the patch cannot be used with HURD filesystems, because it is occupied with a translator field.
2. Changes in fs.h, which is not really required.

I have also developed a patch to take the limits till 8TB, but there are lot of changes in that, including the memory copy of the inode structure. Moreover, it breaks with usual filesystems utils like fsck.

Feedback welcome.

Thanks,

-- 
Goldwyn :o)


diff -Nru linux-2.6.5-orig/fs/ext3/inode.c linux-2.6.5-4TB/fs/ext3/inode.c
--- linux-2.6.5-orig/fs/ext3/inode.c	2004-04-04 09:07:36.000000000 +0530
+++ linux-2.6.5-4TB/fs/ext3/inode.c	2004-06-23 12:30:41.000000000 +0530
@@ -355,7 +355,7 @@
  */
 
 static int ext3_block_to_path(struct inode *inode,
-			long i_block, int offsets[4], int *boundary)
+			sector_t i_block, int offsets[4], int *boundary)
 {
 	int ptrs = EXT3_ADDR_PER_BLOCK(inode->i_sb);
 	int ptrs_bits = EXT3_ADDR_PER_BLOCK_BITS(inode->i_sb);
@@ -906,7 +906,7 @@
  * `handle' can be NULL if create is zero
  */
 struct buffer_head *ext3_getblk(handle_t *handle, struct inode * inode,
-				long block, int create, int * errp)
+				sector_t block, int create, int * errp)
 {
 	struct buffer_head dummy;
 	int fatal = 0, err;
@@ -956,10 +956,10 @@
 }
 
 struct buffer_head *ext3_bread(handle_t *handle, struct inode * inode,
-			       int block, int create, int *err)
+			       sector_t block, int create, int *err)
 {
 	struct buffer_head * bh;
-	int prev_blocks;
+	sector_t prev_blocks;
 
 	prev_blocks = inode->i_blocks;
 
@@ -2126,7 +2126,7 @@
 	Indirect *partial;
 	int nr = 0;
 	int n;
-	long last_block;
+	sector_t last_block;
 	unsigned blocksize = inode->i_sb->s_blocksize;
 	struct page *page;
 
@@ -2516,6 +2516,8 @@
 					 * (for stat), not the fs block
 					 * size */  
 	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+	inode->i_blocks |= ((__u64)le32_to_cpu(raw_inode->i_blocks_high)) << 32;
+
 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
 #ifdef EXT3_FRAGMENTS
 	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
@@ -2542,6 +2544,7 @@
 	 */
 	for (block = 0; block < EXT3_N_BLOCKS; block++)
 		ei->i_data[block] = raw_inode->i_block[block];
+	
 	INIT_LIST_HEAD(&ei->i_orphan);
 
 	if (S_ISREG(inode->i_mode)) {
@@ -2628,6 +2631,9 @@
 	raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
 	raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
 	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+	raw_inode->i_blocks_high = cpu_to_le32(inode->i_blocks >> 32);
+
+
 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
 	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
 #ifdef EXT3_FRAGMENTS
diff -Nru linux-2.6.5-orig/fs/ext3/super.c linux-2.6.5-4TB/fs/ext3/super.c
--- linux-2.6.5-orig/fs/ext3/super.c	2004-04-04 09:08:14.000000000 +0530
+++ linux-2.6.5-4TB/fs/ext3/super.c	2004-06-23 12:32:01.000000000 +0530
@@ -1003,9 +1003,9 @@
 	res += 1LL << (bits-2);
 	res += 1LL << (2*(bits-2));
 	res += 1LL << (3*(bits-2));
-	res <<= bits;
-	if (res > (512LL << 32) - (1 << bits))
-		res = (512LL << 32) - (1 << bits);
+	/* Since another block is added, we add the same number again */
+	res += 1LL << (3*(bits-2));
+	res <<=bits;
 	return res;
 }
 
diff -Nru linux-2.6.5-orig/fs/Kconfig linux-2.6.5-4TB/fs/Kconfig
--- linux-2.6.5-orig/fs/Kconfig	2004-04-04 09:07:23.000000000 +0530
+++ linux-2.6.5-4TB/fs/Kconfig	2004-06-23 12:19:00.000000000 +0530
@@ -114,6 +114,21 @@
 	  of your root partition (the one containing the directory /) cannot
 	  be compiled as a module, and so this may be dangerous.
 
+config EXT3_LARGE_FILE_SUPPORT
+	bool "Large File (>2TB) Support (EXPERIMENTAL)"
+	depends on EXT3_FS
+	depends on LBD
+	default n
+	help
+	  Ext3 filesystem currently has a limit of 2TB. This experimental
+	  release extends this limit to 8TB by using the reserved fields
+	  in the inode. Thus, this feature can be used under Linux only.
+	  This feature is compatible with existing EXT3 filesystem.
+
+	  If unsure say N.
+		
+
+
 config EXT3_FS_XATTR
 	bool "Ext3 extended attributes"
 	depends on EXT3_FS
diff -Nru linux-2.6.5-orig/include/linux/ext3_fs.h linux-2.6.5-4TB/include/linux/ext3_fs.h
--- linux-2.6.5-orig/include/linux/ext3_fs.h	2004-04-04 09:07:23.000000000 +0530
+++ linux-2.6.5-4TB/include/linux/ext3_fs.h	2004-06-23 12:35:26.000000000 +0530
@@ -278,6 +278,10 @@
 #define i_gid_high	osd2.linux2.l_i_gid_high
 #define i_reserved2	osd2.linux2.l_i_reserved2
 
+#ifdef CONFIG_EXT3_LARGE_FILE_SUPPORT
+#define i_blocks_high		osd1.linux1.l_i_reserved1
+#endif
+
 #elif defined(__GNU__)
 
 #define i_translator	osd1.hurd1.h_i_translator
@@ -718,8 +722,8 @@
 
 /* inode.c */
 extern int ext3_forget(handle_t *, int, struct inode *, struct buffer_head *, int);
-extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, long, int, int *);
-extern struct buffer_head * ext3_bread (handle_t *, struct inode *, int, int, int *);
+extern struct buffer_head * ext3_getblk (handle_t *, struct inode *, sector_t, int, int *);
+extern struct buffer_head * ext3_bread (handle_t *, struct inode *, sector_t, int, int *);
 
 extern void ext3_read_inode (struct inode *);
 extern void ext3_write_inode (struct inode *, int);
diff -Nru linux-2.6.5-orig/include/linux/fs.h linux-2.6.5-4TB/include/linux/fs.h
--- linux-2.6.5-orig/include/linux/fs.h	2004-04-04 09:06:52.000000000 +0530
+++ linux-2.6.5-4TB/include/linux/fs.h	2004-06-23 12:18:43.000000000 +0530
@@ -393,7 +393,11 @@
 	unsigned int		i_blkbits;
 	unsigned long		i_blksize;
 	unsigned long		i_version;
+#if !defined(CONFIG_EXT3_LARGE_FILE_SUPPORT) || defined(CONFIG_64BIT)
 	unsigned long		i_blocks;
+#else
+	unsigned long long	i_blocks;
+#endif /* CONFIG_EXT3_LARGE_FILE_SUPPORT */
 	unsigned short          i_bytes;
 	spinlock_t		i_lock;	/* i_blocks, i_bytes, maybe i_size */
 	struct semaphore	i_sem;


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Copyright © 2004, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds