[UPDATE][14/24]ext2 enlarge file size

[email protected]
Newsgroups gmane.linux.kernel,gmane.comp.file-systems.ext2.devel
Message-ID <[email protected]>
Summary of this patch:
  [14/24] extend file size(ext2)
          - If the flag is set to super block, i_blocks of disk inode
            (ext3_inode) is filesystem-block unit, and i_blocks of VFS
            inode is sector unit.

          - If the flag is set to super block, max file size is set to
            (FS blocksize) * (2^32 -1).

Signed-off-by: Takashi Sato [email protected]
---
diff -upNr -X linux-2.6.17-rc4/Documentation/dontdiff linux-2.6.17-rc4/fs/ext2/inode.c linux-2.6.17-rc4.tmp/fs/ext2/inode.c
--- linux-2.6.17-rc4/fs/ext2/inode.c	2006-05-25 16:33:48.509510541 +0900
+++ linux-2.6.17-rc4.tmp/fs/ext2/inode.c	2006-05-25 16:34:32.872791248 +0900
@@ -1095,8 +1095,13 @@ void ext2_read_inode (struct inode * ino
 		goto bad_inode;
 	}
 	inode->i_blksize = PAGE_SIZE;	/* This is the optimal IO size (for stat), not the fs block size */
-	inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
 	ei->i_flags = le32_to_cpu(raw_inode->i_flags);
+	if (ei->i_flags & EXT2_HUGE_FILE_FL) {
+		inode->i_blocks = (blkcnt_t)le32_to_cpu(raw_inode->i_blocks)
+			<< (inode->i_blkbits - EXT2_SECTOR_BITS);
+	} else {
+		inode->i_blocks = le32_to_cpu(raw_inode->i_blocks);
+	}
 	ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
 	ei->i_frag_no = raw_inode->i_frag;
 	ei->i_frag_size = raw_inode->i_fsize;
