Re: [RFC 13/13] extents and 48bit ext3: super block (metadata) changes

Alexandre Ratchov <[email protected]>
Newsgroups gmane.comp.file-systems.ext2.devel
Message-ID <[email protected]>
On Thu, Jun 08, 2006 at 06:24:16PM -0700, Mingming Cao wrote:
> In-kernel and on-disk super block changes to support >32 bit blocks numbers.
> 

hi,

there is a small fix for the 64bit meta-data patch that you posted.

reserved fields of the ext3_super_block that we use to expand 32bit fields
are already in use by e2fsprogs (fs creation time, and journal inodes
backup). This prevents ext3 filesystems to be mounted with the above patch
set).

in the attached patch the issue is fixed by making kernel side and e2fsprogs
side superblock structures compatibles. (I've also changed the
EXT3_FEATURE_RO_COMPAT_64 to EXT3_FEATURE_INCOMPAT_64)

cheers,

-- 
Alexandre


Index: linux-2.6.17-rc6/fs/ext3/balloc.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/ext3/balloc.c	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/fs/ext3/balloc.c	2006-06-13 21:21:33.000000000 +0200
@@ -88,12 +88,16 @@ read_block_bitmap(struct super_block *sb
 	desc = ext3_get_group_desc (sb, block_group, NULL);
 	if (!desc)
 		goto error_out;
-	bh = sb_bread(sb, le32_to_cpu(desc->bg_block_bitmap));
+	bh = sb_bread(sb,
+		      EXT3_BLOCK_BITMAP(desc,
+			      ext3_group_first_block_no(sb, block_group)));
 	if (!bh)
 		ext3_error (sb, "read_block_bitmap",
 			    "Cannot read block bitmap - "
-			    "block_group = %d, block_bitmap = %u",
-			    block_group, le32_to_cpu(desc->bg_block_bitmap));
+			    "block_group = %d, block_bitmap = "E3FSBLK,
+			    block_group,
+			    EXT3_BLOCK_BITMAP(desc,
+			      ext3_group_first_block_no(sb, block_group)));
 error_out:
 	return bh;
 }
