fs/9p: Always ask new inode in create
Aneesh Kumar K.V [Wed, 6 Jul 2011 11:02:31 +0000 (16:02 +0530)]
This make sure we don't end up reusing the unlinked inode object.
The ideal way is to use inode i_generation. But i_generation is
not available in userspace always.

Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>

fs/9p/v9fs.h
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c

index 5d7392e..e78956c 100644 (file)
@@ -153,13 +153,13 @@ extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
                        void *p);
 extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
                                         struct p9_fid *fid,
-                                        struct super_block *sb);
+                                        struct super_block *sb, int new);
 extern const struct inode_operations v9fs_dir_inode_operations_dotl;
 extern const struct inode_operations v9fs_file_inode_operations_dotl;
 extern const struct inode_operations v9fs_symlink_inode_operations_dotl;
 extern 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);
 
 /* other default globals */
 #define V9FS_PORT      564
@@ -201,8 +201,27 @@ v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
                        struct super_block *sb)
 {
        if (v9fs_proto_dotl(v9ses))
-               return v9fs_inode_from_fid_dotl(v9ses, fid, sb);
+               return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0);
        else
-               return v9fs_inode_from_fid(v9ses, fid, sb);
+               return v9fs_inode_from_fid(v9ses, fid, sb, 0);
 }
+
+/**
+ * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by
+ * issuing a attribute request
+ * @v9ses: session information
+ * @fid: fid to issue attribute request for
+ * @sb: superblock on which to create inode
+ *
+ */
+static inline struct inode *
+v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
+                           struct super_block *sb)
+{
+       if (v9fs_proto_dotl(v9ses))
+               return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1);
+       else
+               return v9fs_inode_from_fid(v9ses, fid, sb, 1);
+}
+
 #endif
index 3d8a18e..3bbf705 100644 (file)
@@ -454,6 +454,11 @@ static int v9fs_test_inode(struct inode *inode, void *data)
        return 1;
 }
 
+static int v9fs_test_new_inode(struct inode *inode, void *data)
+{
+       return 0;
+}
+
 static int v9fs_set_inode(struct inode *inode,  void *data)
 {
        struct v9fs_inode *v9inode = V9FS_I(inode);
@@ -465,15 +470,22 @@ static int v9fs_set_inode(struct inode *inode,  void *data)
 
 static struct inode *v9fs_qid_iget(struct super_block *sb,
                                   struct p9_qid *qid,
-                                  struct p9_wstat *st)
+                                  struct p9_wstat *st,
+                                  int new)
 {
        int retval, umode;
        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;
+       else
+               test = v9fs_test_inode;
 
        i_ino = v9fs_qid2ino(qid);
-       inode = iget5_locked(sb, i_ino, v9fs_test_inode, v9fs_set_inode, st);
+       inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st);
        if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
@@ -504,7 +516,7 @@ error:
 
 struct inode *
 v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
-                   struct super_block *sb)
+                   struct super_block *sb, int new)
 {
        struct p9_wstat *st;
        struct inode *inode = NULL;
@@ -513,7 +525,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
        if (IS_ERR(st))
                return ERR_CAST(st);
 
-       inode = v9fs_qid_iget(sb, &st->qid, st);
+       inode = v9fs_qid_iget(sb, &st->qid, st, new);
        p9stat_free(st);
        kfree(st);
        return inode;
@@ -615,7 +627,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
        }
 
        /* instantiate inode and assign the unopened fid to the 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", err);
index dc9e7de..276f4a6 100644 (file)
@@ -108,6 +108,12 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data)
        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);
@@ -121,16 +127,22 @@ static int v9fs_set_inode_dotl(struct inode *inode,  void *data)
 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 = iget5_locked(sb, i_ino, v9fs_test_inode_dotl,
-                            v9fs_set_inode_dotl, st);
+       inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
        if (!inode)
                return ERR_PTR(-ENOMEM);
        if (!(inode->i_state & I_NEW))
@@ -164,7 +176,7 @@ 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;
@@ -173,7 +185,7 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
        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;
 }
@@ -263,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);
@@ -383,7 +395,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",
@@ -636,7 +648,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",
@@ -789,7 +801,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",