diff options
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/dir.c | 52 | ||||
-rw-r--r-- | fs/ext3/file.c | 4 | ||||
-rw-r--r-- | fs/ext3/inode.c | 16 | ||||
-rw-r--r-- | fs/ext3/ioctl.c | 4 | ||||
-rw-r--r-- | fs/ext3/super.c | 6 |
5 files changed, 39 insertions, 43 deletions
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 832867aef3dc..773459164bb2 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -95,11 +95,10 @@ static int ext3_readdir(struct file * filp, | |||
95 | void * dirent, filldir_t filldir) | 95 | void * dirent, filldir_t filldir) |
96 | { | 96 | { |
97 | int error = 0; | 97 | int error = 0; |
98 | unsigned long offset, blk; | 98 | unsigned long offset; |
99 | int i, num, stored; | 99 | int i, stored; |
100 | struct buffer_head * bh, * tmp, * bha[16]; | 100 | struct ext3_dir_entry_2 *de; |
101 | struct ext3_dir_entry_2 * de; | 101 | struct super_block *sb; |
102 | struct super_block * sb; | ||
103 | int err; | 102 | int err; |
104 | struct inode *inode = filp->f_dentry->d_inode; | 103 | struct inode *inode = filp->f_dentry->d_inode; |
105 | int ret = 0; | 104 | int ret = 0; |
@@ -124,12 +123,29 @@ static int ext3_readdir(struct file * filp, | |||
124 | } | 123 | } |
125 | #endif | 124 | #endif |
126 | stored = 0; | 125 | stored = 0; |
127 | bh = NULL; | ||
128 | offset = filp->f_pos & (sb->s_blocksize - 1); | 126 | offset = filp->f_pos & (sb->s_blocksize - 1); |
129 | 127 | ||
130 | while (!error && !stored && filp->f_pos < inode->i_size) { | 128 | while (!error && !stored && filp->f_pos < inode->i_size) { |
131 | blk = (filp->f_pos) >> EXT3_BLOCK_SIZE_BITS(sb); | 129 | unsigned long blk = filp->f_pos >> EXT3_BLOCK_SIZE_BITS(sb); |
132 | bh = ext3_bread(NULL, inode, blk, 0, &err); | 130 | struct buffer_head map_bh; |
131 | struct buffer_head *bh = NULL; | ||
132 | |||
133 | map_bh.b_state = 0; | ||
134 | err = ext3_get_block_handle(NULL, inode, blk, &map_bh, 0, 0); | ||
135 | if (!err) { | ||
136 | page_cache_readahead(sb->s_bdev->bd_inode->i_mapping, | ||
137 | &filp->f_ra, | ||
138 | filp, | ||
139 | map_bh.b_blocknr >> | ||
140 | (PAGE_CACHE_SHIFT - inode->i_blkbits), | ||
141 | 1); | ||
142 | bh = ext3_bread(NULL, inode, blk, 0, &err); | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * We ignore I/O errors on directories so users have a chance | ||
147 | * of recovering data when there's a bad sector | ||
148 | */ | ||
133 | if (!bh) { | 149 | if (!bh) { |
134 | ext3_error (sb, "ext3_readdir", | 150 | ext3_error (sb, "ext3_readdir", |
135 | "directory #%lu contains a hole at offset %lu", | 151 | "directory #%lu contains a hole at offset %lu", |
@@ -138,26 +154,6 @@ static int ext3_readdir(struct file * filp, | |||
138 | continue; | 154 | continue; |
139 | } | 155 | } |
140 | 156 | ||
141 | /* | ||
142 | * Do the readahead | ||
143 | */ | ||
144 | if (!offset) { | ||
145 | for (i = 16 >> (EXT3_BLOCK_SIZE_BITS(sb) - 9), num = 0; | ||
146 | i > 0; i--) { | ||
147 | tmp = ext3_getblk (NULL, inode, ++blk, 0, &err); | ||
148 | if (tmp && !buffer_uptodate(tmp) && | ||
149 | !buffer_locked(tmp)) | ||
150 | bha[num++] = tmp; | ||
151 | else | ||
152 | brelse (tmp); | ||
153 | } | ||
154 | if (num) { | ||
155 | ll_rw_block (READA, num, bha); | ||
156 | for (i = 0; i < num; i++) | ||
157 | brelse (bha[i]); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | revalidate: | 157 | revalidate: |
162 | /* If the dir block has changed since the last call to | 158 | /* If the dir block has changed since the last call to |
163 | * readdir(2), then we might be pointing to an invalid | 159 | * readdir(2), then we might be pointing to an invalid |
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 0384e539b88f..2c361377e0a5 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
@@ -671,7 +671,7 @@ err_out: | |||
671 | * The BKL may not be held on entry here. Be sure to take it early. | 671 | * The BKL may not be held on entry here. Be sure to take it early. |
672 | */ | 672 | */ |
673 | 673 | ||
674 | static int | 674 | int |
675 | ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, | 675 | ext3_get_block_handle(handle_t *handle, struct inode *inode, sector_t iblock, |
676 | struct buffer_head *bh_result, int create, int extend_disksize) | 676 | struct buffer_head *bh_result, int create, int extend_disksize) |
677 | { | 677 | { |
@@ -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 56bf76586019..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 | } |
@@ -2382,8 +2382,8 @@ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) | |||
2382 | * Process 1 Process 2 | 2382 | * Process 1 Process 2 |
2383 | * ext3_create() quota_sync() | 2383 | * ext3_create() quota_sync() |
2384 | * journal_start() write_dquot() | 2384 | * journal_start() write_dquot() |
2385 | * DQUOT_INIT() down(dqio_sem) | 2385 | * DQUOT_INIT() down(dqio_mutex) |
2386 | * down(dqio_sem) journal_start() | 2386 | * down(dqio_mutex) journal_start() |
2387 | * | 2387 | * |
2388 | */ | 2388 | */ |
2389 | 2389 | ||