linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] 2.5.16 iget_locked [1/6]
@ 2002-05-20 13:00 Jan Harkes
  2002-05-20 13:04 ` [PATCH] 2.5.16 iget_locked [2/6] Jan Harkes
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:00 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel

Pulled the iget_locked patch series up to 2.5.16.

Merged Al Viro's earlier comments, no other changes. Tested compilation
after every patch and I'm currently running the final result (so I guess
it works).

iget_locked [1/6]

Fix a race in iget4. The fs specific data that is used to find an inode
should be initialized while still holding the inode lock.

It adds a 'set' callback function that should be a non-blocking FS
provided function which initializes the private parts of the inode so
that the 'test' callback function can correctly match new inodes.

Touches all filesystems that use iget4 (Coda/NFS/ReiserFS).


diff -urN orig/fs/coda/cnode.c iget_locked-1/fs/coda/cnode.c
--- orig/fs/coda/cnode.c	Wed Apr 24 21:39:46 2002
+++ iget_locked-1/fs/coda/cnode.c	Sun May 19 17:55:27 2002
@@ -25,11 +25,6 @@
 	return 1;
 }
 
-static int coda_inocmp(struct inode *inode, unsigned long ino, void *opaque)
-{
-	return (coda_fideq((ViceFid *)opaque, &(ITOC(inode)->c_fid)));
-}
-
 static struct inode_operations coda_symlink_inode_operations = {
 	readlink:	page_readlink,
 	follow_link:	page_follow_link,
@@ -55,27 +50,35 @@
                 init_special_inode(inode, inode->i_mode, attr->va_rdev);
 }
 
+static int coda_test_inode(struct inode *inode, void *data)
+{
+	ViceFid *fid = (ViceFid *)data;
+	return coda_fideq(&(ITOC(inode)->c_fid), fid);
+}
+
+static int coda_set_inode(struct inode *inode, void *data)
+{
+	ViceFid *fid = (ViceFid *)data;
+	ITOC(inode)->c_fid = *fid;
+	return 0;
+}
+
+static int coda_fail_inode(struct inode *inode, void *data)
+{
+	return -1;
+}
+
 struct inode * coda_iget(struct super_block * sb, ViceFid * fid,
 			 struct coda_vattr * attr)
 {
 	struct inode *inode;
-	struct coda_inode_info *cii;
 	ino_t ino = coda_f2i(fid);
 
-	inode = iget4(sb, ino, coda_inocmp, fid);
+	inode = iget4(sb, ino, coda_test_inode, coda_set_inode, fid);
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
-	/* check if the inode is already initialized */
-	cii = ITOC(inode);
-	if (coda_isnullfid(&cii->c_fid))
-		/* new, empty inode found... initializing */
-		cii->c_fid = *fid;
-
-	/* we shouldnt see inode collisions anymore */
-	if (!coda_fideq(fid, &cii->c_fid)) BUG();
-
 	/* always replace the attributes, type might have changed */
 	coda_fill_inode(inode, attr);
 	return inode;
@@ -131,7 +134,6 @@
 {
 	ino_t nr;
 	struct inode *inode;
-	struct coda_inode_info *cii;
 
 	if ( !sb ) {
 		printk("coda_fid_to_inode: no sb!\n");
@@ -139,43 +141,29 @@
 	}
 
 	nr = coda_f2i(fid);
-	inode = iget4(sb, nr, coda_inocmp, fid);
+	inode = iget4(sb, nr, coda_test_inode, coda_fail_inode, fid);
 	if ( !inode ) {
 		printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
 		       sb, (long)nr);
 		return NULL;
 	}
 
-	cii = ITOC(inode);
-
-	/* The inode could already be purged due to memory pressure */
-	if (coda_isnullfid(&cii->c_fid)) {
-		inode->i_nlink = 0;
-		iput(inode);
-		return NULL;
-	}
-
-	/* we shouldn't see inode collisions anymore */
-	if ( !coda_fideq(fid, &cii->c_fid) ) BUG();
-
-        return inode;
+	return inode;
 }
 
 /* the CONTROL inode is made without asking attributes from Venus */
 int coda_cnode_makectl(struct inode **inode, struct super_block *sb)
 {
-    int error = 0;
+	int error = -ENOMEM;
+
+	*inode = iget(sb, CTL_INO);
+	if ( *inode ) {
+		(*inode)->i_op = &coda_ioctl_inode_operations;
+		(*inode)->i_fop = &coda_ioctl_operations;
+		(*inode)->i_mode = 0444;
+		error = 0;
+	}
 
-    *inode = iget(sb, CTL_INO);
-    if ( *inode ) {
-	(*inode)->i_op = &coda_ioctl_inode_operations;
-	(*inode)->i_fop = &coda_ioctl_operations;
-	(*inode)->i_mode = 0444;
-	error = 0;
-    } else { 
-	error = -ENOMEM;
-    }
-    
-    return error;
+	return error;
 }
 
diff -urN orig/fs/inode.c iget_locked-1/fs/inode.c
--- orig/fs/inode.c	Wed May  1 00:27:35 2002
+++ iget_locked-1/fs/inode.c	Sun May 19 18:00:59 2002
@@ -452,7 +452,7 @@
  * by hand after calling find_inode now! This simplifies iunique and won't
  * add any additional branch in the common code.
  */
-static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
+static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), void *data)
 {
 	struct list_head *tmp;
 	struct inode * inode;
@@ -468,7 +468,7 @@
 			continue;
 		if (inode->i_sb != sb)
 			continue;
-		if (find_actor && !find_actor(inode, ino, opaque))
+		if (test && !test(inode, data))
 			continue;
 		break;
 	}
@@ -507,9 +507,10 @@
  * We no longer cache the sb_flags in i_flags - see fs.h
  *	-- rmk@arm.uk.linux.org
  */
-static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, find_inode_t find_actor, void *opaque)
+static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
 	struct inode * inode;
+	int err = 0;
 
 	inode = alloc_inode(sb);
 	if (inode) {
@@ -517,12 +518,15 @@
 
 		spin_lock(&inode_lock);
 		/* We released the lock, so.. */
-		old = find_inode(sb, ino, head, find_actor, opaque);
+		old = find_inode(sb, ino, head, test, data);
 		if (!old) {
+			inode->i_ino = ino;
+			if (set && set(inode, data))
+				goto set_failed;
+
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
 			list_add(&inode->i_hash, head);
-			inode->i_ino = ino;
 			inode->i_state = I_LOCK;
 			spin_unlock(&inode_lock);
 
@@ -532,7 +536,7 @@
 			** -- mason@suse.com 
 			*/
 			if (sb->s_op->read_inode2) {
-				sb->s_op->read_inode2(inode, opaque) ;
+				sb->s_op->read_inode2(inode, data) ;
 			} else {
 				sb->s_op->read_inode(inode);
 			}
@@ -563,6 +567,11 @@
 		wait_on_inode(inode);
 	}
 	return inode;
+
+set_failed:
+	spin_unlock(&inode_lock);
+	destroy_inode(inode);
+	return NULL;
 }
 
 static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
@@ -628,13 +637,13 @@
 }
 
 
-struct inode *iget4(struct super_block *sb, unsigned long ino, find_inode_t find_actor, void *opaque)
+struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
 	struct list_head * head = inode_hashtable + hash(sb,ino);
 	struct inode * inode;
 
 	spin_lock(&inode_lock);
-	inode = find_inode(sb, ino, head, find_actor, opaque);
+	inode = find_inode(sb, ino, head, test, data);
 	if (inode) {
 		__iget(inode);
 		spin_unlock(&inode_lock);
@@ -647,7 +656,7 @@
 	 * get_new_inode() will do the right thing, re-trying the search
 	 * in case it had to block at any point.
 	 */
-	return get_new_inode(sb, ino, head, find_actor, opaque);
+	return get_new_inode(sb, ino, head, test, set, data);
 }
 
 /**
diff -urN orig/fs/nfs/inode.c iget_locked-1/fs/nfs/inode.c
--- orig/fs/nfs/inode.c	Wed May  1 00:27:35 2002
+++ iget_locked-1/fs/nfs/inode.c	Sun May 19 17:55:27 2002
@@ -592,7 +592,7 @@
  * i_ino.
  */
 static int
-nfs_find_actor(struct inode *inode, unsigned long ino, void *opaque)
+nfs_find_actor(struct inode *inode, void *opaque)
 {
 	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;
 	struct nfs_fh		*fh = desc->fh;
@@ -610,6 +610,18 @@
 	return 1;
 }
 
+static int
+nfs_init_locked(struct inode *inode, void *opaque)
+{
+	struct nfs_find_desc	*desc = (struct nfs_find_desc *)opaque;
+	struct nfs_fh		*fh = desc->fh;
+	struct nfs_fattr	*fattr = desc->fattr;
+
+	NFS_FILEID(inode) = fattr->fileid;
+	memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
+	return 0;
+}
+
 /*
  * This is our own version of iget that looks up inodes by file handle
  * instead of inode number.  We use this technique instead of using
@@ -652,7 +664,7 @@
 
 	ino = nfs_fattr_to_ino_t(fattr);
 
-	if (!(inode = iget4(sb, ino, nfs_find_actor, &desc)))
+	if (!(inode = iget4(sb, ino, nfs_find_actor, nfs_init_locked, &desc)))
 		goto out_no_inode;
 
 	if (NFS_NEW(inode)) {
@@ -662,8 +674,6 @@
 
 		/* We can't support UPDATE_ATIME(), since the server will reset it */
 		NFS_FLAGS(inode) &= ~NFS_INO_NEW;
-		NFS_FILEID(inode) = fattr->fileid;
-		memcpy(NFS_FH(inode), fh, sizeof(struct nfs_fh));
 		inode->i_flags |= S_NOATIME;
 		inode->i_mode = fattr->mode;
 		/* Why so? Because we want revalidate for devices/FIFOs, and
diff -urN orig/fs/reiserfs/inode.c iget_locked-1/fs/reiserfs/inode.c
--- orig/fs/reiserfs/inode.c	Fri May 10 10:30:07 2002
+++ iget_locked-1/fs/reiserfs/inode.c	Sun May 19 17:55:27 2002
@@ -1138,6 +1138,13 @@
 // evolved as the prototype did
 //
 
+int reiserfs_init_locked_inode (struct inode * inode, void *p)
+{
+    struct reiserfs_iget4_args *args = (struct reiserfs_iget4_args *)p ;
+    INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->objectid);
+    return 0;
+}
+
 /* looks for stat data in the tree, and fills up the fields of in-core
    inode stat data fields */
 void reiserfs_read_inode2 (struct inode * inode, void *p)
@@ -1213,7 +1220,6 @@
  * reiserfs_find_actor() - "find actor" reiserfs supplies to iget4().
  *
  * @inode:    inode from hash table to check
- * @inode_no: inode number we are looking for
  * @opaque:   "cookie" passed to iget4(). This is &reiserfs_iget4_args.
  *
  * This function is called by iget4() to distinguish reiserfs inodes
@@ -1222,8 +1228,7 @@
  * inode numbers (objectids) are distinguished by parent directory ids.
  *
  */
-static int reiserfs_find_actor( struct inode *inode, 
-				unsigned long inode_no, void *opaque )
+int reiserfs_find_actor( struct inode *inode, void *opaque )
 {
     struct reiserfs_iget4_args *args;
 
@@ -1239,7 +1244,7 @@
 
     args.objectid = key->on_disk_key.k_dir_id ;
     inode = iget4 (s, key->on_disk_key.k_objectid, 
-		   reiserfs_find_actor, (void *)(&args));
+		   reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!inode) 
 	return ERR_PTR(-ENOMEM) ;
 
diff -urN orig/fs/reiserfs/super.c iget_locked-1/fs/reiserfs/super.c
--- orig/fs/reiserfs/super.c	Fri May 10 10:30:07 2002
+++ iget_locked-1/fs/reiserfs/super.c	Sun May 19 17:55:27 2002
@@ -1070,7 +1070,7 @@
 	s->s_flags |= MS_RDONLY ;
     }
     args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
-    root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, 0, (void *)(&args));
+    root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!root_inode) {
 	printk ("reiserfs_fill_super: get root inode failed\n");
 	goto error;
diff -urN orig/include/linux/fs.h iget_locked-1/include/linux/fs.h
--- orig/include/linux/fs.h	Sun May 19 17:52:58 2002
+++ iget_locked-1/include/linux/fs.h	Sun May 19 17:55:27 2002
@@ -1207,11 +1207,10 @@
 extern struct inode * igrab(struct inode *);
 extern ino_t iunique(struct super_block *, ino_t);
 
-typedef int (*find_inode_t)(struct inode *, unsigned long, void *);
-extern struct inode * iget4(struct super_block *, unsigned long, find_inode_t, void *);
+extern struct inode * iget4(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
 static inline struct inode *iget(struct super_block *sb, unsigned long ino)
 {
-	return iget4(sb, ino, NULL, NULL);
+	return iget4(sb, ino, NULL, NULL, NULL);
 }
 
 extern void __iget(struct inode * inode);
diff -urN orig/include/linux/reiserfs_fs.h iget_locked-1/include/linux/reiserfs_fs.h
--- orig/include/linux/reiserfs_fs.h	Fri May 10 10:30:08 2002
+++ iget_locked-1/include/linux/reiserfs_fs.h	Sun May 19 17:55:27 2002
@@ -1820,6 +1820,8 @@
 
 void reiserfs_read_inode (struct inode * inode) ;
 void reiserfs_read_inode2(struct inode * inode, void *p) ;
+int reiserfs_find_actor(struct inode * inode, void *p) ;
+int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
 void reiserfs_delete_inode (struct inode * inode);
 void reiserfs_write_inode (struct inode * inode, int) ;
 struct dentry *reiserfs_get_dentry(struct super_block *, void *) ;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] 2.5.16 iget_locked [2/6]
  2002-05-20 13:00 [PATCH] 2.5.16 iget_locked [1/6] Jan Harkes
@ 2002-05-20 13:04 ` Jan Harkes
  2002-05-20 13:05   ` [PATCH] 2.5.16 iget_locked [3/6] Jan Harkes
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:04 UTC (permalink / raw)
  To: torvalds, linux-kernel


Now we introduce iget_locked and iget5_locked. These are similar to
iget, but return a locked inode and read_inode has not been called. So
the FS has to call read_inode to initialize the inode and then unlock
it with unlock_new_inode().

This patch is based on the icreate patch from the XFS group, i.e.
it is pretty much identical except for function naming.


diff -urN iget_locked-1/fs/Makefile iget_locked-2/fs/Makefile
--- iget_locked-1/fs/Makefile	Wed May  1 00:27:34 2002
+++ iget_locked-2/fs/Makefile	Sun May 19 18:02:05 2002
@@ -7,7 +7,7 @@
 
 O_TARGET := fs.o
 
-export-objs :=	filesystems.o open.o dcache.o buffer.o bio.o
+export-objs :=	filesystems.o open.o dcache.o buffer.o bio.o inode.o
 mod-subdirs :=	nls
 
 obj-y :=	open.o read_write.o devices.o file_table.o buffer.o \
diff -urN iget_locked-1/fs/inode.c iget_locked-2/fs/inode.c
--- iget_locked-1/fs/inode.c	Sun May 19 18:00:59 2002
+++ iget_locked-2/fs/inode.c	Sun May 19 18:02:54 2002
@@ -12,6 +12,7 @@
 #include <linux/quotaops.h>
 #include <linux/slab.h>
 #include <linux/writeback.h>
+#include <linux/module.h>
 
 /*
  * New inode.c implementation.
@@ -501,6 +502,21 @@
 	return inode;
 }
 
+void unlock_new_inode(struct inode *inode)
+{
+	/*
+	 * This is special!  We do not need the spinlock
+	 * when clearing I_LOCK, because we're guaranteed
+	 * that nobody else tries to do anything about the
+	 * state of the inode when it is locked, as we
+	 * just created it (so there can be no old holders
+	 * that haven't tested I_LOCK).
+	 */
+	inode->i_state &= ~(I_LOCK|I_NEW);
+	wake_up(&inode->i_wait);
+}
+
+
 /*
  * This is called without the inode lock held.. Be careful.
  *
@@ -527,31 +543,12 @@
 			inodes_stat.nr_inodes++;
 			list_add(&inode->i_list, &inode_in_use);
 			list_add(&inode->i_hash, head);
-			inode->i_state = I_LOCK;
+			inode->i_state = I_LOCK|I_NEW;
 			spin_unlock(&inode_lock);
 
-			/* reiserfs specific hack right here.  We don't
-			** want this to last, and are looking for VFS changes
-			** that will allow us to get rid of it.
-			** -- mason@suse.com 
-			*/
-			if (sb->s_op->read_inode2) {
-				sb->s_op->read_inode2(inode, data) ;
-			} else {
-				sb->s_op->read_inode(inode);
-			}
-
-			/*
-			 * This is special!  We do not need the spinlock
-			 * when clearing I_LOCK, because we're guaranteed
-			 * that nobody else tries to do anything about the
-			 * state of the inode when it is locked, as we
-			 * just created it (so there can be no old holders
-			 * that haven't tested I_LOCK).
+			/* Return the locked inode with I_NEW set, the
+			 * caller is responsible for filling in the contents
 			 */
-			inode->i_state &= ~I_LOCK;
-			wake_up(&inode->i_wait);
-
 			return inode;
 		}
 
@@ -636,8 +633,12 @@
 	return inode;
 }
 
-
-struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+/*
+ * This is iget without the read_inode portion of get_new_inode
+ * the filesystem gets back a new locked and hashed inode and gets
+ * to fill it in before unlocking it via unlock_new_inode().
+ */
+struct inode *iget5_locked(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
 	struct list_head * head = inode_hashtable + hash(sb,ino);
 	struct inode * inode;
@@ -657,6 +658,36 @@
 	 * in case it had to block at any point.
 	 */
 	return get_new_inode(sb, ino, head, test, set, data);
+}
+
+struct inode *iget_locked(struct super_block *sb, unsigned long ino)
+{
+	return iget5_locked(sb, ino, NULL, NULL, NULL);
+}
+
+EXPORT_SYMBOL(iget5_locked);
+EXPORT_SYMBOL(iget_locked);
+EXPORT_SYMBOL(unlock_new_inode);
+
+struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+{
+	struct inode *inode = iget5_locked(sb, ino, test, set, data);
+
+	if (inode && (inode->i_state & I_NEW)) {
+		/* reiserfs specific hack right here.  We don't
+		** want this to last, and are looking for VFS changes
+		** that will allow us to get rid of it.
+		** -- mason@suse.com 
+		*/
+		if (sb->s_op->read_inode2) {
+			sb->s_op->read_inode2(inode, data);
+		} else {
+			sb->s_op->read_inode(inode);
+		}
+		unlock_new_inode(inode);
+	}
+
+	return inode;
 }
 
 /**
diff -urN iget_locked-1/include/linux/fs.h iget_locked-2/include/linux/fs.h
--- iget_locked-1/include/linux/fs.h	Sun May 19 17:55:27 2002
+++ iget_locked-2/include/linux/fs.h	Sun May 19 18:02:05 2002
@@ -799,6 +799,7 @@
 #define I_LOCK			8
 #define I_FREEING		16
 #define I_CLEAR			32
+#define I_NEW			64
 
 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
 
@@ -1206,6 +1207,10 @@
 extern void force_delete(struct inode *);
 extern struct inode * igrab(struct inode *);
 extern ino_t iunique(struct super_block *, ino_t);
+
+extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
+extern struct inode * iget_locked(struct super_block *, unsigned long);
+extern void unlock_new_inode(struct inode *);
 
 extern struct inode * iget4(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
 static inline struct inode *iget(struct super_block *sb, unsigned long ino)

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] 2.5.16 iget_locked [3/6]
  2002-05-20 13:04 ` [PATCH] 2.5.16 iget_locked [2/6] Jan Harkes
