aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMingming Cao <cmm@us.ibm.com>2005-04-03 17:39:47 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-03 17:39:47 -0700
commita9aab1ec2eaa11abc7d1b61276e840360bf39568 (patch)
tree1e063550a3a573f2963125cf8c92b32a9b2493ff
parent3bc0a5f5c161254ccce512842627dab97a646a70 (diff)
downloadhistory-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.c42
-rw-r--r--fs/ext3/ialloc.c4
-rw-r--r--fs/ext3/inode.c54
-rw-r--r--fs/ext3/ioctl.c14
-rw-r--r--fs/ext3/super.c6
-rw-r--r--include/linux/ext3_fs.h2
-rw-r--r--include/linux/ext3_fs_i.h36
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