Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 82d63fc9 authored by Al Viro's avatar Al Viro Committed by Linus Torvalds
Browse files

cramfs: fix named-pipe handling



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>
Cc: <stable@kernel.org>		[2.6.14 and later]
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent d847471d
Loading
Loading
Loading
Loading
+38 −46
Original line number Original line Diff line number Diff line
@@ -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)
		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)
			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 = {
	.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,