summaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/file.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 20:26:52 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 20:26:52 +0200
commit5f248c9c251c60af3403902b26e08de43964ea0b (patch)
tree6d3328e72a7e4015a64017eb30be18095c6a3c64 /fs/reiserfs/file.c
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6 (diff)
parentno need for list_for_each_entry_safe()/resetting with superblock list (diff)
downloadlinux-5f248c9c251c60af3403902b26e08de43964ea0b.tar.xz
linux-5f248c9c251c60af3403902b26e08de43964ea0b.zip
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: (96 commits) no need for list_for_each_entry_safe()/resetting with superblock list Fix sget() race with failing mount vfs: don't hold s_umount over close_bdev_exclusive() call sysv: do not mark superblock dirty on remount sysv: do not mark superblock dirty on mount btrfs: remove junk sb_dirt change BFS: clean up the superblock usage AFFS: wait for sb synchronization when needed AFFS: clean up dirty flag usage cifs: truncate fallout mbcache: fix shrinker function return value mbcache: Remove unused features add f_flags to struct statfs(64) pass a struct path to vfs_statfs update VFS documentation for method changes. All filesystems that need invalidate_inode_buffers() are doing that explicitly convert remaining ->clear_inode() to ->evict_inode() Make ->drop_inode() just return whether inode needs to be dropped fs/inode.c:clear_inode() is gone fs/inode.c:evict() doesn't care about delete vs. non-delete paths now ... Fix up trivial conflicts in fs/nilfs2/super.c
Diffstat (limited to 'fs/reiserfs/file.c')
-rw-r--r--fs/reiserfs/file.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index b82cdd8a45dd..6846371498b6 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -38,20 +38,24 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
BUG_ON(!S_ISREG(inode->i_mode));
+ if (atomic_add_unless(&REISERFS_I(inode)->openers, -1, 1))
+ return 0;
+
+ mutex_lock(&(REISERFS_I(inode)->tailpack));
+
+ if (!atomic_dec_and_test(&REISERFS_I(inode)->openers)) {
+ mutex_unlock(&(REISERFS_I(inode)->tailpack));
+ return 0;
+ }
+
/* fast out for when nothing needs to be done */
- if ((atomic_read(&inode->i_count) > 1 ||
- !(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
+ if ((!(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) ||
!tail_has_to_be_packed(inode)) &&
REISERFS_I(inode)->i_prealloc_count <= 0) {
+ mutex_unlock(&(REISERFS_I(inode)->tailpack));
return 0;
}
- mutex_lock(&inode->i_mutex);
-
- mutex_lock(&(REISERFS_I(inode)->i_mmap));
- if (REISERFS_I(inode)->i_flags & i_ever_mapped)
- REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask;
-
reiserfs_write_lock(inode->i_sb);
/* freeing preallocation only involves relogging blocks that
* are already in the current transaction. preallocation gets
@@ -94,9 +98,10 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
if (!err)
err = jbegin_failure;
- if (!err && atomic_read(&inode->i_count) <= 1 &&
+ if (!err &&
(REISERFS_I(inode)->i_flags & i_pack_on_close_mask) &&
tail_has_to_be_packed(inode)) {
+
/* if regular file is released by last holder and it has been
appended (we append by unformatted node only) or its direct
item(s) had to be converted, then it may have to be
@@ -104,27 +109,28 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
err = reiserfs_truncate_file(inode, 0);
}
out:
- mutex_unlock(&(REISERFS_I(inode)->i_mmap));
- mutex_unlock(&inode->i_mutex);
reiserfs_write_unlock(inode->i_sb);
+ mutex_unlock(&(REISERFS_I(inode)->tailpack));
return err;
}
-static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+static int reiserfs_file_open(struct inode *inode, struct file *file)
{
- struct inode *inode;
-
- inode = file->f_path.dentry->d_inode;
- mutex_lock(&(REISERFS_I(inode)->i_mmap));
- REISERFS_I(inode)->i_flags |= i_ever_mapped;
- mutex_unlock(&(REISERFS_I(inode)->i_mmap));
-
- return generic_file_mmap(file, vma);
+ int err = dquot_file_open(inode, file);
+ if (!atomic_inc_not_zero(&REISERFS_I(inode)->openers)) {
+ /* somebody might be tailpacking on final close; wait for it */
+ mutex_lock(&(REISERFS_I(inode)->tailpack));
+ atomic_inc(&REISERFS_I(inode)->openers);
+ mutex_unlock(&(REISERFS_I(inode)->tailpack));
+ }
+ return err;
}
static void reiserfs_vfs_truncate_file(struct inode *inode)
{
+ mutex_lock(&(REISERFS_I(inode)->tailpack));
reiserfs_truncate_file(inode, 1);
+ mutex_unlock(&(REISERFS_I(inode)->tailpack));
}
/* Sync a reiserfs file. */
@@ -288,8 +294,8 @@ const struct file_operations reiserfs_file_operations = {
#ifdef CONFIG_COMPAT
.compat_ioctl = reiserfs_compat_ioctl,
#endif
- .mmap = reiserfs_file_mmap,
- .open = dquot_file_open,
+ .mmap = generic_file_mmap,
+ .open = reiserfs_file_open,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
.aio_read = generic_file_aio_read,