@ 2002-05-20 13:05   ` Jan Harkes
  2002-05-20 13:09     ` [PATCH] 2.5.16 iget_locked [4/6] Jan Harkes
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:05 UTC (permalink / raw)
  To: torvalds, linux-kernel


Convert existing filesystems (Coda/NFS/ReiserFS) that currently use
iget4 to iget5_locked.


diff -urN iget_locked-2/fs/coda/cnode.c iget_locked-3/fs/coda/cnode.c
--- iget_locked-2/fs/coda/cnode.c	Sun May 19 17:55:27 2002
+++ iget_locked-3/fs/coda/cnode.c	Sun May 19 18:07:01 2002
@@ -72,13 +72,21 @@
 			 struct coda_vattr * attr)
 {
 	struct inode *inode;
+	struct coda_inode_info *cii;
+	struct coda_sb_info *sbi = coda_sbp(sb);
 	ino_t ino = coda_f2i(fid);
 
-	inode = iget4(sb, ino, coda_test_inode, coda_set_inode, fid);
+	inode = iget5_locked(sb, ino, coda_test_inode, coda_set_inode, fid);
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
+	if (inode->i_state & I_NEW) {
+		cii = ITOC(inode);
+		list_add(&cii->c_cilist, &sbi->sbi_cihead);
+		unlock_new_inode(inode);
+	}
+
 	/* always replace the attributes, type might have changed */
 	coda_fill_inode(inode, attr);
 	return inode;
@@ -141,12 +149,13 @@
 	}
 
 	nr = coda_f2i(fid);
