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, |