Commit 363875f5 authored by Al Viro's avatar Al Viro Committed by Greg Kroah-Hartman

cramfs: fix named-pipe handling

commit 82d63fc9 upstream

After commit a97c9bf3 (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: default avatarAtsushi Nemoto <anemo@mba.ocn.ne.jp>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent c373e9c5
...@@ -43,31 +43,25 @@ static DEFINE_MUTEX(read_mutex); ...@@ -43,31 +43,25 @@ static DEFINE_MUTEX(read_mutex);
static int cramfs_iget5_test(struct inode *inode, void *opaque) static int cramfs_iget5_test(struct inode *inode, void *opaque)
{ {
struct cramfs_inode *cramfs_inode = opaque; struct cramfs_inode *cramfs_inode = opaque;
return inode->i_ino == CRAMINO(cramfs_inode) && inode->i_ino != 1;
if (inode->i_ino != CRAMINO(cramfs_inode))
return 0; /* does not match */
if (inode->i_ino != 1)
return 1;
/* all empty directories, char, block, pipe, and sock, share inode #1 */
if ((inode->i_mode != cramfs_inode->mode) ||
(inode->i_gid != cramfs_inode->gid) ||
(inode->i_uid != cramfs_inode->uid))
return 0; /* does not match */
if ((S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) &&
(inode->i_rdev != old_decode_dev(cramfs_inode->size)))
return 0; /* does not match */
return 1; /* matches */
} }
static int cramfs_iget5_set(struct inode *inode, void *opaque) static int cramfs_iget5_set(struct inode *inode, void *opaque)
{ {
static struct timespec zerotime;
struct cramfs_inode *cramfs_inode = opaque; struct cramfs_inode *cramfs_inode = opaque;
inode->i_ino = CRAMINO(cramfs_inode);
return 0;
}
static struct inode *get_cramfs_inode(struct super_block *sb,
struct cramfs_inode * cramfs_inode)
{
struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
cramfs_iget5_test, cramfs_iget5_set,
cramfs_inode);
static struct timespec zerotime;
if (inode && (inode->i_state & I_NEW)) {
inode->i_mode = cramfs_inode->mode; inode->i_mode = cramfs_inode->mode;
inode->i_uid = cramfs_inode->uid; inode->i_uid = cramfs_inode->uid;
inode->i_size = cramfs_inode->size; inode->i_size = cramfs_inode->size;
...@@ -75,7 +69,6 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque) ...@@ -75,7 +69,6 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque)
inode->i_gid = cramfs_inode->gid; inode->i_gid = cramfs_inode->gid;
/* Struct copy intentional */ /* Struct copy intentional */
inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime; inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
inode->i_ino = CRAMINO(cramfs_inode);
/* inode->i_nlink is left 1 - arguably wrong for directories, /* inode->i_nlink is left 1 - arguably wrong for directories,
but it's the best we can do without reading the directory but it's the best we can do without reading the directory
contents. 1 yields the right result in GNU find, even contents. 1 yields the right result in GNU find, even
...@@ -95,21 +88,19 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque) ...@@ -95,21 +88,19 @@ static int cramfs_iget5_set(struct inode *inode, void *opaque)
init_special_inode(inode, inode->i_mode, init_special_inode(inode, inode->i_mode,
old_decode_dev(cramfs_inode->size)); old_decode_dev(cramfs_inode->size));
} }
return 0;
}
static struct inode *get_cramfs_inode(struct super_block *sb,
struct cramfs_inode * cramfs_inode)
{
struct inode *inode = iget5_locked(sb, CRAMINO(cramfs_inode),
cramfs_iget5_test, cramfs_iget5_set,
cramfs_inode);
if (inode && (inode->i_state & I_NEW)) {
unlock_new_inode(inode); unlock_new_inode(inode);
} }
return inode; return inode;
} }
static void cramfs_drop_inode(struct inode *inode)
{
if (inode->i_ino == 1)
generic_delete_inode(inode);
else
generic_drop_inode(inode);
}
/* /*
* We have our own block cache: don't fill up the buffer cache * We have our own block cache: don't fill up the buffer cache
* with the rom-image, because the way the filesystem is set * with the rom-image, because the way the filesystem is set
...@@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = { ...@@ -534,6 +525,7 @@ static const struct super_operations cramfs_ops = {
.put_super = cramfs_put_super, .put_super = cramfs_put_super,
.remount_fs = cramfs_remount, .remount_fs = cramfs_remount,
.statfs = cramfs_statfs, .statfs = cramfs_statfs,
.drop_inode = cramfs_drop_inode,
}; };
static int cramfs_get_sb(struct file_system_type *fs_type, static int cramfs_get_sb(struct file_system_type *fs_type,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment