diff options
| author | Al Viro <viro@ZenIV.linux.org.uk> | 2008-08-20 17:09:24 -0400 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-08-20 18:40:32 -0400 | 
| commit | 82d63fc9e30687c055b97928942b8893ea65b0bb (patch) | |
| tree | c767b9a7a41893c434e85532f3e02515433076f1 | |
| parent | d847471d063663b9f36927d265c66a270c0cfaab (diff) | |
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>
| -rw-r--r-- | fs/cramfs/inode.c | 84 | 
1 files changed, 38 insertions, 46 deletions
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 0c3b618c15b3..f40423eb1a14 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c  | |||
| @@ -43,58 +43,13 @@ static DEFINE_MUTEX(read_mutex); | |||
| 43 | static int cramfs_iget5_test(struct inode *inode, void *opaque) | 43 | static int cramfs_iget5_test(struct inode *inode, void *opaque) | 
| 44 | { | 44 | { | 
| 45 | struct cramfs_inode *cramfs_inode = opaque; | 45 | struct cramfs_inode *cramfs_inode = opaque; | 
| 46 | 46 | return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1; | |
| 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 */ | ||
| 65 | } | 47 | } | 
| 66 | 48 | ||
| 67 | static int cramfs_iget5_set(struct inode *inode, void *opaque) | 49 | static int cramfs_iget5_set(struct inode *inode, void *opaque) | 
| 68 | { | 50 | { | 
| 69 | static struct timespec zerotime; | ||
| 70 | struct cramfs_inode *cramfs_inode = opaque; | 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 | inode->i_ino = CRAMINO(cramfs_inode); | 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 | return 0; | 53 | return 0; | 
| 99 | } | 54 | } | 
| 100 | 55 | ||
| @@ -104,12 +59,48 @@ static struct inode *get_cramfs_inode(struct super_block *sb, | |||
| 104 | struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), | 59 | struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode), | 
| 105 | cramfs_iget5_test, cramfs_iget5_set, | 60 | cramfs_iget5_test, cramfs_iget5_set, | 
| 106 | cramfs_inode); | 61 | cramfs_inode); | 
| 62 | static struct timespec zerotime; | ||
| 63 | |||
| 107 | if (inode && (inode->i_state & I_NEW)) { | 64 | if (inode && (inode->i_state & I_NEW)) { | 
| 65 | inode->i_mode = cramfs_inode->mode; | ||
| 66 | inode->i_uid = cramfs_inode->uid; | ||
| 67 | inode->i_size = cramfs_inode->size; | ||
| 68 | inode->i_blocks = (cramfs_inode->size - 1) / 512 + 1; | ||
| 69 | inode->i_gid = cramfs_inode->gid; | ||
| 70 | /* Struct copy intentional */ | ||
| 71 | inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; | ||
| 72 | /* inode->i_nlink is left 1 - arguably wrong for directories, | ||
| 73 | but it's the best we can do without reading the directory | ||
| 74 | contents. 1 yields the right result in GNU find, even | ||
| 75 | without -noleaf option. */ | ||
| 76 | if (S_ISREG(inode->i_mode)) { | ||
| 77 | inode->i_fop = &generic_ro_fops; | ||
| 78 | inode->i_data.a_ops = &cramfs_aops; | ||
| 79 | } else if (S_ISDIR(inode->i_mode)) { | ||
| 80 | inode->i_op = &cramfs_dir_inode_operations; | ||
| 81 | inode->i_fop = &cramfs_directory_operations; | ||
| 82 | } else if (S_ISLNK(inode->i_mode)) { | ||
| 83 | inode->i_op = &page_symlink_inode_operations; | ||
| 84 | inode->i_data.a_ops = &cramfs_aops; | ||
| 85 | } else { | ||
| 86 | inode->i_size = 0; | ||
| 87 | inode->i_blocks = 0; | ||
| 88 | init_special_inode(inode, inode->i_mode, | ||
| 89 | old_decode_dev(cramfs_inode->size)); | ||
| 90 | } | ||
| 108 | unlock_new_inode(inode); | 91 | unlock_new_inode(inode); | 
| 109 | } | 92 | } | 
| 110 | return inode; | 93 | return inode; | 
| 111 | } | 94 | } | 
| 112 | 95 | ||
| 96 | static void cramfs_drop_inode(struct inode *inode) | ||
| 97 | { | ||
| 98 | if (inode->i_ino == 1) | ||
| 99 | generic_delete_inode(inode); | ||
| 100 | else | ||
| 101 | generic_drop_inode(inode); | ||
| 102 | } | ||
| 103 | |||
| 113 | /* | 104 | /* | 
| 114 | * We have our own block cache: don't fill up the buffer cache | 105 | * We have our own block cache: don't fill up the buffer cache | 
| 115 | * with the rom-image, because the way the filesystem is set | 106 | * with the rom-image, because the way the filesystem is set | 
| @@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = { | |||
| 534 | .put_super = cramfs_put_super, | 525 | .put_super = cramfs_put_super, | 
| 535 | .remount_fs = cramfs_remount, | 526 | .remount_fs = cramfs_remount, | 
| 536 | .statfs = cramfs_statfs, | 527 | .statfs = cramfs_statfs, | 
| 528 | .drop_inode = cramfs_drop_inode, | ||
| 537 | }; | 529 | }; | 
| 538 | 530 | ||
| 539 | static int cramfs_get_sb(struct file_system_type *fs_type, | 531 | static int cramfs_get_sb(struct file_system_type *fs_type, | 
