[PATCH] sanitize hppfs

* hppfs_iget() and its users are racy; there's no need to pollute icache
  anyway, new_inode() works fine and is safe, unlike the current kludges
  (these relied on overwriting ->i_ino before another iget_locked() gets
  to that one - and did it after unlocking).
* merge hppfs_iget()/init_inode()/hppfs_read_inode(), while we are
  at it.
* to pass proper vfsmount to dentry_open() store the reference
  in hppfs superblock.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
 --
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c
index 0c0f62f..8601d8e 100644
--- a/fs/hppfs/hppfs_kern.c
+++ b/fs/hppfs/hppfs_kern.c
@@ -18,8 +18,7 @@
 #include <asm/uaccess.h>
 #include "os.h"
 
-static int init_inode(struct inode *inode, struct dentry *dentry,
-		      struct vfsmount *mnt);
+static struct inode *get_inode(struct super_block *, struct dentry *);
 
 struct hppfs_data {
 	struct list_head list;
@@ -35,7 +34,6 @@
 
 struct hppfs_inode_info {
         struct dentry *proc_dentry;
-	struct vfsmount *proc_mnt;
 	struct inode vfs_inode;
 };
 
@@ -137,40 +135,6 @@
 	return 0;
 }
 
-static void hppfs_read_inode(struct inode *ino)
-{
-	struct inode *proc_ino;
-
-	if (HPPFS_I(ino)->proc_dentry == NULL)
-		return;
-
-	proc_ino = HPPFS_I(ino)->proc_dentry->d_inode;
-	ino->i_uid = proc_ino->i_uid;
-	ino->i_gid = proc_ino->i_gid;
-	ino->i_atime = proc_ino->i_atime;
-	ino->i_mtime = proc_ino->i_mtime;
-	ino->i_ctime = proc_ino->i_ctime;
-	ino->i_ino = proc_ino->i_ino;
-	ino->i_mode = proc_ino->i_mode;
-	ino->i_nlink = proc_ino->i_nlink;
-	ino->i_size = proc_ino->i_size;
-	ino->i_blocks = proc_ino->i_blocks;
-}
-
-static struct inode *hppfs_iget(struct super_block *sb)
-{
-	struct inode *inode;
-
-	inode = iget_locked(sb, 0);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (inode->i_state & I_NEW) {
-		hppfs_read_inode(inode);
-		unlock_new_inode(inode);
-	}
-	return inode;
-}
-
 static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
                                   struct nameidata *nd)
 {
@@ -206,23 +170,14 @@
 	if (IS_ERR(proc_dentry))
 		return proc_dentry;
 
-	inode = hppfs_iget(ino->i_sb);
-	if (IS_ERR(inode)) {
-		err = PTR_ERR(inode);
+	err = -ENOMEM;
+	inode = get_inode(ino->i_sb, proc_dentry);
+	if (!inode)
 		goto out_dput;
-	}
-
-	err = init_inode(inode, proc_dentry, HPPFS_I(ino)->proc_mnt);
-	if (err)
-		goto out_put;
-
-	hppfs_read_inode(inode);
 
  	d_add(dentry, inode);
 	return NULL;
 
- out_put:
-	iput(inode);
  out_dput:
 	dput(proc_dentry);
  out:
@@ -489,7 +444,7 @@
 		goto out_free2;
 
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
-	proc_mnt = HPPFS_I(inode)->proc_mnt;
+	proc_mnt = inode->i_sb->s_fs_info;
 
 	/* XXX This isn't closed anywhere */
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
@@ -547,7 +502,7 @@
 		goto out;
 
 	proc_dentry = HPPFS_I(inode)->proc_dentry;
-	proc_mnt = HPPFS_I(inode)->proc_mnt;
+	proc_mnt = inode->i_sb->s_fs_info;
 	data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
 				      file_mode(file->f_mode));
 	err = PTR_ERR(data->proc_file);
@@ -659,7 +614,6 @@
 		return NULL;
 
 	hi->proc_dentry = NULL;