-	inode = iget4(sb, nr, coda_test_inode, coda_fail_inode, fid);
-	if ( !inode ) {
-		printk("coda_fid_to_inode: null from iget, sb %p, nr %ld.\n",
-		       sb, (long)nr);
+	inode = iget5_locked(sb, nr, coda_test_inode, coda_fail_inode, fid);
+	if ( !inode )
 		return NULL;
-	}
+
+	/* we should never see newly created inodes because we intentionally
+	 * fail in the initialization callback */
+	BUG_ON(inode->i_state & I_NEW);
 
 	return inode;
 }
@@ -156,8 +165,9 @@
 {
 	int error = -ENOMEM;
 
-	*inode = iget(sb, CTL_INO);
-	if ( *inode ) {
+	*inode = new_inode(sb);
+	if (*inode) {
+		(*inode)->i_ino = CTL_INO;
 		(*inode)->i_op = &coda_ioctl_inode_operations;
 		(*inode)->i_fop = &coda_ioctl_operations;
 		(*inode)->i_mode = 0444;
diff -urN iget_locked-2/fs/coda/inode.c iget_locked-3/fs/coda/inode.c
--- iget_locked-2/fs/coda/inode.c	Wed Apr 24 21:39:46 2002
+++ iget_locked-3/fs/coda/inode.c	Sun May 19 18:08:40 2002
@@ -33,7 +33,6 @@
 #include <linux/coda_cache.h>
 
 /* VFS super_block ops */
-static void coda_read_inode(struct inode *);
 static void coda_clear_inode(struct inode *);
 static void coda_put_super(struct super_block *);
 static int coda_statfs(struct super_block *sb, struct statfs *buf);
@@ -92,7 +91,6 @@
 {
 	alloc_inode:	coda_alloc_inode,
 	destroy_inode:	coda_destroy_inode,
-	read_inode:	coda_read_inode,
 	clear_inode:	coda_clear_inode,
 	put_super:	coda_put_super,
 	statfs:		coda_statfs,
@@ -227,18 +225,6 @@
 
 	printk("Coda: Bye bye.\n");
 	kfree(sbi);
-}
-
-/* all filling in of inodes postponed until lookup */
-static void coda_read_inode(struct inode *inode)
-{
-	struct coda_sb_info *sbi = coda_sbp(inode->i_sb);
-	struct coda_inode_info *cii;
-
-        if (!sbi) BUG();
-
-	cii = ITOC(inode);
-	list_add(&cii->c_cilist, &sbi->sbi_cihead);
 }
 
 static void coda_clear_inode(struct inode *inode)
diff -urN iget_locked-2/fs/nfs/inode.c iget_locked-3/fs/nfs/inode.c
--- iget_locked-2/fs/nfs/inode.c	Sun May 19 17:55:27 2002
+++ iget_locked-3/fs/nfs/inode.c	Sun May 19 18:09:14 2002
@@ -47,7 +47,6 @@
 
 static struct inode *nfs_alloc_inode(struct super_block *sb);
 static void nfs_destroy_inode(struct inode *);
-static void nfs_read_inode(struct inode *);
 static void nfs_write_inode(struct inode *,int);
 static void nfs_delete_inode(struct inode *);
 static void nfs_put_super(struct super_block *);
@@ -59,7 +58,6 @@
 static struct super_operations nfs_sops = { 
 	alloc_inode:	nfs_alloc_inode,
 	destroy_inode:	nfs_destroy_inode,
-	read_inode:	nfs_read_inode,
 	write_inode:	nfs_write_inode,
 	delete_inode:	nfs_delete_inode,
 	put_super:	nfs_put_super,
@@ -98,15 +96,6 @@
 	return nfs_fileid_to_ino_t(fattr->fileid);
 }
 
-/*
- * The "read_inode" function doesn't actually do anything:
- * the real data is filled in later in nfs_fhget.
- */
-static void
-nfs_read_inode(struct inode * inode)
-{
-}
-
 static void
 nfs_write_inode(struct inode *inode, int sync)
 {
@@ -664,16 +653,15 @@
 
 	ino = nfs_fattr_to_ino_t(fattr);
 
-	if (!(inode = iget4(sb, ino, nfs_find_actor, nfs_init_locked, &desc)))
+	if (!(inode = iget5_locked(sb, ino, nfs_find_actor, nfs_init_locked, &desc)))
 		goto out_no_inode;
 
-	if (NFS_NEW(inode)) {
+	if (inode->i_state & I_NEW) {
 		__u64		new_size, new_mtime;
 		loff_t		new_isize;
 		time_t		new_atime;
 
 		/* We can't support UPDATE_ATIME(), since the server will reset it */
-		NFS_FLAGS(inode) &= ~NFS_INO_NEW;
 		inode->i_flags |= S_NOATIME;
 		inode->i_mode = fattr->mode;
 		/* Why so? Because we want revalidate for devices/FIFOs, and
@@ -721,6 +709,8 @@
 		NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode);
 		NFS_ATTRTIMEO_UPDATE(inode) = jiffies;
 		memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+
+		unlock_new_inode(inode);
 	} else
 		nfs_refresh_inode(inode, fattr);
 	dprintk("NFS: __nfs_fhget(%s/%Ld ct=%d)\n",
@@ -1241,7 +1231,7 @@
 	nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL);
 	if (!nfsi)
 		return NULL;
-	nfsi->flags = NFS_INO_NEW;
+	nfsi->flags = 0;
 	nfsi->mm_cred = NULL;
 	return &nfsi->vfs_inode;
 }
diff -urN iget_locked-2/fs/reiserfs/inode.c iget_locked-3/fs/reiserfs/inode.c
--- iget_locked-2/fs/reiserfs/inode.c	Sun May 19 17:55:27 2002
+++ iget_locked-3/fs/reiserfs/inode.c	Sun May 19 18:10:06 2002
@@ -33,7 +33,7 @@
     lock_kernel() ; 
 
     /* The = 0 happens when we abort creating a new inode for some reason like lack of space.. */
-    if (INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
+    if (!(inode->i_state & I_NEW) && INODE_PKEY(inode)->k_objectid != 0) { /* also handles bad_inode case */
 	down (&inode->i_sem); 
 
 	journal_begin(&th, inode->i_sb, jbegin_count) ;
@@ -886,7 +886,7 @@
 // item version directly
 //
 
-// called by read_inode
+// called by read_locked_inode
 static void init_inode (struct inode * inode, struct path * path)
 {
     struct buffer_head * bh;
@@ -1117,7 +1117,7 @@
     return;
 }
 
-/* reiserfs_read_inode2 is called to read the inode off disk, and it
+/* reiserfs_read_locked_inode is called to read the inode off disk, and it
 ** does a make_bad_inode when things go wrong.  But, we need to make sure
 ** and clear the key in the private portion of the inode, otherwise a
 ** corresponding iput might try to delete whatever object the inode last
@@ -1128,11 +1128,6 @@
     make_bad_inode(inode);
 }
 
-void reiserfs_read_inode(struct inode *inode) {
-    reiserfs_make_bad_inode(inode) ;
-}
-
-
 //
 // initially this function was derived from minix or ext2's analog and
 // evolved as the prototype did
@@ -1140,26 +1135,20 @@
 
 int reiserfs_init_locked_inode (struct inode * inode, void *p)
 {
-    struct reiserfs_iget4_args *args = (struct reiserfs_iget4_args *)p ;
+    struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p ;
     INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->objectid);
     return 0;
 }
 
 /* looks for stat data in the tree, and fills up the fields of in-core
    inode stat data fields */
-void reiserfs_read_inode2 (struct inode * inode, void *p)
+void reiserfs_read_locked_inode (struct inode * inode, struct reiserfs_iget_args *args)
 {
     INITIALIZE_PATH (path_to_sd);
     struct cpu_key key;
-    struct reiserfs_iget4_args *args = (struct reiserfs_iget4_args *)p ;
     unsigned long dirino;
     int retval;
 
-    if (!p) {
-	reiserfs_make_bad_inode(inode) ;
-	return;
-    }
-
     dirino = args->objectid ;
 
     /* set version 1, version 2 could be used too, because stat data
@@ -1173,7 +1162,7 @@
     /* look for the object's stat data */
     retval = search_item (inode->i_sb, &key, &path_to_sd);
     if (retval == IO_ERROR) {
-	reiserfs_warning ("vs-13070: reiserfs_read_inode2: "
+	reiserfs_warning ("vs-13070: reiserfs_read_locked_inode: "
                     "i/o failure occurred trying to find stat data of %K\n",
                     &key);
 	reiserfs_make_bad_inode(inode) ;
@@ -1205,7 +1194,7 @@
        during mount (fs/reiserfs/super.c:finish_unfinished()). */
     if( ( inode -> i_nlink == 0 ) && 
 	! REISERFS_SB(inode -> i_sb) -> s_is_unlinked_ok ) {
-	    reiserfs_warning( "vs-13075: reiserfs_read_inode2: "
+	    reiserfs_warning( "vs-13075: reiserfs_read_locked_inode: "
 			      "dead inode read from disk %K. "
 			      "This is likely to be race with knfsd. Ignore\n", 
 			      &key );
@@ -1217,12 +1206,12 @@
 }
 
 /**
- * reiserfs_find_actor() - "find actor" reiserfs supplies to iget4().
+ * reiserfs_find_actor() - "find actor" reiserfs supplies to iget5_locked().
  *
  * @inode:    inode from hash table to check
- * @opaque:   "cookie" passed to iget4(). This is &reiserfs_iget4_args.
+ * @opaque:   "cookie" passed to iget5_locked(). This is &reiserfs_iget_args.
  *
- * This function is called by iget4() to distinguish reiserfs inodes
+ * This function is called by iget5_locked() to distinguish reiserfs inodes
  * having the same inode numbers. Such inodes can only exist due to some
  * error condition. One of them should be bad. Inodes with identical
  * inode numbers (objectids) are distinguished by parent directory ids.
@@ -1230,7 +1219,7 @@
  */
 int reiserfs_find_actor( struct inode *inode, void *opaque )
 {
-    struct reiserfs_iget4_args *args;
+    struct reiserfs_iget_args *args;
 
     args = opaque;
     /* args is already in CPU order */
@@ -1240,13 +1229,18 @@
 struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
 {
     struct inode * inode;
-    struct reiserfs_iget4_args args ;
+    struct reiserfs_iget_args args ;
 
     args.objectid = key->on_disk_key.k_dir_id ;
-    inode = iget4 (s, key->on_disk_key.k_objectid, 
+    inode = iget5_locked (s, key->on_disk_key.k_objectid, 
 		   reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!inode) 
 	return ERR_PTR(-ENOMEM) ;
+
+    if (inode->i_state & I_NEW) {
+	reiserfs_read_locked_inode(inode, &args);
+	unlock_new_inode(inode);
+    }
 
     if (comp_short_keys (INODE_PKEY (inode), key) || is_bad_inode (inode)) {
 	/* either due to i/o error or a stale NFS handle */
diff -urN iget_locked-2/fs/reiserfs/super.c iget_locked-3/fs/reiserfs/super.c
--- iget_locked-2/fs/reiserfs/super.c	Sun May 19 17:55:27 2002
+++ iget_locked-3/fs/reiserfs/super.c	Sun May 19 18:10:31 2002
@@ -484,8 +484,6 @@
 {
   alloc_inode: reiserfs_alloc_inode,
   destroy_inode: reiserfs_destroy_inode,
-  read_inode: reiserfs_read_inode,
-  read_inode2: reiserfs_read_inode2,
   write_inode: reiserfs_write_inode,
   dirty_inode: reiserfs_dirty_inode,
   delete_inode: reiserfs_delete_inode,
@@ -1007,7 +1005,7 @@
     int old_format = 0;
     unsigned long blocks;
     int jinit_done = 0 ;
-    struct reiserfs_iget4_args args ;
+    struct reiserfs_iget_args args ;
     struct reiserfs_super_block * rs;
     char *jdev_name;
     struct reiserfs_sb_info *sbi;
@@ -1070,10 +1068,15 @@
 	s->s_flags |= MS_RDONLY ;
     }
     args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
-    root_inode = iget4 (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
+    root_inode = iget5_locked (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!root_inode) {
 	printk ("reiserfs_fill_super: get root inode failed\n");
 	goto error;
+    }
+
+    if (root_inode->i_state & I_NEW) {
+	reiserfs_read_locked_inode(root_inode, &args);
+	unlock_new_inode(root_inode);
     }
 
     s->s_root = d_alloc_root(root_inode);  
diff -urN iget_locked-2/include/linux/fs.h iget_locked-3/include/linux/fs.h
--- iget_locked-2/include/linux/fs.h	Sun May 19 18:02:05 2002
+++ iget_locked-3/include/linux/fs.h	Sun May 19 18:04:27 2002
@@ -1215,7 +1215,14 @@
 extern struct inode * iget4(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
 static inline struct inode *iget(struct super_block *sb, unsigned long ino)
 {
-	return iget4(sb, ino, NULL, NULL, NULL);
+	struct inode *inode = iget_locked(sb, ino);
+	
+	if (inode && (inode->i_state & I_NEW)) {
+		sb->s_op->read_inode(inode);
+		unlock_new_inode(inode);
+	}
+
+	return inode;
 }
 
 extern void __iget(struct inode * inode);
diff -urN iget_locked-2/include/linux/nfs_fs.h iget_locked-3/include/linux/nfs_fs.h
--- iget_locked-2/include/linux/nfs_fs.h	Sun May  5 15:09:15 2002
+++ iget_locked-3/include/linux/nfs_fs.h	Sun May 19 18:04:27 2002
@@ -170,7 +170,6 @@
 #define NFS_INO_REVALIDATING	0x0004		/* revalidating attrs */
 #define NFS_IS_SNAPSHOT		0x0010		/* a snapshot file */
 #define NFS_INO_FLUSH		0x0020		/* inode is due for flushing */
-#define NFS_INO_NEW		0x0040		/* hadn't been filled yet */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {
@@ -208,7 +207,6 @@
 #define NFS_FLAGS(inode)		(NFS_I(inode)->flags)
 #define NFS_REVALIDATING(inode)		(NFS_FLAGS(inode) & NFS_INO_REVALIDATING)
 #define NFS_STALE(inode)		(NFS_FLAGS(inode) & NFS_INO_STALE)
-#define NFS_NEW(inode)			(NFS_FLAGS(inode) & NFS_INO_NEW)
 
 #define NFS_FILEID(inode)		(NFS_I(inode)->fileid)
 
diff -urN iget_locked-2/include/linux/reiserfs_fs.h iget_locked-3/include/linux/reiserfs_fs.h
--- iget_locked-2/include/linux/reiserfs_fs.h	Sun May 19 17:55:27 2002
+++ iget_locked-3/include/linux/reiserfs_fs.h	Sun May 19 18:10:42 2002
@@ -1564,7 +1564,7 @@
 #define B_I_POS_UNFM_POINTER(bh,ih,pos) le32_to_cpu(*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)))
 #define PUT_B_I_POS_UNFM_POINTER(bh,ih,pos, val) do {*(((unp_t *)B_I_PITEM(bh,ih)) + (pos)) = cpu_to_le32(val); } while (0)
 
-struct reiserfs_iget4_args {
+struct reiserfs_iget_args {
     __u32 objectid ;
 } ;
 
@@ -1818,8 +1818,7 @@
 
 /* inode.c */
 
-void reiserfs_read_inode (struct inode * inode) ;
-void reiserfs_read_inode2(struct inode * inode, void *p) ;
+void reiserfs_read_locked_inode(struct inode * inode, struct reiserfs_iget_args *args) ;
 int reiserfs_find_actor(struct inode * inode, void *p) ;
 int reiserfs_init_locked_inode(struct inode * inode, void *p) ;
 void reiserfs_delete_inode (struct inode * inode);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] 2.5.16 iget_locked [4/6]
  2002-05-20 13:05   ` [PATCH] 2.5.16 iget_locked [3/6] Jan Harkes
@ 2002-05-20 13:09     ` Jan Harkes
  2002-05-20 13:10       ` [PATCH] 2.5.16 iget_locked [5/6] Jan Harkes
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:09 UTC (permalink / raw)
  To: torvalds, linux-kernel


Now that we have no more users of iget4 we can kill the function and the
associated read_inode2 callback (i.e. the 'reiserfs specific hack').

Document iget5_locked as the replacement for iget4 in filesystems/porting.


diff -urN iget_locked-3/Documentation/filesystems/Locking iget_locked-4/Documentation/filesystems/Locking
--- iget_locked-3/Documentation/filesystems/Locking	Mon May  6 11:01:57 2002
+++ iget_locked-4/Documentation/filesystems/Locking	Sun May 19 18:11:28 2002
@@ -115,7 +115,7 @@
 remount_fs:	yes	yes	maybe		(see below)
 umount_begin:	yes	no	maybe		(see below)
 
-->read_inode() is not a method - it's a callback used in iget()/iget4().
+->read_inode() is not a method - it's a callback used in iget().
 rules for mount_sem are not too nice - it is going to die and be replaced
 by better scheme anyway.
 
diff -urN iget_locked-3/Documentation/filesystems/porting iget_locked-4/Documentation/filesystems/porting
--- iget_locked-3/Documentation/filesystems/porting	Sun May 19 17:52:42 2002
+++ iget_locked-4/Documentation/filesystems/porting	Sun May 19 18:12:14 2002
@@ -152,3 +152,36 @@
 s_export_op is now required for exporting a filesystem.
 isofs, ext2, ext3, resierfs, fat
 can be used as examples of very different filesystems.
+
+---
+[mandatory]
+
+iget4() and the read_inode2 callback have been superseded by iget5_locked()
+which has the following prototype,
+
+    struct inode *iget5_locked(struct super_block *sb, unsigned long ino,
+				int (*test)(struct inode *, void *),
+				int (*set)(struct inode *, void *),
+				void *data);
+
+'test' is an additional function that can be used when the inode
+number is not sufficient to identify the actual file object. 'set'
+should be a non-blocking function that initializes those parts of a
+newly created inode to allow the test function to succeed. 'data' is
+passed as an opaque value to both test and set functions.
+
+When the inode has been created by iget5_locked(), it will be returned with
+the I_NEW flag set and will still be locked. read_inode has not been
+called so the file system still has to finalize the initialization. Once
+the inode is initialized it must be unlocked by calling unlock_new_inode().
+
+There is also a simpler iget_locked function that just takes the
+superblock and inode number as arguments.
+
+e.g.
+       inode = iget_locked(sb, ino);
+       if (inode->i_state & I_NEW) {
+               read_inode_from_disk(inode);
+               unlock_new_inode(inode);
+       }
+
diff -urN iget_locked-3/fs/inode.c iget_locked-4/fs/inode.c
--- iget_locked-3/fs/inode.c	Sun May 19 18:02:54 2002
+++ iget_locked-4/fs/inode.c	Sun May 19 18:11:28 2002
@@ -669,27 +669,6 @@
 EXPORT_SYMBOL(iget_locked);
 EXPORT_SYMBOL(unlock_new_inode);
 
-struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
-{
-	struct inode *inode = iget5_locked(sb, ino, test, set, data);
-
-	if (inode && (inode->i_state & I_NEW)) {
-		/* reiserfs specific hack right here.  We don't
-		** want this to last, and are looking for VFS changes
-		** that will allow us to get rid of it.
-		** -- mason@suse.com 
-		*/
-		if (sb->s_op->read_inode2) {
-			sb->s_op->read_inode2(inode, data);
-		} else {
-			sb->s_op->read_inode(inode);
-		}
-		unlock_new_inode(inode);
-	}
-
-	return inode;
-}
-
 /**
  *	insert_inode_hash - hash an inode
  *	@inode: unhashed inode
diff -urN iget_locked-3/include/linux/fs.h iget_locked-4/include/linux/fs.h
--- iget_locked-3/include/linux/fs.h	Sun May 19 18:04:27 2002
+++ iget_locked-4/include/linux/fs.h	Sun May 19 18:11:28 2002
@@ -769,13 +769,6 @@
 
 	void (*read_inode) (struct inode *);
   
-  	/* reiserfs kludge.  reiserfs needs 64 bits of information to
-    	** find an inode.  We are using the read_inode2 call to get
-   	** that information.  We don't like this, and are waiting on some
-   	** VFS changes for the real solution.
-   	** iget4 calls read_inode2, iff it is defined
-   	*/
-    	void (*read_inode2) (struct inode *, void *) ;
    	void (*dirty_inode) (struct inode *);
 	void (*write_inode) (struct inode *, int);
 	void (*put_inode) (struct inode *);
@@ -1212,7 +1205,6 @@
 extern struct inode * iget_locked(struct super_block *, unsigned long);
 extern void unlock_new_inode(struct inode *);
 
-extern struct inode * iget4(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *);
 static inline struct inode *iget(struct super_block *sb, unsigned long ino)
 {
 	struct inode *inode = iget_locked(sb, ino);
diff -urN iget_locked-3/kernel/ksyms.c iget_locked-4/kernel/ksyms.c
--- iget_locked-3/kernel/ksyms.c	Sun May 19 17:52:58 2002
+++ iget_locked-4/kernel/ksyms.c	Sun May 19 18:11:28 2002
@@ -137,7 +137,6 @@
 EXPORT_SYMBOL(fget);
 EXPORT_SYMBOL(igrab);
 EXPORT_SYMBOL(iunique);
-EXPORT_SYMBOL(iget4);
 EXPORT_SYMBOL(iput);
 EXPORT_SYMBOL(inode_init_once);
 EXPORT_SYMBOL(force_delete);

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] 2.5.16 iget_locked [5/6]
  2002-05-20 13:09     ` [PATCH] 2.5.16 iget_locked [4/6] Jan Harkes
@ 2002-05-20 13:10       ` Jan Harkes
  2002-05-20 13:11         ` [PATCH] 2.5.16 iget_locked [6/6] Jan Harkes
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:10 UTC (permalink / raw)
  To: torvalds, linux-kernel


This patch starts taking i_ino dependencies out of the VFS. The FS
provided test and set callbacks become responsible for testing and
setting inode->i_ino.

Because most filesystems are based on 32-bit unique inode numbers
several functions are duplicated to keep iget_locked as a fast path. We
can avoid unnecessary pointer dereferences and function calls for this
specific case.


diff -urN iget_locked-4/Documentation/filesystems/porting iget_locked-5/Documentation/filesystems/porting
--- iget_locked-4/Documentation/filesystems/porting	Sun May 19 18:12:14 2002
+++ iget_locked-5/Documentation/filesystems/porting	Sun May 19 18:15:11 2002
@@ -175,8 +175,10 @@
 called so the file system still has to finalize the initialization. Once
 the inode is initialized it must be unlocked by calling unlock_new_inode().
 
-There is also a simpler iget_locked function that just takes the
-superblock and inode number as arguments.
+The filesystem is responsible for setting (and possibly testing) i_ino
+when appropriate. There is also a simpler iget_locked function that
+just takes the superblock and inode number as arguments and does the
+test and set for you.
 
 e.g.
        inode = iget_locked(sb, ino);
diff -urN iget_locked-4/fs/coda/cnode.c iget_locked-5/fs/coda/cnode.c
--- iget_locked-4/fs/coda/cnode.c	Sun May 19 18:07:01 2002
+++ iget_locked-5/fs/coda/cnode.c	Sun May 19 18:15:11 2002
@@ -83,6 +83,7 @@
 
 	if (inode->i_state & I_NEW) {
 		cii = ITOC(inode);
+		inode->i_ino = ino;
 		list_add(&cii->c_cilist, &sbi->sbi_cihead);
 		unlock_new_inode(inode);
 	}
diff -urN iget_locked-4/fs/inode.c iget_locked-5/fs/inode.c
--- iget_locked-4/fs/inode.c	Sun May 19 18:11:28 2002
+++ iget_locked-5/fs/inode.c	Sun May 19 18:21:19 2002
@@ -453,7 +453,32 @@
  * by hand after calling find_inode now! This simplifies iunique and won't
  * add any additional branch in the common code.
  */
-static struct inode * find_inode(struct super_block * sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), void *data)
+static struct inode * find_inode(struct super_block * sb, struct list_head *head, int (*test)(struct inode *, void *), void *data)
+{
+	struct list_head *tmp;
+	struct inode * inode;
+
+	tmp = head;
+	for (;;) {
+		tmp = tmp->next;
+		inode = NULL;
+		if (tmp == head)
+			break;
+		inode = list_entry(tmp, struct inode, i_hash);
+		if (inode->i_sb != sb)
+			continue;
+		if (!test(inode, data))
+			continue;
+		break;
+	}
+	return inode;
+}
+
+/*
+ * find_inode_fast is the fast path version of find_inode, see the comment at
+ * iget_locked for details.
+ */
+static struct inode * find_inode_fast(struct super_block * sb, struct list_head *head, unsigned long ino)
 {
 	struct list_head *tmp;
 	struct inode * inode;
@@ -469,8 +494,6 @@
 			continue;
 		if (inode->i_sb != sb)
 			continue;
-		if (test && !test(inode, data))
-			continue;
 		break;
 	}
 	return inode;
@@ -523,10 +546,9 @@
  * We no longer cache the sb_flags in i_flags - see fs.h
  *	-- rmk@arm.uk.linux.org
  */
-static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+static struct inode * get_new_inode(struct super_block *sb, struct list_head *head, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
 	struct inode * inode;
-	int err = 0;
 
 	inode = alloc_inode(sb);
 	if (inode) {
@@ -534,10 +556,9 @@
 
 		spin_lock(&inode_lock);
 		/* We released the lock, so.. */
-		old = find_inode(sb, ino, head, test, data);
+		old = find_inode(sb, head, test, data);
 		if (!old) {
-			inode->i_ino = ino;
-			if (set && set(inode, data))
+			if (set(inode, data))
 				goto set_failed;
 
 			inodes_stat.nr_inodes++;
@@ -571,6 +592,49 @@
 	return NULL;
 }
 
+/*
+ * get_new_inode_fast is the fast path version of get_new_inode, see the
+ * comment at iget_locked for details.
+ */
+static struct inode * get_new_inode_fast(struct super_block *sb, struct list_head *head, unsigned long ino)
+{
+	struct inode * inode;
+
+	inode = alloc_inode(sb);
+	if (inode) {
+		struct inode * old;
+
+		spin_lock(&inode_lock);
+		/* We released the lock, so.. */
+		old = find_inode_fast(sb, head, ino);
+		if (!old) {
+			inode->i_ino = ino;
+			inodes_stat.nr_inodes++;
+			list_add(&inode->i_list, &inode_in_use);
+			list_add(&inode->i_hash, head);
+			inode->i_state = I_LOCK|I_NEW;
+			spin_unlock(&inode_lock);
+
+			/* Return the locked inode with I_NEW set, the
+			 * caller is responsible for filling in the contents
+			 */
+			return inode;
+		}
+
+		/*
+		 * Uhhuh, somebody else created the same inode under
+		 * us. Use the old inode instead of the one we just
+		 * allocated.
+		 */
+		__iget(old);
+		spin_unlock(&inode_lock);
+		destroy_inode(inode);
+		inode = old;
+		wait_on_inode(inode);
+	}
+	return inode;
+}
+
 static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
 {
 	unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
@@ -605,7 +669,8 @@
 retry:
 	if (counter > max_reserved) {
 		head = inode_hashtable + hash(sb,counter);
-		inode = find_inode(sb, res = counter++, head, NULL, NULL);
+		res = counter++;
+		inode = find_inode_fast(sb, head, res);
 		if (!inode) {
 			spin_unlock(&inode_lock);
 			return res;
@@ -644,7 +709,7 @@
 	struct inode * inode;
 
 	spin_lock(&inode_lock);
-	inode = find_inode(sb, ino, head, test, data);
+	inode = find_inode(sb, head, test, data);
 	if (inode) {
 		__iget(inode);
 		spin_unlock(&inode_lock);
@@ -657,12 +722,36 @@
 	 * get_new_inode() will do the right thing, re-trying the search
 	 * in case it had to block at any point.
 	 */
-	return get_new_inode(sb, ino, head, test, set, data);
+	return get_new_inode(sb, head, test, set, data);
 }
 
+/*
+ * Because most filesystems are based on 32-bit unique inode numbers some
+ * functions are duplicated to keep iget_locked as a fast path. We can avoid
+ * unnecessary pointer dereferences and function calls for this specific
+ * case. The duplicated functions (find_inode_fast and get_new_inode_fast)
+ * have the same pre- and post-conditions as their original counterparts.
+ */
 struct inode *iget_locked(struct super_block *sb, unsigned long ino)
 {
-	return iget5_locked(sb, ino, NULL, NULL, NULL);
+	struct list_head * head = inode_hashtable + hash(sb, ino);
+	struct inode * inode;
+
+	spin_lock(&inode_lock);
+	inode = find_inode_fast(sb, head, ino);
+	if (inode) {
+		__iget(inode);
+		spin_unlock(&inode_lock);
+		wait_on_inode(inode);
+		return inode;
+	}
+	spin_unlock(&inode_lock);
+
+	/*
+	 * get_new_inode_fast() will do the right thing, re-trying the search
+	 * in case it had to block at any point.
+	 */
+	return get_new_inode_fast(sb, head, ino);
 }
 
 EXPORT_SYMBOL(iget5_locked);
diff -urN iget_locked-4/fs/nfs/inode.c iget_locked-5/fs/nfs/inode.c
--- iget_locked-4/fs/nfs/inode.c	Sun May 19 18:09:14 2002
+++ iget_locked-5/fs/nfs/inode.c	Sun May 19 18:15:11 2002
@@ -661,6 +661,8 @@
 		loff_t		new_isize;
 		time_t		new_atime;
 
+		inode->i_ino = ino;
+
 		/* We can't support UPDATE_ATIME(), since the server will reset it */
 		inode->i_flags |= S_NOATIME;
 		inode->i_mode = fattr->mode;
diff -urN iget_locked-4/fs/reiserfs/inode.c iget_locked-5/fs/reiserfs/inode.c
--- iget_locked-4/fs/reiserfs/inode.c	Sun May 19 18:10:06 2002
+++ iget_locked-5/fs/reiserfs/inode.c	Sun May 19 18:15:11 2002
@@ -1136,7 +1136,8 @@
 int reiserfs_init_locked_inode (struct inode * inode, void *p)
 {
     struct reiserfs_iget_args *args = (struct reiserfs_iget_args *)p ;
-    INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->objectid);
+    inode->i_ino = args->objectid;
+    INODE_PKEY(inode)->k_dir_id = cpu_to_le32(args->dirid);
     return 0;
 }
 
@@ -1149,7 +1150,7 @@
     unsigned long dirino;
     int retval;
 
-    dirino = args->objectid ;
+    dirino = args->dirid ;
 
     /* set version 1, version 2 could be used too, because stat data
        key is the same in both versions */
@@ -1223,7 +1224,8 @@
 
     args = opaque;
     /* args is already in CPU order */
-    return le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args -> objectid;
+    return (inode->i_ino == args->objectid) &&
+	(le32_to_cpu(INODE_PKEY(inode)->k_dir_id) == args->dirid);
 }
 
 struct inode * reiserfs_iget (struct super_block * s, const struct cpu_key * key)
@@ -1231,7 +1233,8 @@
     struct inode * inode;
     struct reiserfs_iget_args args ;
 
-    args.objectid = key->on_disk_key.k_dir_id ;
+    args.objectid = key->on_disk_key.k_objectid ;
+    args.dirid = key->on_disk_key.k_dir_id ;
     inode = iget5_locked (s, key->on_disk_key.k_objectid, 
 		   reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!inode) 
diff -urN iget_locked-4/fs/reiserfs/super.c iget_locked-5/fs/reiserfs/super.c
--- iget_locked-4/fs/reiserfs/super.c	Sun May 19 18:10:31 2002
+++ iget_locked-5/fs/reiserfs/super.c	Sun May 19 18:15:11 2002
@@ -1067,7 +1067,8 @@
         printk("clm-7000: Detected readonly device, marking FS readonly\n") ;
 	s->s_flags |= MS_RDONLY ;
     }
-    args.objectid = REISERFS_ROOT_PARENT_OBJECTID ;
+    args.objectid = REISERFS_ROOT_OBJECTID ;
+    args.dirid = REISERFS_ROOT_PARENT_OBJECTID ;
     root_inode = iget5_locked (s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, reiserfs_init_locked_inode, (void *)(&args));
     if (!root_inode) {
 	printk ("reiserfs_fill_super: get root inode failed\n");
diff -urN iget_locked-4/include/linux/reiserfs_fs.h iget_locked-5/include/linux/reiserfs_fs.h
--- iget_locked-4/include/linux/reiserfs_fs.h	Sun May 19 18:10:42 2002
+++ iget_locked-5/include/linux/reiserfs_fs.h	Sun May 19 18:15:11 2002
@@ -1566,6 +1566,7 @@
 
 struct reiserfs_iget_args {
     __u32 objectid ;
+    __u32 dirid ;
 } ;
 
 /***************************************************************************/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] 2.5.16 iget_locked [6/6]
  2002-05-20 13:10       ` [PATCH] 2.5.16 iget_locked [5/6] Jan Harkes
@ 2002-05-20 13:11         ` Jan Harkes
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Harkes @ 2002-05-20 13:11 UTC (permalink / raw)
  To: torvalds, linux-kernel


As of the last patch the inode_hashtable doesn't really need to be
indexed by i_ino anymore, the only reason we still have to keep the
hashvalue and i_ino identical is because of insert_inode_hash.

If at some point a FS specific getattr method is implemented it will be
possible to completely remove any use of i_ino by the VFS.


diff -urN iget_locked-5/fs/coda/cnode.c iget_locked-6/fs/coda/cnode.c
--- iget_locked-5/fs/coda/cnode.c	Sun May 19 18:15:11 2002
+++ iget_locked-6/fs/coda/cnode.c	Sun May 19 18:22:08 2002
@@ -74,16 +74,17 @@
 	struct inode *inode;
 	struct coda_inode_info *cii;
 	struct coda_sb_info *sbi = coda_sbp(sb);
-	ino_t ino = coda_f2i(fid);
+	unsigned long hash = coda_f2i(fid);
 
-	inode = iget5_locked(sb, ino, coda_test_inode, coda_set_inode, fid);
+	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
 
 	if (!inode)
 		return ERR_PTR(-ENOMEM);
 
 	if (inode->i_state & I_NEW) {
 		cii = ITOC(inode);
-		inode->i_ino = ino;
+		/* we still need to set i_ino for things like stat(2) */
+		inode->i_ino = hash;
 		list_add(&cii->c_cilist, &sbi->sbi_cihead);
 		unlock_new_inode(inode);
 	}
@@ -124,6 +125,7 @@
 		      struct ViceFid *newfid)
 {
 	struct coda_inode_info *cii;
+	unsigned long hash = coda_f2i(newfid);
 	
 	cii = ITOC(inode);
 
@@ -134,23 +136,22 @@
 	/* XXX we probably need to hold some lock here! */
 	remove_inode_hash(inode);
 	cii->c_fid = *newfid;
-	inode->i_ino = coda_f2i(newfid);
-	insert_inode_hash(inode);
+	inode->i_ino = hash;
+	__insert_inode_hash(inode, hash);
 }
 
 /* convert a fid to an inode. */
 struct inode *coda_fid_to_inode(ViceFid *fid, struct super_block *sb) 
 {
-	ino_t nr;
 	struct inode *inode;
+	unsigned long hash = coda_f2i(fid);
 
 	if ( !sb ) {
 		printk("coda_fid_to_inode: no sb!\n");
 		return NULL;
 	}
 
-	nr = coda_f2i(fid);
-	inode = iget5_locked(sb, nr, coda_test_inode, coda_fail_inode, fid);
+	inode = iget5_locked(sb, hash, coda_test_inode, coda_fail_inode, fid);
 	if ( !inode )
 		return NULL;
 
diff -urN iget_locked-5/fs/inode.c iget_locked-6/fs/inode.c
--- iget_locked-5/fs/inode.c	Sun May 19 18:21:19 2002
+++ iget_locked-6/fs/inode.c	Sun May 19 18:29:06 2002
@@ -635,9 +635,9 @@
 	return inode;
 }
 
-static inline unsigned long hash(struct super_block *sb, unsigned long i_ino)
+static inline unsigned long hash(struct super_block *sb, unsigned long hashval)
 {
-	unsigned long tmp = i_ino + ((unsigned long) sb / L1_CACHE_BYTES);
+	unsigned long tmp = hashval + ((unsigned long) sb / L1_CACHE_BYTES);
 	tmp = tmp + (tmp >> I_HASHBITS);
 	return tmp & I_HASHMASK;
 }
@@ -703,9 +703,9 @@
  * the filesystem gets back a new locked and hashed inode and gets
  * to fill it in before unlocking it via unlock_new_inode().
  */
-struct inode *iget5_locked(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
+struct inode *iget5_locked(struct super_block *sb, unsigned long hashval, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data)
 {
-	struct list_head * head = inode_hashtable + hash(sb,ino);
+	struct list_head * head = inode_hashtable + hash(sb, hashval);
 	struct inode * inode;
 
 	spin_lock(&inode_lock);
@@ -759,18 +759,20 @@
 EXPORT_SYMBOL(unlock_new_inode);
 
 /**
- *	insert_inode_hash - hash an inode
+ *	__insert_inode_hash - hash an inode
  *	@inode: unhashed inode
+ *	@hashval: unsigned long value used to locate this object in the
+ *		inode_hashtable.
  *
  *	Add an inode to the inode hash for this superblock. If the inode
  *	has no superblock it is added to a separate anonymous chain.
  */
  
-void insert_inode_hash(struct inode *inode)
+void __insert_inode_hash(struct inode *inode, unsigned long hashval)
 {
 	struct list_head *head = &anon_hash_chain;
 	if (inode->i_sb)
-		head = inode_hashtable + hash(inode->i_sb, inode->i_ino);
+		head = inode_hashtable + hash(inode->i_sb, hashval);
 	spin_lock(&inode_lock);
 	list_add(&inode->i_hash, head);
 	spin_unlock(&inode_lock);
diff -urN iget_locked-5/fs/nfs/inode.c iget_locked-6/fs/nfs/inode.c
--- iget_locked-5/fs/nfs/inode.c	Sun May 19 18:15:11 2002
+++ iget_locked-6/fs/nfs/inode.c	Sun May 19 18:24:12 2002
@@ -641,7 +641,7 @@
 		fattr:	fattr
 	};
 	struct inode *inode = NULL;
-	unsigned long ino;
+	unsigned long hash;
 
 	if ((fattr->valid & NFS_ATTR_FATTR) == 0)
 		goto out_no_inode;
@@ -651,9 +651,9 @@
 		goto out_no_inode;
 	}
 
-	ino = nfs_fattr_to_ino_t(fattr);
+	hash = nfs_fattr_to_ino_t(fattr);
 
-	if (!(inode = iget5_locked(sb, ino, nfs_find_actor, nfs_init_locked, &desc)))
+	if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc)))
 		goto out_no_inode;
 
 	if (inode->i_state & I_NEW) {
@@ -661,7 +661,9 @@
 		loff_t		new_isize;
 		time_t		new_atime;
 
-		inode->i_ino = ino;
+		/* We set i_ino for the few things that still rely on it,
+		 * such as stat(2) */
+		inode->i_ino = hash;
 
 		/* We can't support UPDATE_ATIME(), since the server will reset it */
 		inode->i_flags |= S_NOATIME;
diff -urN iget_locked-5/include/linux/fs.h iget_locked-6/include/linux/fs.h
--- iget_locked-5/include/linux/fs.h	Sun May 19 18:11:28 2002
+++ iget_locked-6/include/linux/fs.h	Sun May 19 18:22:20 2002
@@ -1221,8 +1221,13 @@
 extern void clear_inode(struct inode *);
 extern struct inode *new_inode(struct super_block *);
 extern void remove_suid(struct dentry *);
-extern void insert_inode_hash(struct inode *);
+
+extern void __insert_inode_hash(struct inode *, unsigned long hashval);
 extern void remove_inode_hash(struct inode *);
+static inline void insert_inode_hash(struct inode *inode) {
+	__insert_inode_hash(inode, inode->i_ino);
+}
+
 extern struct file * get_empty_filp(void);
 extern void file_move(struct file *f, struct list_head *list);
 extern void ll_rw_block(int, int, struct buffer_head * bh[]);
diff -urN iget_locked-5/kernel/ksyms.c iget_locked-6/kernel/ksyms.c
--- iget_locked-5/kernel/ksyms.c	Sun May 19 18:11:28 2002
+++ iget_locked-6/kernel/ksyms.c	Sun May 19 18:22:22 2002
@@ -537,7 +537,7 @@
 EXPORT_SYMBOL(init_special_inode);
 EXPORT_SYMBOL(__get_hash_table);
 EXPORT_SYMBOL(new_inode);
-EXPORT_SYMBOL(insert_inode_hash);
+EXPORT_SYMBOL(__insert_inode_hash);
 EXPORT_SYMBOL(remove_inode_hash);
 EXPORT_SYMBOL(buffer_insert_list);
 EXPORT_SYMBOL(make_bad_inode);

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2002-05-20 13:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-05-20 13:00 [PATCH] 2.5.16 iget_locked [1/6] Jan Harkes
2002-05-20 13:04 ` [PATCH] 2.5.16 iget_locked [2/6] Jan Harkes
2002-05-20 13:05   ` [PATCH] 2.5.16 iget_locked [3/6] Jan Harkes
2002-05-20 13:09     ` [PATCH] 2.5.16 iget_locked [4/6] Jan Harkes
2002-05-20 13:10       ` [PATCH] 2.5.16 iget_locked [5/6] Jan Harkes
2002-05-20 13:11         ` [PATCH] 2.5.16 iget_locked [6/6] Jan Harkes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).