support >32 bit ext4 filesystem block type in kernel
Subsystems (2)
PATCH 3/9 support >32 bit ext4 filesystem block type in kernel
Redefine ext4 in-kernel filesystem block type (ext4_fsblk_t) from unsigned long to sector_t, to allow kernel to handle >32 bit ext4 blocks.
---
linux-2.6.18-rc4-ming/fs/ext4/balloc.c | 22 +++++++------------- linux-2.6.18-rc4-ming/fs/ext4/ialloc.c | 11 ++++++---- linux-2.6.18-rc4-ming/fs/ext4/resize.c | 13 +++++------- linux-2.6.18-rc4-ming/fs/ext4/super.c | 8 +++---- linux-2.6.18-rc4-ming/include/linux/ext4_fs.h | 26 ++++++++++++++++++++++++ linux-2.6.18-rc4-ming/include/linux/ext4_fs_i.h | 4 +-- 6 files changed, 53 insertions(+), 31 deletions(-)
fs/ext4/balloc.c renamed from fs/ext4/balloc.c~ext4_fsblk_sector_t +8 -14
@@ -37,7 +37,6 @@#define in_range (b, first, len) ((b) >= (first) && (b) <= (first) + (len) - 1) -struct ext4_group_desc *ext4_get_group_desc (struct super_block * sb,unsigned int block_group,struct buffer_head ** bh)
@@ -339,10 +338,7 @@ void ext4_free_blocks_sb(handle_t *handl do_more: overflow =0 ; - block_group = (block -le32_to_cpu (es->s_first_data_block)) / -EXT4_BLOCKS_PER_GROUP (sb); - bit = (block -le32_to_cpu (es->s_first_data_block)) % -EXT4_BLOCKS_PER_GROUP (sb); +ext4_get_group_no_and_offset (sb, block, &block_group, &bit);/* * Check to see if we are freeing blocks across a group * boundary.
@@ -1204,7 +1200,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *h {struct buffer_head *bitmap_bh =NULL ;struct buffer_head *gdp_bh; -int group_no; +unsigned long group_no;int goal_group;ext4_grpblk_t grp_target_blk;/* blockgroup relative goal block */ ext4_grpblk_t grp_alloc_blk;/* blockgroup-relative allocated block*/
@@ -1267,8 +1263,7 @@ ext4_fsblk_t ext4_new_blocks(handle_t *hif (goal <le32_to_cpu (es->s_first_data_block) || goal >=le32_to_cpu (es->s_blocks_count)) goal =le32_to_cpu (es->s_first_data_block); - group_no = (goal -le32_to_cpu (es->s_first_data_block)) / -EXT4_BLOCKS_PER_GROUP (sb); +ext4_get_group_no_and_offset (sb, goal, &group_no, &grp_target_blk); gdp =ext4_get_group_desc (sb, group_no, &gdp_bh);if (!gdp) goto io_error;
@@ -1285,8 +1280,6 @@ retry: my_rsv =NULL ;if (free_blocks >0 ) { - grp_target_blk = ((goal -le32_to_cpu (es->s_first_data_block)) % -EXT4_BLOCKS_PER_GROUP (sb)); bitmap_bh =read_block_bitmap (sb, group_no);if (!bitmap_bh) goto io_error;
@@ -1413,7 +1406,7 @@ allocated:if (ret_block + num -1 >=le32_to_cpu (es->s_blocks_count)) {ext4_error (sb,"ext4_new_block" ,"block(" E3FSBLK ") >= blocks count(%d) - " -"block_group = %d, es == %p " , ret_block, +"block_group = %lu, es == %p " , ret_block,le32_to_cpu (es->s_blocks_count), group_no, es); goto out; }
@@ -1527,9 +1520,10 @@ ext4_fsblk_t ext4_count_free_blocks(strustatic inline int block_in_use (ext4_fsblk_t block,struct super_block *sb,unsigned char *map) { -return ext4_test_bit ((block - -le32_to_cpu (EXT4_SB (sb)->s_es->s_first_data_block)) % -EXT4_BLOCKS_PER_GROUP (sb), map); +ext4_grpblk_t offset; + +ext4_get_group_no_and_offset (sb, block,NULL , &offset); +return ext4_test_bit (offset, map); }static inline int test_root (int a,int b)
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +7 -4
@@ -23,7 +23,7 @@#include <linux/buffer_head.h> #include <linux/random.h> #include <linux/bitops.h> - +#include <linux/blkdev.h> #include <asm/byteorder.h> #include "xattr.h"
@@ -274,7 +274,8 @@ static int find_group_orlov(struct super freei =percpu_counter_read_positive (&sbi->s_freeinodes_counter); avefreei = freei / ngroups; freeb =percpu_counter_read_positive (&sbi->s_freeblocks_counter); - avefreeb = freeb / ngroups; + avefreeb = freeb; +sector_div (avefreeb, ngroups); ndirs =percpu_counter_read_positive (&sbi->s_dirs_counter); if ((parent == sb->s_root->d_inode) ||
@@ -303,13 +304,15 @@ static int find_group_orlov(struct super goto fallback; } - blocks_per_dir = (le32_to_cpu (es->s_blocks_count) - freeb) / ndirs; + blocks_per_dir =le32_to_cpu (es->s_blocks_count) - freeb; +sector_div (blocks_per_dir, ndirs); max_dirs = ndirs / ngroups + inodes_per_group /16 ; min_inodes = avefreei - inodes_per_group /4 ; min_blocks = avefreeb -EXT4_BLOCKS_PER_GROUP (sb) /4 ; - max_debt =EXT4_BLOCKS_PER_GROUP (sb) /max (blocks_per_dir, (ext4_fsblk_t )BLOCK_COST ); + max_debt =EXT4_BLOCKS_PER_GROUP (sb); +sector_div (max_debt,max (blocks_per_dir, (ext4_fsblk_t )BLOCK_COST ));if (max_debt *INODE_COST > inodes_per_group) max_debt = inodes_per_group /INODE_COST ;if (max_debt >255 )
fs/ext4/resize.c renamed from fs/ext4/resize.c~ext4_fsblk_sector_t +6 -7
@@ -36,7 +36,7 @@ static int verify_group_input(struct sup le16_to_cpu(es->s_reserved_gdt_blocks)) : 0;ext4_fsblk_t metaend = start + overhead;struct buffer_head *bh =NULL ; -ext4_grpblk_t free_blocks_count; +ext4_grpblk_t free_blocks_count, offset;int err = -EINVAL ; input->free_blocks_count = free_blocks_count =
@@ -49,13 +49,13 @@ static int verify_group_input(struct sup"no-super" , input->group, input->blocks_count, free_blocks_count, input->reserved_blocks); +ext4_get_group_no_and_offset (sb, start,NULL , &offset);if (group != sbi->s_groups_count)ext4_warning (sb, __FUNCTION__,"Cannot add at group %u (only %lu groups)" , input->group, sbi->s_groups_count); -else if ((start -le32_to_cpu (es->s_first_data_block)) % -EXT4_BLOCKS_PER_GROUP (sb)) -ext4_warning (sb, __FUNCTION__,"Last group not full" ); +else if (offset !=0 ) +ext4_warning (sb, __FUNCTION__,"Last group not full" );else if (input->reserved_blocks > input->blocks_count /5 )ext4_warning (sb, __FUNCTION__,"Reserved blocks too high (%u)" , input->reserved_blocks);
@@ -932,7 +932,7 @@ int ext4_group_extend(struct super_blockif (n_blocks_count > (sector_t)(~0ULL ) >> (sb->s_blocksize_bits -9 )) {printk (KERN_ERR "EXT4-fs: filesystem on %s:" -" too large to resize to %lu blocks safely\n" , +" too large to resize to " E3FSBLK " blocks safely\n" , sb->s_id, n_blocks_count);if (sizeof (sector_t) <8 ) ext4_warning(sb, __FUNCTION__,
@@ -947,8 +947,7 @@ int ext4_group_extend(struct super_block }/* Handle the remaining blocks in the last group only. */ - last = (o_blocks_count -le32_to_cpu (es->s_first_data_block)) % -EXT4_BLOCKS_PER_GROUP (sb); +ext4_get_group_no_and_offset (sb, o_blocks_count,NULL , &last);if (last ==0 ) { ext4_warning(sb, __FUNCTION__,
fs/ext4/super.c renamed from fs/ext4/super.c~ext4_fsblk_sector_t +4 -4
@@ -1387,8 +1387,8 @@ static int ext4_fill_super (struct super* block sizes. We need to calculate the offset from buffer start. */ if (blocksize !=EXT4_MIN_BLOCK_SIZE ) { - logic_sb_block = (sb_block *EXT4_MIN_BLOCK_SIZE ) / blocksize; - offset = (sb_block *EXT4_MIN_BLOCK_SIZE ) % blocksize; + logic_sb_block = sb_block *EXT4_MIN_BLOCK_SIZE ; + offset =sector_div (logic_sb_block, blocksize); }else { logic_sb_block = sb_block; }
@@ -1493,8 +1493,8 @@ static int ext4_fill_super (struct superbrelse (bh);sb_set_blocksize (sb, blocksize); - logic_sb_block = (sb_block *EXT4_MIN_BLOCK_SIZE ) / blocksize; - offset = (sb_block *EXT4_MIN_BLOCK_SIZE ) % blocksize; + logic_sb_block = sb_block *EXT4_MIN_BLOCK_SIZE ; + offset =sector_div (logic_sb_block, blocksize); bh =sb_bread (sb, logic_sb_block);if (!bh) { printk(KERN_ERR
include/linux/ext4_fs.h renamed from include/linux/ext4_fs.h~ext4_fsblk_sector_t +26 -0
@@ -17,6 +17,7 @@#define _LINUX_EXT4_FS_H#include <linux/types.h> +#include <linux/blkdev.h> /* * The second extended filesystem constants/structures
@@ -728,6 +729,27 @@ ext4_group_first_block_no(struct super_b#define ERR_BAD_DX_DIR -75000/* +* This function calculate the block group number and offset, +* given a block number +*/ + +static inline void ext4_get_group_no_and_offset (struct super_block * sb, +ext4_fsblk_t blocknr,unsigned long * blockgrpp, +ext4_grpblk_t *offsetp) +{ +struct ext4_super_block *es =EXT4_SB (sb)->s_es; +ext4_grpblk_t offset; + + blocknr = blocknr -le32_to_cpu (es->s_first_data_block); + offset =sector_div (blocknr,EXT4_BLOCKS_PER_GROUP (sb)); +if (offsetp) + *offsetp = offset; +if (blockgrpp) + *blockgrpp = blocknr; + +} + +/* * Function prototypes */
@@ -740,6 +762,10 @@ ext4_group_first_block_no(struct super_b# define NORET_AND noreturn,/* balloc.c */ +extern unsigned int ext4_block_group (struct super_block *sb, +ext4_fsblk_t blocknr); +extern ext4_grpblk_t ext4_block_group_offset (struct super_block *sb, +ext4_fsblk_t blocknr);extern int ext4_bg_has_super (struct super_block *sb,int group);extern unsigned long ext4_bg_num_gdb (struct super_block *sb,int group); extern ext4_fsblk_t ext4_new_block (handle_t *handle, struct inode *inode,
include/linux/ext4_fs_i.h renamed from include/linux/ext4_fs_i.h~ext4_fsblk_sector_t +2 -2
@@ -25,9 +25,9 @@typedef int ext4_grpblk_t ;/* data type for filesystem-wide blocks number */ -typedef unsigned long ext4_fsblk_t ; +typedef sector_t ext4_fsblk_t ; -#define E3FSBLK "%lu" +#define E3FSBLK SECTOR_FMTstruct ext4_reserve_window {ext4_fsblk_t _rsv_start;/* First byte reserved */
_
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Quoted 4 lines · On Wed, 09 Aug 2006 18:21:00 -0700 Mingming Cao <[email protected]> wrote:
Redefine ext4 in-kernel filesystem block type (
ext4_fsblk_t) from unsigned long tosector_t, to allow kernel to handle >32 bit ext4 blocks.
I don't get it.
Randomly-chosen snippet:
fs/ext4/ialloc.c static int find_group_orlov(struct super · line 281
Quoted 10 lines
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +2
-1@@ -274,7 +274,8 @@ static int find_group_orlov(struct super freei =percpu_counter_read_positive (&sbi->s_freeinodes_counter); avefreei = freei / ngroups; freeb =percpu_counter_read_positive (&sbi->s_freeblocks_counter); - avefreeb = freeb / ngroups; + avefreeb = freeb; +sector_div (avefreeb, ngroups); ndirs =percpu_counter_read_positive (&sbi->s_dirs_counter); if ((parent == sb->s_root->d_inode) ||
Here, `avefreeb' is still a 32-bit type. Why feed it into sector_div()?
fs/ext4/ialloc.c static int find_group_orlov(struct super · line 308
Quoted 7 lines
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +2
-1@@ -303,13 +304,15 @@ static int find_group_orlov(struct super goto fallback; } - blocks_per_dir = (le32_to_cpu (es->s_blocks_count) - freeb) / ndirs; + blocks_per_dir =le32_to_cpu (es->s_blocks_count) - freeb; +sector_div (blocks_per_dir, ndirs);
And here le32_to_cpu() is very much a 32-bit type. Why sector_div()?
And I agree with me: we want to get all the sector_t's out of this filesystem. unsigned long long, do_div()?
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security? Get stuff done quickly with pre-integrated technology to make your job easier Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
Quoted 10 lines · Andrew Morton
Quoted 3 lines · On Wed, 09 Aug 2006 18:21:00 -0700 Mingming Cao <[email protected]> wrote:
Redefine ext4 in-kernel filesystem block type (
ext4_fsblk_t) from unsigned long tosector_t, to allow kernel to handle >32 bit ext4 blocks.I don't get it.
The intention is able to support 48bit ext4 on 64bit and 32bit arch whenevern CONFIG_LBD is enabled (or when sector_t is actually 64 bit). It just seems waste of memory to support 48bit in-kernel ext4 blks on 32 bit if CONFIG_LBD is disabled, since we won't support large device anyway.
ext3_fsblk_t was a unsigned long type before, which is always 32bit on 32bit arch. Thus we convert the ext3_fsblk_t to sector_t and depend on CONFIG_LBD to decide whether we need 48bit in-kernel variables.(on-disk block numbers are always 48 bit).
Quoted 13 lines
Randomly-chosen snippet:
Quoted 9 lines
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +2
-1@@ -274,7 +274,8 @@ static int find_group_orlov(struct super freei =percpu_counter_read_positive (&sbi->s_freeinodes_counter); avefreei = freei / ngroups; freeb =percpu_counter_read_positive (&sbi->s_freeblocks_counter); - avefreeb = freeb / ngroups; + avefreeb = freeb; +sector_div (avefreeb, ngroups); ndirs =percpu_counter_read_positive (&sbi->s_dirs_counter);
Quoted 5 lines
fs/ext4/ialloc.c static int find_group_orlov(struct super · line 281
Quoted 1 line
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +0
-0if ((parent == sb->s_root->d_inode) ||Here, `avefreeb' is still a 32-bit type. Why feed it into
sector_div()?
avefreeb is ext3_fsblk_t type(sector_t type), which is 64bit on 64bit arch and 64bit on 32bit arch if CONFIG_LBD is enabled.
Quoted 11 lines
fs/ext4/ialloc.c static int find_group_orlov(struct super · line 308
Quoted 8 lines
fs/ext4/ialloc.c renamed from fs/ext4/ialloc.c~ext4_fsblk_sector_t +2
-1@@ -303,13 +304,15 @@ static int find_group_orlov(struct super goto fallback; } - blocks_per_dir = (le32_to_cpu (es->s_blocks_count) - freeb) / ndirs; + blocks_per_dir =le32_to_cpu (es->s_blocks_count) - freeb; +sector_div (blocks_per_dir, ndirs);And here
le32_to_cpu()is very much a 32-bit type. Whysector_div()?
ah, sorry about the confusing, s_blocks_count (the number of blocks on this fs, on-disk) should be always 48bit value, and should not use le32_to_cpu() to read-in. That is being fixed in [patch 9/9] 64bit metadata support, where we convert 32 bit s_blocks_count to sector_t, and also use mixro EXT4_BLOCKS_COUN(es) to read in the blocks count:
@@ -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 = EXT4_BLOCKS_COUNT(es) - freeb;
This patch[3/9] is just fix the in-kernel blocks type...We trying to do this incrementally: first, support in-kernel blocks type >32bit, then change the on-disk blocks type to >32bit.
Quoted 4 lines
And I agree with me: we want to get all the sector_t's out of this filesystem. unsigned long long,
do_div()?
Thanks,Mingming