-	hi->proc_mnt = NULL;
 	inode_init_once(&hi->vfs_inode);
 	return &hi->vfs_inode;
 }
@@ -676,7 +630,7 @@
 
 static void hppfs_put_super(struct super_block *sb)
 {
-	mntput(HPPFS_I(sb->s_root->d_inode)->proc_mnt);
+	mntput(sb->s_fs_info);
 }
 
 static const struct super_operations hppfs_sbops = {
@@ -696,7 +650,7 @@
 	int ret;
 
 	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-	proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt;
+	proc_mnt = dentry->d_sb->s_fs_info;
 
 	proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY);
 	if (IS_ERR(proc_file))
@@ -717,7 +671,7 @@
 	void *ret;
 
 	proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry;
-	proc_mnt = HPPFS_I(dentry->d_inode)->proc_mnt;
+	proc_mnt = dentry->d_sb->s_fs_info;
 
 	proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY);
 	if (IS_ERR(proc_file))
@@ -739,9 +693,14 @@
 	.follow_link	= hppfs_follow_link,
 };
 
-static int init_inode(struct inode *inode, struct dentry *dentry,
-		struct vfsmount *mnt)
+static struct inode *get_inode(struct super_block *sb, struct dentry *dentry)
 {
+	struct inode *proc_ino = dentry->d_inode;
+	struct inode *inode = new_inode(sb);
+
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
 	if (S_ISDIR(dentry->d_inode->i_mode)) {
 		inode->i_op = &hppfs_dir_iops;
 		inode->i_fop = &hppfs_dir_fops;
@@ -754,7 +713,17 @@
 	}
 
 	HPPFS_I(inode)->proc_dentry = dentry;
-	HPPFS_I(inode)->proc_mnt = mnt;
+
+	inode->i_uid = proc_ino->i_uid;
+	inode->i_gid = proc_ino->i_gid;
+	inode->i_atime = proc_ino->i_atime;
+	inode->i_mtime = proc_ino->i_mtime;
+	inode->i_ctime = proc_ino->i_ctime;
+	inode->i_ino = proc_ino->i_ino;
+	inode->i_mode = proc_ino->i_mode;
+	inode->i_nlink = proc_ino->i_nlink;
+	inode->i_size = proc_ino->i_size;
+	inode->i_blocks = proc_ino->i_blocks;
 
 	return 0;
 }
@@ -762,17 +731,10 @@
 static int hppfs_fill_super(struct super_block *sb, void *d, int silent)
 {
 	struct inode *root_inode;
-	struct file_system_type *procfs;
 	struct vfsmount *proc_mnt;
-	int err;
+	int err = -ENOENT;
 
-	err = -ENOENT;
-	procfs = get_fs_type("proc");
-	if (!procfs)
-		goto out;
-
-	proc_mnt = vfs_kern_mount(procfs, 0, procfs->name, NULL);
-	put_filesystem(procfs);
+	proc_mnt = do_kern_mount("proc", 0, "proc", NULL);
 	if (IS_ERR(proc_mnt))
 		goto out;
 
@@ -780,24 +742,17 @@
 	sb->s_blocksize_bits = 10;
 	sb->s_magic = HPPFS_SUPER_MAGIC;
 	sb->s_op = &hppfs_sbops;
-
-	root_inode = hppfs_iget(sb);
-	if (IS_ERR(root_inode)) {
-		err = PTR_ERR(root_inode);
-		goto out;
-	}
-
-	err = init_inode(root_inode, proc_mnt->mnt_sb->s_root, proc_mnt);
-	if (err)
-		goto out_iput;
+	sb->s_fs_info = proc_mnt;
 
 	err = -ENOMEM;
+	root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root);
+	if (!root_inode)
+		goto out_mntput;
+
 	sb->s_root = d_alloc_root(root_inode);
 	if (!sb->s_root)
 		goto out_iput;
 
-	hppfs_read_inode(root_inode);
-
 	return 0;
 
  out_iput: