Revert " fs/9p: mitigate inode collisions"

This reverts commit d05dcfdf5e.

This is a requirement to revert commit 724a08450f ("fs/9p: simplify
iget to remove unnecessary paths"), see that revert for details.

Fixes: 724a08450f ("fs/9p: simplify iget to remove unnecessary paths")
Reported-by: Will Deacon <will@kernel.org>
Link: https://lkml.kernel.org/r/20240923100508.GA32066@willie-the-truck
Cc: stable@vger.kernel.org # v6.9+
Message-ID: <20241024-revert_iget-v1-1-4cac63d25f72@codewreck.org>
Signed-off-by: Dominique Martinet <asmadeus@codewreck.org>
This commit is contained in:
Dominique Martinet 2024-10-24 08:52:10 +09:00
parent 42f7652d3e
commit f69999b5f9
4 changed files with 22 additions and 56 deletions

View File

@ -179,14 +179,13 @@ extern int v9fs_vfs_rename(struct mnt_idmap *idmap,
struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_dentry,
unsigned int flags);
extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid,
bool new);
extern struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid);
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 const struct netfs_request_ops v9fs_req_ops;
extern struct inode *v9fs_fid_iget_dotl(struct super_block *sb,
struct p9_fid *fid, bool new);
struct p9_fid *fid);
/* other default globals */
#define V9FS_PORT 564
@ -225,12 +224,12 @@ static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses)
*/
static inline struct inode *
v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid,
struct super_block *sb, bool new)
struct super_block *sb)
{
if (v9fs_proto_dotl(v9ses))
return v9fs_fid_iget_dotl(sb, fid, new);
return v9fs_fid_iget_dotl(sb, fid);
else
return v9fs_fid_iget(sb, fid, new);
return v9fs_fid_iget(sb, fid);
}
#endif

View File

@ -366,8 +366,7 @@ void v9fs_evict_inode(struct inode *inode)
clear_inode(inode);
}
struct inode *
v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new)
struct inode *v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid)
{
dev_t rdev;
int retval;
@ -379,18 +378,8 @@ v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new)
inode = iget_locked(sb, QID2INO(&fid->qid));
if (unlikely(!inode))
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW)) {
if (!new) {
goto done;
} else {
p9_debug(P9_DEBUG_VFS, "WARNING: Inode collision %ld\n",
inode->i_ino);
iput(inode);
remove_inode_hash(inode);
inode = iget_locked(sb, QID2INO(&fid->qid));
WARN_ON(!(inode->i_state & I_NEW));
}
}
if (!(inode->i_state & I_NEW))
return inode;
/*
* initialize the inode with the stat info
@ -414,11 +403,11 @@ v9fs_fid_iget(struct super_block *sb, struct p9_fid *fid, bool new)
v9fs_set_netfs_context(inode);
v9fs_cache_inode_get_cookie(inode);
unlock_new_inode(inode);
done:
return inode;
error:
iget_failed(inode);
return ERR_PTR(retval);
}
/**
@ -450,15 +439,8 @@ static int v9fs_at_to_dotl_flags(int flags)
*/
static void v9fs_dec_count(struct inode *inode)
{
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2) {
if (inode->i_nlink) {
drop_nlink(inode);
} else {
p9_debug(P9_DEBUG_VFS,
"WARNING: unexpected i_nlink zero %d inode %ld\n",
inode->i_nlink, inode->i_ino);
}
}
if (!S_ISDIR(inode->i_mode) || inode->i_nlink > 2)
drop_nlink(inode);
}
/**
@ -509,9 +491,6 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags)
} else
v9fs_dec_count(inode);
if (inode->i_nlink <= 0) /* no more refs unhash it */
remove_inode_hash(inode);
v9fs_invalidate_inode_attr(inode);
v9fs_invalidate_inode_attr(dir);
@ -577,7 +556,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, true);
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS,
@ -706,7 +685,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
else if (IS_ERR(fid))
inode = ERR_CAST(fid);
else
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb, false);
inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb);
/*
* If we had a rename on the server and a parallel lookup
* for the new name, then make sure we instantiate with

View File

@ -52,10 +52,7 @@ static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
return current_fsgid();
}
struct inode *
v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new)
struct inode *v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid)
{
int retval;
struct inode *inode;
@ -65,18 +62,8 @@ v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new)
inode = iget_locked(sb, QID2INO(&fid->qid));
if (unlikely(!inode))
return ERR_PTR(-ENOMEM);
if (!(inode->i_state & I_NEW)) {
if (!new) {
goto done;
} else { /* deal with race condition in inode number reuse */
p9_debug(P9_DEBUG_ERROR, "WARNING: Inode collision %lx\n",
inode->i_ino);
iput(inode);
remove_inode_hash(inode);
inode = iget_locked(sb, QID2INO(&fid->qid));
WARN_ON(!(inode->i_state & I_NEW));
}
}
if (!(inode->i_state & I_NEW))
return inode;
/*
* initialize the inode with the stat info
@ -103,11 +90,12 @@ v9fs_fid_iget_dotl(struct super_block *sb, struct p9_fid *fid, bool new)
goto error;
unlock_new_inode(inode);
done:
return inode;
error:
iget_failed(inode);
return ERR_PTR(retval);
}
struct dotl_openflag_map {
@ -259,7 +247,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
goto out;
}
inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err);
@ -352,7 +340,7 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
}
/* instantiate inode and assign the unopened fid to the dentry */
inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",
@ -788,7 +776,7 @@ v9fs_vfs_mknod_dotl(struct mnt_idmap *idmap, struct inode *dir,
err);
goto error;
}
inode = v9fs_fid_iget_dotl(dir->i_sb, fid, true);
inode = v9fs_fid_iget_dotl(dir->i_sb, fid);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n",

View File

@ -139,7 +139,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
else
sb->s_d_op = &v9fs_dentry_operations;
inode = v9fs_get_inode_from_fid(v9ses, fid, sb, true);
inode = v9fs_get_inode_from_fid(v9ses, fid, sb);
if (IS_ERR(inode)) {
retval = PTR_ERR(inode);
goto release_sb;