Fix false warning in inode_to_wb
Subsystems (4)
Andreas Gruenbacher
maintainerv3 cover Fix false warning in inode_to_wb
Changes in v3:
- In gfs2_fill_super(), initialize sdp->sd_inode after initializing ->s_blocksize_bits so that ->i_blkbits will be set correctly.
- inode_to_wb(const struct inode *inode) no longer calls inode_cgwb_enabled(struct inode *inode), so its argument can remain const.
Changes in v2:
- In inode_to_wb(), only check if the SB_I_CGROUPWB flag is set so that the consistency checks remain active even when cgroup writeback isn't actively used.
- When new_inode() fails in gfs2_fill_super(), clean up correctly.
- Improve the description of "gfs2: replace sd_aspace with sd_inode".
Andreas Gruenbacher (1):
gfs2: replace sd_aspace with sd_inode
Jan Kara (1):
writeback: Fix false warning in inode_to_wb()
fs/gfs2/glock.c | 3 +-- fs/gfs2/glops.c | 4 ++-- fs/gfs2/incore.h | 9 ++++++++- fs/gfs2/meta_io.c | 2 +- fs/gfs2/meta_io.h | 4 +--- fs/gfs2/ops_fstype.c | 31 ++++++++++++++++++------------- fs/gfs2/super.c | 2 +- include/linux/backing-dev.h | 1 + 8 files changed, 33 insertions(+), 23 deletions(-)
Signature · 1 line
2.48.1
Andreas Gruenbacher
maintainerPATCH v3 1/2 gfs2: replace sd_aspace with sd_inode
Currently, sdp->sd_aspace and the per-inode metadata address spaces use sb->s_bdev->bd_mapping->host as their ->host; folios in those address spaces will thus appear to be on bdev rather than on gfs2 filesystems. This is a problem because gfs2 doesn't support cgroup writeback (SB_I_CGROUPWB), but bdev does.
Fix that by using a "dummy" gfs2 inode as ->host in those address spaces. When coming from a folio, folio->mapping->host->i_sb will then be a gfs2 super block and the SB_I_CGROUPWB flag will not be set in sb->s_iflags.
Based on a previous version from Bob Peterson from several years ago. Thanks to Tetsuo Handa, Jan Kara, and Rafael Aquini for helping figure this out.
--- fs/gfs2/glock.c | 3 +-- fs/gfs2/glops.c | 4 ++-- fs/gfs2/incore.h | 9 ++++++++- fs/gfs2/meta_io.c | 2 +- fs/gfs2/meta_io.h | 4 +--- fs/gfs2/ops_fstype.c | 31 ++++++++++++++++++------------- fs/gfs2/super.c | 2 +- 7 files changed, 32 insertions(+), 23 deletions(-)
fs/gfs2/glock.c +1 -2
@@ -1166,7 +1166,6 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, const struct gfs2_glock_operations *glops, int create, struct gfs2_glock **glp) { - struct super_block *s = sdp->sd_vfs; struct lm_lockname name = { .ln_number = number, .ln_type = glops->go_type, .ln_sbd = sdp };
@@ -1229,7 +1228,7 @@ int gfs2_glock_get(struct gfs2_sbd *sdp, u64 number, mapping =gfs2_glock2aspace (gl);if (mapping) { mapping->a_ops = &gfs2_meta_aops; - mapping->host = s->s_bdev->bd_mapping->host; + mapping->host = sdp->sd_inode; mapping->flags =0 ;mapping_set_gfp_mask (mapping,GFP_NOFS ); mapping->i_private_data =NULL ;
fs/gfs2/glops.c +2 -2
@@ -168,7 +168,7 @@ void gfs2_ail_flush(struct gfs2_glock *gl, bool fsync)static int gfs2_rgrp_metasync (struct gfs2_glock *gl) {struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; -struct address_space *metamapping = &sdp->sd_aspace; +struct address_space *metamapping =gfs2_aspace (sdp);struct gfs2_rgrpd *rgd =gfs2_glock2rgrp (gl);const unsigned bsize = sdp->sd_sb.sb_bsize;loff_t start = (rgd->rd_addr * bsize) &PAGE_MASK ;
@@ -225,7 +225,7 @@ static int rgrp_go_sync(struct gfs2_glock *gl)static void rgrp_go_inval (struct gfs2_glock *gl,int flags) {struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; -struct address_space *mapping = &sdp->sd_aspace; +struct address_space *mapping =gfs2_aspace (sdp);struct gfs2_rgrpd *rgd =gfs2_glock2rgrp (gl);const unsigned bsize = sdp->sd_sb.sb_bsize;loff_t start, end;
fs/gfs2/incore.h +8 -1
@@ -795,7 +795,7 @@ struct gfs2_sbd {/* Log stuff */ -struct address_space sd_aspace; +struct inode *sd_inode;spinlock_t sd_log_lock;
@@ -851,6 +851,13 @@ struct gfs2_sbd {unsigned long sd_glock_dqs_held; }; +#define GFS2_BAD_INO 1 + +static inline struct address_space *gfs2_aspace (struct gfs2_sbd *sdp) +{ +return sdp->sd_inode->i_mapping; +} +static inline void gfs2_glstats_inc (struct gfs2_glock *gl,int which) { gl->gl_stats.stats[which]++;
fs/gfs2/meta_io.c +1 -1
@@ -132,7 +132,7 @@ struct buffer_head *gfs2_getbuf(struct gfs2_glock *gl, u64 blkno, int create)unsigned int bufnum;if (mapping ==NULL ) - mapping = &sdp->sd_aspace; + mapping =gfs2_aspace (sdp); shift =PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift; index = blkno >> shift;/* convert block to page */
fs/gfs2/meta_io.h +1 -3
@@ -44,9 +44,7 @@ static inline struct gfs2_sbd *gfs2_mapping2sbd(struct address_space *mapping)struct gfs2_glock_aspace *gla = container_of(mapping, struct gfs2_glock_aspace, mapping);return gla->glock.gl_name.ln_sbd; - }else if (mapping->a_ops == &gfs2_rgrp_aops) - return container_of(mapping, struct gfs2_sbd, sd_aspace); -else + }else return inode->i_sb->s_fs_info; }
fs/gfs2/ops_fstype.c +18 -13
@@ -72,7 +72,6 @@ void free_sbd(struct gfs2_sbd *sdp)static struct gfs2_sbd *init_sbd (struct super_block *sb) {struct gfs2_sbd *sdp; -struct address_space *mapping; sdp =kzalloc (sizeof (struct gfs2_sbd ),GFP_KERNEL );if (!sdp)
@@ -109,16 +108,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb)INIT_LIST_HEAD (&sdp->sd_sc_inodes_list); - mapping = &sdp->sd_aspace; - -address_space_init_once (mapping); - mapping->a_ops = &gfs2_rgrp_aops; - mapping->host = sb->s_bdev->bd_mapping->host; - mapping->flags =0 ; -mapping_set_gfp_mask (mapping,GFP_NOFS ); - mapping->i_private_data =NULL ; - mapping->writeback_index =0 ; -spin_lock_init (&sdp->sd_log_lock);atomic_set (&sdp->sd_log_pinned,0 );INIT_LIST_HEAD (&sdp->sd_log_revokes);
@@ -1135,6 +1124,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)int silent = fc->sb_flags &SB_SILENT ;struct gfs2_sbd *sdp;struct gfs2_holder mount_gh; +struct address_space *mapping;int error; sdp =init_sbd (sb);
@@ -1156,6 +1146,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) sb->s_flags |=SB_NOSEC ; sb->s_magic =GFS2_MAGIC ; sb->s_op = &gfs2_super_ops; + sb->s_d_op = &gfs2_dops; sb->s_export_op = &gfs2_export_ops; sb->s_qcop = &gfs2_quotactl_ops;
@@ -1181,9 +1172,21 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) sdp->sd_tune.gt_statfs_quantum =30 ; } +/* Set up an address space for metadata writes */ + sdp->sd_inode =new_inode (sb); + error = -ENOMEM ; +if (!sdp->sd_inode) + goto fail_free; + sdp->sd_inode->i_ino =GFS2_BAD_INO ; + sdp->sd_inode->i_size =OFFSET_MAX ; + + mapping =gfs2_aspace (sdp); + mapping->a_ops = &gfs2_rgrp_aops; +mapping_set_gfp_mask (mapping,GFP_NOFS ); + error =init_names (sdp, silent);if (error) - goto fail_free; + goto fail_iput;snprintf (sdp->sd_fsname,sizeof (sdp->sd_fsname),"%s" , sdp->sd_table_name);
@@ -1192,7 +1195,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)WQ_MEM_RECLAIM |WQ_HIGHPRI |WQ_FREEZABLE ,0 , sdp->sd_fsname);if (!sdp->sd_glock_wq) - goto fail_free; + goto fail_iput; sdp->sd_delete_wq =alloc_workqueue ("gfs2-delete/%s" ,WQ_MEM_RECLAIM |WQ_FREEZABLE ,0 , sdp->sd_fsname);
@@ -1309,6 +1312,8 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) fail_glock_wq:if (sdp->sd_glock_wq)destroy_workqueue (sdp->sd_glock_wq); +fail_iput: +iput (sdp->sd_inode); fail_free:free_sbd (sdp); sb->s_fs_info =NULL ;
fs/gfs2/super.c +1 -1
@@ -648,7 +648,7 @@ static void gfs2_put_super(struct super_block *sb)gfs2_jindex_free (sdp);/* Take apart glock structures and buffer lists */ gfs2_gl_hash_clear (sdp); -truncate_inode_pages_final (&sdp->sd_aspace); +iput (sdp->sd_inode);gfs2_delete_debugfs_file (sdp);gfs2_sys_fs_del (sdp);
Signature · 1 line
2.48.1
Andreas Gruenbacher
maintainerPATCH v3 2/2 writeback: Fix false warning in inode_to_wb()
In reply to Andreas GruenbacherFrom: Jan Kara <[email protected]>
inode_to_wb() is used also for filesystems that don't support cgroup writeback. For these filesystems inode->i_wb is stable during the lifetime of the inode (it points to bdi->wb) and there's no need to hold locks protecting the inode->i_wb dereference. Improve the warning in inode_to_wb() to not trigger for these filesystems.
--- include/linux/backing-dev.h | 1 + 1 file changed, 1 insertion(+)
include/linux/backing-dev.h +1 -0
@@ -249,6 +249,7 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) {#ifdef CONFIG_LOCKDEP WARN_ON_ONCE (debug_locks && + (inode->i_sb->s_iflags &SB_I_CGROUPWB ) && (!lockdep_is_held (&inode->i_lock) && !lockdep_is_held (&inode->i_mapping->i_pages.xa_lock) && !lockdep_is_held (&inode->i_wb->list_lock)));
Signature · 1 line
2.48.1
Jan Kara
reviewerRe: [PATCH v3 2/2] writeback: Fix false warning in inode_to_wb()
Hi Andrew!
Can you please take this patch through MM tree? Thanks! Andreas is already taking the first patch in the series through GFS2 tree.
Honza
Quoted 29 lines · Andreas Gruenbacher
From: Jan Kara <[email protected]>
inode_to_wb()is used also for filesystems that don't support cgroup writeback. For these filesystemsinode->i_wbis stable during the lifetime of the inode (it points tobdi->wb) and there's no need to hold locks protecting theinode->i_wbdereference. Improve the warning ininode_to_wb()to not trigger for these filesystems.Signed-off-by Jan Kara <[email protected]>Reviewed-by Andreas Gruenbacher <[email protected]>--- include/linux/backing-dev.h | 1 + 1 file changed, 1 insertion(+)include/linux/backing-dev.h +1
-0@@ -249,6 +249,7 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) {#ifdef CONFIG_LOCKDEP WARN_ON_ONCE (debug_locks && + (inode->i_sb->s_iflags &SB_I_CGROUPWB ) && (!lockdep_is_held (&inode->i_lock) && !lockdep_is_held (&inode->i_mapping->i_pages.xa_lock) && !lockdep_is_held (&inode->i_wb->list_lock)));Signature · 1 line
2.48.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
Andrew Morton
maintainerRe: [PATCH v3 2/2] writeback: Fix false warning in inode_to_wb()
In reply to Andreas GruenbacherQuoted 13 lines · On Sat, 12 Apr 2025 18:39:12 +0200 Andreas Gruenbacher <[email protected]>…
From: Jan Kara <[email protected]>
inode_to_wb()is used also for filesystems that don't support cgroup writeback. For these filesystemsinode->i_wbis stable during the lifetime of the inode (it points tobdi->wb) and there's no need to hold locks protecting theinode->i_wbdereference. Improve the warning ininode_to_wb()to not trigger for these filesystems....
include/linux/backing-dev.h static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) · line 255
Quoted 7 lines
include/linux/backing-dev.h +1
-0@@ -249,6 +249,7 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) {#ifdef CONFIG_LOCKDEP WARN_ON_ONCE (debug_locks && + (inode->i_sb->s_iflags &SB_I_CGROUPWB ) && (!lockdep_is_held (&inode->i_lock) && !lockdep_is_held (&inode->i_mapping->i_pages.xa_lock) && !lockdep_is_held (&inode->i_wb->list_lock)));
Is this a does-nothing now GFS2 has been altered?
Otherwise, a bogus WARN is something we'll want to eliminate from -stable kernels also. Are we able to identify a Fixes: for this?
Thanks.
Andreas Gruenbacher
maintainerRe: [PATCH v3 2/2] writeback: Fix false warning in inode_to_wb()
Quoted 24 lines · Andrew Morton
Quoted 13 lines · On Sat, 12 Apr 2025 18:39:12 +0200 Andreas Gruenbacher <[email protected]>…
From: Jan Kara <[email protected]>
inode_to_wb()is used also for filesystems that don't support cgroup writeback. For these filesystemsinode->i_wbis stable during the lifetime of the inode (it points tobdi->wb) and there's no need to hold locks protecting theinode->i_wbdereference. Improve the warning ininode_to_wb()to not trigger for these filesystems....
include/linux/backing-dev.h static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) · line 255
Quoted 7 lines
include/linux/backing-dev.h +1
-0@@ -249,6 +249,7 @@ static inline struct bdi_writeback *inode_to_wb(const struct inode *inode) {#ifdef CONFIG_LOCKDEP WARN_ON_ONCE (debug_locks && + (inode->i_sb->s_iflags &SB_I_CGROUPWB ) && (!lockdep_is_held (&inode->i_lock) && !lockdep_is_held (&inode->i_mapping->i_pages.xa_lock) && !lockdep_is_held (&inode->i_wb->list_lock)));Is this a does-nothing now GFS2 has been altered?
Quoted 2 lines
Otherwise, a bogus WARN is something we'll want to eliminate from -stable kernels also. Are we able to identify a Fixes: for this?
The excess warnings started with commit:
Getting rid of them requires this change, together with "gfs2: replace sd_aspace with sd_inode" from gfs2 for-next:
https://web.git.kernel.org/pub/scm/linux/kernel/git/gfs2/linux-gfs2.git/commit/?h=
a5fb828aba730d08aa6dec6bce3839f25e1f7a9d
Thanks,
Andreas
Andrew Morton
maintainerRe: [PATCH v3 2/2] writeback: Fix false warning in inode_to_wb()
In reply to Andreas GruenbacherQuoted 8 lines · On Sat, 12 Apr 2025 18:39:12 +0200 Andreas Gruenbacher <[email protected]>…
inode_to_wb()is used also for filesystems that don't support cgroup writeback. For these filesystemsinode->i_wbis stable during the lifetime of the inode (it points tobdi->wb) and there's no need to hold locks protecting theinode->i_wbdereference. Improve the warning ininode_to_wb()to not trigger for these filesystems.Signed-off-by Jan Kara <[email protected]>Reviewed-by Andreas Gruenbacher <[email protected]>
Yoo were on the patch delivery path so there should be a signed-off-by:Andreas somewhere. I made that change to the mm.git copy of this patch.
Andreas Gruenbacher
maintainerRe: [PATCH v3 2/2] writeback: Fix false warning in inode_to_wb()
Quoted 8 lines · Andrew Morton
Quoted 6 lines · On Sat, 12 Apr 2025 18:39:12 +0200 Andreas Gruenbacher <[email protected]>…
inode_to_wb()is used also for filesystems that don't support cgroup writeback. For these filesystemsinode->i_wbis stable during the lifetime of the inode (it points tobdi->wb) and there's no need to hold locks protecting theinode->i_wbdereference. Improve the warning ininode_to_wb()to not trigger for these filesystems.
Quoted 6 lines
Quoted 2 lines
Signed-off-by Jan Kara <[email protected]>Reviewed-by Andreas Gruenbacher <[email protected]>Yoo were on the patch delivery path so there should be a signed-off-by:Andreas somewhere. I made that change to the mm.git copy of this patch.
I guess that's fine as long as Jan is credited as the author.
Thanks,
Andreas