---

 fs/hpfs/dir.c   |    7 +-
 fs/hpfs/inode.c |   10 ++
 fs/hpfs/namei.c |  195 ++++++++++++++++++++++++++++++++------------------------
 fs/hpfs/super.c |   44 +++++++-----
 4 files changed, 155 insertions(+), 101 deletions(-)

diff -puN fs/hpfs/dir.c~HPFS3-hpfs_iget-RC4-rc1 fs/hpfs/dir.c
--- 25/fs/hpfs/dir.c~HPFS3-hpfs_iget-RC4-rc1	2004-02-29 12:48:31.000000000 -0800
+++ 25-akpm/fs/hpfs/dir.c	2004-02-29 12:48:31.000000000 -0800
@@ -244,11 +244,16 @@ struct dentry *hpfs_lookup(struct inode 
 	 */
 
 	hpfs_lock_iget(dir->i_sb, de->directory || (de->ea_size && hpfs_sb(dir->i_sb)->sb_eas) ? 1 : 2);
-	if (!(result = iget(dir->i_sb, ino))) {
+	result = iget_locked(dir->i_sb, ino);
+	if (!result) {
 		hpfs_unlock_iget(dir->i_sb);
 		hpfs_error(dir->i_sb, "hpfs_lookup: can't get inode");
 		goto bail1;
 	}
+	if (result->i_state & I_NEW) {
+		hpfs_read_inode(result);
+		unlock_new_inode(result);
+	}
 	hpfs_result = hpfs_i(result);
 	if (!de->directory) hpfs_result->i_parent_dir = dir->i_ino;
 	hpfs_unlock_iget(dir->i_sb);
diff -puN fs/hpfs/inode.c~HPFS3-hpfs_iget-RC4-rc1 fs/hpfs/inode.c
--- 25/fs/hpfs/inode.c~HPFS3-hpfs_iget-RC4-rc1	2004-02-29 12:48:31.000000000 -0800
+++ 25-akpm/fs/hpfs/inode.c	2004-02-29 12:48:31.000000000 -0800
@@ -242,7 +242,15 @@ void hpfs_write_inode(struct inode *i)
 	}
 	hpfs_inode->i_dirty = 0;
 	hpfs_lock_iget(i->i_sb, 1);
-	parent = iget(i->i_sb, hpfs_inode->i_parent_dir);
+	parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir);
+	if (!parent) {
+		hpfs_unlock_iget(i->i_sb);
+		return;
+	}
+	if (parent->i_state & I_NEW) {
+		hpfs_read_inode(parent);
+		unlock_new_inode(parent);
+	}
 	hpfs_unlock_iget(i->i_sb);
 	hpfs_lock_inode(parent);
 	hpfs_write_inode_nolock(i);
