forked from Minki/linux
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: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Signed-off-by: Eric Van Hensbergen <ericvh@gmail.com>
This commit is contained in:
parent
4d63055fa9
commit
ed80fcfac2
27
fs/9p/v9fs.h
27
fs/9p/v9fs.h
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user