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.

cramfs: fix named-pipe handling

After commit a97c9bf33f4612e2aed6f000f6b1d268b6814f3c (fix cramfs
making duplicate entries in inode cache) in kernel 2.6.14, named-pipe
on cramfs does not work properly.

It seems the commit make all named-pipe on cramfs share their inode
(and named-pipe buffer).

Make ..._test() refuse to merge inodes with ->i_ino == 1, take inode setup
back to get_cramfs_inode() and make ->drop_inode() evict ones with ->i_ino
== 1 immediately.

Reported-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: <stable@kernel.org> [2.6.14 and later]
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Al Viro and committed by
Linus Torvalds
82d63fc9 d847471d

+38 -46
+38 -46
fs/cramfs/inode.c
··· 43 43 static int cramfs_iget5_test(struct inode *inode, void *opaque) 44 44 { 45 45 struct cramfs_inode *cramfs_inode = opaque; 46 - 47 - if (inode->i_ino != CRAMINO(cramfs_inode)) 48 - return 0; /* does not match */ 49 - 50 - if (inode->i_ino != 1) 51 - return 1; 52 - 53 - /* all empty directories, char, block, pipe, and sock, share inode #1 */ 54 - 55 - if ((inode->i_mode != cramfs_inode->mode) || 56 - (inode->i_gid != cramfs_inode->gid) || 57 - (inode->i_uid != cramfs_inode->uid)) 58 - return 0; /* does not match */ 59 - 60 - if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) && 61 - (inode->i_rdev != old_decode_dev(cramfs_inode->size))) 62 - return 0; /* does not match */ 63 - 64 - return 1; /* matches */ 46 + return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; 65 47 } 66 48 67 49 static int cramfs_iget5_set(struct inode *inode, void *opaque) 68 50 { 69 - static struct timespec zerotime; 70 51 struct cramfs_inode *cramfs_inode = opaque; 71 - inode->i_mode = cramfs_inode->mode; 72 - inode->i_uid = cramfs_inode->uid; 73 - inode->i_size = cramfs_inode->size; 74 - inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; 75 - inode->i_gid = cramfs_inode->gid; 76 - /* Struct copy intentional */ 77 - inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; 78 52 inode->i_ino = CRAMINO(cramfs_inode); 79 - /* inode->i_nlink is left 1 - arguably wrong for directories, 80 - but it's the best we can do without reading the directory 81 - contents. 1 yields the right result in GNU find, even 82 - without -noleaf option. */ 83 - if (S_ISREG(inode->i_mode)) { 84 - inode->i_fop = &generic_ro_fops; 85 - inode->i_data.a_ops = &cramfs_aops; 86 - } else if (S_ISDIR(inode->i_mode)) { 87 - inode->i_op = &cramfs_dir_inode_operations; 88 - inode->i_fop = &cramfs_directory_operations; 89 - } else if (S_ISLNK(inode->i_mode)) { 90 - inode->i_op = &page_symlink_inode_operations; 91 - inode->i_data.a_ops = &cramfs_aops; 92 - } else { 93 - inode->i_size = 0; 94 - inode->i_blocks = 0; 95 - init_special_inode(inode, inode->i_mode, 96 - old_decode_dev(cramfs_inode->size)); 97 - } 98 53 return 0; 99 54 } 100 55 ··· 59 104 struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), 60 105 cramfs_iget5_test, cramfs_iget5_set, 61 106 cramfs_inode); 107 + static struct timespec zerotime; 108 + 62 109 if (inode && (inode->i_state & I_NEW)) { 110 + inode->i_mode = cramfs_inode->mode; 111 + inode->i_uid = cramfs_inode->uid; 112 + inode->i_size = cramfs_inode->size; 113 + inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; 114 + inode->i_gid = cramfs_inode->gid; 115 + /* Struct copy intentional */ 116 + inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; 117 + /* inode->i_nlink is left 1 - arguably wrong for directories, 118 + but it's the best we can do without reading the directory 119 + contents. 1 yields the right result in GNU find, even 120 + without -noleaf option. */ 121 + if (S_ISREG(inode->i_mode)) { 122 + inode->i_fop = &generic_ro_fops; 123 + inode->i_data.a_ops = &cramfs_aops; 124 + } else if (S_ISDIR(inode->i_mode)) { 125 + inode->i_op = &cramfs_dir_inode_operations; 126 + inode->i_fop = &cramfs_directory_operations; 127 + } else if (S_ISLNK(inode->i_mode)) { 128 + inode->i_op = &page_symlink_inode_operations; 129 + inode->i_data.a_ops = &cramfs_aops; 130 + } else { 131 + inode->i_size = 0; 132 + inode->i_blocks = 0; 133 + init_special_inode(inode, inode->i_mode, 134 + old_decode_dev(cramfs_inode->size)); 135 + } 63 136 unlock_new_inode(inode); 64 137 } 65 138 return inode; 139 + } 140 + 141 + static void cramfs_drop_inode(struct inode *inode) 142 + { 143 + if (inode->i_ino == 1) 144 + generic_delete_inode(inode); 145 + else 146 + generic_drop_inode(inode); 66 147 } 67 148 68 149 /* ··· 525 534 .put_super = cramfs_put_super, 526 535 .remount_fs = cramfs_remount, 527 536 .statfs = cramfs_statfs, 537 + .drop_inode = cramfs_drop_inode, 528 538 }; 529 539 530 540 static int cramfs_get_sb(struct file_system_type *fs_type,