diff -puN fs/hpfs/namei.c~HPFS3-hpfs_iget-RC4-rc1 fs/hpfs/namei.c
--- 25/fs/hpfs/namei.c~HPFS3-hpfs_iget-RC4-rc1	2004-02-29 12:48:31.000000000 -0800
+++ 25-akpm/fs/hpfs/namei.c	2004-02-29 12:48:31.000000000 -0800
@@ -73,24 +73,32 @@ int hpfs_mkdir(struct inode *dir, struct
 	hpfs_brelse4(&qbh0);
 	dir->i_nlink++;
 	hpfs_lock_iget(dir->i_sb, 1);
-	if ((result = iget(dir->i_sb, fno))) {
-		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
-		result->i_ctime.tv_nsec = 0; 
-		result->i_mtime.tv_nsec = 0; 
-		result->i_atime.tv_nsec = 0; 
-		hpfs_i(result)->i_ea_size = 0;
-		if (dee.read_only) result->i_mode &= ~0222;
-		if (result->i_uid != current->fsuid ||
-		    result->i_gid != current->fsgid ||
-		    result->i_mode != (mode | S_IFDIR)) {
-			result->i_uid = current->fsuid;
-			result->i_gid = current->fsgid;
-			result->i_mode = mode | S_IFDIR;
-			hpfs_write_inode_nolock(result);
-		}
-		d_instantiate(dentry, result);
+
+	result = iget_locked(dir->i_sb, fno);
+	if (!result)
+		goto out;
+
+	hpfs_read_inode(result);
+	unlock_new_inode(result);
+
+	hpfs_i(result)->i_parent_dir = dir->i_ino;
+	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+	result->i_ctime.tv_nsec = 0;
+	result->i_mtime.tv_nsec = 0;
+	result->i_atime.tv_nsec = 0;
+	hpfs_i(result)->i_ea_size = 0;
+	if (dee.read_only) result->i_mode &= ~0222;
+	if (result->i_uid != current->fsuid ||
+	    result->i_gid != current->fsgid ||
+	    result->i_mode != (mode | S_IFDIR)) {
+		result->i_uid = current->fsuid;
+		result->i_gid = current->fsgid;
+		result->i_mode = mode | S_IFDIR;
+		hpfs_write_inode_nolock(result);
 	}
+	d_instantiate(dentry, result);
+
+out:
 	hpfs_unlock_iget(dir->i_sb);
 	hpfs_unlock_inode(dir);
 	unlock_kernel();
@@ -145,31 +153,38 @@ int hpfs_create(struct inode *dir, struc
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	hpfs_lock_iget(dir->i_sb, 2);
-	if ((result = iget(dir->i_sb, fno))) {
-		hpfs_decide_conv(result, (char *)name, len);
-		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
-		result->i_ctime.tv_nsec = 0;
-		result->i_mtime.tv_nsec = 0;
-		result->i_atime.tv_nsec = 0;
-		hpfs_i(result)->i_ea_size = 0;
-		if (dee.read_only) result->i_mode &= ~0222;
-		if (result->i_blocks == -1) result->i_blocks = 1;
-		if (result->i_size == -1) {
-			result->i_size = 0;
-			result->i_data.a_ops = &hpfs_aops;
-			hpfs_i(result)->mmu_private = 0;
-		}
-		if (result->i_uid != current->fsuid ||
-		    result->i_gid != current->fsgid ||
-		    result->i_mode != (mode | S_IFREG)) {
-			result->i_uid = current->fsuid;
-			result->i_gid = current->fsgid;
-			result->i_mode = mode | S_IFREG;
-			hpfs_write_inode_nolock(result);
-		}
-		d_instantiate(dentry, result);
+
+	result = iget_locked(dir->i_sb, fno);
+	if (!result)
+		goto out;
+
+	hpfs_read_inode(result);
+	unlock_new_inode(result);
+
+	hpfs_decide_conv(result, (char *)name, len);
+	hpfs_i(result)->i_parent_dir = dir->i_ino;
+	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+	result->i_ctime.tv_nsec = 0;
+	result->i_mtime.tv_nsec = 0;
+	result->i_atime.tv_nsec = 0;
+	hpfs_i(result)->i_ea_size = 0;
+	if (dee.read_only) result->i_mode &= ~0222;
+	if (result->i_blocks == -1) result->i_blocks = 1;
+	if (result->i_size == -1) {
+		result->i_size = 0;
+		result->i_data.a_ops = &hpfs_aops;
+		hpfs_i(result)->mmu_private = 0;
 	}
+	if (result->i_uid != current->fsuid ||
+	    result->i_gid != current->fsgid ||
+	    result->i_mode != (mode | S_IFREG)) {
+		result->i_uid = current->fsuid;
+		result->i_gid = current->fsgid;
+		result->i_mode = mode | S_IFREG;
+		hpfs_write_inode_nolock(result);
+	}
+	d_instantiate(dentry, result);
+out:
 	hpfs_unlock_iget(dir->i_sb);
 	hpfs_unlock_inode(dir);
 	unlock_kernel();
@@ -222,24 +237,32 @@ int hpfs_mknod(struct inode *dir, struct
 	fnode->up = dir->i_ino;
 	mark_buffer_dirty(bh);
 	hpfs_lock_iget(dir->i_sb, 2);
-	if ((result = iget(dir->i_sb, fno))) {
-		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
-		result->i_ctime.tv_nsec = 0;
-		result->i_mtime.tv_nsec = 0;
-		result->i_atime.tv_nsec = 0;
-		hpfs_i(result)->i_ea_size = 0;
-		/*if (result->i_blocks == -1) result->i_blocks = 1;
-		if (result->i_size == -1) result->i_size = 0;*/
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
-		result->i_nlink = 1;
-		result->i_size = 0;
-		result->i_blocks = 1;
-		init_special_inode(result, mode, rdev);
-		hpfs_write_inode_nolock(result);
-		d_instantiate(dentry, result);
-	}
+
+	result = iget_locked(dir->i_sb, fno);
+	if (!result)
+		goto out;
+
+	hpfs_read_inode(result);
+	unlock_new_inode(result);
+
+	hpfs_i(result)->i_parent_dir = dir->i_ino;
+	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+	result->i_ctime.tv_nsec = 0;
+	result->i_mtime.tv_nsec = 0;
+	result->i_atime.tv_nsec = 0;
+	hpfs_i(result)->i_ea_size = 0;
+	/*if (result->i_blocks == -1) result->i_blocks = 1;
+	if (result->i_size == -1) result->i_size = 0;*/
+	result->i_uid = current->fsuid;
+	result->i_gid = current->fsgid;
+	result->i_nlink = 1;
+	result->i_size = 0;
+	result->i_blocks = 1;
+	init_special_inode(result, mode, rdev);
+	hpfs_write_inode_nolock(result);
+	d_instantiate(dentry, result);
+
+out:
 	hpfs_unlock_iget(dir->i_sb);
 	hpfs_unlock_inode(dir);
 	brelse(bh);
@@ -296,30 +319,38 @@ int hpfs_symlink(struct inode *dir, stru
 	mark_buffer_dirty(bh);
 	brelse(bh);
 	hpfs_lock_iget(dir->i_sb, 2);
-	if ((result = iget(dir->i_sb, fno))) {
-		hpfs_i(result)->i_parent_dir = dir->i_ino;
-		result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
-		result->i_ctime.tv_nsec = 0;
-		result->i_mtime.tv_nsec = 0;
-		result->i_atime.tv_nsec = 0;
-		hpfs_i(result)->i_ea_size = 0;
-		/*if (result->i_blocks == -1) result->i_blocks = 1;
-		if (result->i_size == -1) result->i_size = 0;*/
-		result->i_mode = S_IFLNK | 0777;
-		result->i_uid = current->fsuid;
-		result->i_gid = current->fsgid;
-		result->i_blocks = 1;
-		result->i_size = strlen(symlink);
-		result->i_op = &page_symlink_inode_operations;
-		result->i_data.a_ops = &hpfs_symlink_aops;
-		if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
-			hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
-			mark_buffer_dirty(bh);
-			brelse(bh);
-		}
-		hpfs_write_inode_nolock(result);
-		d_instantiate(dentry, result);
+
+	result = iget_locked(dir->i_sb, fno);
+	if (!result)
+		goto out;
+
+	hpfs_read_inode(result);
+	unlock_new_inode(result);
+
+	hpfs_i(result)->i_parent_dir = dir->i_ino;
+	result->i_ctime.tv_sec = result->i_mtime.tv_sec = result->i_atime.tv_sec = local_to_gmt(dir->i_sb, dee.creation_date);
+	result->i_ctime.tv_nsec = 0;
+	result->i_mtime.tv_nsec = 0;
+	result->i_atime.tv_nsec = 0;
+	hpfs_i(result)->i_ea_size = 0;
+	/*if (result->i_blocks == -1) result->i_blocks = 1;
+	if (result->i_size == -1) result->i_size = 0;*/
+	result->i_mode = S_IFLNK | 0777;
+	result->i_uid = current->fsuid;
+	result->i_gid = current->fsgid;
+	result->i_blocks = 1;
+	result->i_size = strlen(symlink);
+	result->i_op = &page_symlink_inode_operations;
+	result->i_data.a_ops = &hpfs_symlink_aops;
+	if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
+		hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
+		mark_buffer_dirty(bh);
+		brelse(bh);
 	}
+	hpfs_write_inode_nolock(result);
+	d_instantiate(dentry, result);
+
+out:
 	hpfs_unlock_iget(dir->i_sb);
 	hpfs_unlock_inode(dir);
 	unlock_kernel();
diff -puN fs/hpfs/super.c~HPFS3-hpfs_iget-RC4-rc1 fs/hpfs/super.c
--- 25/fs/hpfs/super.c~HPFS3-hpfs_iget-RC4-rc1	2004-02-29 12:48:31.000000000 -0800
+++ 25-akpm/fs/hpfs/super.c	2004-02-29 12:48:31.000000000 -0800
@@ -448,6 +448,7 @@ static int hpfs_fill_super(struct super_
 	struct hpfs_super_block *superblock;
 	struct hpfs_spare_block *spareblock;
 	struct hpfs_sb_info *sbi;
+	struct inode *root;
 
 	uid_t uid;
 	gid_t gid;
@@ -613,10 +614,17 @@ static int hpfs_fill_super(struct super_
 	brelse(bh0);
 
 	hpfs_lock_iget(s, 1);
-	s->s_root = d_alloc_root(iget(s, sbi->sb_root));
+	root = iget_locked(s, sbi->sb_root);
+	if (!root) {
+		hpfs_unlock_iget(s);
+		goto bail0;
+	}
+	hpfs_read_inode(root);
+	unlock_new_inode(root);
 	hpfs_unlock_iget(s);
-	if (!s->s_root || !s->s_root->d_inode) {
-		printk("HPFS: iget failed. Why???\n");
+	s->s_root = d_alloc_root(root);
+	if (!s->s_root) {
+		iput(root);
 		goto bail0;
 	}
 	hpfs_set_dentry_operations(s->s_root);
@@ -627,22 +635,24 @@ static int hpfs_fill_super(struct super_
 
 	root_dno = hpfs_fnode_dno(s, sbi->sb_root);
 	if (root_dno)
-		de = map_dirent(s->s_root->d_inode, root_dno, "\001\001", 2, NULL, &qbh);
-	if (!root_dno || !de) hpfs_error(s, "unable to find root dir");
+		de = map_dirent(root, root_dno, "\001\001", 2, NULL, &qbh);
+	if (!de)
+		hpfs_error(s, "unable to find root dir");
 	else {
-		s->s_root->d_inode->i_atime.tv_sec = local_to_gmt(s, de->read_date);
-		s->s_root->d_inode->i_atime.tv_nsec = 0;
-		s->s_root->d_inode->i_mtime.tv_sec = local_to_gmt(s, de->write_date);
-		s->s_root->d_inode->i_mtime.tv_nsec = 0;
-		s->s_root->d_inode->i_ctime.tv_sec = local_to_gmt(s, de->creation_date);
-		s->s_root->d_inode->i_ctime.tv_nsec = 0;
-		hpfs_i(s->s_root->d_inode)->i_ea_size = de->ea_size;
-		hpfs_i(s->s_root->d_inode)->i_parent_dir = s->s_root->d_inode->i_ino;
-		if (s->s_root->d_inode->i_size == -1) s->s_root->d_inode->i_size = 2048;
-		if (s->s_root->d_inode->i_blocks == -1) s->s_root->d_inode->i_blocks = 5;
+		root->i_atime.tv_sec = local_to_gmt(s, de->read_date);
+		root->i_atime.tv_nsec = 0;
+		root->i_mtime.tv_sec = local_to_gmt(s, de->write_date);
+		root->i_mtime.tv_nsec = 0;
+		root->i_ctime.tv_sec = local_to_gmt(s, de->creation_date);
+		root->i_ctime.tv_nsec = 0;
+		hpfs_i(root)->i_ea_size = de->ea_size;
+		hpfs_i(root)->i_parent_dir = root->i_ino;
+		if (root->i_size == -1)
+			root->i_size = 2048;
+		if (root->i_blocks == -1)
+			root->i_blocks = 5;
+		hpfs_brelse4(&qbh);
 	}
-	if (de) hpfs_brelse4(&qbh);
-
 	return 0;
 
 bail4:	brelse(bh2);

_