Commit 9950435b authored by Jeff Garzik's avatar Jeff Garzik

Andrew Morton's ext2 sync mount speedup. Description:

At present, when mounted synchronously or with `chattr +S' in effect,
ext2 syncs the indirect blocks for every new block when extending a
file.

This is not necessary, because a sync is performed on the way out of
generic_file_write().  This will pick up all necessary data from
inode->i_dirty_buffers and inode->i_dirty_data_buffers, and is
sufficient.

The patch removes all the syncing of indirect blocks.

On a non-write-caching scsi disk, an untar of the util-linux tarball
runs three times faster.  Writing a 100 megabyte file in one megabyte
chunks speeds up ten times.

The patch also removes the intermediate indirect block syncing on the
truncate() path.  Instead, we sync the indirects at a single place, via
inode->i_dirty_buffers.  This not only means that the writes (may)
cluster better.  It means that we perform much, much less actual I/O
during truncate, because most or all of the indirects will no longer be
needed for the file, and will be invalidated.

fsync() and msync() still work correctly.  One side effect of this
patch is that VM-initiated writepage() against a file hole will no
longer block on writeout of indirect blocks.  This is good.
parent b1a5f642
...@@ -10,7 +10,6 @@ struct ext2_inode_info { ...@@ -10,7 +10,6 @@ struct ext2_inode_info {
__u32 i_faddr; __u32 i_faddr;
__u8 i_frag_no; __u8 i_frag_no;
__u8 i_frag_size; __u8 i_frag_size;
__u16 i_osync;
__u32 i_file_acl; __u32 i_file_acl;
__u32 i_dir_acl; __u32 i_dir_acl;
__u32 i_dtime; __u32 i_dtime;
......
...@@ -393,7 +393,6 @@ struct inode * ext2_new_inode(struct inode * dir, int mode) ...@@ -393,7 +393,6 @@ struct inode * ext2_new_inode(struct inode * dir, int mode)
ei->i_faddr = 0; ei->i_faddr = 0;
ei->i_frag_no = 0; ei->i_frag_no = 0;
ei->i_frag_size = 0; ei->i_frag_size = 0;
ei->i_osync = 0;
ei->i_file_acl = 0; ei->i_file_acl = 0;
ei->i_dir_acl = 0; ei->i_dir_acl = 0;
ei->i_dtime = 0; ei->i_dtime = 0;
......
...@@ -405,10 +405,10 @@ static int ext2_alloc_branch(struct inode *inode, ...@@ -405,10 +405,10 @@ static int ext2_alloc_branch(struct inode *inode,
mark_buffer_uptodate(bh, 1); mark_buffer_uptodate(bh, 1);
unlock_buffer(bh); unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode); mark_buffer_dirty_inode(bh, inode);
if (IS_SYNC(inode) || EXT2_I(inode)->i_osync) { /* We used to sync bh here if IS_SYNC(inode).
ll_rw_block (WRITE, 1, &bh); * But we now rely upon generic_osync_inode()
wait_on_buffer (bh); * and b_inode_buffers
} */
parent = nr; parent = nr;
} }
if (n == num) if (n == num)
...@@ -467,17 +467,9 @@ static inline int ext2_splice_branch(struct inode *inode, ...@@ -467,17 +467,9 @@ static inline int ext2_splice_branch(struct inode *inode,
inode->i_ctime = CURRENT_TIME; inode->i_ctime = CURRENT_TIME;
/* had we spliced it onto indirect block? */ /* had we spliced it onto indirect block? */
if (where->bh) { if (where->bh)
mark_buffer_dirty_inode(where->bh, inode); mark_buffer_dirty_inode(where->bh, inode);
if (IS_SYNC(inode) || ei->i_osync) {
ll_rw_block (WRITE, 1, &where->bh);
wait_on_buffer(where->bh);
}
}
if (IS_SYNC(inode) || ei->i_osync)
ext2_sync_inode (inode);
else
mark_inode_dirty(inode); mark_inode_dirty(inode);
return 0; return 0;
...@@ -833,10 +825,6 @@ void ext2_truncate (struct inode * inode) ...@@ -833,10 +825,6 @@ void ext2_truncate (struct inode * inode)
(u32*)partial->bh->b_data + addr_per_block, (u32*)partial->bh->b_data + addr_per_block,
(chain+n-1) - partial); (chain+n-1) - partial);
mark_buffer_dirty_inode(partial->bh, inode); mark_buffer_dirty_inode(partial->bh, inode);
if (IS_SYNC(inode)) {
ll_rw_block (WRITE, 1, &partial->bh);
wait_on_buffer (partial->bh);
}
brelse (partial->bh); brelse (partial->bh);
partial--; partial--;
} }
...@@ -868,10 +856,12 @@ void ext2_truncate (struct inode * inode) ...@@ -868,10 +856,12 @@ void ext2_truncate (struct inode * inode)
; ;
} }
inode->i_mtime = inode->i_ctime = CURRENT_TIME; inode->i_mtime = inode->i_ctime = CURRENT_TIME;
if (IS_SYNC(inode)) if (IS_SYNC(inode)) {
fsync_inode_buffers(inode);
ext2_sync_inode (inode); ext2_sync_inode (inode);
else } else {
mark_inode_dirty(inode); mark_inode_dirty(inode);
}
} }
static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino, static struct ext2_inode *ext2_get_inode(struct super_block *sb, ino_t ino,
...@@ -958,7 +948,6 @@ void ext2_read_inode (struct inode * inode) ...@@ -958,7 +948,6 @@ void ext2_read_inode (struct inode * inode)
ei->i_faddr = le32_to_cpu(raw_inode->i_faddr); ei->i_faddr = le32_to_cpu(raw_inode->i_faddr);
ei->i_frag_no = raw_inode->i_frag; ei->i_frag_no = raw_inode->i_frag;
ei->i_frag_size = raw_inode->i_fsize; ei->i_frag_size = raw_inode->i_fsize;
ei->i_osync = 0;
ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl); ei->i_file_acl = le32_to_cpu(raw_inode->i_file_acl);
ei->i_dir_acl = 0; ei->i_dir_acl = 0;
if (S_ISREG(inode->i_mode)) if (S_ISREG(inode->i_mode))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment