Commit ed80fcfa authored by Aneesh Kumar K.V's avatar Aneesh Kumar K.V Committed by Eric Van Hensbergen

fs/9p: Always ask new inode in create

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: default avatarAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarEric Van Hensbergen <ericvh@gmail.com>
parent 4d63055f
...@@ -153,13 +153,13 @@ extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, ...@@ -153,13 +153,13 @@ extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
void *p); void *p);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
struct p9_fid *fid, 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_dir_inode_operations_dotl;
extern const struct inode_operations v9fs_file_inode_operations_dotl; extern const struct inode_operations v9fs_file_inode_operations_dotl;
extern const struct inode_operations v9fs_symlink_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, extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses,
struct p9_fid *fid, struct p9_fid *fid,
struct super_block *sb); struct super_block *sb, int new);
/* other default globals */ /* other default globals */
#define V9FS_PORT 564 #define V9FS_PORT 564
...@@ -201,8 +201,27 @@ v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, ...@@ -201,8 +201,27 @@ v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
struct super_block *sb) struct super_block *sb)
{ {
if (v9fs_proto_dotl(v9ses)) 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 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 #endif
...@@ -454,6 +454,11 @@ static int v9fs_test_inode(struct inode *inode, void *data) ...@@ -454,6 +454,11 @@ static int v9fs_test_inode(struct inode *inode, void *data)
return 1; 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) static int v9fs_set_inode(struct inode *inode, void *data)
{ {
struct v9fs_inode *v9inode = V9FS_I(inode); struct v9fs_inode *v9inode = V9FS_I(inode);
...@@ -465,15 +470,22 @@ static int v9fs_set_inode(struct inode *inode, void *data) ...@@ -465,15 +470,22 @@ static int v9fs_set_inode(struct inode *inode, void *data)
static struct inode *v9fs_qid_iget(struct super_block *sb, static struct inode *v9fs_qid_iget(struct super_block *sb,
struct p9_qid *qid, struct p9_qid *qid,
struct p9_wstat *st) struct p9_wstat *st,
int new)
{ {
int retval, umode; int retval, umode;
unsigned long i_ino; unsigned long i_ino;
struct inode *inode; struct inode *inode;
struct v9fs_session_info *v9ses = sb->s_fs_info; 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); 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) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW)) if (!(inode->i_state & I_NEW))
...@@ -504,7 +516,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, ...@@ -504,7 +516,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb,
struct inode * struct inode *
v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, 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 p9_wstat *st;
struct inode *inode = NULL; struct inode *inode = NULL;
...@@ -513,7 +525,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, ...@@ -513,7 +525,7 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
if (IS_ERR(st)) if (IS_ERR(st))
return ERR_CAST(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); p9stat_free(st);
kfree(st); kfree(st);
return inode; return inode;
...@@ -615,7 +627,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, ...@@ -615,7 +627,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
} }
/* instantiate inode and assign the unopened fid to the dentry */ /* 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)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
......
...@@ -108,6 +108,12 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data) ...@@ -108,6 +108,12 @@ static int v9fs_test_inode_dotl(struct inode *inode, void *data)
return 1; 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) static int v9fs_set_inode_dotl(struct inode *inode, void *data)
{ {
struct v9fs_inode *v9inode = V9FS_I(inode); struct v9fs_inode *v9inode = V9FS_I(inode);
...@@ -121,16 +127,22 @@ static int v9fs_set_inode_dotl(struct inode *inode, void *data) ...@@ -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, static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
struct p9_qid *qid, struct p9_qid *qid,
struct p9_fid *fid, struct p9_fid *fid,
struct p9_stat_dotl *st) struct p9_stat_dotl *st,
int new)
{ {
int retval; int retval;
unsigned long i_ino; unsigned long i_ino;
struct inode *inode; struct inode *inode;
struct v9fs_session_info *v9ses = sb->s_fs_info; 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); i_ino = v9fs_qid2ino(qid);
inode = iget5_locked(sb, i_ino, v9fs_test_inode_dotl, inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st);
v9fs_set_inode_dotl, st);
if (!inode) if (!inode)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW)) if (!(inode->i_state & I_NEW))
...@@ -164,7 +176,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, ...@@ -164,7 +176,7 @@ static struct inode *v9fs_qid_iget_dotl(struct super_block *sb,
struct inode * struct inode *
v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, 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 p9_stat_dotl *st;
struct inode *inode = NULL; struct inode *inode = NULL;
...@@ -173,7 +185,7 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, ...@@ -173,7 +185,7 @@ v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid,
if (IS_ERR(st)) if (IS_ERR(st))
return ERR_CAST(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); kfree(st);
return inode; return inode;
} }
...@@ -263,7 +275,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode, ...@@ -263,7 +275,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, int omode,
fid = NULL; fid = NULL;
goto error; 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)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err); P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", err);
...@@ -383,7 +395,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, ...@@ -383,7 +395,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
goto error; 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)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
...@@ -636,7 +648,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, ...@@ -636,7 +648,7 @@ v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry,
} }
/* instantiate inode and assign the unopened fid to 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)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", 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, ...@@ -789,7 +801,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, int omode,
goto error; 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)) { if (IS_ERR(inode)) {
err = PTR_ERR(inode); err = PTR_ERR(inode);
P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n", P9_DPRINTK(P9_DEBUG_VFS, "inode creation failed %d\n",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment