From d8733c2956968a01394a4d2a9e97a8b431a78776 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 23 Mar 2006 03:00:11 -0800 Subject: [PATCH] ext3_readdir: use generic readahead Linus points out that ext3_readdir's readahead only cuts in when ext3_readdir() is operating at the very start of the directory. So for large directories we end up performing no readahead at all and we suck. So take it all out and use the core VM's page_cache_readahead(). This means that ext3 directory reads will use all of readahead's dynamic sizing goop. Note that we're using the directory's filp->f_ra to hold the readahead state, but readahead is actually being performed against the underlying blockdev's address_space. Fortunately the readahead code is all set up to handle this. Tested with printk. It works. I was struggling to find a real workload which actually cared. (The patch also exports page_cache_readahead() to GPL modules) Cc: "Stephen C. Tweedie" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs/ext3/inode.c') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 0384e539b88..d59d5a667b0 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -671,7 +671,7 @@ err_out: * The BKL may not be held on entry here. Be sure to take it early. */ -static int +int ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create, int extend_disksize) { -- cgit v1.2.3-70-g09d2 From 97461518610fb1679f67333bb699bb81136e49fe Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Thu, 23 Mar 2006 03:00:42 -0800 Subject: [PATCH] convert ext3's truncate_sem to a mutex ext3's truncate_sem is always released in the same function it's taken and it otherwise is a mutex as well.. Signed-off-by: Arjan van de Ven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/file.c | 4 ++-- fs/ext3/inode.c | 14 +++++++------- fs/ext3/ioctl.c | 4 ++-- fs/ext3/super.c | 2 +- include/linux/ext3_fs_i.h | 7 ++++--- 5 files changed, 16 insertions(+), 15 deletions(-) (limited to 'fs/ext3/inode.c') diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 98e78345ead..59098ea5671 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -37,9 +37,9 @@ static int ext3_release_file (struct inode * inode, struct file * filp) if ((filp->f_mode & FMODE_WRITE) && (atomic_read(&inode->i_writecount) == 1)) { - down(&EXT3_I(inode)->truncate_sem); + mutex_lock(&EXT3_I(inode)->truncate_mutex); ext3_discard_reservation(inode); - up(&EXT3_I(inode)->truncate_sem); + mutex_unlock(&EXT3_I(inode)->truncate_mutex); } if (is_dx(inode) && filp->private_data) ext3_htree_free_dir_info(filp->private_data); diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index d59d5a667b0..2c361377e0a 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -702,7 +702,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, if (!create || err == -EIO) goto cleanup; - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); /* * If the indirect block is missing while we are reading @@ -723,7 +723,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, } partial = ext3_get_branch(inode, depth, offsets, chain, &err); if (!partial) { - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); if (err) goto cleanup; clear_buffer_new(bh_result); @@ -759,13 +759,13 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, err = ext3_splice_branch(handle, inode, iblock, chain, partial, left); /* - * i_disksize growing is protected by truncate_sem. Don't forget to + * i_disksize growing is protected by truncate_mutex. Don't forget to * protect it if you're about to implement concurrent * ext3_get_block() -bzzz */ if (!err && extend_disksize && inode->i_size > ei->i_disksize) ei->i_disksize = inode->i_size; - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); if (err) goto cleanup; @@ -1227,7 +1227,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ... * * Same applies to ext3_get_block(). We will deadlock on various things like - * lock_journal and i_truncate_sem. + * lock_journal and i_truncate_mutex. * * Setting PF_MEMALLOC here doesn't work - too many internal memory * allocations fail. @@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode) * From here we block out all ext3_get_block() callers who want to * modify the block allocation tree. */ - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); if (n == 1) { /* direct blocks */ ext3_free_data(handle, inode, NULL, i_data+offsets[0], @@ -2228,7 +2228,7 @@ do_indirects: ext3_discard_reservation(inode); - up(&ei->truncate_sem); + mutex_unlock(&ei->truncate_mutex); inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; ext3_mark_inode_dirty(handle, inode); diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 556cd551007..aaf1da17b6d 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -182,7 +182,7 @@ flags_err: * need to allocate reservation structure for this inode * before set the window size */ - down(&ei->truncate_sem); + mutex_lock(&ei->truncate_mutex); if (!ei->i_block_alloc_info) ext3_init_block_alloc_info(inode); @@ -190,7 +190,7 @@ flags_err: 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); + mutex_unlock(&ei->truncate_mutex); return 0; } case EXT3_IOC_GROUP_EXTEND: { diff --git a/fs/ext3/super.c b/fs/ext3/super.c index efa83205914..efe5b20d7a5 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -472,7 +472,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) #ifdef CONFIG_EXT3_FS_XATTR init_rwsem(&ei->xattr_sem); #endif - init_MUTEX(&ei->truncate_sem); + mutex_init(&ei->truncate_mutex); inode_init_once(&ei->vfs_inode); } } diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h index e71dd98dbca..7abf9014718 100644 --- a/include/linux/ext3_fs_i.h +++ b/include/linux/ext3_fs_i.h @@ -19,6 +19,7 @@ #include #include #include +#include struct ext3_reserve_window { __u32 _rsv_start; /* First byte reserved */ @@ -122,16 +123,16 @@ struct ext3_inode_info { __u16 i_extra_isize; /* - * truncate_sem is for serialising ext3_truncate() against + * truncate_mutex is for serialising ext3_truncate() against * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's * data tree are chopped off during truncate. We can't do that in * ext3 because whenever we perform intermediate commits during * truncate, the inode and all the metadata blocks *must* be in a * consistent state which allows truncation of the orphans to restart * during recovery. Hence we must fix the get_block-vs-truncate race - * by other means, so we have truncate_sem. + * by other means, so we have truncate_mutex. */ - struct semaphore truncate_sem; + struct mutex truncate_mutex; struct inode vfs_inode; }; -- cgit v1.2.3-70-g09d2