Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] resierfs: avoid tail packing if an inode was ever mmapped

This patch fixes a confusion reiserfs has for a long time.

On release file operation reiserfs used to try to pack file data stored in
last incomplete page of some files into metadata blocks. After packing the
page got cleared with clear_page_dirty. It did not take into account that
the page may be mmaped into other process's address space. Recent
replacement for clear_page_dirty cancel_dirty_page found the confusion with
sanity check that page has to be not mapped.

The patch fixes the confusion by making reiserfs avoid tail packing if an
inode was ever mmapped. reiserfs_mmap and reiserfs_file_release are
serialized with mutex in reiserfs specific inode. reiserfs_mmap locks the
mutex and sets a bit in reiserfs specific inode flags.
reiserfs_file_release checks the bit having the mutex locked. If bit is
set - tail packing is avoided. This eliminates a possibility that mmapped
page gets cancel_page_dirty-ed.

Signed-off-by: Vladimir Saveliev <vs@namesys.com>
Cc: Jeff Mahoney <jeffm@suse.com>
Cc: Chris Mason <mason@suse.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Vladimir Saveliev and committed by
Linus Torvalds
de14569f 30150f8d

+23 -1
+19 -1
fs/reiserfs/file.c
··· 48 48 } 49 49 50 50 mutex_lock(&inode->i_mutex); 51 + 52 + mutex_lock(&(REISERFS_I(inode)->i_mmap)); 53 + if (REISERFS_I(inode)->i_flags & i_ever_mapped) 54 + REISERFS_I(inode)->i_flags &= ~i_pack_on_close_mask; 55 + 51 56 reiserfs_write_lock(inode->i_sb); 52 57 /* freeing preallocation only involves relogging blocks that 53 58 * are already in the current transaction. preallocation gets ··· 105 100 err = reiserfs_truncate_file(inode, 0); 106 101 } 107 102 out: 103 + mutex_unlock(&(REISERFS_I(inode)->i_mmap)); 108 104 mutex_unlock(&inode->i_mutex); 109 105 reiserfs_write_unlock(inode->i_sb); 110 106 return err; 107 + } 108 + 109 + static int reiserfs_file_mmap(struct file *file, struct vm_area_struct *vma) 110 + { 111 + struct inode *inode; 112 + 113 + inode = file->f_path.dentry->d_inode; 114 + mutex_lock(&(REISERFS_I(inode)->i_mmap)); 115 + REISERFS_I(inode)->i_flags |= i_ever_mapped; 116 + mutex_unlock(&(REISERFS_I(inode)->i_mmap)); 117 + 118 + return generic_file_mmap(file, vma); 111 119 } 112 120 113 121 static void reiserfs_vfs_truncate_file(struct inode *inode) ··· 1545 1527 #ifdef CONFIG_COMPAT 1546 1528 .compat_ioctl = reiserfs_compat_ioctl, 1547 1529 #endif 1548 - .mmap = generic_file_mmap, 1530 + .mmap = reiserfs_file_mmap, 1549 1531 .open = generic_file_open, 1550 1532 .release = reiserfs_file_release, 1551 1533 .fsync = reiserfs_sync_file,
+2
fs/reiserfs/inode.c
··· 1125 1125 REISERFS_I(inode)->i_prealloc_count = 0; 1126 1126 REISERFS_I(inode)->i_trans_id = 0; 1127 1127 REISERFS_I(inode)->i_jl = NULL; 1128 + mutex_init(&(REISERFS_I(inode)->i_mmap)); 1128 1129 reiserfs_init_acl_access(inode); 1129 1130 reiserfs_init_acl_default(inode); 1130 1131 reiserfs_init_xattr_rwsem(inode); ··· 1833 1832 REISERFS_I(inode)->i_attrs = 1834 1833 REISERFS_I(dir)->i_attrs & REISERFS_INHERIT_MASK; 1835 1834 sd_attrs_to_i_attrs(REISERFS_I(inode)->i_attrs, inode); 1835 + mutex_init(&(REISERFS_I(inode)->i_mmap)); 1836 1836 reiserfs_init_acl_access(inode); 1837 1837 reiserfs_init_acl_default(inode); 1838 1838 reiserfs_init_xattr_rwsem(inode);
+2
include/linux/reiserfs_fs_i.h
··· 25 25 i_link_saved_truncate_mask = 0x0020, 26 26 i_has_xattr_dir = 0x0040, 27 27 i_data_log = 0x0080, 28 + i_ever_mapped = 0x0100 28 29 } reiserfs_inode_flags; 29 30 30 31 struct reiserfs_inode_info { ··· 53 52 ** flushed */ 54 53 unsigned long i_trans_id; 55 54 struct reiserfs_journal_list *i_jl; 55 + struct mutex i_mmap; 56 56 #ifdef CONFIG_REISERFS_FS_POSIX_ACL 57 57 struct posix_acl *i_acl_access; 58 58 struct posix_acl *i_acl_default;