fs/9p: Add inode hashing
[deliverable/linux.git] / fs / 9p / vfs_inode_dotl.c
index fe3ffa9aace4eb35d0a6799d20d006ff4d9937b3..6f62320eda89c951121e8e90389c1319e4b318ee 100644 (file)
@@ -86,40 +86,63 @@ static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
        return dentry;
 }
 
+static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
+                                       struct p9_qid *qid,
+                                       struct p9_fid *fid,
+                                       struct p9_stat_dotl *st)
+{
+       int retval;
+       unsigned long i_ino;
+       struct inode *inode;
+       struct v9fs_session_info *v9ses = sb->s_fs_info;
+
+       i_ino = v9fs_qid2ino(qid);
+       inode = iget_locked(sb, i_ino);
+       if (!inode)
+               return ERR_PTR(-ENOMEM);
+       if (!(inode->i_state & I_NEW))
+               return inode;
+       /*
+        * initialize the inode with the stat info
+        * FIXME!! we may need support for stale inodes
+        * later.
+        */
+       retval = v9fs_init_inode(v9ses, inode, st->st_mode);
+       if (retval)
+               goto error;
+
+       v9fs_stat2inode_dotl(st, inode);
+#ifdef CONFIG_9P_FSCACHE
+       v9fs_vcookie_set_qid(inode, &st->qid);
+       v9fs_cache_inode_get_cookie(inode);
+#endif
+       retval = v9fs_get_acl(inode, fid);
+       if (retval)
+               goto error;
+
+       unlock_new_inode(inode);
+       return inode;
+error:
+       unlock_new_inode(inode);
+       iput(inode);
+       return ERR_PTR(retval);
+
+}
+
 struct inode *
 v9fs_inode_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
        struct super_block *sb)
 {
-       struct inode *ret = NULL;
-       int err;
        struct p9_stat_dotl *st;
+       struct inode *inode = NULL;
 
        st = p9_client_getattr_dotl(fid, P9_STATS_BASIC);
        if (IS_ERR(st))
                return ERR_CAST(st);
 
-       ret = v9fs_get_inode(sb, st->st_mode);
-       if (IS_ERR(ret)) {
-               err = PTR_ERR(ret);
-               goto error;
-       }
-
-       v9fs_stat2inode_dotl(st, ret);
-       ret->i_ino = v9fs_qid2ino(&st->qid);
-#ifdef CONFIG_9P_FSCACHE
-       v9fs_vcookie_set_qid(ret, &st->qid);
-       v9fs_cache_inode_get_cookie(ret);
-#endif
-       err = v9fs_get_acl(ret, fid);
-       if (err) {
-               iput(ret);
-               goto error;
-       }
-       kfree(st);
-       return ret;
-error:
+       inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st);
        kfree(st);
-       return ERR_PTR(err);
+       return inode;
 }
 
 /**
@@ -142,7 +165,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
        mode_t mode;
        struct v9fs_session_info *v9ses;
        struct p9_fid *fid = NULL;
-       struct p9_fid *dfid, *ofid;
+       struct p9_fid *dfid, *ofid, *inode_fid;
        struct file *filp;
        struct p9_qid qid;
        struct inode *inode;
@@ -218,7 +241,21 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
 
        /* Now set the ACL based on the default value */
        v9fs_set_create_acl(dentry, dacl, pacl);
-
+       if (v9ses->cache && !inode->i_private) {
+               /*
+                * clone a fid and add it to inode->i_private
+                * we do it during open time instead of
+                * page dirty time via write_begin/page_mkwrite
+                * because we want write after unlink usecase
+                * to work.
+                */
+               inode_fid = v9fs_writeback_fid(dentry);
+               if (IS_ERR(inode_fid)) {
+                       err = PTR_ERR(inode_fid);
+                       goto error;
+               }
+               inode->i_private = (void *) inode_fid;
+       }
        /* Since we are opening a file, assign the open fid to the file */
        filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
        if (IS_ERR(filp)) {
@@ -226,6 +263,10 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
                return PTR_ERR(filp);
        }
        filp->private_data = ofid;
+#ifdef CONFIG_9P_FSCACHE
+       if (v9ses->cache)
+               v9fs_cache_inode_set_cookie(inode, filp);
+#endif
        return 0;
 
 error:
@@ -632,13 +673,8 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
                v9fs_stat2inode_dotl(st, old_dentry->d_inode);
 
                kfree(st);
-       } else {
-               /* Caching disabled. No need to get upto date stat info.
-                * This dentry will be released immediately. So, just hold the
-                * inode
-                */
-               ihold(old_dentry->d_inode);
        }
+       ihold(old_dentry->d_inode);
        d_instantiate(dentry, old_dentry->d_inode);
 
        return err;
This page took 0.026 seconds and 5 git commands to generate.