Skip to content

Commit 82d63fc

Browse files
Al Virotorvalds
authored andcommitted
cramfs: fix named-pipe handling
After commit a97c9bf (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 <[email protected]> Cc: Al Viro <[email protected]> Cc: <[email protected]> [2.6.14 and later] Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent d847471 commit 82d63fc

File tree

1 file changed

+38
-46
lines changed

1 file changed

+38
-46
lines changed

fs/cramfs/inode.c

Lines changed: 38 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -43,58 +43,13 @@ static DEFINE_MUTEX(read_mutex);
4343
static int cramfs_iget5_test(struct inode *inode, void *opaque)
4444
{
4545
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;
6547
}
6648

6749
static int cramfs_iget5_set(struct inode *inode, void *opaque)
6850
{
69-
static struct timespec zerotime;
7051
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;
7852
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-
}
9853
return 0;
9954
}
10055

@@ -104,12 +59,48 @@ static struct inode *get_cramfs_inode(struct super_block *sb,
10459
struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
10560
cramfs_iget5_test, cramfs_iget5_set,
10661
cramfs_inode);
62+
static struct timespec zerotime;
63+
10764
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+
}
10891
unlock_new_inode(inode);
10992
}
11093
return inode;
11194
}
11295

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+
113104
/*
114105
* We have our own block cache: don't fill up the buffer cache
115106
* with the rom-image, because the way the filesystem is set
@@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = {
534525
.put_super = cramfs_put_super,
535526
.remount_fs = cramfs_remount,
536527
.statfs = cramfs_statfs,
528+
.drop_inode = cramfs_drop_inode,
537529
};
538530

539531
static int cramfs_get_sb(struct file_system_type *fs_type,

0 commit comments

Comments
 (0)