@@ -1215,10 +1220,22 @@ static int ext2_update_inode(struct inod
 	raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
 	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_flags = cpu_to_le32(ei->i_flags);
 
-	raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+	if (inode->i_blocks <= ~0U) {
+		raw_inode->i_flags &= ~EXT2_HUGE_FILE_FL;
+		raw_inode->i_blocks = cpu_to_le32(inode->i_blocks);
+	} else {
+		ext2_update_dynamic_rev(sb);
+		EXT2_SET_RO_COMPAT_FEATURE(sb,
+				EXT2_FEATURE_RO_COMPAT_HUGE_FILE);
+		ext2_write_super(sb);
+		printk("ext2_update_inode: Now the file size is more than 2TB on (%s)!!\n", sb->s_id);
+		raw_inode->i_flags |= EXT2_HUGE_FILE_FL;
+		raw_inode->i_blocks = cpu_to_le32((inode->i_blocks)
+			>> (inode->i_blkbits - EXT2_SECTOR_BITS));
+	}
 	raw_inode->i_dtime = cpu_to_le32(ei->i_dtime);
-	raw_inode->i_flags = cpu_to_le32(ei->i_flags);
 	raw_inode->i_faddr = cpu_to_le32(ei->i_faddr);
 	raw_inode->i_frag = ei->i_frag_no;
 	raw_inode->i_fsize = ei->i_frag_size;
diff -upNr -X linux-2.6.17-rc4/Documentation/dontdiff linux-2.6.17-rc4/fs/ext2/super.c linux-2.6.17-rc4.tmp/fs/ext2/super.c
--- linux-2.6.17-rc4/fs/ext2/super.c	2006-05-25 16:33:48.510487104 +0900
+++ linux-2.6.17-rc4.tmp/fs/ext2/super.c	2006-05-25 16:34:32.873767810 +0900
@@ -557,14 +557,21 @@ static int ext2_check_descriptors (struc
  * block limit, and also a limit of (2^32 - 1) 512-byte sectors in i_blocks.
  * We need to be 1 filesystem block less than the 2^32 sector limit.
  */
-static loff_t ext2_max_size(int bits)
+static loff_t ext2_max_size(int bits, struct super_block *sb)
 {
 	loff_t res = EXT2_NDIR_BLOCKS;
 	/* This constant is calculated to be the largest file size for a
 	 * dense, 4k-blocksize file such that the total number of
 	 * sectors in the file, including data and all indirect blocks,
 	 * does not exceed 2^32. */
-	const loff_t upper_limit = 0x1ff7fffd000LL;
+	loff_t upper_limit;
+	if (sizeof(blkcnt_t) < sizeof(u64)) {
+		upper_limit = 0x1ff7fffd000LL;
+	}
+	/* With CONFIG_LSF on, file size is limited to blocksize*(4G-1) */
+	else { 
+		upper_limit = (1LL << (bits + 32)) - (1LL << bits);
+	}
 
 	res += 1LL << (bits-2);
 	res += 1LL << (2*(bits-2));
@@ -748,7 +755,7 @@ static int ext2_fill_super(struct super_
 		}
 	}
 
-	sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits);
+	sb->s_maxbytes = ext2_max_size(sb->s_blocksize_bits, sb);
 
 	if (le32_to_cpu(es->s_rev_level) == EXT2_GOOD_OLD_REV) {
 		sbi->s_inode_size = EXT2_GOOD_OLD_INODE_SIZE;
@@ -873,6 +880,19 @@ static int ext2_fill_super(struct super_
 	sb->s_export_op = &ext2_export_ops;
 	sb->s_xattr = ext2_xattr_handlers;
 	root = iget(sb, EXT2_ROOT_INO);
+
+	if (EXT2_HAS_RO_COMPAT_FEATURE(sb,
+	    EXT2_FEATURE_RO_COMPAT_HUGE_FILE)) {
+		if (sizeof(root->i_blocks) < sizeof(u64)) {
+			if (!(sb->s_flags & MS_RDONLY)) {
+				printk(KERN_ERR "EXT2-fs: %s: Having huge file with "
+						"LSF off, you must mount filesystem "
+						"read-only.\n", sb->s_id);
+				goto failed_mount;
+			}
+		}
+	}
+
 	sb->s_root = d_alloc_root(root);
 	if (!sb->s_root) {
 		iput(root);
diff -upNr -X linux-2.6.17-rc4/Documentation/dontdiff linux-2.6.17-rc4/include/linux/ext2_fs.h linux-2.6.17-rc4.tmp/include/linux/ext2_fs.h
--- linux-2.6.17-rc4/include/linux/ext2_fs.h	2006-05-25 16:34:05.951893140 +0900
+++ linux-2.6.17-rc4.tmp/include/linux/ext2_fs.h	2006-05-25 16:34:32.874744373 +0900
@@ -104,6 +104,7 @@ static inline struct ext2_sb_info *EXT2_
 #else
 # define EXT2_BLOCK_SIZE_BITS(s)	((s)->s_log_block_size + 10)
 #endif
+#define EXT2_SECTOR_BITS	9	/* log2(SECTOR_SIZE) */
 #ifdef __KERNEL__
 #define	EXT2_ADDR_PER_BLOCK_BITS(s)	(EXT2_SB(s)->s_addr_per_block_bits)
 #define EXT2_INODE_SIZE(s)		(EXT2_SB(s)->s_inode_size)
@@ -193,6 +194,7 @@ struct ext2_group_desc
 #define EXT2_NOTAIL_FL			0x00008000 /* file tail should not be merged */
 #define EXT2_DIRSYNC_FL			0x00010000 /* dirsync behaviour (directories only) */
 #define EXT2_TOPDIR_FL			0x00020000 /* Top of directory hierarchies*/
+#define EXT2_HUGE_FILE_FL               0x00040000 /* Set to each huge file */
 #define EXT2_RESERVED_FL		0x80000000 /* reserved for ext2 lib */
 
 #define EXT2_FL_USER_VISIBLE		0x0003DFFF /* User visible flags */
@@ -465,6 +467,7 @@ struct ext2_super_block {
 #define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER	0x0001
 #define EXT2_FEATURE_RO_COMPAT_LARGE_FILE	0x0002
 #define EXT2_FEATURE_RO_COMPAT_BTREE_DIR	0x0004
+#define EXT2_FEATURE_RO_COMPAT_HUGE_FILE        0x0008
 #define EXT2_FEATURE_RO_COMPAT_ANY		0xffffffff
 
 #define EXT2_FEATURE_INCOMPAT_COMPRESSION	0x0001
@@ -481,7 +484,8 @@ struct ext2_super_block {
 					 EXT2_FEATURE_INCOMPAT_HUGE_FS)
 #define EXT2_FEATURE_RO_COMPAT_SUPP	(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER| \
 					 EXT2_FEATURE_RO_COMPAT_LARGE_FILE| \
-					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR)
+					 EXT2_FEATURE_RO_COMPAT_BTREE_DIR| \
+					 EXT2_FEATURE_RO_COMPAT_HUGE_FILE)
 #define EXT2_FEATURE_RO_COMPAT_UNSUPPORTED	~EXT2_FEATURE_RO_COMPAT_SUPP
 #define EXT2_FEATURE_INCOMPAT_UNSUPPORTED	~EXT2_FEATURE_INCOMPAT_SUPP
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.