]> err.no Git - linux-2.6/commitdiff
[GFS2] Remove i_mode passing from NFS File Handle
authorWendy Cheng <wcheng@redhat.com>
Wed, 27 Jun 2007 21:07:53 +0000 (17:07 -0400)
committerSteven Whitehouse <swhiteho@redhat.com>
Mon, 9 Jul 2007 07:24:11 +0000 (08:24 +0100)
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.

Signed-off-by: S. Wendy Cheng <wcheng@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
fs/gfs2/inode.c
fs/gfs2/inode.h
fs/gfs2/ops_export.c
fs/gfs2/rgrp.c

index 26aaf54959d92ace19ab1574d9af1e0894ca995c..34f7bcdea1e972e00187013eddd98272d65a40f0 100644 (file)
@@ -77,6 +77,36 @@ static struct inode *gfs2_iget(struct super_block *sb, u64 no_addr)
        return iget5_locked(sb, hash, iget_test, iget_set, &no_addr);
 }
 
+/**
+ * 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
@@ -101,7 +131,6 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
 
        if (inode->i_state & I_NEW) {
                struct gfs2_sbd *sdp = GFS2_SB(inode);
-               umode_t mode;
                inode->i_private = ip;
                ip->i_no_formal_ino = no_formal_ino;
 
@@ -122,6 +151,11 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
 
                gfs2_glock_put(io_gl);
 
+               if ((type == DT_UNKNOWN) && (no_formal_ino == 0))
+                       goto gfs2_nfsbypass;
+
+               inode->i_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
@@ -129,33 +163,19 @@ struct inode *gfs2_inode_lookup(struct super_block *sb,
                 * 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);
                        if (unlikely(error))
                                goto fail_glock;
                        /* Inode is now uptodate */
-                       mode = inode->i_mode;
                        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;
-               }
-
-               unlock_new_inode(inode);
+               gfs2_set_iop(inode);
        }
 
+gfs2_nfsbypass:
        return inode;
 fail_glock:
        gfs2_glock_dq(&ip->i_iopen_gh);
index 3268a2fed6724d63ccd0f02b3396fc0528f21561..4517ac82c01c7953b75bc65375e45328262b86dc 100644 (file)
@@ -47,6 +47,7 @@ static inline void gfs2_inum_out(const struct gfs2_inode *ip,
 
 
 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, unsigned type, 
                                u64 no_addr, u64 no_formal_ino);
 struct inode *gfs2_ilookup(struct super_block *sb, u64 no_addr);
index 0fe14478a54d1597cef17508fd7181f0c99c807d..e317db2a5548c35ff97d77097f1fe54a0fd90331 100644 (file)
 #include "util.h"
 
 #define GFS2_SMALL_FH_SIZE 4
-#define GFS2_LARGE_FH_SIZE 10
-
-struct gfs2_fh_obj {
-       struct gfs2_inum_host this;
-       u32 imode;
-};
+#define GFS2_LARGE_FH_SIZE 8
 
 static struct dentry *gfs2_decode_fh(struct super_block *sb,
                                     __u32 *p,
@@ -43,11 +38,8 @@ static struct dentry *gfs2_decode_fh(struct super_block *sb,
                                     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(struct super_block *sb,
                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);
 }
 
@@ -102,9 +93,6 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
        fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
        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 +189,7 @@ static struct dentry *gfs2_get_parent(struct dentry *child)
 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 = inum_obj;
        struct gfs2_holder i_gh, ri_gh, rgd_gh;
        struct gfs2_rgrpd *rgd;
        struct inode *inode;
@@ -245,9 +232,9 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
        gfs2_glock_dq_uninit(&rgd_gh);
        gfs2_glock_dq_uninit(&ri_gh);
 
-       inode = gfs2_inode_lookup(sb, fh_obj->imode,
+       inode = gfs2_inode_lookup(sb, DT_UNKNOWN,
                                        inum->no_addr,
-                                       inum->no_formal_ino);
+                                       0);
        if (!inode)
                goto fail;
        if (IS_ERR(inode)) {
@@ -260,6 +247,11 @@ static struct dentry *gfs2_get_dentry(struct super_block *sb, void *inum_obj)
                iput(inode);
                goto fail;
        }
+
+       /* Pick up the works we bypass in gfs2_inode_lookup */
+       if (inode->i_state & I_NEW) 
+               gfs2_set_iop(inode);
+
        if (GFS2_I(inode)->i_no_formal_ino != inum->no_formal_ino) {
                iput(inode);
                goto fail;
index 7fb74484af633ad5e71ab15ec9d32e974df6a5df..e4e040625153aa29b2254e51276eb6ac9807380e 100644 (file)
@@ -872,7 +872,7 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked)
                        continue;
                *last_unlinked = no_addr;
                inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN,
-                                       no_addr, 0);
+                                       no_addr, -1);
                if (!IS_ERR(inode))
                        return inode;
        }