Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[pandora-kernel.git] / fs / 9p / vfs_inode_dotl.c
index 9d808d0..9a26dce 100644 (file)
@@ -86,18 +86,63 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
        return dentry;
 }
 
+static int v9fs_test_inode_dotl(struct inode *inode, void *data)
+{
+       struct v9fs_inode *v9inode = V9FS_I(inode);
+       struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
+
+       /* don't match inode of different type */
+       if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT))
+               return 0;
+
+       if (inode->i_generation != st->st_gen)
+               return 0;
+
+       /* compare qid details */
+       if (memcmp(&v9inode->qid.version,
+                  &st->qid.version, sizeof(v9inode->qid.version)))
+               return 0;
+
+       if (v9inode->qid.type != st->qid.type)
+               return 0;
+       return 1;
+}
+
+/* Always get a new inode */
+static int v9fs_test_new_inode_dotl(struct inode *inode, void *data)
+{
+       return 0;
+}
+
+static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
+{
+       struct v9fs_inode *v9inode = V9FS_I(inode);
+       struct p9_stat_dotl *st = (struct p9_stat_dotl *)data;
+
+       memcpy(&v9inode->qid, &st->qid, sizeof(st->qid));
+       inode->i_generation = st->st_gen;
+       return 0;
+}
+
 static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
                                        struct p9_qid *qid,
                                        struct p9_fid *fid,
-                                       struct p9_stat_dotl *st)
+                                       struct p9_stat_dotl *st,
+                                       int new)
 {
        int retval;
        unsigned long i_ino;
        struct inode *inode;
        struct v9fs_session_info *v9ses = sb->s_fs_info;
+       int (*test)(struct inode *, void *);
+
+       if (new)
+               test = v9fs_test_new_inode_dotl;
+       else
+               test = v9fs_test_inode_dotl;
 
        i_ino = v9fs_qid2ino(qid);
-       inode = iget_locked(sb, i_ino);
+       inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
        if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
@@ -107,13 +152,13 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
         * FIXME!! we may need support for stale inodes
         * later.
         */
+       inode->i_ino = i_ino;
        retval = v9fs_init_inode(v9ses, inode, st->st_mode);
        if (retval)
                goto error;
 
        v9fs_stat2inode_dotl(st, inode);
 #ifdef CONFIG_9P_FSCACHE
-       v9fs_fscache_set_key(inode, &st->qid);
        v9fs_cache_inode_get_cookie(inode);
 #endif
        retval = v9fs_get_acl(inode, fid);
@@ -131,16 +176,16 @@ error:
 
 struct inode *
 v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-                        struct super_block *sb)
+                        struct super_block *sb, int new)
 {
        struct p9_stat_dotl *st;
        struct inode *inode = NULL;
 
-       st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
+       st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN);
        if (IS_ERR(st))
                return ERR_CAST(st);
 
-       inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st);
+       inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new);
        kfree(st);
        return inode;
 }
@@ -230,7 +275,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
                fid = NULL;
                goto error;
        }
-       inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+       inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
        if (IS_ERR(inode)) {
                err = PTR_ERR(inode);
                P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@@ -351,7 +396,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
                        goto error;
                }
 
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -549,7 +594,7 @@ v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode)
                        inode->i_blocks = stat->st_blocks;
        }
        if (stat->st_result_mask & P9_STATS_GEN)
-                       inode->i_generation = stat->st_gen;
+               inode->i_generation = stat->st_gen;
 
        /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION
         * because the inode structure does not have fields for them.
@@ -605,7 +650,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
                }
 
                /* instantiate inode and assign the unopened fid to dentry */
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
@@ -758,7 +803,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
                        goto error;
                }
 
-               inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
+               inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb);
                if (IS_ERR(inode)) {
                        err = PTR_ERR(inode);
                        P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",