summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/reiserfs/file.c20
-rw-r--r--fs/reiserfs/inode.c2
-rw-r--r--include/linux/reiserfs_fs_i.h2
3 files changed, 23 insertions, 1 deletions
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c
index be12879bb179..fdd96365218b 100644
--- a/fs/reiserfs/file.c
+++ b/fs/reiserfs/file.c
@@ -50,6 +50,11 @@ static int reiserfs_file_release(struct inode *inode, struct file *filp)
reiserfs_write_lock(inode->i_sb);
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;
+
/* freeing preallocation only involves relogging blocks that
* are already in the current transaction. preallocation gets
* freed at the end of each transaction, so it is impossible for
@@ -100,11 +105,24 @@ 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);
return err;
}
+static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct inode *inode;
+
+ inode = file->f_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);
+}
+
static void reiserfs_vfs_truncate_file(struct inode *inode)
{
reiserfs_truncate_file(inode, 1);
@@ -1570,7 +1588,7 @@ struct file_operations reiserfs_file_operations = {
.read = generic_file_read,
.write = reiserfs_file_write,
.ioctl = reiserfs_ioctl,
- .mmap = generic_file_mmap,
+ .mmap = reiserfs_file_mmap,
.release = reiserfs_file_release,
.fsync = reiserfs_sync_file,
.sendfile = generic_file_sendfile,
diff --git a/fs/reiserfs/inode.c b/fs/reiserfs/inode.c
index d60f6238c66a..4cb01689aecf 100644
--- a/fs/reiserfs/inode.c
+++ b/fs/reiserfs/inode.c
@@ -1140,6 +1140,7 @@ static void init_inode(struct inode *inode, struct path *path)
REISERFS_I(inode)->i_prealloc_count = 0;
REISERFS_I(inode)->i_trans_id = 0;
REISERFS_I(inode)->i_jl = NULL;
+ mutex_init(&(REISERFS_I(inode)->i_mmap));
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
init_rwsem(&REISERFS_I(inode)->xattr_sem);
@@ -1847,6 +1848,7 @@ int reiserfs_new_inode(struct reiserfs_transaction_handle *th,
REISERFS_I(inode)->i_attrs =
REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK;
sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode);
+ mutex_init(&(REISERFS_I(inode)->i_mmap));
REISERFS_I(inode)->i_acl_access = NULL;
REISERFS_I(inode)->i_acl_default = NULL;
init_rwsem(&REISERFS_I(inode)->xattr_sem);
diff --git a/include/linux/reiserfs_fs_i.h b/include/linux/reiserfs_fs_i.h
index 149be8d9a0c9..547bbf3a1190 100644
--- a/include/linux/reiserfs_fs_i.h
+++ b/include/linux/reiserfs_fs_i.h
@@ -25,6 +25,7 @@ typedef enum {
i_link_saved_truncate_mask = 0x0020,
i_has_xattr_dir = 0x0040,
i_data_log = 0x0080,
+ i_ever_mapped = 0x0100
} reiserfs_inode_flags;
struct reiserfs_inode_info {
@@ -52,6 +53,7 @@ struct reiserfs_inode_info {
** flushed */
unsigned long i_trans_id;
struct reiserfs_journal_list *i_jl;
+ struct mutex i_mmap;
struct posix_acl *i_acl_access;
struct posix_acl *i_acl_default;