diff options
author | Mingming Cao <cmm@us.ibm.com> | 2005-04-03 17:39:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-03 17:39:47 -0700 |
commit | a9aab1ec2eaa11abc7d1b61276e840360bf39568 (patch) | |
tree | 1e063550a3a573f2963125cf8c92b32a9b2493ff | |
parent | 3bc0a5f5c161254ccce512842627dab97a646a70 (diff) | |
download | history-a9aab1ec2eaa11abc7d1b61276e840360bf39568.tar.gz |
[PATCH] ext3: move goal logical block into block allocation info structure
Moved i_next_alloc_block and i_next_goal_block out from ext3_inod_info, and
put it together with the reservation structure into the
ext3_block_alloc_info structure, and dynamically allocate that structure
whenever need to allocation a block. This is also apply for noreservation
mount. Also cleanup ext3_find_goal() code.
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | fs/ext3/balloc.c | 42 | ||||
-rw-r--r-- | fs/ext3/ialloc.c | 4 | ||||
-rw-r--r-- | fs/ext3/inode.c | 54 | ||||
-rw-r--r-- | fs/ext3/ioctl.c | 14 | ||||
-rw-r--r-- | fs/ext3/super.c | 6 | ||||
-rw-r--r-- | include/linux/ext3_fs.h | 2 | ||||
-rw-r--r-- | include/linux/ext3_fs_i.h | 36 |
7 files changed, 91 insertions, 67 deletions
diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index ff3fc6b96144d0..ccd632fcc6d87e 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -259,28 +259,47 @@ static inline int rsv_is_empty(struct ext3_reserve_window *rsv) /* a valid reservation end block could not be 0 */ return (rsv->_rsv_end == EXT3_RESERVE_WINDOW_NOT_ALLOCATED); } -void ext3_alloc_init_reservation(struct inode *inode) +void ext3_init_block_alloc_info(struct inode *inode) { struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_reserve_window_node *rsv = ei->i_rsv_window; + struct ext3_block_alloc_info *block_i = ei->i_block_alloc_info; + struct super_block *sb = inode->i_sb; + + block_i = kmalloc(sizeof(*block_i), GFP_NOFS); + if (block_i) { + struct ext3_reserve_window_node *rsv = &block_i->rsv_window_node; - rsv = kmalloc(sizeof(*rsv), GFP_NOFS); - if (rsv) { rsv->rsv_start = EXT3_RESERVE_WINDOW_NOT_ALLOCATED; rsv->rsv_end = EXT3_RESERVE_WINDOW_NOT_ALLOCATED; - rsv->rsv_goal_size = EXT3_DEFAULT_RESERVE_BLOCKS; + + /* + * if filesystem is mounted with NORESERVATION, the goal + * reservation window size is set to zero to indicate + * block reservation is off + */ + if (!test_opt(sb, RESERVATION)) + rsv->rsv_goal_size = 0; + else + rsv->rsv_goal_size = EXT3_DEFAULT_RESERVE_BLOCKS; rsv->rsv_alloc_hit = 0; + block_i->last_alloc_logical_block = 0; + block_i->last_alloc_physical_block = 0; } - ei->i_rsv_window = rsv; + ei->i_block_alloc_info = block_i; } void ext3_discard_reservation(struct inode *inode) { struct ext3_inode_info *ei = EXT3_I(inode); - struct ext3_reserve_window_node *rsv = ei->i_rsv_window; + struct ext3_block_alloc_info *block_i = ei->i_block_alloc_info; + struct ext3_reserve_window_node *rsv; spinlock_t *rsv_lock = &EXT3_SB(inode->i_sb)->s_rsv_window_lock; - if (rsv && !rsv_is_empty(&rsv->rsv_window)) { + if (!block_i) + return; + + rsv = &block_i->rsv_window_node; + if (!rsv_is_empty(&rsv->rsv_window)) { spin_lock(rsv_lock); if (!rsv_is_empty(&rsv->rsv_window)) rsv_window_remove(inode->i_sb, rsv); @@ -1161,7 +1180,7 @@ int ext3_new_block(handle_t *handle, struct inode *inode, struct ext3_super_block *es; struct ext3_sb_info *sbi; struct ext3_reserve_window_node *my_rsv = NULL; - struct ext3_reserve_window_node *rsv = EXT3_I(inode)->i_rsv_window; + struct ext3_block_alloc_info *block_i; unsigned short windowsz = 0; #ifdef EXT3FS_DEBUG static int goal_hits, goal_attempts; @@ -1194,8 +1213,9 @@ int ext3_new_block(handle_t *handle, struct inode *inode, * command EXT3_IOC_SETRSVSZ to set the window size to 0 to turn off * reservation on that particular file) */ - if (rsv && ((windowsz = rsv->rsv_goal_size) > 0)) - my_rsv = rsv; + block_i = EXT3_I(inode)->i_block_alloc_info; + if (block_i && ((windowsz = block_i->rsv_window_node.rsv_goal_size) > 0)) + my_rsv = &block_i->rsv_window_node; if (!ext3_has_free_blocks(sbi)) { *errp = -ENOSPC; diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index bf2cb4e7ff4d3f..1e6f3ea2871341 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -562,8 +562,6 @@ got: inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC; memset(ei->i_data, 0, sizeof(ei->i_data)); - ei->i_next_alloc_block = 0; - ei->i_next_alloc_goal = 0; ei->i_dir_start_lookup = 0; ei->i_disksize = 0; @@ -581,7 +579,7 @@ got: ei->i_file_acl = 0; ei->i_dir_acl = 0; ei->i_dtime = 0; - ei->i_rsv_window = NULL; + ei->i_block_alloc_info = NULL; ei->i_block_group = group; ext3_set_inode_flags(inode); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 55531ed7ea4996..040eb288bb1cb7 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -462,26 +462,22 @@ static unsigned long ext3_find_near(struct inode *inode, Indirect *ind) static int ext3_find_goal(struct inode *inode, long block, Indirect chain[4], Indirect *partial, unsigned long *goal) { - struct ext3_inode_info *ei = EXT3_I(inode); - /* Writer: ->i_next_alloc* */ - if ((block == ei->i_next_alloc_block + 1)&& ei->i_next_alloc_goal) { - ei->i_next_alloc_block++; - ei->i_next_alloc_goal++; + struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info; + + /* + * try the heuristic for sequential allocation, + * failing that at least try to get decent locality. + */ + if (block_i && (block == block_i->last_alloc_logical_block + 1) + && (block_i->last_alloc_physical_block != 0)) { + *goal = block_i->last_alloc_physical_block + 1; + return 0; } - /* Writer: end */ - /* Reader: pointers, ->i_next_alloc* */ + if (verify_chain(chain, partial)) { - /* - * try the heuristic for sequential allocation, - * failing that at least try to get decent locality. - */ - if (block == ei->i_next_alloc_block) - *goal = ei->i_next_alloc_goal; - if (!*goal) - *goal = ext3_find_near(inode, partial); + *goal = ext3_find_near(inode, partial); return 0; } - /* Reader: end */ return -EAGAIN; } @@ -599,7 +595,7 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, { int i; int err = 0; - struct ext3_inode_info *ei = EXT3_I(inode); + struct ext3_block_alloc_info *block_i = EXT3_I(inode)->i_block_alloc_info; /* * If we're splicing into a [td]indirect block (as opposed to the @@ -614,7 +610,6 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, } /* Verify that place we are splicing to is still there and vacant */ - /* Writer: pointers, ->i_next_alloc* */ if (!verify_chain(chain, where-1) || *where->p) /* Writer: end */ goto changed; @@ -622,9 +617,16 @@ static int ext3_splice_branch(handle_t *handle, struct inode *inode, long block, /* That's it */ *where->p = where->key; - ei->i_next_alloc_block = block; - ei->i_next_alloc_goal = le32_to_cpu(where[num-1].key); - /* Writer: end */ + + /* + * update the most recently allocated logical & physical block + * in i_block_alloc_info, to assist find the proper goal block for next + * allocation + */ + if (block_i) { + block_i->last_alloc_logical_block = block; + block_i->last_alloc_physical_block = le32_to_cpu(where[num-1].key); + } /* We are done with atomic stuff, now do the rest of housekeeping */ @@ -708,7 +710,6 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, int boundary = 0; int depth = ext3_block_to_path(inode, iblock, offsets, &boundary); struct ext3_inode_info *ei = EXT3_I(inode); - struct super_block *sb = inode->i_sb; J_ASSERT(handle != NULL || create == 0); @@ -755,9 +756,8 @@ out: down(&ei->truncate_sem); /* lazy initialize the block allocation info here if necessary */ - if (test_opt(sb, RESERVATION) && S_ISREG(inode->i_mode) - && (!ei->i_rsv_window)) { - ext3_alloc_init_reservation(inode); + if (S_ISREG(inode->i_mode) && (!ei->i_block_alloc_info)) { + ext3_init_block_alloc_info(inode); } if (ext3_find_goal(inode, iblock, chain, partial, &goal) < 0) { @@ -2503,7 +2503,7 @@ void ext3_read_inode(struct inode * inode) ei->i_acl = EXT3_ACL_NOT_CACHED; ei->i_default_acl = EXT3_ACL_NOT_CACHED; #endif - ei->i_rsv_window = NULL; + ei->i_block_alloc_info = NULL; if (__ext3_get_inode_loc(inode, &iloc, 0)) goto bad_inode; @@ -2524,8 +2524,6 @@ void ext3_read_inode(struct inode * inode) inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; ei->i_state = 0; - ei->i_next_alloc_block = 0; - ei->i_next_alloc_goal = 0; ei->i_dir_start_lookup = 0; ei->i_dtime = le32_to_cpu(raw_inode->i_dtime); /* We now have enough fields to check if the inode was active or not. diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 8a07bb08474dbd..706d6860838143 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -155,8 +155,8 @@ flags_err: case EXT3_IOC_GETRSVSZ: if (test_opt(inode->i_sb, RESERVATION) && S_ISREG(inode->i_mode) - && ei->i_rsv_window) { - rsv_window_size = ei->i_rsv_window->rsv_goal_size; + && ei->i_block_alloc_info) { + rsv_window_size = ei->i_block_alloc_info->rsv_window_node.rsv_goal_size; return put_user(rsv_window_size, (int __user *)arg); } return -ENOTTY; @@ -182,11 +182,13 @@ flags_err: * before set the window size */ down(&ei->truncate_sem); - if (!ei->i_rsv_window) - ext3_alloc_init_reservation(inode); + if (!ei->i_block_alloc_info) + ext3_init_block_alloc_info(inode); - if (ei->i_rsv_window) - ei->i_rsv_window->rsv_goal_size = rsv_window_size; + if (ei->i_block_alloc_info){ + struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; + rsv->rsv_goal_size = rsv_window_size; + } up(&ei->truncate_sem); return 0; } diff --git a/fs/ext3/super.c b/fs/ext3/super.c index e8b45bcca96adb..53b054263a2b84 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -441,7 +441,7 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) ei->i_acl = EXT3_ACL_NOT_CACHED; ei->i_default_acl = EXT3_ACL_NOT_CACHED; #endif - ei->i_rsv_window = NULL; + ei->i_block_alloc_info = NULL; ei->vfs_inode.i_version = 1; return &ei->vfs_inode; } @@ -485,7 +485,7 @@ static void destroy_inodecache(void) static void ext3_clear_inode(struct inode *inode) { - struct ext3_reserve_window_node *rsv = EXT3_I(inode)->i_rsv_window; + struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info; #ifdef CONFIG_EXT3_FS_POSIX_ACL if (EXT3_I(inode)->i_acl && EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) { @@ -499,7 +499,7 @@ static void ext3_clear_inode(struct inode *inode) } #endif ext3_discard_reservation(inode); - EXT3_I(inode)->i_rsv_window = NULL; + EXT3_I(inode)->i_block_alloc_info = NULL; kfree(rsv); } diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index 45d15e5f8a0432..74ad31781e3ea7 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -725,7 +725,7 @@ extern struct ext3_group_desc * ext3_get_group_desc(struct super_block * sb, unsigned int block_group, struct buffer_head ** bh); extern int ext3_should_retry_alloc(struct super_block *sb, int *retries); -extern void ext3_alloc_init_reservation(struct inode *); +extern void ext3_init_block_alloc_info(struct inode *); extern void ext3_rsv_window_add(struct super_block *sb, struct ext3_reserve_window_node *rsv); /* dir.c */ diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index 45a81d3ce5ab1f..2914f7b0715661 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h @@ -32,6 +32,26 @@ struct ext3_reserve_window_node { struct ext3_reserve_window rsv_window; }; +struct ext3_block_alloc_info { + /* information about reservation window */ + struct ext3_reserve_window_node rsv_window_node; + /* + * was i_next_alloc_block in ext3_inode_info + * is the logical (file-relative) number of the + * most-recently-allocated block in this file. + * We use this for detecting linearly ascending allocation requests. + */ + __u32 last_alloc_logical_block; + /* + * Was i_next_alloc_goal in ext3_inode_info + * is the *physical* companion to i_next_alloc_block. + * it the the physical block number of the block which was most-recentl + * allocated to this file. This give us the goal (target) for the next + * allocation when we detect linearly ascending requests. + */ + __u32 last_alloc_physical_block; +}; + #define rsv_start rsv_window._rsv_start #define rsv_end rsv_window._rsv_end @@ -60,22 +80,8 @@ struct ext3_inode_info { __u32 i_block_group; __u32 i_state; /* Dynamic state flags for ext3 */ - /* - * i_next_alloc_block is the logical (file-relative) number of the - * most-recently-allocated block in this file. Yes, it is misnamed. - * We use this for detecting linearly ascending allocation requests. - */ - __u32 i_next_alloc_block; - - /* - * i_next_alloc_goal is the *physical* companion to i_next_alloc_block. - * it the the physical block number of the block which was most-recently - * allocated to this file. This give us the goal (target) for the next - * allocation when we detect linearly ascending requests. - */ - __u32 i_next_alloc_goal; /* block reservation info */ - struct ext3_reserve_window_node *i_rsv_window; + struct ext3_block_alloc_info *i_block_alloc_info; __u32 i_dir_start_lookup; #ifdef CONFIG_EXT3_FS_XATTR |