[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Cluster-devel] [GFS2 PATCH 3/3] Remove i_mode passing from NFS File Handle



GFS2 has been passing i_mode within NFS File Handle. Other than the wrong assumption that there is always room for this extra 16 bit value, the current gfs2_get_dentry doesn't really need the i_mode to work correctly. Note that GFS2 NFS code does go thru the same lookup code path as direct file access route (where the mode is obtained from name lookup) but gfs2_get_dentry() is coded for different purpose. It is not used during lookup time. It is part of the file access procedure call. When the call is invoked, if on-disk inode is not in-memory, it has to be read-in. This makes i_mode passing a useless overhead.

-- Wendy

 Signed-off-by: S. Wendy Cheng <wcheng redhat com>

 dir.c        |    2 +-
 inode.c      |   56 ++++++++++++++++++++++++++++++++++++++++----------------
 inode.h      |    5 ++++-
 ops_export.c |   37 ++++++++++++++++---------------------
 ops_fstype.c |    2 +-
 rgrp.c       |    3 ++-
 6 files changed, 64 insertions(+), 41 deletions(-)

--- gfs2-nfs2/fs/gfs2/inode.h	2007-06-23 01:24:22.000000000 -0400
+++ gfs2-nfs/fs/gfs2/inode.h	2007-06-24 00:48:46.000000000 -0400
@@ -47,8 +47,11 @@ static inline void gfs2_inum_out(const s
 
 
 void gfs2_inode_attr_in(struct gfs2_inode *ip);
+void gfs2_set_iop(struct inode *inode);
 struct inode *gfs2_inode_lookup(struct super_block *sb, 
-				struct gfs2_inum_host *ino, unsigned type);
+				struct gfs2_inum_host *ino, 
+				unsigned type,
+				int nfsbypass);
 struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
 
 int gfs2_inode_refresh(struct gfs2_inode *ip);
--- gfs2-nfs2/fs/gfs2/dir.c	2007-06-23 01:24:22.000000000 -0400
+++ gfs2-nfs/fs/gfs2/dir.c	2007-06-23 01:39:15.000000000 -0400
@@ -1502,7 +1502,7 @@ struct inode *gfs2_dir_search(struct ino
 		ino.no_formal_ino = be64_to_cpu(dent->de_inum.no_formal_ino);
 		ino.no_addr = be64_to_cpu(dent->de_inum.no_addr);
 		inode = gfs2_inode_lookup(dir->i_sb, &ino,
-					  be16_to_cpu(dent->de_type));
+					  be16_to_cpu(dent->de_type), 0);
 		brelse(bh);
 		return inode;
 	}
--- gfs2-nfs2/fs/gfs2/inode.c	2007-06-23 01:24:22.000000000 -0400
+++ gfs2-nfs/fs/gfs2/inode.c	2007-06-24 00:46:33.000000000 -0400
@@ -78,6 +78,36 @@ static struct inode *gfs2_iget(struct su
 }
 
 /**
+ * GFS2 lookup code fills in vfs inode contents based on info obtained 
+ * from directory entry inside gfs2_inode_lookup(). This has caused issues 
+ * with NFS code path since its get_dentry routine doesn't have the relevant
+ * directory entry when gfs2_inode_lookup() is invoked. Part of the code 
+ * segment inside gfs2_inode_lookup code needs to get moved around.
+ *
+ * Clean up I_LOCK and I_NEW as well.
+ */
+
+void gfs2_set_iop(struct inode *inode)
+{
+	umode_t mode = inode->i_mode;
+
+	if (S_ISREG(mode)) {
+		inode->i_op = &gfs2_file_iops;
+		inode->i_fop = &gfs2_file_fops;
+		inode->i_mapping->a_ops = &gfs2_file_aops;
+	} else if (S_ISDIR(mode)) {
+		inode->i_op = &gfs2_dir_iops;
+		inode->i_fop = &gfs2_dir_fops;
+	} else if (S_ISLNK(mode)) {
+		inode->i_op = &gfs2_symlink_iops;
+	} else {
+		inode->i_op = &gfs2_dev_iops;
+	}
+
+	unlock_new_inode(inode);
+}
+
+/**
  * gfs2_inode_lookup - Lookup an inode
  * @sb: The super block
  * @no_addr: The inode number
@@ -88,7 +118,8 @@ static struct inode *gfs2_iget(struct su
 
 struct inode *gfs2_inode_lookup(struct super_block *sb, 
 				struct gfs2_inum_host *ino,
-				unsigned int type)
+				unsigned int type,
+				int nfsbypass)
 {
 	struct inode *inode = gfs2_iget(sb, ino->no_addr);
 	struct gfs2_inode *ip = GFS2_I(inode);
@@ -121,6 +152,11 @@ struct inode *gfs2_inode_lookup(struct s
 
 		gfs2_glock_put(io_gl);
 
+		if (nfsbypass)
+			goto gfs2_nfsbypass;
+
+		inode->i_mode = mode = DT2IF(type);
+
 		/*
 		 * We must read the inode in order to work out its type in
 		 * this case. Note that this doesn't happen often as we normally
@@ -128,7 +164,6 @@ struct inode *gfs2_inode_lookup(struct s
 		 * unlinked inode recovery (where it is safe to do this glock,
 		 * which is not true in the general case).
 		 */
