diff options
author | Roman Zippel <zippel@linux-m68k.org> | 2008-04-29 11:02:20 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-05-06 13:45:33 -0400 |
commit | dca3c33652e437ed02c30ed3eca3cecd0cc00838 (patch) | |
tree | 590db1cd28a19c85532ba8ec8abf5eeb70f993ea /fs/affs/file.c | |
parent | a15306365a16380f3bafee9e181ba01231d4acd7 (diff) |
[PATCH] fix reservation discarding in affs
- remove affs_put_inode, so preallocations aren't discared unnecessarily
often.
- remove affs_drop_inode, it's called with a spinlock held, so it can't
use a mutex.
- make i_opencnt atomic
- avoid direct b_count manipulations
- a few allocation failure fixes, so that these are more gracefully
handled now.
Signed-off-by: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/affs/file.c')
-rw-r--r-- | fs/affs/file.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/fs/affs/file.c b/fs/affs/file.c index 1a4f092f24ef..6eac7bdeec94 100644 --- a/fs/affs/file.c +++ b/fs/affs/file.c | |||
@@ -48,8 +48,9 @@ affs_file_open(struct inode *inode, struct file *filp) | |||
48 | { | 48 | { |
49 | if (atomic_read(&filp->f_count) != 1) | 49 | if (atomic_read(&filp->f_count) != 1) |
50 | return 0; | 50 | return 0; |
51 | pr_debug("AFFS: open(%d)\n", AFFS_I(inode)->i_opencnt); | 51 | pr_debug("AFFS: open(%lu,%d)\n", |
52 | AFFS_I(inode)->i_opencnt++; | 52 | inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); |
53 | atomic_inc(&AFFS_I(inode)->i_opencnt); | ||
53 | return 0; | 54 | return 0; |
54 | } | 55 | } |
55 | 56 | ||
@@ -58,10 +59,16 @@ affs_file_release(struct inode *inode, struct file *filp) | |||
58 | { | 59 | { |
59 | if (atomic_read(&filp->f_count) != 0) | 60 | if (atomic_read(&filp->f_count) != 0) |
60 | return 0; | 61 | return 0; |
61 | pr_debug("AFFS: release(%d)\n", AFFS_I(inode)->i_opencnt); | 62 | pr_debug("AFFS: release(%lu, %d)\n", |
62 | AFFS_I(inode)->i_opencnt--; | 63 | inode->i_ino, atomic_read(&AFFS_I(inode)->i_opencnt)); |
63 | if (!AFFS_I(inode)->i_opencnt) | 64 | |
65 | if (atomic_dec_and_test(&AFFS_I(inode)->i_opencnt)) { | ||
66 | mutex_lock(&inode->i_mutex); | ||
67 | if (inode->i_size != AFFS_I(inode)->mmu_private) | ||
68 | affs_truncate(inode); | ||
64 | affs_free_prealloc(inode); | 69 | affs_free_prealloc(inode); |
70 | mutex_unlock(&inode->i_mutex); | ||
71 | } | ||
65 | 72 | ||
66 | return 0; | 73 | return 0; |
67 | } | 74 | } |
@@ -180,7 +187,7 @@ affs_get_extblock(struct inode *inode, u32 ext) | |||
180 | /* inline the simplest case: same extended block as last time */ | 187 | /* inline the simplest case: same extended block as last time */ |
181 | struct buffer_head *bh = AFFS_I(inode)->i_ext_bh; | 188 | struct buffer_head *bh = AFFS_I(inode)->i_ext_bh; |
182 | if (ext == AFFS_I(inode)->i_ext_last) | 189 | if (ext == AFFS_I(inode)->i_ext_last) |
183 | atomic_inc(&bh->b_count); | 190 | get_bh(bh); |
184 | else | 191 | else |
185 | /* we have to do more (not inlined) */ | 192 | /* we have to do more (not inlined) */ |
186 | bh = affs_get_extblock_slow(inode, ext); | 193 | bh = affs_get_extblock_slow(inode, ext); |
@@ -306,7 +313,7 @@ store_ext: | |||
306 | affs_brelse(AFFS_I(inode)->i_ext_bh); | 313 | affs_brelse(AFFS_I(inode)->i_ext_bh); |
307 | AFFS_I(inode)->i_ext_last = ext; | 314 | AFFS_I(inode)->i_ext_last = ext; |
308 | AFFS_I(inode)->i_ext_bh = bh; | 315 | AFFS_I(inode)->i_ext_bh = bh; |
309 | atomic_inc(&bh->b_count); | 316 | get_bh(bh); |
310 | 317 | ||
311 | return bh; | 318 | return bh; |
312 | 319 | ||
@@ -324,7 +331,6 @@ affs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh_resul | |||
324 | 331 | ||
325 | pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block); | 332 | pr_debug("AFFS: get_block(%u, %lu)\n", (u32)inode->i_ino, (unsigned long)block); |
326 | 333 | ||
327 | |||
328 | BUG_ON(block > (sector_t)0x7fffffffUL); | 334 | BUG_ON(block > (sector_t)0x7fffffffUL); |
329 | 335 | ||
330 | if (block >= AFFS_I(inode)->i_blkcnt) { | 336 | if (block >= AFFS_I(inode)->i_blkcnt) { |
@@ -827,6 +833,8 @@ affs_truncate(struct inode *inode) | |||
827 | res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); | 833 | res = mapping->a_ops->write_begin(NULL, mapping, size, 0, 0, &page, &fsdata); |
828 | if (!res) | 834 | if (!res) |
829 | res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); | 835 | res = mapping->a_ops->write_end(NULL, mapping, size, 0, 0, page, fsdata); |
836 | else | ||
837 | inode->i_size = AFFS_I(inode)->mmu_private; | ||
830 | mark_inode_dirty(inode); | 838 | mark_inode_dirty(inode); |
831 | return; | 839 | return; |
832 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) | 840 | } else if (inode->i_size == AFFS_I(inode)->mmu_private) |
@@ -862,6 +870,7 @@ affs_truncate(struct inode *inode) | |||
862 | blk++; | 870 | blk++; |
863 | } else | 871 | } else |
864 | AFFS_HEAD(ext_bh)->first_data = 0; | 872 | AFFS_HEAD(ext_bh)->first_data = 0; |
873 | AFFS_HEAD(ext_bh)->block_count = cpu_to_be32(i); | ||
865 | size = AFFS_SB(sb)->s_hashsize; | 874 | size = AFFS_SB(sb)->s_hashsize; |
866 | if (size > blkcnt - blk + i) | 875 | if (size > blkcnt - blk + i) |
867 | size = blkcnt - blk + i; | 876 | size = blkcnt - blk + i; |