Commit 97461518 authored by Arjan van de Ven's avatar Arjan van de Ven Committed by Linus Torvalds

[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: default avatarArjan van de Ven <arjan@infradead.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 7bf6d78d
...@@ -37,9 +37,9 @@ static int ext3_release_file (struct inode * inode, struct file * filp) ...@@ -37,9 +37,9 @@ static int ext3_release_file (struct inode * inode, struct file * filp)
if ((filp->f_mode & FMODE_WRITE) && if ((filp->f_mode & FMODE_WRITE) &&
(atomic_read(&inode->i_writecount) == 1)) (atomic_read(&inode->i_writecount) == 1))
{ {
down(&EXT3_I(inode)->truncate_sem); mutex_lock(&EXT3_I(inode)->truncate_mutex);
ext3_discard_reservation(inode); ext3_discard_reservation(inode);
up(&EXT3_I(inode)->truncate_sem); mutex_unlock(&EXT3_I(inode)->truncate_mutex);
} }
if (is_dx(inode) && filp->private_data) if (is_dx(inode) && filp->private_data)
ext3_htree_free_dir_info(filp->private_data); ext3_htree_free_dir_info(filp->private_data);
......
...@@ -702,7 +702,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, ...@@ -702,7 +702,7 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
if (!create || err == -EIO) if (!create || err == -EIO)
goto cleanup; goto cleanup;
down(&ei->truncate_sem); mutex_lock(&ei->truncate_mutex);
/* /*
* If the indirect block is missing while we are reading * 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, ...@@ -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); partial = ext3_get_branch(inode, depth, offsets, chain, &err);
if (!partial) { if (!partial) {
up(&ei->truncate_sem); mutex_unlock(&ei->truncate_mutex);
if (err) if (err)
goto cleanup; goto cleanup;
clear_buffer_new(bh_result); clear_buffer_new(bh_result);
...@@ -759,13 +759,13 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, ...@@ -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, err = ext3_splice_branch(handle, inode, iblock, chain,
partial, left); 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 * protect it if you're about to implement concurrent
* ext3_get_block() -bzzz * ext3_get_block() -bzzz
*/ */
if (!err && extend_disksize && inode->i_size > ei->i_disksize) if (!err && extend_disksize && inode->i_size > ei->i_disksize)
ei->i_disksize = inode->i_size; ei->i_disksize = inode->i_size;
up(&ei->truncate_sem); mutex_unlock(&ei->truncate_mutex);
if (err) if (err)
goto cleanup; goto cleanup;
...@@ -1227,7 +1227,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) ...@@ -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() -> ... * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ...
* *
* Same applies to ext3_get_block(). We will deadlock on various things like * 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 * Setting PF_MEMALLOC here doesn't work - too many internal memory
* allocations fail. * allocations fail.
...@@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode) ...@@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode)
* From here we block out all ext3_get_block() callers who want to * From here we block out all ext3_get_block() callers who want to
* modify the block allocation tree. * modify the block allocation tree.
*/ */
down(&ei->truncate_sem); mutex_lock(&ei->truncate_mutex);
if (n == 1) { /* direct blocks */ if (n == 1) { /* direct blocks */
ext3_free_data(handle, inode, NULL, i_data+offsets[0], ext3_free_data(handle, inode, NULL, i_data+offsets[0],
...@@ -2228,7 +2228,7 @@ do_indirects: ...@@ -2228,7 +2228,7 @@ do_indirects:
ext3_discard_reservation(inode); ext3_discard_reservation(inode);
up(&ei->truncate_sem); mutex_unlock(&ei->truncate_mutex);
inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
ext3_mark_inode_dirty(handle, inode); ext3_mark_inode_dirty(handle, inode);
......
...@@ -182,7 +182,7 @@ flags_err: ...@@ -182,7 +182,7 @@ flags_err:
* need to allocate reservation structure for this inode * need to allocate reservation structure for this inode
* before set the window size * before set the window size
*/ */
down(&ei->truncate_sem); mutex_lock(&ei->truncate_mutex);
if (!ei->i_block_alloc_info) if (!ei->i_block_alloc_info)
ext3_init_block_alloc_info(inode); ext3_init_block_alloc_info(inode);
...@@ -190,7 +190,7 @@ flags_err: ...@@ -190,7 +190,7 @@ flags_err:
struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
rsv->rsv_goal_size = rsv_window_size; rsv->rsv_goal_size = rsv_window_size;
} }
up(&ei->truncate_sem); mutex_unlock(&ei->truncate_mutex);
return 0; return 0;
} }
case EXT3_IOC_GROUP_EXTEND: { case EXT3_IOC_GROUP_EXTEND: {
......
...@@ -472,7 +472,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -472,7 +472,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
#ifdef CONFIG_EXT3_FS_XATTR #ifdef CONFIG_EXT3_FS_XATTR
init_rwsem(&ei->xattr_sem); init_rwsem(&ei->xattr_sem);
#endif #endif
init_MUTEX(&ei->truncate_sem); mutex_init(&ei->truncate_mutex);
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/rwsem.h> #include <linux/rwsem.h>
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include <linux/seqlock.h> #include <linux/seqlock.h>
#include <linux/mutex.h>
struct ext3_reserve_window { struct ext3_reserve_window {
__u32 _rsv_start; /* First byte reserved */ __u32 _rsv_start; /* First byte reserved */
...@@ -122,16 +123,16 @@ struct ext3_inode_info { ...@@ -122,16 +123,16 @@ struct ext3_inode_info {
__u16 i_extra_isize; __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 * 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 * data tree are chopped off during truncate. We can't do that in
* ext3 because whenever we perform intermediate commits during * ext3 because whenever we perform intermediate commits during
* truncate, the inode and all the metadata blocks *must* be in a * truncate, the inode and all the metadata blocks *must* be in a
* consistent state which allows truncation of the orphans to restart * consistent state which allows truncation of the orphans to restart
* during recovery. Hence we must fix the get_block-vs-truncate race * 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; struct inode vfs_inode;
}; };
......
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