-		inode->i_mode = mode = DT2IF(type);
 		if (type == DT_UNKNOWN) {
 			struct gfs2_holder gh;
 			error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
@@ -139,22 +174,11 @@ struct inode *gfs2_inode_lookup(struct s
 			gfs2_glock_dq_uninit(&gh);
 		}
 
-		if (S_ISREG(mode)) {
-			inode->i_op = &gfs2_file_iops;
-			inode->i_fop = &gfs2_file_fops;
-			inode->i_mapping->a_ops = &gfs2_file_aops;
-		} else if (S_ISDIR(mode)) {
-			inode->i_op = &gfs2_dir_iops;
-			inode->i_fop = &gfs2_dir_fops;
-		} else if (S_ISLNK(mode)) {
-			inode->i_op = &gfs2_symlink_iops;
-		} else {
-			inode->i_op = &gfs2_dev_iops;
-		}
+		(void) gfs2_set_iop(inode);
 
-		unlock_new_inode(inode);
 	}
 
+gfs2_nfsbypass:
 	return inode;
 fail_glock:
 	gfs2_glock_dq(&ip->i_iopen_gh);
@@ -918,7 +942,7 @@ struct inode *gfs2_createi(struct gfs2_h
 	if (error)
 		goto fail_gunlock2;
 
-	inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode));
+	inode = gfs2_inode_lookup(dir->i_sb, &inum, IF2DT(mode), 0);
 	if (IS_ERR(inode))
 		goto fail_gunlock2;
 
--- gfs2-nfs2/fs/gfs2/ops_export.c	2007-06-23 23:43:45.000000000 -0400
+++ gfs2-nfs/fs/gfs2/ops_export.c	2007-06-24 13:43:35.000000000 -0400
@@ -29,11 +29,6 @@
 #define GFS2_SMALL_FH_SIZE 4
 #define GFS2_LARGE_FH_SIZE 10
 