@@ -328,7 +332,7 @@ void ext3_free_blocks_sb(handle_t *handl
 	es = sbi->s_es;
 	if (block < le32_to_cpu(es->s_first_data_block) ||
 	    block + count < block ||
-	    block + count > le32_to_cpu(es->s_blocks_count)) {
+	    block + count > EXT3_BLOCKS_COUNT(es)) {
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks not in datazone - "
 			    "block = "E3FSBLK", count = %lu", block, count);
@@ -356,11 +360,19 @@ do_more:
 	if (!desc)
 		goto error_return;
 
-	if (in_range (le32_to_cpu(desc->bg_block_bitmap), block, count) ||
-	    in_range (le32_to_cpu(desc->bg_inode_bitmap), block, count) ||
-	    in_range (block, le32_to_cpu(desc->bg_inode_table),
+	if (in_range (EXT3_BLOCK_BITMAP(desc,
+				ext3_group_first_block_no(sb, block_group)),
+		      block, count) ||
+	    in_range (EXT3_INODE_BITMAP(desc,
+			    	ext3_group_first_block_no(sb, block_group)),
+		      block, count) ||
+	    in_range (block,
+		      EXT3_INODE_TABLE(desc,
+			      	ext3_group_first_block_no(sb, block_group)),
 		      sbi->s_itb_per_group) ||
-	    in_range (block + count - 1, le32_to_cpu(desc->bg_inode_table),
+	    in_range (block + count - 1,
+		      EXT3_INODE_TABLE(desc,
+			      	ext3_group_first_block_no(sb, block_group)),
 		      sbi->s_itb_per_group))
 		ext3_error (sb, "ext3_free_blocks",
 			    "Freeing blocks in system zones - "
@@ -1163,7 +1175,7 @@ static int ext3_has_free_blocks(struct e
 	ext3_fsblk_t free_blocks, root_blocks;
 
 	free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter);
-	root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count);
+	root_blocks = EXT3_R_BLOCKS_COUNT(sbi->s_es);
 	if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) &&
 		sbi->s_resuid != current->fsuid &&
 		(sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) {
@@ -1262,7 +1274,7 @@ ext3_fsblk_t ext3_new_blocks(handle_t *h
 	 * First, test whether the goal block is free.
 	 */
 	if (goal < le32_to_cpu(es->s_first_data_block) ||
-	    goal >= le32_to_cpu(es->s_blocks_count))
+	    goal >= EXT3_BLOCKS_COUNT(es))
 		goal = le32_to_cpu(es->s_first_data_block);
 	ext3_get_group_no_and_offset(sb, goal, &group_no, &grp_target_blk);
 	gdp = ext3_get_group_desc(sb, group_no, &gdp_bh);
@@ -1361,11 +1373,15 @@ allocated:
 
 	ret_block = grp_alloc_blk + ext3_group_first_block_no(sb, group_no);
 
-	if (in_range(le32_to_cpu(gdp->bg_block_bitmap), ret_block, num) ||
-	    in_range(le32_to_cpu(gdp->bg_inode_bitmap), ret_block, num) ||
-	    in_range(ret_block, le32_to_cpu(gdp->bg_inode_table),
+	if (in_range(EXT3_BLOCK_BITMAP(gdp, ext3_group_first_block_no(sb, group_no)),
+				ret_block, num) ||
+	    in_range(EXT3_BLOCK_BITMAP(gdp, ext3_group_first_block_no(sb, group_no)),
+		    		ret_block, num) ||
+	    in_range(ret_block, EXT3_INODE_TABLE(gdp,
+			    	ext3_group_first_block_no(sb, group_no)),
 		      EXT3_SB(sb)->s_itb_per_group) ||
-	    in_range(ret_block + num - 1, le32_to_cpu(gdp->bg_inode_table),
+	    in_range(ret_block + num - 1, EXT3_INODE_TABLE(gdp,
+			    ext3_group_first_block_no(sb, group_no)),
 		      EXT3_SB(sb)->s_itb_per_group))
 		ext3_error(sb, "ext3_new_block",
 			    "Allocating block in system zone - "
@@ -1404,11 +1420,11 @@ allocated:
 	jbd_unlock_bh_state(bitmap_bh);
 #endif
 
-	if (ret_block + num - 1 >= le32_to_cpu(es->s_blocks_count)) {
+	if (ret_block + num - 1 >= EXT3_BLOCKS_COUNT(es)) {
 		ext3_error(sb, "ext3_new_block",
-			    "block("E3FSBLK") >= blocks count(%d) - "
+			    "block("E3FSBLK") >= blocks count("E3FSBLK") - "
 			    "block_group = %lu, es == %p ", ret_block,
-			le32_to_cpu(es->s_blocks_count), group_no, es);
+			EXT3_BLOCKS_COUNT(es), group_no, es);
 		goto out;
 	}
 
@@ -1501,7 +1517,7 @@ ext3_fsblk_t ext3_count_free_blocks(stru
 	brelse(bitmap_bh);
 	printk("ext3_count_free_blocks: stored = "E3FSBLK
 		", computed = "E3FSBLK", "E3FSBLK"\n",
-	       le32_to_cpu(es->s_free_blocks_count),
+	       EXT3_FREE_BLOCKS_COUNT(es),
 		desc_count, bitmap_count);
 	return bitmap_count;
 #else
Index: linux-2.6.17-rc6/fs/ext3/ialloc.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/ext3/ialloc.c	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/fs/ext3/ialloc.c	2006-06-13 21:21:33.000000000 +0200
@@ -60,12 +60,14 @@ read_inode_bitmap(struct super_block * s
 	if (!desc)
 		goto error_out;
 
-	bh = sb_bread(sb, le32_to_cpu(desc->bg_inode_bitmap));
+	bh = sb_bread(sb, EXT3_INODE_BITMAP(desc,
+			      ext3_group_first_block_no(sb, block_group)));
 	if (!bh)
 		ext3_error(sb, "read_inode_bitmap",
 			    "Cannot read inode bitmap - "
-			    "block_group = %lu, inode_bitmap = %u",
-			    block_group, le32_to_cpu(desc->bg_inode_bitmap));
+			    "block_group = %lu, inode_bitmap = %llu",
+			    block_group, EXT3_INODE_BITMAP(desc,
+			      ext3_group_first_block_no(sb, block_group)));
 error_out:
 	return bh;
 }
@@ -304,7 +306,7 @@ static int find_group_orlov(struct super
 		goto fallback;
 	}
 
-	blocks_per_dir = le32_to_cpu(es->s_blocks_count) - freeb;
+	blocks_per_dir = EXT3_BLOCKS_COUNT(es) - freeb;
 	sector_div(blocks_per_dir, ndirs);
 
 	max_dirs = ndirs / ngroups + inodes_per_group / 16;
Index: linux-2.6.17-rc6/fs/ext3/inode.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/ext3/inode.c	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/fs/ext3/inode.c	2006-06-13 21:21:33.000000000 +0200
@@ -2433,8 +2433,9 @@ static ext3_fsblk_t ext3_get_inode_block
 	 */
 	offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) *
 		EXT3_INODE_SIZE(sb);
-	block = le32_to_cpu(gdp[desc].bg_inode_table) +
-		(offset >> EXT3_BLOCK_SIZE_BITS(sb));
+	block = EXT3_INODE_TABLE((gdp+desc),
+			ext3_group_first_block_no(sb, block_group)) +
+			(offset >> EXT3_BLOCK_SIZE_BITS(sb));
 
 	iloc->block_group = block_group;
 	iloc->offset = offset & (EXT3_BLOCK_SIZE(sb) - 1);
@@ -2501,7 +2502,9 @@ static int __ext3_get_inode_loc(struct i
 				goto make_io;
 
 			bitmap_bh = sb_getblk(inode->i_sb,
-					le32_to_cpu(desc->bg_inode_bitmap));
+				EXT3_INODE_BITMAP(desc,
+				     ext3_group_first_block_no(inode->i_sb,
+						     block_group)));
 			if (!bitmap_bh)
 				goto make_io;
 
Index: linux-2.6.17-rc6/fs/ext3/resize.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/ext3/resize.c	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/fs/ext3/resize.c	2006-06-13 21:21:33.000000000 +0200
@@ -27,7 +27,7 @@ static int verify_group_input(struct sup
 {
 	struct ext3_sb_info *sbi = EXT3_SB(sb);
 	struct ext3_super_block *es = sbi->s_es;
-	ext3_fsblk_t start = le32_to_cpu(es->s_blocks_count);
+	ext3_fsblk_t start = EXT3_BLOCKS_COUNT(es);
 	ext3_fsblk_t end = start + input->blocks_count;
 	unsigned group = input->group;
 	ext3_fsblk_t itend = input->inode_table + sbi->s_itb_per_group;
@@ -817,9 +817,12 @@ int ext3_group_add(struct super_block *s
 	/* Update group descriptor block for new group */
 	gdp = (struct ext3_group_desc *)primary->b_data + gdb_off;
 
-	gdp->bg_block_bitmap = cpu_to_le32(input->block_bitmap);
-	gdp->bg_inode_bitmap = cpu_to_le32(input->inode_bitmap);
-	gdp->bg_inode_table = cpu_to_le32(input->inode_table);
+	EXT3_BLOCK_BITMAP_SET(gdp, ext3_group_first_block_no(sb, gdb_num),
+				   input->block_bitmap); /* LV FIXME */
+	EXT3_INODE_BITMAP_SET(gdp, ext3_group_first_block_no(sb, gdb_num),
+			           input->inode_bitmap); /* LV FIXME */
+	EXT3_INODE_TABLE_SET(gdp, ext3_group_first_block_no(sb, gdb_num),
+			          input->inode_table); /* LV FIXME */
 	gdp->bg_free_blocks_count = cpu_to_le16(input->free_blocks_count);
 	gdp->bg_free_inodes_count = cpu_to_le16(EXT3_INODES_PER_GROUP(sb));
 
@@ -833,7 +836,7 @@ int ext3_group_add(struct super_block *s
 	 * blocks/inodes before the group is live won't actually let us
 	 * allocate the new space yet.
 	 */
-	es->s_blocks_count = cpu_to_le32(le32_to_cpu(es->s_blocks_count) +
+	EXT3_BLOCKS_COUNT_SET(es, EXT3_BLOCKS_COUNT(es) +
 		input->blocks_count);
 	es->s_inodes_count = cpu_to_le32(le32_to_cpu(es->s_inodes_count) +
 		EXT3_INODES_PER_GROUP(sb));
@@ -869,7 +872,7 @@ int ext3_group_add(struct super_block *s
 
 	/* Update the reserved block counts only once the new group is
 	 * active. */
-	es->s_r_blocks_count = cpu_to_le32(le32_to_cpu(es->s_r_blocks_count) +
+	EXT3_R_BLOCKS_COUNT_SET(es, EXT3_R_BLOCKS_COUNT(es) +
 		input->reserved_blocks);
 
 	/* Update the free space counts */
@@ -920,7 +923,7 @@ int ext3_group_extend(struct super_block
 	/* We don't need to worry about locking wrt other resizers just
 	 * yet: we're going to revalidate es->s_blocks_count after
 	 * taking lock_super() below. */
-	o_blocks_count = le32_to_cpu(es->s_blocks_count);
+	o_blocks_count = EXT3_BLOCKS_COUNT(es);
 	o_groups_count = EXT3_SB(sb)->s_groups_count;
 
 	if (test_opt(sb, DEBUG))
@@ -986,7 +989,7 @@ int ext3_group_extend(struct super_block
 	}
 
 	lock_super(sb);
-	if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) {
+	if (o_blocks_count != EXT3_BLOCKS_COUNT(es)) {
 		ext3_warning(sb, __FUNCTION__,
 			     "multiple resizers run on filesystem!");
 		unlock_super(sb);
@@ -1002,7 +1005,7 @@ int ext3_group_extend(struct super_block
 		ext3_journal_stop(handle);
 		goto exit_put;
 	}
-	es->s_blocks_count = cpu_to_le32(o_blocks_count + add);
+	EXT3_BLOCKS_COUNT_SET(es, o_blocks_count + add);
 	ext3_journal_dirty_metadata(handle, EXT3_SB(sb)->s_sbh);
 	sb->s_dirt = 1;
 	unlock_super(sb);
@@ -1014,8 +1017,8 @@ int ext3_group_extend(struct super_block
 	if ((err = ext3_journal_stop(handle)))
 		goto exit_put;
 	if (test_opt(sb, DEBUG))
-		printk(KERN_DEBUG "EXT3-fs: extended group to %u blocks\n",
-		       le32_to_cpu(es->s_blocks_count));
+		printk(KERN_DEBUG "EXT3-fs: extended group to %llu blocks\n",
+		       EXT3_BLOCKS_COUNT(es));
 	update_backups(sb, EXT3_SB(sb)->s_sbh->b_blocknr, (char *)es,
 		       sizeof(struct ext3_super_block));
 exit_put:
Index: linux-2.6.17-rc6/fs/ext3/super.c
===================================================================
--- linux-2.6.17-rc6.orig/fs/ext3/super.c	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/fs/ext3/super.c	2006-06-13 21:21:33.000000000 +0200
@@ -1146,44 +1146,48 @@ static int ext3_check_descriptors (struc
 		if ((i % EXT3_DESC_PER_BLOCK(sb)) == 0)
 			gdp = (struct ext3_group_desc *)
 					sbi->s_group_desc[desc_block++]->b_data;
-		if (le32_to_cpu(gdp->bg_block_bitmap) < block ||
-		    le32_to_cpu(gdp->bg_block_bitmap) >=
+		if (EXT3_BLOCK_BITMAP(gdp, ext3_group_first_block_no(sb, i)) <
+				block ||
+		    	EXT3_BLOCK_BITMAP(gdp, ext3_group_first_block_no(sb, i)) >=
 				block + EXT3_BLOCKS_PER_GROUP(sb))
 		{
 			ext3_error (sb, "ext3_check_descriptors",
 				    "Block bitmap for group %d"
 				    " not in group (block %lu)!",
 				    i, (unsigned long)
-					le32_to_cpu(gdp->bg_block_bitmap));
+					EXT3_BLOCK_BITMAP(gdp, ext3_group_first_block_no(sb, i)));
 			return 0;
 		}
-		if (le32_to_cpu(gdp->bg_inode_bitmap) < block ||
-		    le32_to_cpu(gdp->bg_inode_bitmap) >=
+		if (EXT3_INODE_BITMAP(gdp, ext3_group_first_block_no(sb, i)) <
+				block ||
+		    EXT3_INODE_BITMAP(gdp, ext3_group_first_block_no(sb, i)) >=
 				block + EXT3_BLOCKS_PER_GROUP(sb))
 		{
 			ext3_error (sb, "ext3_check_descriptors",
 				    "Inode bitmap for group %d"
 				    " not in group (block %lu)!",
 				    i, (unsigned long)
-					le32_to_cpu(gdp->bg_inode_bitmap));
+					EXT3_INODE_BITMAP(gdp, ext3_group_first_block_no(sb, i)));
 			return 0;
 		}
-		if (le32_to_cpu(gdp->bg_inode_table) < block ||
-		    le32_to_cpu(gdp->bg_inode_table) + sbi->s_itb_per_group >=
-		    block + EXT3_BLOCKS_PER_GROUP(sb))
+		if (EXT3_INODE_TABLE(gdp, ext3_group_first_block_no(sb, i)) <
+			block ||
+		    EXT3_INODE_TABLE(gdp, ext3_group_first_block_no(sb, i)) +
+							sbi->s_itb_per_group >=
+			block + EXT3_BLOCKS_PER_GROUP(sb))
 		{
 			ext3_error (sb, "ext3_check_descriptors",
 				    "Inode table for group %d"
 				    " not in group (block %lu)!",
 				    i, (unsigned long)
-					le32_to_cpu(gdp->bg_inode_table));
+					EXT3_INODE_TABLE(gdp, ext3_group_first_block_no(sb, i)));
 			return 0;
 		}
 		block += EXT3_BLOCKS_PER_GROUP(sb);
 		gdp++;
 	}
 
-	sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb));
+	EXT3_FREE_BLOCKS_COUNT_SET(sbi->s_es, ext3_count_free_blocks(sb));
 	sbi->s_es->s_free_inodes_count=cpu_to_le32(ext3_count_free_inodes(sb));
 	return 1;
 }
@@ -1360,6 +1364,7 @@ static int ext3_fill_super (struct super
 	int i;
 	int needs_recovery;
 	__le32 features;
+	__u64 blocks_count;
 
 	sbi = kmalloc(sizeof(*sbi), GFP_KERNEL);
 	if (!sbi)
@@ -1572,10 +1577,11 @@ static int ext3_fill_super (struct super
 
 	if (EXT3_BLOCKS_PER_GROUP(sb) == 0)
 		goto cantfind_ext3;
-	sbi->s_groups_count = (le32_to_cpu(es->s_blocks_count) -
-			       le32_to_cpu(es->s_first_data_block) +
-			       EXT3_BLOCKS_PER_GROUP(sb) - 1) /
-			      EXT3_BLOCKS_PER_GROUP(sb);
+	blocks_count = (EXT3_BLOCKS_COUNT(es) -
+			le32_to_cpu(es->s_first_data_block) +
+			EXT3_BLOCKS_PER_GROUP(sb) - 1);
+	do_div(blocks_count, EXT3_BLOCKS_PER_GROUP(sb));
+	sbi->s_groups_count = blocks_count;
 	db_count = (sbi->s_groups_count + EXT3_DESC_PER_BLOCK(sb) - 1) /
 		   EXT3_DESC_PER_BLOCK(sb);
 	sbi->s_group_desc = kmalloc(db_count * sizeof (struct buffer_head *),
@@ -1585,7 +1591,7 @@ static int ext3_fill_super (struct super
 		goto failed_mount;
 	}
 
-	if (le32_to_cpu(es->s_blocks_count) >
+	if (EXT3_BLOCKS_COUNT(es) >
 			(sector_t)(~0ULL) >> (sb->s_blocksize_bits - 9)) {
 		printk(KERN_ERR "EXT3-fs: filesystem on %s"
 			" too large to mount safely\n", sb->s_id);
@@ -1900,7 +1906,7 @@ static journal_t *ext3_get_dev_journal(s
 		goto out_bdev;
 	}
 
-	len = le32_to_cpu(es->s_blocks_count);
+	len = EXT3_BLOCKS_COUNT(es);
 	start = sb_block + 1;
 	brelse(bh);	/* we're done with the superblock */
 
@@ -2070,7 +2076,7 @@ static void ext3_commit_super (struct su
 	if (!sbh)
 		return;
 	es->s_wtime = cpu_to_le32(get_seconds());
-	es->s_free_blocks_count = cpu_to_le32(ext3_count_free_blocks(sb));
+	EXT3_FREE_BLOCKS_COUNT_SET(es, ext3_count_free_blocks(sb));
 	es->s_free_inodes_count = cpu_to_le32(ext3_count_free_inodes(sb));
 	BUFFER_TRACE(sbh, "marking dirty");
 	mark_buffer_dirty(sbh);
@@ -2263,7 +2269,7 @@ static int ext3_remount (struct super_bl
 	ext3_init_journal_params(sb, sbi->s_journal);
 
 	if ((*flags & MS_RDONLY) != (sb->s_flags & MS_RDONLY) ||
-		n_blocks_count > le32_to_cpu(es->s_blocks_count)) {
+		n_blocks_count > EXT3_BLOCKS_COUNT(es)) {
 		if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) {
 			err = -EROFS;
 			goto restore_opts;
@@ -2383,10 +2389,10 @@ static int ext3_statfs (struct super_blo
 
 	buf->f_type = EXT3_SUPER_MAGIC;
 	buf->f_bsize = sb->s_blocksize;
-	buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+	buf->f_blocks = EXT3_BLOCKS_COUNT(es) - overhead;
 	buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
-	buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
-	if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
+	buf->f_bavail = buf->f_bfree - EXT3_R_BLOCKS_COUNT(es);
+	if (buf->f_bfree < EXT3_R_BLOCKS_COUNT(es))
 		buf->f_bavail = 0;
 	buf->f_files = le32_to_cpu(es->s_inodes_count);
 	buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
Index: linux-2.6.17-rc6/include/linux/ext3_fs.h
===================================================================
--- linux-2.6.17-rc6.orig/include/linux/ext3_fs.h	2006-06-13 21:21:30.000000000 +0200
+++ linux-2.6.17-rc6/include/linux/ext3_fs.h	2006-06-13 21:23:25.000000000 +0200
@@ -140,6 +140,54 @@ struct ext3_group_desc
 	__le32	bg_reserved[3];
 };
 
+static inline u32 EXT3_RELATIVE_ENCODE(ext3_fsblk_t group_base,
+				       ext3_fsblk_t fs_block)
+{
+	s32 gdp_block;
+
+	if (fs_block < (1ULL<<32) && group_base < (1ULL<<32))
+		return fs_block;
+
+	gdp_block = (fs_block - group_base);
+	BUG_ON ((group_base + gdp_block) != fs_block);
+
+	return gdp_block;
+}
+
+static inline ext3_fsblk_t EXT3_RELATIVE_DECODE(ext3_fsblk_t group_base,
+						u32 gdp_block)
+{
+	if (group_base >= (1ULL<<32))
+		return group_base + (s32) gdp_block;
+
+	if ((s32) gdp_block >= 0 && gdp_block < group_base &&
+		  group_base + gdp_block >= (1ULL<<32))
+		return group_base + gdp_block;
+
+	return gdp_block;
+}
+
+#define EXT3_BLOCK_BITMAP(bg, group_base)	\
+		EXT3_RELATIVE_DECODE(group_base, le32_to_cpu((bg)->bg_block_bitmap))
+#define EXT3_INODE_BITMAP(bg, group_base)	\
+		EXT3_RELATIVE_DECODE(group_base, le32_to_cpu((bg)->bg_inode_bitmap))
+#define EXT3_INODE_TABLE(bg, group_base)	\
+		EXT3_RELATIVE_DECODE(group_base, le32_to_cpu((bg)->bg_inode_table))
+
+#define EXT3_BLOCK_BITMAP_SET(bg, group_base, value)	\
+	do {(bg)->bg_block_bitmap = EXT3_RELATIVE_ENCODE(group_base, value);} while(0)
+#define EXT3_INODE_BITMAP_SET(bg, group_base, value)	\
+	do {(bg)->bg_inode_bitmap = EXT3_RELATIVE_ENCODE(group_base, value);} while(0)
+#define EXT3_INODE_TABLE_SET(bg, group_base, value)	\
+	do {(bg)->bg_inode_table = EXT3_RELATIVE_ENCODE(group_base, value);} while(0)
+
+#define EXT3_IS_USED_BLOCK_BITMAP(bg)	\
+	((bg)->bg_block_bitmap != 0)
+#define EXT3_IS_USED_INODE_BITMAP(bg)	\
+	((bg)->bg_inode_bitmap != 0)
+#define EXT3_IS_USED_INODE_TABLE(bg)	\
+	((bg)->bg_inode_table != 0)
+
 /*
  * Macro-instructions used to manage group descriptors
  */
@@ -487,9 +535,40 @@ struct ext3_super_block {
 	__u16	s_reserved_word_pad;
 	__le32	s_default_mount_opts;
 	__le32	s_first_meta_bg; 	/* First metablock block group */
-	__u32	s_reserved[190];	/* Padding to the end of the block */
+	__le32	s_mkfs_time;		/* When the filesystem was created */
+	__le32	s_jnl_blocks[17]; 	/* Backup of the journal inode */
+	/* 64bit support valid if EXT3_FEATURE_INCOMPAT_64BIT */
+	__le32	s_blocks_count_hi;	/* Blocks count */
+	__le32	s_r_blocks_count_hi;	/* Reserved blocks count */
+	__le32	s_free_blocks_count_hi;	/* Free blocks count */
+	__u32	s_reserved[169];	/* Padding to the end of the block */
 };
 
+
+#define EXT3_BLOCKS_COUNT(s)	\
+	(ext3_fsblk_t)(((__u64)le32_to_cpu((s)->s_blocks_count_hi) << 32) |	\
+	 	(__u64)le32_to_cpu((s)->s_blocks_count))
+#define EXT3_BLOCKS_COUNT_SET(s,v)	do {				\
+	(s)->s_blocks_count = cpu_to_le32((v));				\
+	(s)->s_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32);	\
+} while (0)
+
+#define EXT3_R_BLOCKS_COUNT(s)	\
+	(ext3_fsblk_t)(((__u64)le32_to_cpu((s)->s_r_blocks_count_hi) << 32) |	\
+		 (__u64)le32_to_cpu((s)->s_r_blocks_count))
+#define EXT3_R_BLOCKS_COUNT_SET(s,v)	do {				\
+	(s)->s_r_blocks_count = cpu_to_le32((v));			\
+	(s)->s_r_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32);	\
+} while (0)
+
+#define EXT3_FREE_BLOCKS_COUNT(s)					\
+	(ext3_fsblk_t)(((__u64)le32_to_cpu((s)->s_free_blocks_count_hi) << 32) | \
+		 (__u64)le32_to_cpu((s)->s_free_blocks_count))
+#define EXT3_FREE_BLOCKS_COUNT_SET(s,v)	do {				\
+	(s)->s_free_blocks_count = cpu_to_le32((v));			\
+	(s)->s_free_blocks_count_hi = cpu_to_le32(((__u64)(v)) >> 32);	\
+} while (0)
+
 #ifdef __KERNEL__
 static inline struct ext3_sb_info * EXT3_SB(struct super_block *sb)
 {
@@ -568,12 +647,14 @@ static inline struct ext3_inode_info *EX
 #define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV	0x0008 /* Journal device */
 #define EXT3_FEATURE_INCOMPAT_META_BG		0x0010
 #define EXT3_FEATURE_INCOMPAT_EXTENTS		0x0040 /* extents support */
+#define EXT3_FEATURE_INCOMPAT_64BIT		0x0080
 
 #define EXT3_FEATURE_COMPAT_SUPP	EXT2_FEATURE_COMPAT_EXT_ATTR
 #define EXT3_FEATURE_INCOMPAT_SUPP	(EXT3_FEATURE_INCOMPAT_FILETYPE| \
 					 EXT3_FEATURE_INCOMPAT_RECOVER| \
 					 EXT3_FEATURE_INCOMPAT_META_BG| \
-					 EXT3_FEATURE_INCOMPAT_EXTENTS)
+					 EXT3_FEATURE_INCOMPAT_EXTENTS| \
+					 EXT3_FEATURE_INCOMPAT_64BIT)
 #define EXT3_FEATURE_RO_COMPAT_SUPP	(EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER| \
 					 EXT3_FEATURE_RO_COMPAT_LARGE_FILE| \
 					 EXT3_FEATURE_RO_COMPAT_BTREE_DIR)
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.