Message ID | 20240228160213.1988854-3-mszeredi@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [1/4] fuse: replace remaining make_bad_inode() with fuse_make_bad() | expand |
On 2/28/24 17:02, Miklos Szeredi wrote: > The root inode is assumed to be always hashed. Do not unhash the root > inode even if it is marked BAD. > > Fixes: 5d069dbe8aaf ("fuse: fix bad inode") > Cc: <stable@vger.kernel.org> # v5.11 > Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> > --- > fs/fuse/fuse_i.h | 1 - > fs/fuse/inode.c | 7 +++++-- > 2 files changed, 5 insertions(+), 3 deletions(-) > > diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h > index 7bd3552b1e80..4ef6087f0e5c 100644 > --- a/fs/fuse/fuse_i.h > +++ b/fs/fuse/fuse_i.h > @@ -994,7 +994,6 @@ static inline bool fuse_stale_inode(const struct inode *inode, int generation, > > static inline void fuse_make_bad(struct inode *inode) > { > - remove_inode_hash(inode); > set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state); > } Hmm, what about callers like fuse_direntplus_link? It now never removes the inode hash for these? Depend on lookup/revalidate? Thanks, Bernd > > diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c > index c26a84439934..aa0614e8791c 100644 > --- a/fs/fuse/inode.c > +++ b/fs/fuse/inode.c > @@ -475,8 +475,11 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, > } else if (fuse_stale_inode(inode, generation, attr)) { > /* nodeid was reused, any I/O on the old inode should fail */ > fuse_make_bad(inode); > - iput(inode); > - goto retry; > + if (inode != d_inode(sb->s_root)) { > + remove_inode_hash(inode); > + iput(inode); > + goto retry; > + } > } > fi = get_fuse_inode(inode); > spin_lock(&fi->lock);
On Wed, 28 Feb 2024 at 17:34, Bernd Schubert <bernd.schubert@fastmail.fm> wrote: > > > > On 2/28/24 17:02, Miklos Szeredi wrote: > > The root inode is assumed to be always hashed. Do not unhash the root > > inode even if it is marked BAD. > > > > Fixes: 5d069dbe8aaf ("fuse: fix bad inode") > > Cc: <stable@vger.kernel.org> # v5.11 > > Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> > > --- > > fs/fuse/fuse_i.h | 1 - > > fs/fuse/inode.c | 7 +++++-- > > 2 files changed, 5 insertions(+), 3 deletions(-) > > > > diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h > > index 7bd3552b1e80..4ef6087f0e5c 100644 > > --- a/fs/fuse/fuse_i.h > > +++ b/fs/fuse/fuse_i.h > > @@ -994,7 +994,6 @@ static inline bool fuse_stale_inode(const struct inode *inode, int generation, > > > > static inline void fuse_make_bad(struct inode *inode) > > { > > - remove_inode_hash(inode); > > set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state); > > } > > Hmm, what about callers like fuse_direntplus_link? It now never removes > the inode hash for these? Depend on lookup/revalidate? Good questions. In that case the dentry will be unhashed, and after retrying it will go through fuse_iget(), which will unhash the inode. So AFAICS the only place the inode needs to be unhashed is in fuse_iget(), which is the real fix in 775c5033a0d1 ("fuse: fix live lock in fuse_iget()"). Thanks, Miklos
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7bd3552b1e80..4ef6087f0e5c 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -994,7 +994,6 @@ static inline bool fuse_stale_inode(const struct inode *inode, int generation, static inline void fuse_make_bad(struct inode *inode) { - remove_inode_hash(inode); set_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state); } diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index c26a84439934..aa0614e8791c 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -475,8 +475,11 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, } else if (fuse_stale_inode(inode, generation, attr)) { /* nodeid was reused, any I/O on the old inode should fail */ fuse_make_bad(inode); - iput(inode); - goto retry; + if (inode != d_inode(sb->s_root)) { + remove_inode_hash(inode); + iput(inode); + goto retry; + } } fi = get_fuse_inode(inode); spin_lock(&fi->lock);
The root inode is assumed to be always hashed. Do not unhash the root inode even if it is marked BAD. Fixes: 5d069dbe8aaf ("fuse: fix bad inode") Cc: <stable@vger.kernel.org> # v5.11 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- fs/fuse/fuse_i.h | 1 - fs/fuse/inode.c | 7 +++++-- 2 files changed, 5 insertions(+), 3 deletions(-)