---

 fs/hpfs/buffer.c  |    4 -
 fs/hpfs/dnode.c   |   14 +--
 fs/hpfs/ea.c      |    6 -
 fs/hpfs/hpfs_fn.h |    2 
 fs/hpfs/inode.c   |    6 -
 fs/hpfs/namei.c   |  211 ++++++++++++++++++++++++++++--------------------------
 fs/hpfs/super.c   |    2 
 7 files changed, 130 insertions(+), 115 deletions(-)

diff -puN fs/hpfs/buffer.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/buffer.c
--- 25/fs/hpfs/buffer.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/buffer.c	2004-02-29 12:49:52.000000000 -0800
@@ -70,7 +70,7 @@ void *hpfs_map_4sectors(struct super_blo
 		return 0;
 	}
 
-	qbh->data = data = (char *)kmalloc(2048, GFP_KERNEL);
+	qbh->data = data = (char *)kmalloc(2048, GFP_NOFS);
 	if (!data) {
 		printk("HPFS: hpfs_map_4sectors: out of memory\n");
 		goto bail;
@@ -122,7 +122,7 @@ void *hpfs_get_4sectors(struct super_blo
 	}
 
 	/*return hpfs_map_4sectors(s, secno, qbh, 0);*/
-	if (!(qbh->data = kmalloc(2048, GFP_KERNEL))) {
+	if (!(qbh->data = kmalloc(2048, GFP_NOFS))) {
 		printk("HPFS: hpfs_get_4sectors: out of memory\n");
 		return NULL;
 	}
diff -puN fs/hpfs/dnode.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/dnode.c
--- 25/fs/hpfs/dnode.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/dnode.c	2004-02-29 12:49:52.000000000 -0800
@@ -31,7 +31,7 @@ void hpfs_add_pos(struct inode *inode, l
 		for (; hpfs_inode->i_rddir_off[i]; i++)
 			if (hpfs_inode->i_rddir_off[i] == pos) return;
 	if (!(i&0x0f)) {
-		if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_KERNEL))) {
+		if (!(ppos = kmalloc((i+0x11) * sizeof(loff_t*), GFP_NOFS))) {
 			printk("HPFS: out of memory for position list\n");
 			return;
 		}
@@ -235,7 +235,7 @@ int hpfs_add_to_dnode(struct inode *i, d
 	struct buffer_head *bh;
 	struct fnode *fnode;
 	int c1, c2 = 0;
-	if (!(nname = kmalloc(256, GFP_KERNEL))) {
+	if (!(nname = kmalloc(256, GFP_NOFS))) {
 		printk("HPFS: out of memory, can't add to dnode\n");
 		return 1;
 	}
@@ -272,7 +272,7 @@ int hpfs_add_to_dnode(struct inode *i, d
 		kfree(nname);
 		return 0;
 	}
-	if (!nd) if (!(nd = kmalloc(0x924, GFP_KERNEL))) {
+	if (!nd) if (!(nd = kmalloc(0x924, GFP_NOFS))) {
 		/* 0x924 is a max size of dnode after adding a dirent with
 		   max name length. We alloc this only once. There must
 		   not be any error while splitting dnodes, otherwise the
@@ -477,7 +477,7 @@ static secno move_to_top(struct inode *i
 	t = get_pos(dnode, de);
 	for_all_poss(i, hpfs_pos_subst, t, 4);
 	for_all_poss(i, hpfs_pos_subst, t + 1, 5);
-	if (!(nde = kmalloc(de->length, GFP_KERNEL))) {
+	if (!(nde = kmalloc(de->length, GFP_NOFS))) {
 		hpfs_error(i->i_sb, "out of memory for dirent - directory will be corrupted");
 		hpfs_brelse4(&qbh);
 		return 0;
@@ -587,7 +587,7 @@ static void delete_empty_dnode(struct in
 		struct quad_buffer_head qbh1;
 		if (!de_next->down) goto endm;
 		ndown = de_down_pointer(de_next);
-		if (!(de_cp = kmalloc(de->length, GFP_KERNEL))) {
+		if (!(de_cp = kmalloc(de->length, GFP_NOFS))) {
 			printk("HPFS: out of memory for dtree balancing\n");
 			goto endm;
 		}
@@ -649,7 +649,7 @@ static void delete_empty_dnode(struct in
 			} else if (down)
 				*(dnode_secno *) ((void *) del + del->length - 4) = down;
 		} else goto endm;
-		if (!(de_cp = kmalloc(de_prev->length, GFP_KERNEL))) {
+		if (!(de_cp = kmalloc(de_prev->length, GFP_NOFS))) {
 			printk("HPFS: out of memory for dtree balancing\n");
 			hpfs_brelse4(&qbh1);
 			goto endm;
@@ -993,7 +993,7 @@ struct hpfs_dirent *map_fnode_dirent(str
 	int c1, c2 = 0;
 	int d1, d2 = 0;
 	name1 = f->name;
-	if (!(name2 = kmalloc(256, GFP_KERNEL))) {
+	if (!(name2 = kmalloc(256, GFP_NOFS))) {
 		printk("HPFS: out of memory, can't map dirent\n");
 		return NULL;
 	}
diff -puN fs/hpfs/ea.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/ea.c
--- 25/fs/hpfs/ea.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/ea.c	2004-02-29 12:49:52.000000000 -0800
@@ -50,7 +50,7 @@ void hpfs_ea_ext_remove(struct super_blo
 static char *get_indirect_ea(struct super_block *s, int ano, secno a, int size)
 {
 	char *ret;
-	if (!(ret = kmalloc(size + 1, GFP_KERNEL))) {
+	if (!(ret = kmalloc(size + 1, GFP_NOFS))) {
 		printk("HPFS: out of memory for EA\n");
 		return NULL;
 	}
@@ -138,7 +138,7 @@ char *hpfs_get_ea(struct super_block *s,
 		if (!strcmp(ea->name, key)) {
 			if (ea->indirect)
 				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
-			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
+			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
 				printk("HPFS: out of memory for EA\n");
 				return NULL;
 			}
@@ -164,7 +164,7 @@ char *hpfs_get_ea(struct super_block *s,
 		if (!strcmp(ea->name, key)) {
 			if (ea->indirect)
 				return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
-			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_KERNEL))) {
+			if (!(ret = kmalloc((*size = ea->valuelen) + 1, GFP_NOFS))) {
 				printk("HPFS: out of memory for EA\n");
 				return NULL;
 			}
diff -puN fs/hpfs/hpfs_fn.h~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/hpfs_fn.h
--- 25/fs/hpfs/hpfs_fn.h~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/hpfs_fn.h	2004-02-29 12:49:52.000000000 -0800
@@ -58,7 +58,7 @@ struct hpfs_inode_info {
 	unsigned i_ea_gid : 1;	/* file's gid is stored in ea */
 	unsigned i_dirty : 1;
 	struct rw_semaphore i_sem;
-	struct semaphore i_parent;
+	struct rw_semaphore i_parent;
 	loff_t **i_rddir_off;
 	struct inode vfs_inode;
 };
diff -puN fs/hpfs/inode.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/inode.c
--- 25/fs/hpfs/inode.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/inode.c	2004-02-29 12:49:52.000000000 -0800
@@ -186,9 +186,9 @@ void hpfs_write_inode(struct inode *i)
 		kfree(hpfs_inode->i_rddir_off);
 		hpfs_inode->i_rddir_off = NULL;
 	}
-	down(&hpfs_inode->i_parent);
+	down_read(&hpfs_inode->i_parent);
 	if (!i->i_nlink) {
-		up(&hpfs_inode->i_parent);
+		up_read(&hpfs_inode->i_parent);
 		return;
 	}
 	hpfs_inode->i_dirty = 0;
@@ -204,7 +204,7 @@ void hpfs_write_inode(struct inode *i)
 		up_read(&hpfs_i(parent)->i_sem);
 		iput(parent);
 	}
-	up(&hpfs_inode->i_parent);
+	up_read(&hpfs_inode->i_parent);
 }
 
 void hpfs_write_inode_nolock(struct inode *i)
diff -puN fs/hpfs/namei.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/namei.c
--- 25/fs/hpfs/namei.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/namei.c	2004-02-29 12:49:52.000000000 -0800
@@ -39,13 +39,34 @@ static int hpfs_mkdir(struct inode *dir,
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
+	result = new_inode(dir->i_sb);
+	if (!result)
+		goto bail2;
+	hpfs_init_inode(result);
+	result->i_ino = fno;
+	hpfs_i(result)->i_parent_dir = dir->i_ino;
+	hpfs_i(result)->i_dno = dno;
+	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;
+	result->i_mode |= S_IFDIR;
+	result->i_op = &hpfs_dir_iops;
+	result->i_fop = &hpfs_dir_ops;
+	result->i_blocks = 4;
+	result->i_size = 2048;
+	result->i_nlink = 2;
+	if (dee.read_only)
+		result->i_mode &= ~0222;
+
 	down_write(&hpfs_i(dir)->i_sem);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1)
-		goto bail2;
+		goto bail3;
 	if (r == -1) {
 		err = -EEXIST;
-		goto bail2;
+		goto bail3;
 	}
 	fnode->len = len;
 	memcpy(fnode->name, name, len > 15 ? 15 : len);
@@ -69,28 +90,8 @@ static int hpfs_mkdir(struct inode *dir,
 	hpfs_mark_4buffers_dirty(&qbh0);
 	hpfs_brelse4(&qbh0);
 	dir->i_nlink++;
+	insert_inode_hash(result);
 
-	result = iget_locked(dir->i_sb, fno);
-	if (!result)
-		goto out;
-
-	hpfs_init_inode(result);
-	unlock_new_inode(result);
-
-	hpfs_i(result)->i_parent_dir = dir->i_ino;
-	hpfs_i(result)->i_dno = dno;
-	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;
-	result->i_mode |= S_IFDIR;
-	result->i_op = &hpfs_dir_iops;
-	result->i_fop = &hpfs_dir_ops;
-	result->i_blocks = 4;
-	result->i_size = 2048;
-	result->i_nlink = 2;
-	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)) {
@@ -101,14 +102,16 @@ static int hpfs_mkdir(struct inode *dir,
 	}
 	d_instantiate(dentry, result);
 
-out:
 	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
+
+bail3:
+	up_write(&hpfs_i(dir)->i_sem);
+	iput(result);
 bail2:
 	hpfs_brelse4(&qbh0);
 	hpfs_free_dnode(dir->i_sb, dno);
-	up_write(&hpfs_i(dir)->i_sem);
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
@@ -141,32 +144,18 @@ static int hpfs_create(struct inode *dir
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	down_write(&hpfs_i(dir)->i_sem);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
-	if (r == 1)
-		goto bail1;
-	if (r == -1) {
-		err = -EEXIST;
-		goto bail1;
-	}
-	fnode->len = len;
-	memcpy(fnode->name, name, len > 15 ? 15 : len);
-	fnode->up = dir->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
 
-	result = iget_locked(dir->i_sb, fno);
+	result = new_inode(dir->i_sb);
 	if (!result)
-		goto out;
+		goto bail1;
 
 	hpfs_init_inode(result);
-	unlock_new_inode(result);
+	result->i_ino = fno;
 	result->i_mode |= S_IFREG;
 	result->i_mode &= ~0111;
 	result->i_op = &hpfs_file_iops;
 	result->i_fop = &hpfs_file_ops;
 	result->i_nlink = 1;
-
 	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);
@@ -174,13 +163,29 @@ static int hpfs_create(struct inode *dir
 	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 (dee.read_only)
+		result->i_mode &= ~0222;
+	result->i_blocks = 1;
+	result->i_size = 0;
+	result->i_data.a_ops = &hpfs_aops;
+	hpfs_i(result)->mmu_private = 0;
+
+	down_write(&hpfs_i(dir)->i_sem);
+	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	if (r == 1)
+		goto bail2;
+	if (r == -1) {
+		err = -EEXIST;
+		goto bail2;
 	}
+	fnode->len = len;
+	memcpy(fnode->name, name, len > 15 ? 15 : len);
+	fnode->up = dir->i_ino;
+	mark_buffer_dirty(bh);
+	brelse(bh);
+
+	insert_inode_hash(result);
+
 	if (result->i_uid != current->fsuid ||
 	    result->i_gid != current->fsgid ||
 	    result->i_mode != (mode | S_IFREG)) {
@@ -190,14 +195,16 @@ static int hpfs_create(struct inode *dir
 		hpfs_write_inode_nolock(result);
 	}
 	d_instantiate(dentry, result);
-out:
 	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
+
+bail2:
+	up_write(&hpfs_i(dir)->i_sem);
+	iput(result);
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -229,26 +236,13 @@ static int hpfs_mknod(struct inode *dir,
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	down_write(&hpfs_i(dir)->i_sem);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
-	if (r == 1)
-		goto bail1;
-	if (r == -1) {
-		err = -EEXIST;
-		goto bail1;
-	}
-	fnode->len = len;
-	memcpy(fnode->name, name, len > 15 ? 15 : len);
-	fnode->up = dir->i_ino;
-	mark_buffer_dirty(bh);
 
-	result = iget_locked(dir->i_sb, fno);
+	result = new_inode(dir->i_sb);
 	if (!result)
-		goto out;
+		goto bail1;
 
 	hpfs_init_inode(result);
-	unlock_new_inode(result);
-
+	result->i_ino = 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;
@@ -261,18 +255,35 @@ static int hpfs_mknod(struct inode *dir,
 	result->i_size = 0;
 	result->i_blocks = 1;
 	init_special_inode(result, mode, rdev);
+
+	down_write(&hpfs_i(dir)->i_sem);
+	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	if (r == 1)
+		goto bail2;
+	if (r == -1) {
+		err = -EEXIST;
+		goto bail2;
+	}
+	fnode->len = len;
+	memcpy(fnode->name, name, len > 15 ? 15 : len);
+	fnode->up = dir->i_ino;
+	mark_buffer_dirty(bh);
+
+	insert_inode_hash(result);
+
 	hpfs_write_inode_nolock(result);
 	d_instantiate(dentry, result);
-
-out:
 	up_write(&hpfs_i(dir)->i_sem);
 	brelse(bh);
 	unlock_kernel();
 	return 0;
+
+bail2:
+	up_write(&hpfs_i(dir)->i_sem);
+	iput(result);
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -304,27 +315,12 @@ static int hpfs_symlink(struct inode *di
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	down_write(&hpfs_i(dir)->i_sem);
-	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
-	if (r == 1)
-		goto bail1;
-	if (r == -1) {
-		err = -EEXIST;
-		goto bail1;
-	}
-	fnode->len = len;
-	memcpy(fnode->name, name, len > 15 ? 15 : len);
-	fnode->up = dir->i_ino;
-	mark_buffer_dirty(bh);
-	brelse(bh);
 
-	result = iget_locked(dir->i_sb, fno);
+	result = new_inode(dir->i_sb);
 	if (!result)
-		goto out;
-
+		goto bail1;
+	result->i_ino = fno;
 	hpfs_init_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;
@@ -339,6 +335,23 @@ static int hpfs_symlink(struct inode *di
 	result->i_size = strlen(symlink);
 	result->i_op = &page_symlink_inode_operations;
 	result->i_data.a_ops = &hpfs_symlink_aops;
+
+	down_write(&hpfs_i(dir)->i_sem);
+	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
+	if (r == 1)
+		goto bail2;
+	if (r == -1) {
+		err = -EEXIST;
+		goto bail2;
+	}
+	fnode->len = len;
+	memcpy(fnode->name, name, len > 15 ? 15 : len);
+	fnode->up = dir->i_ino;
+	mark_buffer_dirty(bh);
+	brelse(bh);
+
+	insert_inode_hash(result);
+
 	if ((fnode = hpfs_map_fnode(dir->i_sb, fno, &bh))) {
 		hpfs_set_ea(result, fnode, "SYMLINK", (char *)symlink, strlen(symlink));
 		mark_buffer_dirty(bh);
@@ -347,14 +360,16 @@ static int hpfs_symlink(struct inode *di
 	hpfs_write_inode_nolock(result);
 	d_instantiate(dentry, result);
 
-out:
 	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
+
+bail2:
+	up_write(&hpfs_i(dir)->i_sem);
+	iput(result);
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -376,7 +391,7 @@ static int hpfs_unlink(struct inode *dir
 	lock_kernel();
 	hpfs_adjust_length((char *)name, &len);
 again:
-	down(&hpfs_i(inode)->i_parent);
+	down_write(&hpfs_i(inode)->i_parent);
 	down_write(&hpfs_i(dir)->i_sem);
 	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
 	err = -ENOENT;
@@ -405,7 +420,7 @@ again:
 			break;
 
 		up_write(&hpfs_i(dir)->i_sem);
-		up(&hpfs_i(inode)->i_parent);
+		up_write(&hpfs_i(inode)->i_parent);
 		d_drop(dentry);
 		spin_lock(&dentry->d_lock);
 		if (atomic_read(&dentry->d_count) > 1 ||
@@ -437,7 +452,7 @@ out1:
 	hpfs_brelse4(&qbh);
 out:
 	up_write(&hpfs_i(dir)->i_sem);
-	up(&hpfs_i(inode)->i_parent);
+	up_write(&hpfs_i(inode)->i_parent);
 	unlock_kernel();
 	return err;
 }
@@ -457,7 +472,7 @@ static int hpfs_rmdir(struct inode *dir,
 
 	hpfs_adjust_length((char *)name, &len);
 	lock_kernel();
-	down(&hpfs_i(inode)->i_parent);
+	down_write(&hpfs_i(inode)->i_parent);
 	down_write(&hpfs_i(dir)->i_sem);
 	err = -ENOENT;
 	de = map_dirent(dir, hpfs_i(dir)->i_dno, (char *)name, len, &dno, &qbh);
@@ -497,7 +512,7 @@ out1:
 	hpfs_brelse4(&qbh);
 out:
 	up_write(&hpfs_i(dir)->i_sem);
-	up(&hpfs_i(inode)->i_parent);
+	up_write(&hpfs_i(inode)->i_parent);
 	unlock_kernel();
 	return err;
 }
@@ -559,9 +574,9 @@ static int hpfs_rename(struct inode *old
 
 	lock_kernel();
 	/* order doesn't matter, due to VFS exclusion */
-	down(&hpfs_i(i)->i_parent);
+	down_write(&hpfs_i(i)->i_parent);
 	if (new_inode)
-		down(&hpfs_i(new_inode)->i_parent);
+		down_write(&hpfs_i(new_inode)->i_parent);
 	down_write(&hpfs_i(old_dir)->i_sem);
 	if (new_dir != old_dir)
 		down_write(&hpfs_i(new_dir)->i_sem);
@@ -646,9 +661,9 @@ end1:
 	if (old_dir != new_dir)
 		up_write(&hpfs_i(new_dir)->i_sem);
 	up_write(&hpfs_i(old_dir)->i_sem);
-	up(&hpfs_i(i)->i_parent);
+	up_write(&hpfs_i(i)->i_parent);
 	if (new_inode)
-		up(&hpfs_i(new_inode)->i_parent);
+		up_write(&hpfs_i(new_inode)->i_parent);
 	unlock_kernel();
 	return err;
 }
diff -puN fs/hpfs/super.c~HPFS9-hpfs_deadlock-RC4-rc1 fs/hpfs/super.c
--- 25/fs/hpfs/super.c~HPFS9-hpfs_deadlock-RC4-rc1	2004-02-29 12:49:52.000000000 -0800
+++ 25-akpm/fs/hpfs/super.c	2004-02-29 12:49:52.000000000 -0800
@@ -182,7 +182,7 @@ static void init_once(void * foo, kmem_c
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
 		init_rwsem(&ei->i_sem);
-		init_MUTEX(&ei->i_parent);
+		init_rwsem(&ei->i_parent);
 		inode_init_once(&ei->vfs_inode);
 	}
 }

_