---

 fs/hpfs/buffer.c          |   16 ---------
 fs/hpfs/dir.c             |   77 ++++++++++++++++------------------------------
 fs/hpfs/file.c            |   11 ------
 fs/hpfs/hpfs_fn.h         |    3 -
 fs/hpfs/inode.c           |   13 ++++---
 fs/hpfs/namei.c           |   56 ++++++++++++++++-----------------
 fs/hpfs/super.c           |    3 +
 include/linux/hpfs_fs_i.h |    3 +
 8 files changed, 68 insertions(+), 114 deletions(-)

diff -puN fs/hpfs/buffer.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/buffer.c
--- 25/fs/hpfs/buffer.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/buffer.c	2004-02-29 12:48:33.000000000 -0800
@@ -26,22 +26,6 @@ void hpfs_unlock_creation(struct super_b
 	up(&hpfs_sb(s)->hpfs_creation_de);
 }
 
-void hpfs_lock_inode(struct inode *i)
-{
-	if (i) {
-		struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-		down(&hpfs_inode->i_sem);
-	}
-}
-
-void hpfs_unlock_inode(struct inode *i)
-{
-	if (i) {
-		struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
-		up(&hpfs_inode->i_sem);
-	}
-}
-
 /* Map a sector into a buffer and return pointers to it and to the buffer. */
 
 void *hpfs_map_sector(struct super_block *s, unsigned secno, struct buffer_head **bhp,
diff -puN fs/hpfs/dir.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/dir.c
--- 25/fs/hpfs/dir.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/dir.c	2004-02-29 12:48:33.000000000 -0800
@@ -35,19 +35,19 @@ loff_t hpfs_dir_lseek(struct file *filp,
 
 	/*printk("dir lseek\n");*/
 	if (new_off == 0 || new_off == 1 || new_off == 11 || new_off == 12 || new_off == 13) goto ok;
-	hpfs_lock_inode(i);
+	down(&i->i_sem);
 	pos = ((loff_t) hpfs_de_as_down_as_possible(s, hpfs_inode->i_dno) << 4) + 1;
 	while (pos != new_off) {
 		if (map_pos_dirent(i, &pos, &qbh)) hpfs_brelse4(&qbh);
 		else goto fail;
 		if (pos == 12) goto fail;
 	}
-	hpfs_unlock_inode(i);
-	ok:
+	up(&i->i_sem);
+ok:
 	unlock_kernel();
 	return filp->f_pos = new_off;
-	fail:
-	hpfs_unlock_inode(i);
+fail:
+	up(&i->i_sem);
 	/*printk("illegal lseek: %016llx\n", new_off);*/
 	unlock_kernel();
 	return -ESPIPE;
@@ -109,8 +109,6 @@ int hpfs_readdir(struct file *filp, void
 		goto out;
 	}
 	
-	hpfs_lock_inode(inode);
-	
 	while (1) {
 		again:
 		/* This won't work when cycle is longer than number of dirents
@@ -118,31 +116,22 @@ int hpfs_readdir(struct file *filp, void
 		   maybe killall -9 ls helps */
 		if (hpfs_sb(inode->i_sb)->sb_chk)
 			if (hpfs_stop_cycles(inode->i_sb, filp->f_pos, &c1, &c2, "hpfs_readdir")) {
-				hpfs_unlock_inode(inode);
 				ret = -EFSERROR;
 				goto out;
 			}
-		if (filp->f_pos == 12) {
-			hpfs_unlock_inode(inode);
+		if (filp->f_pos == 12)
 			goto out;
-		}
-		if (filp->f_pos == 3 || filp->f_pos == 4 || filp->f_pos == 5) {
+		if (filp->f_pos == 3 || filp->f_pos == 4 || filp->f_pos == 5)
 			printk("HPFS: warning: pos==%d\n",(int)filp->f_pos);
-			hpfs_unlock_inode(inode);
 			goto out;
-		}
 		if (filp->f_pos == 0) {
-			if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0) {
-				hpfs_unlock_inode(inode);
+			if (filldir(dirent, ".", 1, filp->f_pos, inode->i_ino, DT_DIR) < 0)
 				goto out;
-			}
 			filp->f_pos = 11;
 		}
 		if (filp->f_pos == 11) {
-			if (filldir(dirent, "..", 2, filp->f_pos, hpfs_inode->i_parent_dir, DT_DIR) < 0) {
-				hpfs_unlock_inode(inode);
+			if (filldir(dirent, "..", 2, filp->f_pos, hpfs_inode->i_parent_dir, DT_DIR) < 0)
 				goto out;
-			}
 			filp->f_pos = 1;
 		}
 		if (filp->f_pos == 1) {
@@ -150,35 +139,28 @@ int hpfs_readdir(struct file *filp, void
 			hpfs_add_pos(inode, &filp->f_pos);
 			filp->f_version = inode->i_version;
 		}
-			/*if (filp->f_version != inode->i_version) {
-				hpfs_unlock_inode(inode);
-				ret = -ENOENT;
-				goto out;
-			}*/	
-			old_pos = filp->f_pos;
-			if (!(de = map_pos_dirent(inode, &filp->f_pos, &qbh))) {
-				hpfs_unlock_inode(inode);
-				ret = -EIOERROR;
-				goto out;
-			}
-			if (de->first || de->last) {
-				if (hpfs_sb(inode->i_sb)->sb_chk) {
-					if (de->first && !de->last && (de->namelen != 2 || de ->name[0] != 1 || de->name[1] != 1)) hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08x", old_pos);
-					if (de->last && (de->namelen != 1 || de ->name[0] != 255)) hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08x", old_pos);
-				}
-				hpfs_brelse4(&qbh);
-				goto again;
-			}
-			tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
-			if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
-				filp->f_pos = old_pos;
-				if (tempname != (char *)de->name) kfree(tempname);
-				hpfs_brelse4(&qbh);
-				hpfs_unlock_inode(inode);
-				goto out;
+		old_pos = filp->f_pos;
+		if (!(de = map_pos_dirent(inode, &filp->f_pos, &qbh))) {
+			ret = -EIOERROR;
+			goto out;
+		}
+		if (de->first || de->last) {
+			if (hpfs_sb(inode->i_sb)->sb_chk) {
+				if (de->first && !de->last && (de->namelen != 2 || de ->name[0] != 1 || de->name[1] != 1)) hpfs_error(inode->i_sb, "hpfs_readdir: bad ^A^A entry; pos = %08x", old_pos);
+				if (de->last && (de->namelen != 1 || de ->name[0] != 255)) hpfs_error(inode->i_sb, "hpfs_readdir: bad \\377 entry; pos = %08x", old_pos);
 			}
+			hpfs_brelse4(&qbh);
+			goto again;
+		}
+		tempname = hpfs_translate_name(inode->i_sb, de->name, de->namelen, lc, de->not_8x3);
+		if (filldir(dirent, tempname, de->namelen, old_pos, de->fnode, DT_UNKNOWN) < 0) {
+			filp->f_pos = old_pos;
 			if (tempname != (char *)de->name) kfree(tempname);
 			hpfs_brelse4(&qbh);
+			goto out;
+		}
+		if (tempname != (char *)de->name) kfree(tempname);
+		hpfs_brelse4(&qbh);
 	}
 out:
 	unlock_kernel();
@@ -220,7 +202,6 @@ struct dentry *hpfs_lookup(struct inode 
 		goto end_add;
 	}
 
-	hpfs_lock_inode(dir);
 	/*
 	 * '.' and '..' will never be passed here.
 	 */
@@ -306,7 +287,6 @@ struct dentry *hpfs_lookup(struct inode 
 	 */
 
 	end:
-	hpfs_unlock_inode(dir);
 	end_add:
 	hpfs_set_dentry_operations(dentry);
 	unlock_kernel();
@@ -322,7 +302,6 @@ struct dentry *hpfs_lookup(struct inode 
 	
 	/*bail:*/
 
-	hpfs_unlock_inode(dir);
 	unlock_kernel();
 	return ERR_PTR(-ENOENT);
 }
diff -puN fs/hpfs/file.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/file.c
--- 25/fs/hpfs/file.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/file.c	2004-02-29 12:48:33.000000000 -0800
@@ -15,17 +15,6 @@
 
 #define BLOCKS(size) (((size) + 511) >> 9)
 
-/* HUH? */
-int hpfs_open(struct inode *i, struct file *f)
-{
-	lock_kernel();
-	hpfs_lock_inode(i);
-	hpfs_unlock_inode(i); /* make sure nobody is deleting the file */
-	unlock_kernel();
-	if (!i->i_nlink) return -ENOENT;
-	return 0;
-}
-
 int hpfs_file_release(struct inode *inode, struct file *file)
 {
 	lock_kernel();
diff -puN fs/hpfs/hpfs_fn.h~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/hpfs_fn.h
--- 25/fs/hpfs/hpfs_fn.h~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/hpfs_fn.h	2004-02-29 12:48:33.000000000 -0800
@@ -192,8 +192,6 @@ void hpfs_remove_fnode(struct super_bloc
 
 void hpfs_lock_creation(struct super_block *);
 void hpfs_unlock_creation(struct super_block *);
-void hpfs_lock_inode(struct inode *);
-void hpfs_unlock_inode(struct inode *);
 void *hpfs_map_sector(struct super_block *, unsigned, struct buffer_head **, int);
 void *hpfs_get_sector(struct super_block *, unsigned, struct buffer_head **);
 void *hpfs_map_4sectors(struct super_block *, unsigned, struct quad_buffer_head *, int);
@@ -238,7 +236,6 @@ void hpfs_set_ea(struct inode *, struct 
 /* file.c */
 
 int hpfs_file_release(struct inode *, struct file *);
-int hpfs_open(struct inode *, struct file *);
 int hpfs_file_fsync(struct file *, struct dentry *, int);
 secno hpfs_bmap(struct inode *, unsigned);
 void hpfs_truncate(struct inode *);
diff -puN fs/hpfs/inode.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/inode.c
--- 25/fs/hpfs/inode.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/inode.c	2004-02-29 12:48:33.000000000 -0800
@@ -18,7 +18,6 @@ static struct file_operations hpfs_file_
 	.read		= generic_file_read,
 	.write		= hpfs_file_write,
 	.mmap		= generic_file_mmap,
-	.open		= hpfs_open,
 	.release	= hpfs_file_release,
 	.fsync		= hpfs_file_fsync,
 	.sendfile	= generic_file_sendfile,
@@ -35,7 +34,6 @@ static struct file_operations hpfs_dir_o
 	.llseek		= hpfs_dir_lseek,
 	.read		= generic_read_dir,
 	.readdir	= hpfs_readdir,
-	.open		= hpfs_open,
 	.release	= hpfs_dir_release,
 	.fsync		= hpfs_file_fsync,
 };
@@ -261,13 +259,17 @@ void hpfs_write_inode(struct inode *i)
 {
 	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
 	struct inode *parent;
-	if (!i->i_nlink) return;
 	if (i->i_ino == hpfs_sb(i->i_sb)->sb_root) return;
 	if (hpfs_inode->i_rddir_off && !atomic_read(&i->i_count)) {
 		if (*hpfs_inode->i_rddir_off) printk("HPFS: write_inode: some position still there\n");
 		kfree(hpfs_inode->i_rddir_off);
 		hpfs_inode->i_rddir_off = NULL;
 	}
+	down(&hpfs_inode->i_parent);
+	if (!i->i_nlink) {
+		up(&hpfs_inode->i_parent);
+		return;
+	}
 	hpfs_inode->i_dirty = 0;
 	parent = iget_locked(i->i_sb, hpfs_inode->i_parent_dir);
 	if (parent) {
@@ -275,11 +277,12 @@ void hpfs_write_inode(struct inode *i)
 			hpfs_read_inode(parent);
 			unlock_new_inode(parent);
 		}
-		hpfs_lock_inode(parent);
+		down_read(&hpfs_i(parent)->i_sem);
 		hpfs_write_inode_nolock(i);
-		hpfs_unlock_inode(parent);
+		up_read(&hpfs_i(parent)->i_sem);
 		iput(parent);
 	}
+	up(&hpfs_inode->i_parent);
 }
 
 void hpfs_write_inode_nolock(struct inode *i)
diff -puN fs/hpfs/namei.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/namei.c
--- 25/fs/hpfs/namei.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/namei.c	2004-02-29 12:48:33.000000000 -0800
@@ -42,7 +42,7 @@ int hpfs_mkdir(struct inode *dir, struct
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	hpfs_lock_inode(dir);
+	down_write(&hpfs_i(dir)->i_sem);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1)
 		goto bail2;
@@ -98,13 +98,13 @@ int hpfs_mkdir(struct inode *dir, struct
 	d_instantiate(dentry, result);
 
 out:
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
 bail2:
 	hpfs_brelse4(&qbh0);
 	hpfs_free_dnode(dir->i_sb, dno);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
@@ -137,7 +137,7 @@ int hpfs_create(struct inode *dir, struc
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	hpfs_lock_inode(dir);
+	down_write(&hpfs_i(dir)->i_sem);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1)
 		goto bail1;
@@ -182,13 +182,13 @@ int hpfs_create(struct inode *dir, struc
 	}
 	d_instantiate(dentry, result);
 out:
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -220,7 +220,7 @@ int hpfs_mknod(struct inode *dir, struct
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	hpfs_lock_inode(dir);
+	down_write(&hpfs_i(dir)->i_sem);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1)
 		goto bail1;
@@ -258,14 +258,14 @@ int hpfs_mknod(struct inode *dir, struct
 	d_instantiate(dentry, result);
 
 out:
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 	brelse(bh);
 	unlock_kernel();
 	return 0;
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -299,7 +299,7 @@ int hpfs_symlink(struct inode *dir, stru
 	dee.hidden = name[0] == '.';
 	dee.fnode = fno;
 	dee.creation_date = dee.write_date = dee.read_date = gmt_to_local(dir->i_sb, get_seconds());
-	hpfs_lock_inode(dir);
+	down_write(&hpfs_i(dir)->i_sem);
 	r = hpfs_add_dirent(dir, (char *)name, len, &dee, 0);
 	if (r == 1)
 		goto bail1;
@@ -344,13 +344,13 @@ int hpfs_symlink(struct inode *dir, stru
 	d_instantiate(dentry, result);
 
 out:
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 	unlock_kernel();
 	return 0;
 bail1:
 	brelse(bh);
 	hpfs_free_sectors(dir->i_sb, fno, 1);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
 bail:
 	unlock_kernel();
 	return err;
@@ -372,8 +372,8 @@ int hpfs_unlink(struct inode *dir, struc
 	lock_kernel();
 	hpfs_adjust_length((char *)name, &len);
 again:
-	hpfs_lock_inode(dir);
-	hpfs_lock_inode(inode);
+	down(&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;
 	if (!de)
@@ -400,8 +400,8 @@ again:
 		if (rep++)
 			break;
 
-		hpfs_unlock_inode(inode);
-		hpfs_unlock_inode(dir);
+		up_write(&hpfs_i(dir)->i_sem);
+		up(&hpfs_i(inode)->i_parent);
 		d_drop(dentry);
 		spin_lock(&dentry->d_lock);
 		if (atomic_read(&dentry->d_count) > 1 ||
@@ -432,8 +432,8 @@ again:
 out1:
 	hpfs_brelse4(&qbh);
 out:
-	hpfs_unlock_inode(inode);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
+	up(&hpfs_i(inode)->i_parent);
 	unlock_kernel();
 	return err;
 }
@@ -453,8 +453,8 @@ int hpfs_rmdir(struct inode *dir, struct
 
 	hpfs_adjust_length((char *)name, &len);
 	lock_kernel();
-	hpfs_lock_inode(dir);
-	hpfs_lock_inode(inode);
+	down(&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);
 	if (!de)
@@ -492,8 +492,8 @@ int hpfs_rmdir(struct inode *dir, struct
 out1:
 	hpfs_brelse4(&qbh);
 out:
-	hpfs_unlock_inode(inode);
-	hpfs_unlock_inode(dir);
+	up_write(&hpfs_i(dir)->i_sem);
+	up(&hpfs_i(inode)->i_parent);
 	unlock_kernel();
 	return err;
 }
@@ -550,10 +550,10 @@ int hpfs_rename(struct inode *old_dir, s
 	hpfs_adjust_length((char *)old_name, &old_len);
 
 	lock_kernel();
-	hpfs_lock_inode(old_dir);
+	down(&hpfs_i(i)->i_parent);
+	down_write(&hpfs_i(old_dir)->i_sem);
 	if (new_dir != old_dir)
-		hpfs_lock_inode(new_dir);
-	hpfs_lock_inode(i);
+		down_write(&hpfs_i(new_dir)->i_sem);
 	
 	/* Erm? Moving over the empty non-busy directory is perfectly legal */
 	if (new_inode && S_ISDIR(new_inode->i_mode)) {
@@ -632,10 +632,10 @@ int hpfs_rename(struct inode *old_dir, s
 	hpfs_i(i)->i_conv = hpfs_sb(i->i_sb)->sb_conv;
 	hpfs_decide_conv(i, (char *)new_name, new_len);
 	end1:
-	hpfs_unlock_inode(i);
 	if (old_dir != new_dir)
-		hpfs_unlock_inode(new_dir);
-	hpfs_unlock_inode(old_dir);
+		up_write(&hpfs_i(new_dir)->i_sem);
+	up_write(&hpfs_i(old_dir)->i_sem);
+	up(&hpfs_i(i)->i_parent);
 	unlock_kernel();
 	return err;
 }
diff -puN fs/hpfs/super.c~HPFS5-hpfs_locking-RC4-rc1 fs/hpfs/super.c
--- 25/fs/hpfs/super.c~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/fs/hpfs/super.c	2004-02-29 12:48:33.000000000 -0800
@@ -183,7 +183,8 @@ static void init_once(void * foo, kmem_c
 
 	if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) ==
 	    SLAB_CTOR_CONSTRUCTOR) {
-		init_MUTEX(&ei->i_sem);
+		init_rwsem(&ei->i_sem);
+		init_MUTEX(&ei->i_parent);
 		inode_init_once(&ei->vfs_inode);
 	}
 }
diff -puN include/linux/hpfs_fs_i.h~HPFS5-hpfs_locking-RC4-rc1 include/linux/hpfs_fs_i.h
--- 25/include/linux/hpfs_fs_i.h~HPFS5-hpfs_locking-RC4-rc1	2004-02-29 12:48:33.000000000 -0800
+++ 25-akpm/include/linux/hpfs_fs_i.h	2004-02-29 12:48:33.000000000 -0800
@@ -16,7 +16,8 @@ struct hpfs_inode_info {
 	unsigned i_ea_uid : 1;	/* file's uid is stored in ea */
 	unsigned i_ea_gid : 1;	/* file's gid is stored in ea */
 	unsigned i_dirty : 1;
-	struct semaphore i_sem;	/* semaphore */
+	struct rw_semaphore i_sem;
+	struct semaphore i_parent;
 	loff_t **i_rddir_off;
 	struct inode vfs_inode;
 };

_