-struct gfs2_fh_obj {
-	struct gfs2_inum_host this;
-	u32 imode;
-};
-
 static struct dentry *gfs2_decode_fh(struct super_block *sb,
 				     __u32 *p,
 				     int fh_len,
@@ -43,11 +38,8 @@ static struct dentry *gfs2_decode_fh(str
 				     void *context)
 {
 	__be32 *fh = (__force __be32 *)p;
-	struct gfs2_fh_obj fh_obj;
-	struct gfs2_inum_host *this, parent;
+	struct gfs2_inum_host inum, parent;
 
-	this 		= &fh_obj.this;
-	fh_obj.imode 	= DT_UNKNOWN;
 	memset(&parent, 0, sizeof(struct gfs2_inum));
 
 	switch (fh_len) {
@@ -56,18 +48,17 @@ static struct dentry *gfs2_decode_fh(str
 		parent.no_formal_ino |= be32_to_cpu(fh[5]);
 		parent.no_addr = ((u64)be32_to_cpu(fh[6])) << 32;
 		parent.no_addr |= be32_to_cpu(fh[7]);
-		fh_obj.imode = be32_to_cpu(fh[8]);
 	case GFS2_SMALL_FH_SIZE:
-		this->no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
-		this->no_formal_ino |= be32_to_cpu(fh[1]);
-		this->no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
-		this->no_addr |= be32_to_cpu(fh[3]);
+		inum.no_formal_ino = ((u64)be32_to_cpu(fh[0])) << 32;
+		inum.no_formal_ino |= be32_to_cpu(fh[1]);
+		inum.no_addr = ((u64)be32_to_cpu(fh[2])) << 32;
+		inum.no_addr |= be32_to_cpu(fh[3]);
 		break;
 	default:
 		return NULL;
 	}
 
-	return gfs2_export_ops.find_exported_dentry(sb, &fh_obj, &parent,
+	return gfs2_export_ops.find_exported_dentry(sb, &inum, &parent,
 						    acceptable, context);
 }
 
@@ -94,8 +85,8 @@ static int gfs2_encode_fh(struct dentry 
 
 	spin_lock(&dentry->d_lock);
 	inode = dentry->d_parent->d_inode;
-	ip = GFS2_I(inode);
 	igrab(inode);
+	ip = GFS2_I(inode);
 	spin_unlock(&dentry->d_lock);
 
 	fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
@@ -103,8 +94,6 @@ static int gfs2_encode_fh(struct dentry 
 	fh[6] = cpu_to_be32(ip->i_no_addr >> 32);
 	fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
 
-	fh[8]  = cpu_to_be32(inode->i_mode);
-	fh[9]  = 0;	/* pad to double word */
 	*len = GFS2_LARGE_FH_SIZE;
 
 	iput(inode);
@@ -201,8 +190,7 @@ static struct dentry *gfs2_get_parent(st
 static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
 {
 	struct gfs2_sbd *sdp = sb->s_fs_info;
-	struct gfs2_fh_obj *fh_obj = (struct gfs2_fh_obj *)inum_obj;
-	struct gfs2_inum_host *inum = &fh_obj->this;
+	struct gfs2_inum_host *inum = (struct gfs2_inum_host *) inum_obj;
 	struct gfs2_holder i_gh, ri_gh, rgd_gh;
 	struct gfs2_rgrpd *rgd;
 	struct inode *inode;
@@ -245,7 +233,7 @@ static struct dentry *gfs2_get_dentry(st
 	gfs2_glock_dq_uninit(&rgd_gh);
 	gfs2_glock_dq_uninit(&ri_gh);
 
-	inode = gfs2_inode_lookup(sb, inum, fh_obj->imode);
+	inode = gfs2_inode_lookup(sb, inum, 0, 1);
 	if (!inode)
 		goto fail;
 	if (IS_ERR(inode)) {
@@ -258,6 +246,13 @@ static struct dentry *gfs2_get_dentry(st
 		iput(inode);
 		goto fail;
 	}
+
+	/* Pick up the works we bypass in gfs2_inode_lookup */
+	if (inode->i_state & I_NEW) {
+		inode->i_mode = GFS2_I(inode)->i_inode.i_mode;
+		(void) gfs2_set_iop(inode);
+	}
+
 	if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
 		iput(inode);
 		goto fail;
--- gfs2-nfs2/fs/gfs2/ops_fstype.c	2007-06-23 23:42:38.000000000 -0400
+++ gfs2-nfs/fs/gfs2/ops_fstype.c	2007-06-23 23:54:03.000000000 -0400
@@ -236,7 +236,7 @@ fail:
 static inline struct inode *gfs2_lookup_root(struct super_block *sb,
 					     struct gfs2_inum_host *ino)
 {
-	return gfs2_inode_lookup(sb, ino, DT_DIR);
+	return gfs2_inode_lookup(sb, ino, DT_DIR, 0);
 }
 
 static int init_sb(struct gfs2_sbd *sdp, int silent, int undo)
--- gfs2-nfs2/fs/gfs2/rgrp.c	2007-06-23 01:24:22.000000000 -0400
+++ gfs2-nfs/fs/gfs2/rgrp.c	2007-06-23 01:40:49.000000000 -0400
@@ -872,7 +872,8 @@ static struct inode *try_rgrp_unlink(str
 		if (ino.no_addr <= *last_unlinked)
 			continue;
 		*last_unlinked = ino.no_addr;
-		inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, &ino, DT_UNKNOWN);
+		inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, &ino, 
+						DT_UNKNOWN, 0);
 		if (!IS_ERR(inode))
 			return inode;
 	}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]