aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@infradead.org>2006-03-23 06:00:42 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-23 10:38:14 -0500
commit97461518610fb1679f67333bb699bb81136e49fe (patch)
tree483fcaf10744a96ad9fced97910fa75610c3fcdb
parent7bf6d78dd93ccc52cd2cac5066c4b84834e4f1f2 (diff)
[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 <arjan@infradead.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--fs/ext3/file.c4
-rw-r--r--fs/ext3/inode.c14
-rw-r--r--fs/ext3/ioctl.c4
-rw-r--r--fs/ext3/super.c2
-rw-r--r--include/linux/ext3_fs_i.h7
5 files changed, 16 insertions, 15 deletions
diff --git a/fs/ext3/file.c b/fs/ext3/file.c
index 98e78345ead9..59098ea56711 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)
37 if ((filp->f_mode & FMODE_WRITE) && 37 if ((filp->f_mode & FMODE_WRITE) &&
38 (atomic_read(&inode->i_writecount) == 1)) 38 (atomic_read(&inode->i_writecount) == 1))
39 { 39 {
40 down(&EXT3_I(inode)->truncate_sem); 40 mutex_lock(&EXT3_I(inode)->truncate_mutex);
41 ext3_discard_reservation(inode); 41 ext3_discard_reservation(inode);
42 up(&EXT3_I(inode)->truncate_sem); 42 mutex_unlock(&EXT3_I(inode)->truncate_mutex);
43 } 43 }
44 if (is_dx(inode) && filp->private_data) 44 if (is_dx(inode) && filp->private_data)
45 ext3_htree_free_dir_info(filp->private_data); 45 ext3_htree_free_dir_info(filp->private_data);
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c
index d59d5a667b0b..2c361377e0a5 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,
702 if (!create || err == -EIO) 702 if (!create || err == -EIO)
703 goto cleanup; 703 goto cleanup;
704 704
705 down(&ei->truncate_sem); 705 mutex_lock(&ei->truncate_mutex);
706 706
707 /* 707 /*
708 * If the indirect block is missing while we are reading 708 * 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 } 723 }
724 partial = ext3_get_branch(inode, depth, offsets, chain, &err); 724 partial = ext3_get_branch(inode, depth, offsets, chain, &err);
725 if (!partial) { 725 if (!partial) {
726 up(&ei->truncate_sem); 726 mutex_unlock(&ei->truncate_mutex);
727 if (err) 727 if (err)
728 goto cleanup; 728 goto cleanup;
729 clear_buffer_new(bh_result); 729 clear_buffer_new(bh_result);
@@ -759,13 +759,13 @@ ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock,
759 err = ext3_splice_branch(handle, inode, iblock, chain, 759 err = ext3_splice_branch(handle, inode, iblock, chain,
760 partial, left); 760 partial, left);
761 /* 761 /*
762 * i_disksize growing is protected by truncate_sem. Don't forget to 762 * i_disksize growing is protected by truncate_mutex. Don't forget to
763 * protect it if you're about to implement concurrent 763 * protect it if you're about to implement concurrent
764 * ext3_get_block() -bzzz 764 * ext3_get_block() -bzzz
765 */ 765 */
766 if (!err && extend_disksize && inode->i_size > ei->i_disksize) 766 if (!err && extend_disksize && inode->i_size > ei->i_disksize)
767 ei->i_disksize = inode->i_size; 767 ei->i_disksize = inode->i_size;
768 up(&ei->truncate_sem); 768 mutex_unlock(&ei->truncate_mutex);
769 if (err) 769 if (err)
770 goto cleanup; 770 goto cleanup;
771 771
@@ -1227,7 +1227,7 @@ static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh)
1227 * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ... 1227 * ext3_file_write() -> generic_file_write() -> __alloc_pages() -> ...
1228 * 1228 *
1229 * Same applies to ext3_get_block(). We will deadlock on various things like 1229 * Same applies to ext3_get_block(). We will deadlock on various things like
1230 * lock_journal and i_truncate_sem. 1230 * lock_journal and i_truncate_mutex.
1231 * 1231 *
1232 * Setting PF_MEMALLOC here doesn't work - too many internal memory 1232 * Setting PF_MEMALLOC here doesn't work - too many internal memory
1233 * allocations fail. 1233 * allocations fail.
@@ -2161,7 +2161,7 @@ void ext3_truncate(struct inode * inode)
2161 * From here we block out all ext3_get_block() callers who want to 2161 * From here we block out all ext3_get_block() callers who want to
2162 * modify the block allocation tree. 2162 * modify the block allocation tree.
2163 */ 2163 */
2164 down(&ei->truncate_sem); 2164 mutex_lock(&ei->truncate_mutex);
2165 2165
2166 if (n == 1) { /* direct blocks */ 2166 if (n == 1) { /* direct blocks */
2167 ext3_free_data(handle, inode, NULL, i_data+offsets[0], 2167 ext3_free_data(handle, inode, NULL, i_data+offsets[0],
@@ -2228,7 +2228,7 @@ do_indirects:
2228 2228
2229 ext3_discard_reservation(inode); 2229 ext3_discard_reservation(inode);
2230 2230
2231 up(&ei->truncate_sem); 2231 mutex_unlock(&ei->truncate_mutex);
2232 inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; 2232 inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC;
2233 ext3_mark_inode_dirty(handle, inode); 2233 ext3_mark_inode_dirty(handle, inode);
2234 2234
diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c
index 556cd5510078..aaf1da17b6d4 100644
--- a/fs/ext3/ioctl.c
+++ b/fs/ext3/ioctl.c
@@ -182,7 +182,7 @@ flags_err:
182 * need to allocate reservation structure for this inode 182 * need to allocate reservation structure for this inode
183 * before set the window size 183 * before set the window size
184 */ 184 */
185 down(&ei->truncate_sem); 185 mutex_lock(&ei->truncate_mutex);
186 if (!ei->i_block_alloc_info) 186 if (!ei->i_block_alloc_info)
187 ext3_init_block_alloc_info(inode); 187 ext3_init_block_alloc_info(inode);
188 188
@@ -190,7 +190,7 @@ flags_err:
190 struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node; 190 struct ext3_reserve_window_node *rsv = &ei->i_block_alloc_info->rsv_window_node;
191 rsv->rsv_goal_size = rsv_window_size; 191 rsv->rsv_goal_size = rsv_window_size;
192 } 192 }
193 up(&ei->truncate_sem); 193 mutex_unlock(&ei->truncate_mutex);
194 return 0; 194 return 0;
195 } 195 }
196 case EXT3_IOC_GROUP_EXTEND: { 196 case EXT3_IOC_GROUP_EXTEND: {
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index efa832059143..efe5b20d7a5a 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)
472#ifdef CONFIG_EXT3_FS_XATTR 472#ifdef CONFIG_EXT3_FS_XATTR
473 init_rwsem(&ei->xattr_sem); 473 init_rwsem(&ei->xattr_sem);
474#endif 474#endif
475 init_MUTEX(&ei->truncate_sem); 475 mutex_init(&ei->truncate_mutex);
476 inode_init_once(&ei->vfs_inode); 476 inode_init_once(&ei->vfs_inode);
477 } 477 }
478} 478}
diff --git a/include/linux/ext3_fs_i.h b/include/linux/ext3_fs_i.h
index e71dd98dbcae..7abf90147180 100644
--- a/include/linux/ext3_fs_i.h
+++ b/include/linux/ext3_fs_i.h
@@ -19,6 +19,7 @@
19#include <linux/rwsem.h> 19#include <linux/rwsem.h>
20#include <linux/rbtree.h> 20#include <linux/rbtree.h>
21#include <linux/seqlock.h> 21#include <linux/seqlock.h>
22#include <linux/mutex.h>
22 23
23struct ext3_reserve_window { 24struct ext3_reserve_window {
24 __u32 _rsv_start; /* First byte reserved */ 25 __u32 _rsv_start; /* First byte reserved */
@@ -122,16 +123,16 @@ struct ext3_inode_info {
122 __u16 i_extra_isize; 123 __u16 i_extra_isize;
123 124
124 /* 125 /*
125 * truncate_sem is for serialising ext3_truncate() against 126 * truncate_mutex is for serialising ext3_truncate() against
126 * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's 127 * ext3_getblock(). In the 2.4 ext2 design, great chunks of inode's
127 * data tree are chopped off during truncate. We can't do that in 128 * data tree are chopped off during truncate. We can't do that in
128 * ext3 because whenever we perform intermediate commits during 129 * ext3 because whenever we perform intermediate commits during
129 * truncate, the inode and all the metadata blocks *must* be in a 130 * truncate, the inode and all the metadata blocks *must* be in a
130 * consistent state which allows truncation of the orphans to restart 131 * consistent state which allows truncation of the orphans to restart
131 * during recovery. Hence we must fix the get_block-vs-truncate race 132 * during recovery. Hence we must fix the get_block-vs-truncate race
132 * by other means, so we have truncate_sem. 133 * by other means, so we have truncate_mutex.
133 */ 134 */
134 struct semaphore truncate_sem; 135 struct mutex truncate_mutex;
135 struct inode vfs_inode; 136 struct inode vfs_inode;
136}; 137};
137 138