From e0600e95bd5b5a31d83fe29143f44069dacf821d Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 13:40:45 +0200 Subject: [PATCH 01/19] gfs2: Avoid ip->i_gl dereferences in gfs2_inode_lookup and gfs2_create_inode Store the inode glock in a separate variable instead of repeatedly retrieving it as ip->i_gl. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/inode.c | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index f361876c5583..438519bc06d4 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -130,6 +130,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, { struct inode *inode; struct gfs2_inode *ip; + struct gfs2_glock *gl = NULL; struct gfs2_holder i_gh; int error; @@ -147,9 +148,10 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, gfs2_setup_inode(inode); error = gfs2_glock_get(sdp, no_addr, &gfs2_inode_glops, CREATE, - &ip->i_gl); + &gl); if (unlikely(error)) goto fail; + ip->i_gl = gl; error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); @@ -178,14 +180,14 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, * block. We read the inode when instantiating it * after possibly checking the block type. */ - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, GL_SKIP, &i_gh); if (error) goto fail; error = -ESTALE; if (no_formal_ino && - gfs2_inode_already_deleted(ip->i_gl, no_formal_ino)) + gfs2_inode_already_deleted(gl, no_formal_ino)) goto fail; if (blktype != GFS2_BLKST_FREE) { @@ -196,20 +198,20 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, } } - set_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags); + set_bit(GLF_INSTANTIATE_NEEDED, &gl->gl_flags); /* Lowest possible timestamp; will be overwritten in gfs2_dinode_in. */ inode_set_atime(inode, 1LL << (8 * sizeof(inode_get_atime_sec(inode)) - 1), 0); - glock_set_object(ip->i_gl, ip); + glock_set_object(gl, ip); if (type == DT_UNKNOWN) { /* Inode glock must be locked already */ error = gfs2_instantiate(&i_gh); if (error) { - glock_clear_object(ip->i_gl, ip); + glock_clear_object(gl, ip); goto fail; } } else { @@ -240,8 +242,8 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, gfs2_glock_dq_uninit(&ip->i_iopen_gh); if (gfs2_holder_initialized(&i_gh)) gfs2_glock_dq_uninit(&i_gh); - if (ip->i_gl) { - gfs2_glock_put(ip->i_gl); + if (gl) { + gfs2_glock_put(gl); ip->i_gl = NULL; } iget_failed(inode); @@ -708,7 +710,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, struct inode *inode = NULL; struct gfs2_inode *dip = GFS2_I(dir), *ip; struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); - struct gfs2_glock *io_gl; + struct gfs2_glock *gl = NULL, *io_gl; int error, dealloc_error; u32 aflags = 0; unsigned blocks = 1; @@ -832,9 +834,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, gfs2_set_inode_blocks(inode, blocks); - error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &ip->i_gl); + error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &gl); if (error) goto fail_dealloc_inode; + ip->i_gl = gl; error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl); if (error) @@ -854,10 +857,10 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (error) goto fail_gunlock2; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, GL_SKIP, &gh); if (error) goto fail_gunlock3; - clear_bit(GLF_INSTANTIATE_NEEDED, &ip->i_gl->gl_flags); + clear_bit(GLF_INSTANTIATE_NEEDED, &gl->gl_flags); error = gfs2_trans_begin(sdp, blocks, 0); if (error) @@ -870,7 +873,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, init_dinode(dip, ip, symname); gfs2_trans_end(sdp); - glock_set_object(ip->i_gl, ip); + glock_set_object(gl, ip); glock_set_object(io_gl, ip); gfs2_set_iop(inode); @@ -914,7 +917,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, return error; fail_gunlock4: - glock_clear_object(ip->i_gl, ip); + glock_clear_object(gl, ip); glock_clear_object(io_gl, ip); fail_gunlock3: gfs2_glock_dq_uninit(&ip->i_iopen_gh); @@ -932,8 +935,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, fs_warn(sdp, "%s: %d\n", __func__, dealloc_error); ip->i_no_addr = 0; fail_free_inode: - if (ip->i_gl) { - gfs2_glock_put(ip->i_gl); + if (gl) { + gfs2_glock_put(gl); ip->i_gl = NULL; } gfs2_rs_deltree(&ip->i_res); From 9fa5390e3e70a4d9e2cca4565ae44c5385cf63a2 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 13:45:28 +0200 Subject: [PATCH 02/19] gfs2: Get to super block from inode in tracepoints When we have a gfs2 inode, use that to get to the super block instead of going via the glock. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/trace_gfs2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/gfs2/trace_gfs2.h b/fs/gfs2/trace_gfs2.h index bc40320ef239..0c60d755ba76 100644 --- a/fs/gfs2/trace_gfs2.h +++ b/fs/gfs2/trace_gfs2.h @@ -457,7 +457,7 @@ TRACE_EVENT(gfs2_bmap, ), TP_fast_assign( - __entry->dev = glock_sbd(ip->i_gl)->sd_vfs->s_dev; + __entry->dev = ip->i_inode.i_sb->s_dev; __entry->lblock = lblock; __entry->pblock = buffer_mapped(bh) ? bh->b_blocknr : 0; __entry->inum = ip->i_no_addr; @@ -493,7 +493,7 @@ TRACE_EVENT(gfs2_iomap_start, ), TP_fast_assign( - __entry->dev = glock_sbd(ip->i_gl)->sd_vfs->s_dev; + __entry->dev = ip->i_inode.i_sb->s_dev; __entry->inum = ip->i_no_addr; __entry->pos = pos; __entry->length = length; @@ -525,7 +525,7 @@ TRACE_EVENT(gfs2_iomap_end, ), TP_fast_assign( - __entry->dev = glock_sbd(ip->i_gl)->sd_vfs->s_dev; + __entry->dev = ip->i_inode.i_sb->s_dev; __entry->inum = ip->i_no_addr; __entry->offset = iomap->offset; __entry->length = iomap->length; From 96e08c4dfed57790af22e0e2c1401fc8d12a9e0b Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 14:47:05 +0200 Subject: [PATCH 03/19] gfs2: Add inode variables Add inode variables in a few places to get rid of '&ip->i_inode'. This cleans up the code a little and prepares for the next step of adding an accessor function for ip->i_gl. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 37 ++++++++++++++++++++----------------- fs/gfs2/dir.c | 4 +++- fs/gfs2/file.c | 5 +++-- fs/gfs2/quota.c | 25 ++++++++++++++----------- fs/gfs2/recovery.c | 5 +++-- 5 files changed, 43 insertions(+), 33 deletions(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 73c626971163..636139f463b0 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -89,6 +89,7 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh, static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) { + struct inode *inode = &ip->i_inode; struct buffer_head *bh, *dibh; struct gfs2_dinode *di; u64 block = 0; @@ -99,7 +100,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) if (error) return error; - if (i_size_read(&ip->i_inode)) { + if (i_size_read(inode)) { /* Get a free block, fill it with the stuffed data, and write it out to disk */ @@ -108,7 +109,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) if (error) goto out_brelse; if (isdir) { - gfs2_trans_remove_revoke(GFS2_SB(&ip->i_inode), block, 1); + gfs2_trans_remove_revoke(GFS2_SB(inode), block, 1); error = gfs2_dir_get_new_buffer(ip, block, &bh); if (error) goto out_brelse; @@ -128,10 +129,10 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) di = (struct gfs2_dinode *)dibh->b_data; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); - if (i_size_read(&ip->i_inode)) { + if (i_size_read(inode)) { *(__be64 *)(di + 1) = cpu_to_be64(block); - gfs2_add_inode_blocks(&ip->i_inode, 1); - di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(&ip->i_inode)); + gfs2_add_inode_blocks(inode, 1); + di->di_blocks = cpu_to_be64(gfs2_get_inode_blocks(inode)); } ip->i_height = 1; @@ -1488,7 +1489,8 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, struct buffer_head *bh, __be64 *start, __be64 *end, bool meta, u32 *btotal) { - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct inode *inode = &ip->i_inode; + struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_rgrpd *rgd; struct gfs2_trans *tr; __be64 *p; @@ -1546,7 +1548,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, jblocks_rqsted = rgd->rd_length + RES_DINODE + RES_INDIRECT; - isize_blks = gfs2_get_inode_blocks(&ip->i_inode); + isize_blks = gfs2_get_inode_blocks(inode); if (isize_blks > atomic_read(&sdp->sd_log_thresh2)) jblocks_rqsted += atomic_read(&sdp->sd_log_thresh2); @@ -1597,7 +1599,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, if (bstart) { __gfs2_free_blocks(ip, rgd, bstart, (u32)blen, meta); (*btotal) += blen; - gfs2_add_inode_blocks(&ip->i_inode, -blen); + gfs2_add_inode_blocks(inode, -blen); } bstart = bn; blen = 1; @@ -1605,7 +1607,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, if (bstart) { __gfs2_free_blocks(ip, rgd, bstart, (u32)blen, meta); (*btotal) += blen; - gfs2_add_inode_blocks(&ip->i_inode, -blen); + gfs2_add_inode_blocks(inode, -blen); } out_unlock: if (!ret && blks_outside_rgrp) { /* If buffer still has non-zero blocks @@ -1620,7 +1622,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, /* Every transaction boundary, we rewrite the dinode to keep its di_blocks current in case of failure. */ - inode_set_mtime_to_ts(&ip->i_inode, inode_set_ctime_current(&ip->i_inode)); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); gfs2_trans_add_meta(ip->i_gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -1746,7 +1748,8 @@ static inline bool walk_done(struct gfs2_sbd *sdp, */ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) { - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct inode *inode = &ip->i_inode; + struct gfs2_sbd *sdp = GFS2_SB(inode); u64 maxsize = sdp->sd_heightsize[ip->i_height]; struct metapath mp = {}; struct buffer_head *dibh, *bh; @@ -1985,9 +1988,8 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) down_write(&ip->i_rw_mutex); } gfs2_statfs_change(sdp, 0, +btotal, 0); - gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid, - ip->i_inode.i_gid); - inode_set_mtime_to_ts(&ip->i_inode, inode_set_ctime_current(&ip->i_inode)); + gfs2_quota_change(ip, -(s64)btotal, inode->i_uid, inode->i_gid); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); gfs2_trans_add_meta(ip->i_gl, dibh); gfs2_dinode_out(ip, dibh->b_data); up_write(&ip->i_rw_mutex); @@ -2010,7 +2012,8 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) static int trunc_end(struct gfs2_inode *ip) { - struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); + struct inode *inode = &ip->i_inode; + struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh; int error; @@ -2024,13 +2027,13 @@ static int trunc_end(struct gfs2_inode *ip) if (error) goto out; - if (!i_size_read(&ip->i_inode)) { + if (!i_size_read(inode)) { ip->i_height = 0; ip->i_goal = ip->i_no_addr; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); gfs2_ordered_del_inode(ip); } - inode_set_mtime_to_ts(&ip->i_inode, inode_set_ctime_current(&ip->i_inode)); + inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG; gfs2_trans_add_meta(ip->i_gl, dibh); diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index 0237b36b9eb1..f6111276ebb0 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -759,10 +759,12 @@ static struct gfs2_dirent *gfs2_dirent_split_alloc(struct inode *inode, static int get_leaf(struct gfs2_inode *dip, u64 leaf_no, struct buffer_head **bhp) { + struct inode *inode = &dip->i_inode; + struct gfs2_sbd *sdp = GFS2_SB(inode); int error; error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, 0, bhp); - if (!error && gfs2_metatype_check(GFS2_SB(&dip->i_inode), *bhp, GFS2_METATYPE_LF)) { + if (!error && gfs2_metatype_check(sdp, *bhp, GFS2_METATYPE_LF)) { /* pr_info("block num=%llu\n", leaf_no); */ error = -EIO; } diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index b8c10de113ba..164e160e9064 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -812,7 +812,8 @@ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to, struct gfs2_holder *gh) { struct file *file = iocb->ki_filp; - struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); + struct inode *inode = file->f_mapping->host; + struct gfs2_inode *ip = GFS2_I(inode); size_t prev_count = 0, window_size = 0; size_t read = 0; ssize_t ret; @@ -906,7 +907,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from, if (ret) goto out_uninit; /* Silently fall back to buffered I/O when writing beyond EOF */ - if (iocb->ki_pos + iov_iter_count(from) > i_size_read(&ip->i_inode)) + if (iocb->ki_pos + iov_iter_count(from) > i_size_read(inode)) goto out_unlock; from->nofault = true; diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 001c8b39ca55..0cb2bb0aec7b 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -740,8 +740,8 @@ static void do_qc(struct gfs2_quota_data *qd, s64 change) static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index, unsigned off, void *buf, unsigned bytes) { - struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); - struct inode *inode = &ip->i_inode; + struct inode *inode = sdp->sd_quota_inode; + struct gfs2_inode *ip = GFS2_I(inode); struct address_space *mapping = inode->i_mapping; struct folio *folio; struct buffer_head *bh; @@ -908,7 +908,8 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, u64 sync_gen) { struct gfs2_sbd *sdp = (*qda)->qd_sbd; - struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); + struct inode *inode = sdp->sd_quota_inode; + struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_alloc_parms ap = {}; unsigned int data_blocks, ind_blocks; struct gfs2_holder *ghs, i_gh; @@ -927,7 +928,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, return -ENOMEM; sort(qda, num_qd, sizeof(struct gfs2_quota_data *), sort_qd, NULL); - inode_lock(&ip->i_inode); + inode_lock(inode); for (qx = 0; qx < num_qd; qx++) { error = gfs2_glock_nq_init(qda[qx]->qd_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, &ghs[qx]); @@ -991,9 +992,9 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, out_dq: while (qx--) gfs2_glock_dq_uninit(&ghs[qx]); - inode_unlock(&ip->i_inode); + inode_unlock(inode); kfree(ghs); - gfs2_log_flush(glock_sbd(ip->i_gl), ip->i_gl, + gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC); if (!error) { for (x = 0; x < num_qd; x++) { @@ -1402,7 +1403,8 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) int gfs2_quota_init(struct gfs2_sbd *sdp) { - struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); + struct inode *inode = sdp->sd_qc_inode; + struct gfs2_inode *ip = GFS2_I(inode); u64 size = i_size_read(sdp->sd_qc_inode); unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift; unsigned int x, slot = 0; @@ -1434,7 +1436,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) if (!extlen) { extlen = 32; - error = gfs2_get_extent(&ip->i_inode, x, &dblock, &extlen); + error = gfs2_get_extent(inode, x, &dblock, &extlen); if (error) goto fail; } @@ -1714,7 +1716,8 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, struct qc_dqblk *fdq) { struct gfs2_sbd *sdp = sb->s_fs_info; - struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); + struct inode *inode = sdp->sd_quota_inode; + struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_quota_data *qd; struct gfs2_holder q_gh, i_gh; unsigned int data_blocks, ind_blocks; @@ -1741,7 +1744,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, if (error) goto out_put; - inode_lock(&ip->i_inode); + inode_lock(inode); error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); if (error) goto out_unlockput; @@ -1807,7 +1810,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, gfs2_glock_dq_uninit(&q_gh); out_unlockput: gfs2_qa_put(ip); - inode_unlock(&ip->i_inode); + inode_unlock(inode); out_put: qd_put(qd); return error; diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 616c46aa3434..b45aa3032ca2 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -32,14 +32,15 @@ struct workqueue_struct *gfs2_recovery_wq; int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, struct buffer_head **bh) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); + struct inode *inode = jd->jd_inode; + struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_glock *gl = ip->i_gl; u64 dblock; u32 extlen; int error; extlen = 32; - error = gfs2_get_extent(&ip->i_inode, blk, &dblock, &extlen); + error = gfs2_get_extent(inode, blk, &dblock, &extlen); if (error) return error; if (!dblock) { From b2ac87810d6027fa0823d9158c7477feeaed3e1a Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 12:55:19 +0200 Subject: [PATCH 04/19] gfs2: Introduce gfs2_inode_glock Introduce gfs2_inode_glock(inode) for getting from an inode to its inode glock. This obsoletes the local variable 'ip' in several places. The remaining direct accesses to ip->i_gl are for inode creation and distruction, and will be cleaned up in the next patch. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/acl.c | 11 +++--- fs/gfs2/aops.c | 17 ++++----- fs/gfs2/bmap.c | 48 +++++++++++++++---------- fs/gfs2/dentry.c | 6 ++-- fs/gfs2/dir.c | 57 ++++++++++++++++++------------ fs/gfs2/export.c | 7 ++-- fs/gfs2/file.c | 69 ++++++++++++++++++++---------------- fs/gfs2/glock.c | 4 ++- fs/gfs2/glops.c | 3 +- fs/gfs2/incore.h | 5 ++- fs/gfs2/inode.c | 83 ++++++++++++++++++++++++-------------------- fs/gfs2/lops.c | 18 +++++----- fs/gfs2/meta_io.c | 7 ++-- fs/gfs2/ops_fstype.c | 25 +++++++------ fs/gfs2/quota.c | 29 ++++++++-------- fs/gfs2/recovery.c | 12 +++---- fs/gfs2/rgrp.c | 4 +-- fs/gfs2/super.c | 70 +++++++++++++++++++------------------ fs/gfs2/util.c | 8 ++--- fs/gfs2/xattr.c | 69 +++++++++++++++++++++--------------- 20 files changed, 307 insertions(+), 245 deletions(-) diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index a5b60778b91c..49e489fe27ef 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -59,7 +59,7 @@ static struct posix_acl *__gfs2_get_acl(struct inode *inode, int type) struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu) { - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; bool need_unlock = false; struct posix_acl *acl; @@ -67,8 +67,8 @@ struct posix_acl *gfs2_get_acl(struct inode *inode, int type, bool rcu) if (rcu) return ERR_PTR(-ECHILD); - if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { - int ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, + if (!gfs2_glock_is_locked_by_me(gl)) { + int ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); if (ret) return ERR_PTR(ret); @@ -106,6 +106,7 @@ int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, struct posix_acl *acl, int type) { struct inode *inode = d_inode(dentry); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; bool need_unlock = false; @@ -119,8 +120,8 @@ int gfs2_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, if (ret) return ret; - if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (!gfs2_glock_is_locked_by_me(gl)) { + ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &gh); if (ret) goto out; need_unlock = true; diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c index 0a7b8076af3a..ee11d494e47c 100644 --- a/fs/gfs2/aops.c +++ b/fs/gfs2/aops.c @@ -102,7 +102,7 @@ static int __gfs2_jdata_write_folio(struct folio *folio, struct writeback_control *wbc) { struct inode *inode = folio->mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); if (folio_test_checked(folio)) { folio_clear_checked(folio); @@ -111,7 +111,7 @@ static int __gfs2_jdata_write_folio(struct folio *folio, inode->i_sb->s_blocksize, BIT(BH_Dirty)|BIT(BH_Uptodate)); } - gfs2_trans_add_databufs(ip->i_gl, folio, 0, folio_size(folio)); + gfs2_trans_add_databufs(gl, folio, 0, folio_size(folio)); } return gfs2_write_jdata_folio(folio, wbc); } @@ -126,13 +126,13 @@ static int __gfs2_jdata_write_folio(struct folio *folio, int gfs2_jdata_writeback(struct address_space *mapping, struct writeback_control *wbc) { struct inode *inode = mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(mapping->host); struct folio *folio = NULL; int error; BUG_ON(current->journal_info); - if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE)) + if (gfs2_assert_withdraw(sdp, gl->gl_state == LM_ST_EXCLUSIVE)) return 0; while ((folio = writeback_iter(mapping, wbc, folio, &error))) { @@ -362,14 +362,14 @@ static int gfs2_write_cache_jdata(struct address_space *mapping, static int gfs2_jdata_writepages(struct address_space *mapping, struct writeback_control *wbc) { - struct gfs2_inode *ip = GFS2_I(mapping->host); + struct gfs2_glock *gl = gfs2_inode_glock(mapping->host); struct gfs2_sbd *sdp = GFS2_SB(mapping->host); int ret; ret = gfs2_write_cache_jdata(mapping, wbc); if (ret == 0 && wbc->sync_mode == WB_SYNC_ALL) { - gfs2_log_flush(sdp, ip->i_gl, GFS2_LOG_HEAD_FLUSH_NORMAL | - GFS2_LFC_JDATA_WPAGES); + gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL | + GFS2_LFC_JDATA_WPAGES); ret = gfs2_write_cache_jdata(mapping, wbc); } return ret; @@ -561,12 +561,13 @@ static bool gfs2_jdata_dirty_folio(struct address_space *mapping, static sector_t gfs2_bmap(struct address_space *mapping, sector_t lblock) { + struct gfs2_glock *gl = gfs2_inode_glock(mapping->host); struct gfs2_inode *ip = GFS2_I(mapping->host); struct gfs2_holder i_gh; sector_t dblock = 0; int error; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) return 0; diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 636139f463b0..b5ddd936f489 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -55,6 +55,7 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh, u64 block, struct folio *folio) { struct inode *inode = &ip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); if (!folio_test_uptodate(folio)) { void *kaddr = kmap_local_folio(folio, 0); @@ -78,7 +79,7 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh, map_bh(bh, inode->i_sb, block); set_buffer_uptodate(bh); - gfs2_trans_add_data(ip->i_gl, bh); + gfs2_trans_add_data(gl, bh); } else { folio_mark_dirty(folio); gfs2_ordered_add_inode(ip); @@ -90,6 +91,7 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh, static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) { struct inode *inode = &ip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct buffer_head *bh, *dibh; struct gfs2_dinode *di; u64 block = 0; @@ -125,7 +127,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio) /* Set up the pointer to the new block */ - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); di = (struct gfs2_dinode *)dibh->b_data; gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); @@ -663,6 +665,7 @@ enum alloc_state { static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, struct metapath *mp) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh = metapath_dibh(mp); @@ -679,7 +682,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, BUG_ON(dibh == NULL); BUG_ON(dblks < 1); - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); down_write(&ip->i_rw_mutex); @@ -723,7 +726,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, } for (; i - 1 < mp->mp_fheight - ip->i_height && n > 0; i++, n--) - gfs2_indirect_init(mp, ip->i_gl, i, 0, bn++); + gfs2_indirect_init(mp, gl, i, 0, bn++); if (i - 1 == mp->mp_fheight - ip->i_height) { i--; gfs2_buffer_copy_tail(mp->mp_bh[i], @@ -749,9 +752,9 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, fallthrough; /* To branching from existing tree */ case ALLOC_GROW_DEPTH: if (i > 1 && i < mp->mp_fheight) - gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[i-1]); + gfs2_trans_add_meta(gl, mp->mp_bh[i-1]); for (; i < mp->mp_fheight && n > 0; i++, n--) - gfs2_indirect_init(mp, ip->i_gl, i, + gfs2_indirect_init(mp, gl, i, mp->mp_list[i-1], bn++); if (i == mp->mp_fheight) state = ALLOC_DATA; @@ -761,7 +764,7 @@ static int __gfs2_iomap_alloc(struct inode *inode, struct iomap *iomap, case ALLOC_DATA: BUG_ON(n > dblks); BUG_ON(mp->mp_bh[end_of_metadata] == NULL); - gfs2_trans_add_meta(ip->i_gl, mp->mp_bh[end_of_metadata]); + gfs2_trans_add_meta(gl, mp->mp_bh[end_of_metadata]); dblks = n; ptr = metapointer(end_of_metadata, mp); iomap->addr = bn << inode->i_blkbits; @@ -990,12 +993,12 @@ static void gfs2_iomap_put_folio(struct inode *inode, loff_t pos, unsigned copied, struct folio *folio) { struct gfs2_trans *tr = current->journal_info; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); if (gfs2_is_jdata(ip) && !gfs2_is_stuffed(ip)) - gfs2_trans_add_databufs(ip->i_gl, folio, - offset_in_folio(folio, pos), + gfs2_trans_add_databufs(gl, folio, offset_in_folio(folio, pos), copied); folio_unlock(folio); @@ -1151,6 +1154,7 @@ static int gfs2_iomap_begin(struct inode *inode, loff_t pos, loff_t length, static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length, ssize_t written, unsigned flags, struct iomap *iomap) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); @@ -1197,7 +1201,7 @@ static int gfs2_iomap_end(struct inode *inode, loff_t pos, loff_t length, if (iomap->flags & IOMAP_F_SIZE_CHANGED) mark_inode_dirty(inode); - set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); + set_bit(GLF_DIRTY, &gl->gl_flags); return 0; } @@ -1388,6 +1392,7 @@ static int gfs2_journaled_truncate(struct inode *inode, u64 oldsize, u64 newsize static int trunc_start(struct inode *inode, u64 newsize) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh = NULL; @@ -1416,7 +1421,7 @@ static int trunc_start(struct inode *inode, u64 newsize) if (error) goto out; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); if (gfs2_is_stuffed(ip)) gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode) + newsize); @@ -1490,6 +1495,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, bool meta, u32 *btotal) { struct inode *inode = &ip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_rgrpd *rgd; struct gfs2_trans *tr; @@ -1589,7 +1595,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, goto out_unlock; } - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); buf_in_tr = true; *p = 0; if (bstart + blen == bn) { @@ -1623,7 +1629,7 @@ static int sweep_bh_for_rgrps(struct gfs2_inode *ip, struct gfs2_holder *rd_gh, /* Every transaction boundary, we rewrite the dinode to keep its di_blocks current in case of failure. */ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); up_write(&ip->i_rw_mutex); @@ -1749,6 +1755,7 @@ static inline bool walk_done(struct gfs2_sbd *sdp, static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) { struct inode *inode = &ip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); u64 maxsize = sdp->sd_heightsize[ip->i_height]; struct metapath mp = {}; @@ -1836,7 +1843,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) for (mp_h = 0; mp_h < mp.mp_aheight - 1; mp_h++) { metapointer_range(&mp, mp_h, start_list, start_aligned, end_list, end_aligned, &start, &end); - gfs2_metapath_ra(ip->i_gl, start, end); + gfs2_metapath_ra(gl, start, end); } if (mp.mp_aheight == ip->i_height) @@ -1956,7 +1963,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) start_list, start_aligned, end_list, end_aligned, &start, &end); - gfs2_metapath_ra(ip->i_gl, start, end); + gfs2_metapath_ra(gl, start, end); } } @@ -1990,7 +1997,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) gfs2_statfs_change(sdp, 0, +btotal, 0); gfs2_quota_change(ip, -(s64)btotal, inode->i_uid, inode->i_gid); inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); up_write(&ip->i_rw_mutex); gfs2_trans_end(sdp); @@ -2013,6 +2020,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) static int trunc_end(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *dibh; int error; @@ -2036,7 +2044,7 @@ static int trunc_end(struct gfs2_inode *ip) inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); ip->i_diskflags &= ~GFS2_DIF_TRUNC_IN_PROG; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -2097,6 +2105,7 @@ static int do_shrink(struct inode *inode, u64 newsize) static int do_grow(struct inode *inode, u64 size) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_alloc_parms ap = { .target = 1, }; @@ -2141,7 +2150,7 @@ static int do_grow(struct inode *inode, u64 size) truncate_setsize(inode, size); inode_set_mtime_to_ts(&ip->i_inode, inode_set_ctime_current(&ip->i_inode)); - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -2380,6 +2389,7 @@ int gfs2_write_alloc_required(struct gfs2_inode *ip, u64 offset, static int stuffed_zero_range(struct inode *inode, loff_t offset, loff_t length) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct buffer_head *dibh; int error; @@ -2392,7 +2402,7 @@ static int stuffed_zero_range(struct inode *inode, loff_t offset, loff_t length) error = gfs2_meta_inode_buffer(ip, &dibh); if (error) return error; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); memset(dibh->b_data + sizeof(struct gfs2_dinode) + offset, 0, length); brelse(dibh); diff --git a/fs/gfs2/dentry.c b/fs/gfs2/dentry.c index 95050e719233..7b344461658e 100644 --- a/fs/gfs2/dentry.c +++ b/fs/gfs2/dentry.c @@ -35,8 +35,8 @@ static int gfs2_drevalidate(struct inode *dir, const struct qstr *name, struct dentry *dentry, unsigned int flags) { + struct gfs2_glock *gl = gfs2_inode_glock(dir); struct gfs2_sbd *sdp = GFS2_SB(dir); - struct gfs2_inode *dip = GFS2_I(dir); struct inode *inode; struct gfs2_holder d_gh; struct gfs2_inode *ip = NULL; @@ -57,9 +57,9 @@ static int gfs2_drevalidate(struct inode *dir, const struct qstr *name, if (sdp->sd_lockstruct.ls_ops->lm_mount == NULL) return 1; - had_lock = (gfs2_glock_is_locked_by_me(dip->i_gl) != NULL); + had_lock = (gfs2_glock_is_locked_by_me(gl) != NULL); if (!had_lock) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &d_gh); if (error) return 0; } diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c index f6111276ebb0..6cfe335fd590 100644 --- a/fs/gfs2/dir.c +++ b/fs/gfs2/dir.c @@ -90,10 +90,11 @@ typedef int (*gfs2_dscan_t)(const struct gfs2_dirent *dent, int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, struct buffer_head **bhp) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct buffer_head *bh; - bh = gfs2_meta_new(ip->i_gl, block); - gfs2_trans_add_meta(ip->i_gl, bh); + bh = gfs2_meta_new(gl, block); + gfs2_trans_add_meta(gl, bh); gfs2_metatype_set(bh, GFS2_METATYPE_JD, GFS2_FORMAT_JD); gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); *bhp = bh; @@ -103,10 +104,11 @@ int gfs2_dir_get_new_buffer(struct gfs2_inode *ip, u64 block, static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block, struct buffer_head **bhp) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct buffer_head *bh; int error; - error = gfs2_meta_read(ip->i_gl, block, DIO_WAIT, 0, &bh); + error = gfs2_meta_read(gl, block, DIO_WAIT, 0, &bh); if (error) return error; if (gfs2_metatype_check(GFS2_SB(&ip->i_inode), bh, GFS2_METATYPE_JD)) { @@ -120,6 +122,7 @@ static int gfs2_dir_get_existing_buffer(struct gfs2_inode *ip, u64 block, static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, unsigned int offset, unsigned int size) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct buffer_head *dibh; int error; @@ -127,7 +130,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, if (error) return error; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); memcpy(dibh->b_data + offset + sizeof(struct gfs2_dinode), buf, size); if (ip->i_inode.i_size < offset + size) i_size_write(&ip->i_inode, offset + size); @@ -153,6 +156,7 @@ static int gfs2_dir_write_stuffed(struct gfs2_inode *ip, const char *buf, static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, u64 offset, unsigned int size) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *dibh; u64 lblock, dblock; @@ -208,7 +212,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, if (error) goto fail; - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); memcpy(bh->b_data + o, buf, amount); brelse(bh); @@ -230,7 +234,7 @@ static int gfs2_dir_write_data(struct gfs2_inode *ip, const char *buf, i_size_write(&ip->i_inode, offset + copied); inode_set_mtime_to_ts(&ip->i_inode, inode_set_ctime_current(&ip->i_inode)); - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); @@ -268,6 +272,7 @@ static int gfs2_dir_read_stuffed(struct gfs2_inode *ip, __be64 *buf, static int gfs2_dir_read_data(struct gfs2_inode *ip, __be64 *buf, unsigned int size) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); u64 lblock, dblock; u32 extlen = 0; @@ -299,9 +304,9 @@ static int gfs2_dir_read_data(struct gfs2_inode *ip, __be64 *buf, if (error || !dblock) goto fail; BUG_ON(extlen < 1); - bh = gfs2_meta_ra(ip->i_gl, dblock, extlen); + bh = gfs2_meta_ra(gl, dblock, extlen); } else { - error = gfs2_meta_read(ip->i_gl, dblock, DIO_WAIT, 0, &bh); + error = gfs2_meta_read(gl, dblock, DIO_WAIT, 0, &bh); if (error) goto fail; } @@ -672,6 +677,7 @@ static int dirent_next(struct gfs2_inode *dip, struct buffer_head *bh, static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, struct gfs2_dirent *prev, struct gfs2_dirent *cur) { + struct gfs2_glock *gl = gfs2_inode_glock(&dip->i_inode); u16 cur_rec_len, prev_rec_len; if (gfs2_dirent_sentinel(cur)) { @@ -679,7 +685,7 @@ static void dirent_del(struct gfs2_inode *dip, struct buffer_head *bh, return; } - gfs2_trans_add_meta(dip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); /* If there is no prev entry, this is the first entry in the block. The de_rec_len is already as big as it needs to be. Just zero @@ -712,13 +718,13 @@ static struct gfs2_dirent *do_init_dirent(struct inode *inode, struct buffer_head *bh, unsigned offset) { - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_dirent *ndent; unsigned totlen; totlen = be16_to_cpu(dent->de_rec_len); BUG_ON(offset + name->len > totlen); - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); ndent = (struct gfs2_dirent *)((char *)dent + offset); dent->de_rec_len = cpu_to_be16(offset); gfs2_qstr2dirent(name, totlen - offset, ndent); @@ -760,10 +766,11 @@ static int get_leaf(struct gfs2_inode *dip, u64 leaf_no, struct buffer_head **bhp) { struct inode *inode = &dip->i_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); int error; - error = gfs2_meta_read(dip->i_gl, leaf_no, DIO_WAIT, 0, bhp); + error = gfs2_meta_read(gl, leaf_no, DIO_WAIT, 0, bhp); if (!error && gfs2_metatype_check(sdp, *bhp, GFS2_METATYPE_LF)) { /* pr_info("block num=%llu\n", leaf_no); */ error = -EIO; @@ -865,6 +872,7 @@ static struct gfs2_dirent *gfs2_dirent_search(struct inode *inode, static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, u16 depth) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); unsigned int n = 1; u64 bn; @@ -877,12 +885,12 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, error = gfs2_alloc_blocks(ip, &bn, &n, 0); if (error) return NULL; - bh = gfs2_meta_new(ip->i_gl, bn); + bh = gfs2_meta_new(gl, bn); if (!bh) return NULL; gfs2_trans_remove_revoke(GFS2_SB(inode), bn, 1); - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); gfs2_metatype_set(bh, GFS2_METATYPE_LF, GFS2_FORMAT_LF); leaf = (struct gfs2_leaf *)bh->b_data; leaf->lf_depth = cpu_to_be16(depth); @@ -909,6 +917,7 @@ static struct gfs2_leaf *new_leaf(struct inode *inode, struct buffer_head **pbh, static int dir_make_exhash(struct inode *inode) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *dip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_dirent *dent; @@ -970,7 +979,7 @@ static int dir_make_exhash(struct inode *inode) /* We're done with the new leaf block, now setup the new hash table. */ - gfs2_trans_add_meta(dip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_buffer_clear_tail(dibh, sizeof(struct gfs2_dinode)); lp = (__be64 *)(dibh->b_data + sizeof(struct gfs2_dinode)); @@ -1000,6 +1009,7 @@ static int dir_make_exhash(struct inode *inode) static int dir_split_leaf(struct inode *inode, const struct qstr *name) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *dip = GFS2_I(inode); struct buffer_head *nbh, *obh, *dibh; struct gfs2_leaf *nleaf, *oleaf; @@ -1027,7 +1037,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) return 1; /* can't split */ } - gfs2_trans_add_meta(dip->i_gl, obh); + gfs2_trans_add_meta(gl, obh); nleaf = new_leaf(inode, &nbh, be16_to_cpu(oleaf->lf_depth) + 1); if (!nleaf) { @@ -1120,7 +1130,7 @@ static int dir_split_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(dip, &dibh); if (!gfs2_assert_withdraw(GFS2_SB(&dip->i_inode), !error)) { - gfs2_trans_add_meta(dip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_add_inode_blocks(&dip->i_inode, 1); gfs2_dinode_out(dip, dibh->b_data); brelse(dibh); @@ -1482,8 +1492,8 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index, struct file_ra_state *f_ra) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_glock *gl = ip->i_gl; struct buffer_head *bh; u64 blocknr = 0, last; unsigned count; @@ -1724,6 +1734,7 @@ int gfs2_dir_check(struct inode *dir, const struct qstr *name, static int dir_new_leaf(struct inode *inode, const struct qstr *name) { struct buffer_head *bh, *obh; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_leaf *leaf, *oleaf; u32 dist = 1; @@ -1747,7 +1758,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) return error; } while(1); - gfs2_trans_add_meta(ip->i_gl, obh); + gfs2_trans_add_meta(gl, obh); leaf = new_leaf(inode, &bh, be16_to_cpu(oleaf->lf_depth)); if (!leaf) { @@ -1762,7 +1773,7 @@ static int dir_new_leaf(struct inode *inode, const struct qstr *name) error = gfs2_meta_inode_buffer(ip, &bh); if (error) return error; - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); gfs2_add_inode_blocks(&ip->i_inode, 1); gfs2_dinode_out(ip, bh->b_data); brelse(bh); @@ -1937,6 +1948,7 @@ int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry) int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, const struct gfs2_inode *nip, unsigned int new_type) { + struct gfs2_glock *gl = gfs2_inode_glock(&dip->i_inode); struct buffer_head *bh; struct gfs2_dirent *dent; @@ -1948,7 +1960,7 @@ int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, if (IS_ERR(dent)) return PTR_ERR(dent); - gfs2_trans_add_meta(dip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); gfs2_inum_out(nip, dent); dent->de_type = cpu_to_be16(new_type); brelse(bh); @@ -1974,6 +1986,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, u64 leaf_no, struct buffer_head *leaf_bh, int last_dealloc) { + struct gfs2_glock *gl = gfs2_inode_glock(&dip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&dip->i_inode); struct gfs2_leaf *tmp_leaf; struct gfs2_rgrp_list rlist; @@ -2068,7 +2081,7 @@ static int leaf_dealloc(struct gfs2_inode *dip, u32 index, u32 len, if (error) goto out_end_trans; - gfs2_trans_add_meta(dip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); /* On the last dealloc, make this a regular file in case we crash. (We don't want to free these blocks a second time.) */ if (last_dealloc) diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c index 3334c394ce9c..970bf2d72388 100644 --- a/fs/gfs2/export.c +++ b/fs/gfs2/export.c @@ -87,7 +87,8 @@ static int gfs2_get_name(struct dentry *parent, char *name, { struct inode *dir = d_inode(parent); struct inode *inode = d_inode(child); - struct gfs2_inode *dip, *ip; + struct gfs2_glock *gl; + struct gfs2_inode *ip; struct get_name_filldir gnfd = { .ctx.actor = get_name_filldir, .name = name @@ -102,14 +103,14 @@ static int gfs2_get_name(struct dentry *parent, char *name, if (!S_ISDIR(dir->i_mode) || !inode) return -EINVAL; - dip = GFS2_I(dir); + gl = gfs2_inode_glock(dir); ip = GFS2_I(inode); *name = 0; gnfd.inum.no_addr = ip->i_no_addr; gnfd.inum.no_formal_ino = ip->i_no_formal_ino; - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &gh); if (error) return error; diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 164e160e9064..6fb2adeef274 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -57,13 +57,13 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence) { - struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); + struct gfs2_glock *gl = gfs2_inode_glock(file->f_mapping->host); struct gfs2_holder i_gh; loff_t error; switch (whence) { case SEEK_END: - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (!error) { error = generic_file_llseek(file, offset, whence); @@ -105,11 +105,11 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence) static int gfs2_readdir(struct file *file, struct dir_context *ctx) { struct inode *dir = file->f_mapping->host; - struct gfs2_inode *dip = GFS2_I(dir); + struct gfs2_glock *gl = gfs2_inode_glock(dir); struct gfs2_holder d_gh; int error; - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &d_gh); if (error) return error; @@ -158,6 +158,7 @@ static inline u32 gfs2_gfsflags_to_fsflags(struct inode *inode, u32 gfsflags) int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa) { struct inode *inode = d_inode(dentry); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int error; @@ -166,7 +167,7 @@ int gfs2_fileattr_get(struct dentry *dentry, struct file_kattr *fa) if (d_is_special(dentry)) return -ENOTTY; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + gfs2_holder_init(gl, LM_ST_SHARED, 0, &gh); error = gfs2_glock_nq(&gh); if (error) goto out_uninit; @@ -218,6 +219,7 @@ void gfs2_set_inode_flags(struct inode *inode) */ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *bh; @@ -225,7 +227,7 @@ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) int error; u32 new_flags, flags; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &gh); if (error) return error; @@ -242,7 +244,7 @@ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) } if ((flags ^ new_flags) & GFS2_DIF_JDATA) { if (new_flags & GFS2_DIF_JDATA) - gfs2_log_flush(sdp, ip->i_gl, + gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_SET_FLAGS); error = filemap_fdatawrite(inode->i_mapping); @@ -262,7 +264,7 @@ static int do_gfs2_set_flags(struct inode *inode, u32 reqflags, u32 mask) if (error) goto out_trans_end; inode_set_ctime_current(inode); - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); ip->i_diskflags = new_flags; gfs2_dinode_out(ip, bh->b_data); brelse(bh); @@ -417,6 +419,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) { struct folio *folio = page_folio(vmf->page); struct inode *inode = file_inode(vmf->vma->vm_file); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_alloc_parms ap = {}; @@ -430,7 +433,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) sb_start_pagefault(inode->i_sb); - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + gfs2_holder_init(gl, LM_ST_EXCLUSIVE, 0, &gh); err = gfs2_glock_nq(&gh); if (err) { ret = vmf_fs_error(err); @@ -455,7 +458,7 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) gfs2_size_hint(vmf->vma->vm_file, pos, length); - set_bit(GLF_DIRTY, &ip->i_gl->gl_flags); + set_bit(GLF_DIRTY, &gl->gl_flags); set_bit(GIF_SW_PAGED, &ip->i_flags); /* @@ -552,12 +555,12 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) static vm_fault_t gfs2_fault(struct vm_fault *vmf) { struct inode *inode = file_inode(vmf->vma->vm_file); - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; vm_fault_t ret; int err; - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + gfs2_holder_init(gl, LM_ST_SHARED, 0, &gh); err = gfs2_glock_nq(&gh); if (err) { ret = vmf_fs_error(err); @@ -590,6 +593,7 @@ static const struct vm_operations_struct gfs2_vm_ops = { static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) { + struct gfs2_glock *gl = gfs2_inode_glock(file->f_mapping->host); struct gfs2_inode *ip = GFS2_I(file->f_mapping->host); if (!(file->f_flags & O_NOATIME) && @@ -597,7 +601,7 @@ static int gfs2_mmap(struct file *file, struct vm_area_struct *vma) struct gfs2_holder i_gh; int error; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) return error; @@ -674,13 +678,14 @@ int gfs2_open_common(struct inode *inode, struct file *file) static int gfs2_open(struct inode *inode, struct file *file) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder i_gh; int error; bool need_unlock = false; if (S_ISREG(ip->i_inode.i_mode)) { - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); if (error) return error; @@ -745,6 +750,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, struct address_space *mapping = file->f_mapping; struct inode *inode = mapping->host; int sync_state = inode_state_read_once(inode) & I_DIRTY; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); int ret = 0, ret1 = 0; @@ -767,7 +773,7 @@ static int gfs2_fsync(struct file *file, loff_t start, loff_t end, ret = file_write_and_wait(file); if (ret) return ret; - gfs2_ail_flush(ip->i_gl, 1); + gfs2_ail_flush(gl, 1); } if (mapping->nrpages) @@ -813,7 +819,7 @@ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); size_t prev_count = 0, window_size = 0; size_t read = 0; ssize_t ret; @@ -838,7 +844,7 @@ static ssize_t gfs2_file_direct_read(struct kiocb *iocb, struct iov_iter *to, if (!iov_iter_count(to)) return 0; /* skip atime */ - gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh); + gfs2_holder_init(gl, LM_ST_DEFERRED, 0, gh); retry: ret = gfs2_glock_nq(gh); if (ret) @@ -877,7 +883,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from, { struct file *file = iocb->ki_filp; struct inode *inode = file->f_mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); size_t prev_count = 0, window_size = 0; size_t written = 0; bool enough_retries; @@ -901,7 +907,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from, * unfortunately, have the option of only flushing a range like the * VFS does. */ - gfs2_holder_init(ip->i_gl, LM_ST_DEFERRED, 0, gh); + gfs2_holder_init(gl, LM_ST_DEFERRED, 0, gh); retry: ret = gfs2_glock_nq(gh); if (ret) @@ -949,7 +955,7 @@ static ssize_t gfs2_file_direct_write(struct kiocb *iocb, struct iov_iter *from, static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) { - struct gfs2_inode *ip; + struct gfs2_glock *gl; struct gfs2_holder gh; size_t prev_count = 0, window_size = 0; size_t read = 0; @@ -980,8 +986,8 @@ static ssize_t gfs2_file_read_iter(struct kiocb *iocb, struct iov_iter *to) if (iocb->ki_flags & IOCB_NOWAIT) return ret; } - ip = GFS2_I(iocb->ki_filp->f_mapping->host); - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + gl = gfs2_inode_glock(iocb->ki_filp->f_mapping->host); + gfs2_holder_init(gl, LM_ST_SHARED, 0, &gh); retry: ret = gfs2_glock_nq(&gh); if (ret) @@ -1014,7 +1020,7 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, { struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_holder *statfs_gh = NULL; size_t prev_count = 0, window_size = 0; @@ -1035,7 +1041,7 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, return -ENOMEM; } - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, gh); + gfs2_holder_init(gl, LM_ST_EXCLUSIVE, 0, gh); if (should_fault_in_pages(from, iocb, &prev_count, &window_size)) { retry: window_size -= fault_in_iov_iter_readable(from, window_size); @@ -1050,9 +1056,9 @@ static ssize_t gfs2_file_buffered_write(struct kiocb *iocb, goto out_uninit; if (inode == sdp->sd_rindex) { - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); + struct gfs2_glock *m_gl = gfs2_inode_glock(sdp->sd_statfs_inode); - ret = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, + ret = gfs2_glock_nq_init(m_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, statfs_gh); if (ret) goto out_unlock; @@ -1106,14 +1112,15 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) { struct file *file = iocb->ki_filp; struct inode *inode = file_inode(file); - struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; ssize_t ret; gfs2_size_hint(file, iocb->ki_pos, iov_iter_count(from)); if (iocb->ki_flags & IOCB_APPEND) { - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + struct gfs2_glock *gl = gfs2_inode_glock(inode); + + ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &gh); if (ret) return ret; gfs2_glock_dq_uninit(&gh); @@ -1181,6 +1188,7 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len) { struct super_block *sb = inode->i_sb; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); loff_t end = offset + len; struct buffer_head *dibh; @@ -1190,7 +1198,7 @@ static int fallocate_chunk(struct inode *inode, loff_t offset, loff_t len) if (unlikely(error)) return error; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); if (gfs2_is_stuffed(ip)) { error = gfs2_unstuff_dinode(ip); @@ -1379,6 +1387,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le { struct inode *inode = file_inode(file); struct gfs2_sbd *sdp = GFS2_SB(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int ret; @@ -1391,7 +1400,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset, loff_t le inode_lock(inode); - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + gfs2_holder_init(gl, LM_ST_EXCLUSIVE, 0, &gh); ret = gfs2_glock_nq(&gh); if (ret) goto out_uninit; diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index d59ea71a84db..d0612014408e 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -891,7 +891,9 @@ static void gfs2_try_to_evict(struct gfs2_glock *gl) /* If the inode was evicted, gl->gl_object will now be NULL. */ ip = gfs2_grab_existing_inode(gl); if (ip) { - gfs2_glock_poke(ip->i_gl); + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); + + gfs2_glock_poke(gl); iput(&ip->i_inode); } } diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 28f32424ee64..662d033fd2ca 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -602,8 +602,7 @@ static void freeze_go_callback(struct gfs2_glock *gl, bool remote) static int freeze_go_xmote_bh(struct gfs2_glock *gl) { struct gfs2_sbd *sdp = glock_sbd(gl); - struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); - struct gfs2_glock *j_gl = ip->i_gl; + struct gfs2_glock *j_gl = gfs2_inode_glock(sdp->sd_jdesc->jd_inode); struct gfs2_log_header_host head; int error; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index dadb4d3c9d3d..3ae8e2be486c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -879,5 +879,8 @@ static inline unsigned gfs2_max_stuffed_size(const struct gfs2_inode *ip) return GFS2_SB(&ip->i_inode)->sd_sb.sb_bsize - sizeof(struct gfs2_dinode); } +static inline struct gfs2_glock *gfs2_inode_glock(struct inode *inode) +{ + return GFS2_I(inode)->i_gl; +} #endif /* __INCORE_DOT_H__ */ - diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 438519bc06d4..5aaed0018fb3 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -324,8 +324,8 @@ struct inode *gfs2_lookup_meta(struct inode *dip, const char *name) struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, int is_root) { + struct gfs2_glock *gl = gfs2_inode_glock(dir); struct super_block *sb = dir->i_sb; - struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_holder d_gh; int error = 0; struct inode *inode = NULL; @@ -341,8 +341,8 @@ struct inode *gfs2_lookupi(struct inode *dir, const struct qstr *name, return dir; } - if (gfs2_glock_is_locked_by_me(dip->i_gl) == NULL) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); + if (gfs2_glock_is_locked_by_me(gl) == NULL) { + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &d_gh); if (error) return ERR_PTR(error); } @@ -458,7 +458,7 @@ static int alloc_dinode(struct gfs2_inode *ip, u32 flags, unsigned *dblocks) static void gfs2_final_release_pages(struct gfs2_inode *ip) { struct inode *inode = &ip->i_inode; - struct gfs2_glock *gl = ip->i_gl; + struct gfs2_glock *gl = gfs2_inode_glock(inode); /* This can only happen during incomplete inode creation. */ if (unlikely(!gl)) @@ -548,12 +548,13 @@ static void gfs2_init_dir(struct buffer_head *dibh, static void gfs2_init_xattr(struct gfs2_inode *ip) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *bh; struct gfs2_ea_header *ea; - bh = gfs2_meta_new(ip->i_gl, ip->i_eattr); - gfs2_trans_add_meta(ip->i_gl, bh); + bh = gfs2_meta_new(gl, ip->i_eattr); + gfs2_trans_add_meta(gl, bh); gfs2_metatype_set(bh, GFS2_METATYPE_EA, GFS2_FORMAT_EA); gfs2_buffer_clear_tail(bh, sizeof(struct gfs2_meta_header)); @@ -576,11 +577,12 @@ static void gfs2_init_xattr(struct gfs2_inode *ip) static void init_dinode(struct gfs2_inode *dip, struct gfs2_inode *ip, const char *symname) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_dinode *di; struct buffer_head *dibh; - dibh = gfs2_meta_new(ip->i_gl, ip->i_no_addr); - gfs2_trans_add_meta(ip->i_gl, dibh); + dibh = gfs2_meta_new(gl, ip->i_no_addr); + gfs2_trans_add_meta(gl, dibh); di = (struct gfs2_dinode *)dibh->b_data; gfs2_dinode_out(ip, di); @@ -728,7 +730,8 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (error) goto fail; - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh); + error = gfs2_glock_nq_init(gfs2_inode_glock(dir), LM_ST_EXCLUSIVE, 0, + &d_gh); if (error) goto fail; gfs2_holder_mark_uninitialized(&gh); @@ -999,7 +1002,7 @@ static struct dentry *__gfs2_lookup(struct inode *dir, struct dentry *dentry, if (inode == NULL || IS_ERR(inode)) return d_splice_alias(inode, dentry); - gl = GFS2_I(inode)->i_gl; + gl = gfs2_inode_glock(inode); error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); if (error) { iput(inode); @@ -1059,8 +1062,8 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, if (error) return error; - gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh); - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + gfs2_holder_init(gfs2_inode_glock(dir), LM_ST_EXCLUSIVE, 0, &d_gh); + gfs2_holder_init(gfs2_inode_glock(inode), LM_ST_EXCLUSIVE, 0, &gh); error = gfs2_glock_nq(&d_gh); if (error) @@ -1133,7 +1136,7 @@ static int gfs2_link(struct dentry *old_dentry, struct inode *dir, if (error) goto out_brelse; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gfs2_inode_glock(inode), dibh); inc_nlink(&ip->i_inode); inode_set_ctime_current(&ip->i_inode); ihold(inode); @@ -1259,8 +1262,8 @@ static int gfs2_unlink(struct inode *dir, struct dentry *dentry) error = -EROFS; - gfs2_holder_init(dip->i_gl, LM_ST_EXCLUSIVE, 0, &d_gh); - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + gfs2_holder_init(gfs2_inode_glock(dir), LM_ST_EXCLUSIVE, 0, &d_gh); + gfs2_holder_init(gfs2_inode_glock(inode), LM_ST_EXCLUSIVE, 0, &gh); rgd = gfs2_blk2rgrpd(sdp, ip->i_no_addr, 1); if (!rgd) @@ -1534,18 +1537,19 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, } num_gh = 1; - gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs); + gfs2_holder_init(gfs2_inode_glock(odir), LM_ST_EXCLUSIVE, GL_ASYNC, ghs); if (odip != ndip) { - gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE,GL_ASYNC, + gfs2_holder_init(gfs2_inode_glock(ndir), LM_ST_EXCLUSIVE,GL_ASYNC, ghs + num_gh); num_gh++; } - gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); + gfs2_holder_init(gfs2_inode_glock(&ip->i_inode), LM_ST_EXCLUSIVE, + GL_ASYNC, ghs + num_gh); num_gh++; if (nip) { - gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, - ghs + num_gh); + gfs2_holder_init(gfs2_inode_glock(&nip->i_inode), + LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); num_gh++; } @@ -1780,16 +1784,19 @@ static int gfs2_exchange(struct inode *odir, struct dentry *odentry, } num_gh = 1; - gfs2_holder_init(odip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs); + gfs2_holder_init(gfs2_inode_glock(odir), LM_ST_EXCLUSIVE, GL_ASYNC, + ghs); if (odip != ndip) { - gfs2_holder_init(ndip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, - ghs + num_gh); + gfs2_holder_init(gfs2_inode_glock(ndir), LM_ST_EXCLUSIVE, + GL_ASYNC, ghs + num_gh); num_gh++; } - gfs2_holder_init(oip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); + gfs2_holder_init(gfs2_inode_glock(&oip->i_inode), LM_ST_EXCLUSIVE, + GL_ASYNC, ghs + num_gh); num_gh++; - gfs2_holder_init(nip->i_gl, LM_ST_EXCLUSIVE, GL_ASYNC, ghs + num_gh); + gfs2_holder_init(gfs2_inode_glock(&nip->i_inode), LM_ST_EXCLUSIVE, + GL_ASYNC, ghs + num_gh); num_gh++; again: @@ -1910,6 +1917,7 @@ static const char *gfs2_get_link(struct dentry *dentry, struct inode *inode, struct delayed_call *done) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder i_gh; struct buffer_head *dibh; @@ -1920,7 +1928,7 @@ static const char *gfs2_get_link(struct dentry *dentry, if (!dentry) return ERR_PTR(-ECHILD); - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + gfs2_holder_init(gl, LM_ST_SHARED, 0, &i_gh); error = gfs2_glock_nq(&i_gh); if (error) { gfs2_holder_uninit(&i_gh); @@ -2102,6 +2110,7 @@ static int gfs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { struct inode *inode = d_inode(dentry); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder i_gh; int error; @@ -2110,7 +2119,7 @@ static int gfs2_setattr(struct mnt_idmap *idmap, if (error) return error; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) goto out; @@ -2164,14 +2173,15 @@ static int gfs2_getattr(struct mnt_idmap *idmap, u32 request_mask, unsigned int flags) { struct inode *inode = d_inode(path->dentry); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; u32 gfsflags; int error; gfs2_holder_mark_uninitialized(&gh); - if (gfs2_glock_is_locked_by_me(ip->i_gl) == NULL) { - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); + if (gfs2_glock_is_locked_by_me(gl) == NULL) { + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); if (error) return error; } @@ -2207,14 +2217,14 @@ static bool fault_in_fiemap(struct fiemap_extent_info *fi) static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; int ret; inode_lock_shared(inode); retry: - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &gh); if (ret) goto out; @@ -2237,12 +2247,12 @@ static int gfs2_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, loff_t gfs2_seek_data(struct file *file, loff_t offset) { struct inode *inode = file->f_mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; loff_t ret; inode_lock_shared(inode); - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &gh); if (!ret) ret = iomap_seek_data(inode, offset, &gfs2_iomap_ops); gfs2_glock_dq_uninit(&gh); @@ -2256,12 +2266,12 @@ loff_t gfs2_seek_data(struct file *file, loff_t offset) loff_t gfs2_seek_hole(struct file *file, loff_t offset) { struct inode *inode = file->f_mapping->host; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; loff_t ret; inode_lock_shared(inode); - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &gh); + ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &gh); if (!ret) ret = iomap_seek_hole(inode, offset, &gfs2_iomap_ops); gfs2_glock_dq_uninit(&gh); @@ -2275,8 +2285,7 @@ loff_t gfs2_seek_hole(struct file *file, loff_t offset) static int gfs2_update_time(struct inode *inode, enum fs_update_time type, unsigned int flags) { - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_glock *gl = ip->i_gl; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder *gh; int error; diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 6dabe73ad790..77ef22eab368 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -775,9 +775,8 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, struct gfs2_log_descriptor *ld, __be64 *ptr, int pass) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); - struct gfs2_glock *gl = ip->i_gl; unsigned int blks = be32_to_cpu(ld->ld_data1); struct buffer_head *bh_log, *bh_ip; u64 blkno; @@ -828,17 +827,17 @@ static int buf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, static void buf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); if (error) { - gfs2_inode_metasync(ip->i_gl); + gfs2_inode_metasync(gl); return; } if (pass != 1) return; - gfs2_inode_metasync(ip->i_gl); + gfs2_inode_metasync(gl); fs_info(sdp, "jid=%u: Replayed %u of %u blocks\n", jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks); @@ -1000,8 +999,7 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, struct gfs2_log_descriptor *ld, __be64 *ptr, int pass) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); - struct gfs2_glock *gl = ip->i_gl; + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); unsigned int blks = be32_to_cpu(ld->ld_data1); struct buffer_head *bh_log, *bh_ip; u64 blkno; @@ -1048,18 +1046,18 @@ static int databuf_lo_scan_elements(struct gfs2_jdesc *jd, u32 start, static void databuf_lo_after_scan(struct gfs2_jdesc *jd, int error, int pass) { - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); if (error) { - gfs2_inode_metasync(ip->i_gl); + gfs2_inode_metasync(gl); return; } if (pass != 1) return; /* data sync? */ - gfs2_inode_metasync(ip->i_gl); + gfs2_inode_metasync(gl); fs_info(sdp, "jid=%u: Replayed %u of %u data blocks\n", jd->jd_jid, jd->jd_replayed_blocks, jd->jd_found_blocks); diff --git a/fs/gfs2/meta_io.c b/fs/gfs2/meta_io.c index a87cfbf0df38..63591a4be10a 100644 --- a/fs/gfs2/meta_io.c +++ b/fs/gfs2/meta_io.c @@ -402,18 +402,19 @@ static struct buffer_head *gfs2_getjdatabuf(struct gfs2_inode *ip, u64 blkno) void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *bh; int ty; /* This can only happen during incomplete inode creation. */ - if (!ip->i_gl) + if (!gl) return; gfs2_ail1_wipe(sdp, bstart, blen); while (blen) { ty = REMOVE_META; - bh = gfs2_getbuf(ip->i_gl, bstart, NO_CREATE); + bh = gfs2_getbuf(gl, bstart, NO_CREATE); if (!bh && gfs2_is_jdata(ip)) { bh = gfs2_getjdatabuf(ip, bstart); ty = REMOVE_JDATA; @@ -447,8 +448,8 @@ void gfs2_journal_wipe(struct gfs2_inode *ip, u64 bstart, u32 blen) int gfs2_meta_buffer(struct gfs2_inode *ip, u32 mtype, u64 num, struct buffer_head **bhp) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); - struct gfs2_glock *gl = ip->i_gl; struct buffer_head *bh; int ret = 0; int rahead = 0; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 718e0da7dfce..188b3e67f2d1 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -534,7 +534,7 @@ static void gfs2_others_may_mount(struct gfs2_sbd *sdp) static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) { - struct gfs2_inode *dip = GFS2_I(sdp->sd_jindex); + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_jindex); struct qstr name; char buf[20]; struct gfs2_jdesc *jd; @@ -545,7 +545,7 @@ static int gfs2_jindex_hold(struct gfs2_sbd *sdp, struct gfs2_holder *ji_gh) mutex_lock(&sdp->sd_jindex_mutex); for (;;) { - error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, ji_gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, ji_gh); if (error) break; @@ -611,7 +611,6 @@ static int init_statfs(struct gfs2_sbd *sdp) struct inode *pn = NULL; char buf[30]; struct gfs2_jdesc *jd; - struct gfs2_inode *ip; sdp->sd_statfs_inode = gfs2_lookup_meta(master, "statfs"); if (IS_ERR(sdp->sd_statfs_inode)) { @@ -656,15 +655,15 @@ static int init_statfs(struct gfs2_sbd *sdp) iput(pn); pn = NULL; - ip = GFS2_I(sdp->sd_sc_inode); - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_NOPID, - &sdp->sd_sc_gh); + error = gfs2_glock_nq_init(gfs2_inode_glock(sdp->sd_sc_inode), + LM_ST_EXCLUSIVE, GL_NOPID, &sdp->sd_sc_gh); if (error) { fs_err(sdp, "can't lock local \"sc\" file: %d\n", error); goto free_local; } /* read in the local statfs buffer - other nodes don't change it. */ - error = gfs2_meta_inode_buffer(ip, &sdp->sd_sc_bh); + error = gfs2_meta_inode_buffer(GFS2_I(sdp->sd_sc_inode), + &sdp->sd_sc_bh); if (error) { fs_err(sdp, "Cannot read in local statfs: %d\n", error); goto unlock_sd_gh; @@ -697,7 +696,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) { struct inode *master = d_inode(sdp->sd_master_dir); struct gfs2_holder ji_gh; - struct gfs2_inode *ip; + struct gfs2_glock *gl; int error = 0; gfs2_holder_mark_uninitialized(&ji_gh); @@ -751,8 +750,8 @@ static int init_journal(struct gfs2_sbd *sdp, int undo) goto fail_jindex; } - ip = GFS2_I(sdp->sd_jdesc->jd_inode); - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, + gl = gfs2_inode_glock(sdp->sd_jdesc->jd_inode); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_RECOVER | GL_EXACT | GL_NOCACHE | GL_NOPID, &sdp->sd_jinode_gh); @@ -893,7 +892,7 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) struct inode *pn = NULL; char buf[30]; int error = 0; - struct gfs2_inode *ip; + struct gfs2_glock *gl; struct inode *master = d_inode(sdp->sd_master_dir); if (sdp->sd_args.ar_spectator) @@ -920,8 +919,8 @@ static int init_per_node(struct gfs2_sbd *sdp, int undo) iput(pn); pn = NULL; - ip = GFS2_I(sdp->sd_qc_inode); - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_NOPID, + gl = gfs2_inode_glock(sdp->sd_qc_inode); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, GL_NOPID, &sdp->sd_qc_gh); if (error) { fs_err(sdp, "can't lock local \"qc\" file: %d\n", error); diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 0cb2bb0aec7b..b62431724eea 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -408,7 +408,7 @@ static int bh_get(struct gfs2_quota_data *qd) { struct gfs2_sbd *sdp = qd->qd_sbd; struct inode *inode = sdp->sd_qc_inode; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); unsigned int block, offset; struct buffer_head *bh = NULL; struct iomap iomap = { }; @@ -434,7 +434,7 @@ static int bh_get(struct gfs2_quota_data *qd) if (iomap.type != IOMAP_MAPPED) return error; - error = gfs2_meta_read(ip->i_gl, iomap.addr >> inode->i_blkbits, + error = gfs2_meta_read(gl, iomap.addr >> inode->i_blkbits, DIO_WAIT, 0, &bh); if (error) return error; @@ -687,12 +687,12 @@ static int sort_qd(const void *a, const void *b) static void do_qc(struct gfs2_quota_data *qd, s64 change) { struct gfs2_sbd *sdp = qd->qd_sbd; - struct gfs2_inode *ip = GFS2_I(sdp->sd_qc_inode); + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_qc_inode); struct gfs2_quota_change *qc = qd->qd_bh_qc; bool needs_put = false; s64 x; - gfs2_trans_add_meta(ip->i_gl, qd->qd_bh); + gfs2_trans_add_meta(gl, qd->qd_bh); /* * The QDF_CHANGE flag indicates that the slot in the quota change file @@ -741,7 +741,7 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index, unsigned off, void *buf, unsigned bytes) { struct inode *inode = sdp->sd_quota_inode; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct address_space *mapping = inode->i_mapping; struct folio *folio; struct buffer_head *bh; @@ -780,7 +780,7 @@ static int gfs2_write_buf_to_page(struct gfs2_sbd *sdp, unsigned long index, set_buffer_uptodate(bh); if (bh_read(bh, REQ_META | REQ_PRIO) < 0) goto unlock_out; - gfs2_trans_add_data(ip->i_gl, bh); + gfs2_trans_add_data(gl, bh); /* If we need to write to the next block as well */ if (to_write > (bsize - boff)) { @@ -909,6 +909,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, { struct gfs2_sbd *sdp = (*qda)->qd_sbd; struct inode *inode = sdp->sd_quota_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_alloc_parms ap = {}; unsigned int data_blocks, ind_blocks; @@ -936,7 +937,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, goto out_dq; } - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) goto out_dq; @@ -994,8 +995,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda, gfs2_glock_dq_uninit(&ghs[qx]); inode_unlock(inode); kfree(ghs); - gfs2_log_flush(sdp, ip->i_gl, - GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC); + gfs2_log_flush(sdp, gl, GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC); if (!error) { for (x = 0; x < num_qd; x++) { qd = qda[x]; @@ -1039,7 +1039,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, struct gfs2_holder *q_gh) { struct gfs2_sbd *sdp = qd->qd_sbd; - struct gfs2_inode *ip = GFS2_I(sdp->sd_quota_inode); + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_quota_inode); struct gfs2_holder i_gh; int error; @@ -1063,7 +1063,7 @@ static int do_glock(struct gfs2_quota_data *qd, int force_refresh, if (error) return error; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &i_gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &i_gh); if (error) goto fail; @@ -1404,7 +1404,7 @@ int gfs2_quota_refresh(struct gfs2_sbd *sdp, struct kqid qid) int gfs2_quota_init(struct gfs2_sbd *sdp) { struct inode *inode = sdp->sd_qc_inode; - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); u64 size = i_size_read(sdp->sd_qc_inode); unsigned int blocks = size >> sdp->sd_sb.sb_bsize_shift; unsigned int x, slot = 0; @@ -1441,7 +1441,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) goto fail; } error = -EIO; - bh = gfs2_meta_ra(ip->i_gl, dblock, extlen); + bh = gfs2_meta_ra(gl, dblock, extlen); if (!bh) goto fail; if (gfs2_metatype_check(sdp, bh, GFS2_METATYPE_QC)) @@ -1717,6 +1717,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, { struct gfs2_sbd *sdp = sb->s_fs_info; struct inode *inode = sdp->sd_quota_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_quota_data *qd; struct gfs2_holder q_gh, i_gh; @@ -1748,7 +1749,7 @@ static int gfs2_set_dqblk(struct super_block *sb, struct kqid qid, error = gfs2_glock_nq_init(qd->qd_gl, LM_ST_EXCLUSIVE, 0, &q_gh); if (error) goto out_unlockput; - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &i_gh); + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &i_gh); if (error) goto out_q; diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index b45aa3032ca2..5b1f494dc3c0 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -33,8 +33,8 @@ int gfs2_replay_read_block(struct gfs2_jdesc *jd, unsigned int blk, struct buffer_head **bh) { struct inode *inode = jd->jd_inode; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_glock *gl = ip->i_gl; u64 dblock; u32 extlen; int error; @@ -307,15 +307,13 @@ static int update_statfs_inode(struct gfs2_jdesc *jd, struct inode *inode) { struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); - struct gfs2_inode *ip; struct buffer_head *bh; struct gfs2_statfs_change_host sc; int error = 0; BUG_ON(!inode); - ip = GFS2_I(inode); - error = gfs2_meta_inode_buffer(ip, &bh); + error = gfs2_meta_inode_buffer(GFS2_I(inode), &bh); if (error) goto out; @@ -346,7 +344,7 @@ static int update_statfs_inode(struct gfs2_jdesc *jd, mark_buffer_dirty(bh); brelse(bh); - gfs2_inode_metasync(ip->i_gl); + gfs2_inode_metasync(gfs2_inode_glock(inode)); out: return error; @@ -399,7 +397,7 @@ static void recover_local_statfs(struct gfs2_jdesc *jd, void gfs2_recover_func(struct work_struct *work) { struct gfs2_jdesc *jd = container_of(work, struct gfs2_jdesc, jd_work); - struct gfs2_inode *ip = GFS2_I(jd->jd_inode); + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode); struct gfs2_log_header_host head; struct gfs2_holder j_gh, ji_gh; @@ -441,7 +439,7 @@ void gfs2_recover_func(struct work_struct *work) goto fail; } - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_RECOVER | GL_NOCACHE, &ji_gh); if (error) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 5988a165a830..f6048a73e5c3 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -1033,8 +1033,8 @@ static int gfs2_ri_update(struct gfs2_inode *ip) int gfs2_rindex_update(struct gfs2_sbd *sdp) { + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_rindex); struct gfs2_inode *ip = GFS2_I(sdp->sd_rindex); - struct gfs2_glock *gl = ip->i_gl; struct gfs2_holder ri_gh; int error = 0; int unlock_required = 0; @@ -2453,7 +2453,7 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks, if (error == 0) { struct gfs2_dinode *di = (struct gfs2_dinode *)dibh->b_data; - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gfs2_inode_glock(&ip->i_inode), dibh); di->di_goal_meta = di->di_goal_data = cpu_to_be64(ip->i_goal); brelse(dibh); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 06302c29340f..af8c71576833 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -132,8 +132,7 @@ int gfs2_jdesc_check(struct gfs2_jdesc *jd) int gfs2_make_fs_rw(struct gfs2_sbd *sdp) { - struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode); - struct gfs2_glock *j_gl = ip->i_gl; + struct gfs2_glock *j_gl = gfs2_inode_glock(sdp->sd_jdesc->jd_inode); int error; j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); @@ -176,6 +175,7 @@ void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc, void *buf) int gfs2_statfs_init(struct gfs2_sbd *sdp) { + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_statfs_inode); struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; @@ -183,7 +183,7 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp) struct gfs2_holder gh; int error; - error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, + error = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, GL_NOCACHE, &gh); if (error) return error; @@ -216,13 +216,13 @@ int gfs2_statfs_init(struct gfs2_sbd *sdp) void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, s64 dinodes) { - struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); + struct gfs2_glock *gl = gfs2_inode_glock(sdp->sd_sc_inode); struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; s64 x, y; int need_sync = 0; - gfs2_trans_add_meta(l_ip->i_gl, sdp->sd_sc_bh); + gfs2_trans_add_meta(gl, sdp->sd_sc_bh); spin_lock(&sdp->sd_statfs_spin); l_sc->sc_total += total; @@ -244,13 +244,13 @@ void gfs2_statfs_change(struct gfs2_sbd *sdp, s64 total, s64 free, void update_statfs(struct gfs2_sbd *sdp, struct buffer_head *m_bh) { - struct gfs2_inode *m_ip = GFS2_I(sdp->sd_statfs_inode); - struct gfs2_inode *l_ip = GFS2_I(sdp->sd_sc_inode); + struct gfs2_glock *m_gl = gfs2_inode_glock(sdp->sd_statfs_inode); + struct gfs2_glock *l_gl = gfs2_inode_glock(sdp->sd_sc_inode); struct gfs2_statfs_change_host *m_sc = &sdp->sd_statfs_master; struct gfs2_statfs_change_host *l_sc = &sdp->sd_statfs_local; - gfs2_trans_add_meta(l_ip->i_gl, sdp->sd_sc_bh); - gfs2_trans_add_meta(m_ip->i_gl, m_bh); + gfs2_trans_add_meta(l_gl, sdp->sd_sc_bh); + gfs2_trans_add_meta(m_gl, m_bh); spin_lock(&sdp->sd_statfs_spin); m_sc->sc_total += l_sc->sc_total; @@ -273,8 +273,8 @@ int gfs2_statfs_sync(struct super_block *sb, int type) struct buffer_head *m_bh; int error; - error = gfs2_glock_nq_init(m_ip->i_gl, LM_ST_EXCLUSIVE, GL_NOCACHE, - &gh); + error = gfs2_glock_nq_init(gfs2_inode_glock(&m_ip->i_inode), + LM_ST_EXCLUSIVE, GL_NOCACHE, &gh); if (error) goto out; @@ -323,7 +323,6 @@ struct lfcc { static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp) { - struct gfs2_inode *ip; struct gfs2_jdesc *jd; struct lfcc *lfcc; LIST_HEAD(list); @@ -336,13 +335,14 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp) */ list_for_each_entry(jd, &sdp->sd_jindex_list, jd_list) { + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); + lfcc = kmalloc_obj(struct lfcc); if (!lfcc) { error = -ENOMEM; goto out; } - ip = GFS2_I(jd->jd_inode); - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, 0, &lfcc->gh); + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, 0, &lfcc->gh); if (error) { kfree(lfcc); goto out; @@ -438,15 +438,16 @@ void gfs2_dinode_out(const struct gfs2_inode *ip, void *buf) static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); - struct address_space *metamapping = gfs2_glock2aspace(ip->i_gl); + struct address_space *metamapping = gfs2_glock2aspace(gl); struct backing_dev_info *bdi = inode_to_bdi(metamapping->host); int ret = 0; bool flush_all = (wbc->sync_mode == WB_SYNC_ALL || gfs2_is_jdata(ip)); if (flush_all) - gfs2_log_flush(GFS2_SB(inode), ip->i_gl, + gfs2_log_flush(GFS2_SB(inode), gl, GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_WRITE_INODE); if (bdi_wb_dirty_exceeded(bdi)) @@ -481,6 +482,7 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc) static void gfs2_dirty_inode(struct inode *inode, int flags) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct buffer_head *bh; @@ -490,20 +492,20 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) int ret; /* This can only happen during incomplete inode creation. */ - if (unlikely(!ip->i_gl)) + if (unlikely(!gl)) return; if (gfs2_withdrawn(sdp)) return; - if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (!gfs2_glock_is_locked_by_me(gl)) { + ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &gh); if (ret) { fs_err(sdp, "dirty_inode: glock %d\n", ret); - gfs2_dump_glock(NULL, ip->i_gl, true); + gfs2_dump_glock(NULL, gl, true); return; } need_unlock = 1; - } else if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) + } else if (WARN_ON_ONCE(gl->gl_state != LM_ST_EXCLUSIVE)) return; if (current->journal_info == NULL) { @@ -517,7 +519,7 @@ static void gfs2_dirty_inode(struct inode *inode, int flags) ret = gfs2_meta_inode_buffer(ip, &bh); if (ret == 0) { - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); gfs2_dinode_out(ip, bh->b_data); brelse(bh); } @@ -1176,6 +1178,7 @@ static void gfs2_glock_put_eventually(struct gfs2_glock *gl) static enum evict_behavior gfs2_upgrade_iopen_glock(struct inode *inode) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_holder *gh = &ip->i_iopen_gh; @@ -1211,11 +1214,11 @@ static enum evict_behavior gfs2_upgrade_iopen_glock(struct inode *inode) wait_event_interruptible_timeout(sdp->sd_async_glock_wait, !test_bit(HIF_WAIT, &gh->gh_iflags) || - glock_needs_demote(ip->i_gl), + glock_needs_demote(gl), 5 * HZ); if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) { gfs2_glock_dq(gh); - if (glock_needs_demote(ip->i_gl)) + if (glock_needs_demote(gl)) return EVICT_SHOULD_SKIP_DELETE; return EVICT_SHOULD_DEFER_DELETE; } @@ -1238,6 +1241,7 @@ static enum evict_behavior gfs2_upgrade_iopen_glock(struct inode *inode) static enum evict_behavior evict_should_delete(struct inode *inode, struct gfs2_holder *gh) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct super_block *sb = inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; @@ -1255,11 +1259,11 @@ static enum evict_behavior evict_should_delete(struct inode *inode, return EVICT_SHOULD_DEFER_DELETE; /* Must not read inode block until block type has been verified */ - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, GL_SKIP, gh); + ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, GL_SKIP, gh); if (unlikely(ret)) return EVICT_SHOULD_SKIP_DELETE; - if (gfs2_inode_already_deleted(ip->i_gl, ip->i_no_formal_ino)) + if (gfs2_inode_already_deleted(gl, ip->i_no_formal_ino)) return EVICT_SHOULD_SKIP_DELETE; ret = gfs2_check_blk_type(sdp, ip->i_no_addr, GFS2_BLKST_UNLINKED); if (ret) @@ -1288,8 +1292,8 @@ static enum evict_behavior evict_should_delete(struct inode *inode, */ static int evict_unlinked_inode(struct inode *inode, struct gfs2_holder *gh) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_glock *gl = ip->i_gl; int ret; /* The inode glock must be held exclusively and be instantiated. */ @@ -1390,8 +1394,7 @@ static int evict_linked_inode(struct inode *inode, struct gfs2_holder *gh) { struct super_block *sb = inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; - struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_glock *gl = ip->i_gl; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct address_space *metamapping = gfs2_glock2aspace(gl); int ret; @@ -1446,13 +1449,14 @@ static void gfs2_evict_inode(struct inode *inode) { struct super_block *sb = inode->i_sb; struct gfs2_sbd *sdp = sb->s_fs_info; + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; enum evict_behavior behavior; int ret; gfs2_holder_mark_uninitialized(&gh); - if (sb_rdonly(sb) || !ip->i_no_addr || !ip->i_gl) + if (sb_rdonly(sb) || !ip->i_no_addr || !gl) goto out; /* @@ -1505,10 +1509,10 @@ static void gfs2_evict_inode(struct inode *inode) gfs2_glock_dq_uninit(&ip->i_iopen_gh); gfs2_glock_put_eventually(gl); } - if (ip->i_gl) { - glock_clear_object(ip->i_gl, ip); + if (gl) { + glock_clear_object(gl, ip); wait_on_bit_io(&ip->i_flags, GIF_GLOP_PENDING, TASK_UNINTERRUPTIBLE); - gfs2_glock_put_eventually(ip->i_gl); + gfs2_glock_put_eventually(gl); rcu_assign_pointer(ip->i_gl, NULL); } } diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 83b8bb6446e5..61b0668ecabc 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -55,10 +55,9 @@ int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, int error; struct gfs2_holder j_gh; struct gfs2_log_header_host head; - struct gfs2_inode *ip; + struct gfs2_glock *gl = gfs2_inode_glock(jd->jd_inode); - ip = GFS2_I(jd->jd_inode); - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_RECOVER | + error = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_RECOVER | GL_EXACT | GL_NOCACHE, &j_gh); if (error) { if (verbose) @@ -333,6 +332,7 @@ void gfs2_consist_i(struct gfs2_sbd *sdp, const char *function, void gfs2_consist_inode_i(struct gfs2_inode *ip, const char *function, char *file, unsigned int line) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); gfs2_lm(sdp, @@ -342,7 +342,7 @@ void gfs2_consist_inode_i(struct gfs2_inode *ip, (unsigned long long)ip->i_no_formal_ino, (unsigned long long)ip->i_no_addr, function, file, line); - gfs2_dump_glock(NULL, ip->i_gl, 1); + gfs2_dump_glock(NULL, gl, 1); gfs2_withdraw(sdp); } diff --git a/fs/gfs2/xattr.c b/fs/gfs2/xattr.c index b9f48d6f10a9..db38d972debd 100644 --- a/fs/gfs2/xattr.c +++ b/fs/gfs2/xattr.c @@ -128,11 +128,12 @@ static int ea_foreach_i(struct gfs2_inode *ip, struct buffer_head *bh, static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct buffer_head *bh, *eabh; __be64 *eablk, *end; int error; - error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0, &bh); + error = gfs2_meta_read(gl, ip->i_eattr, DIO_WAIT, 0, &bh); if (error) return error; @@ -156,7 +157,7 @@ static int ea_foreach(struct gfs2_inode *ip, ea_call_t ea_call, void *data) break; bn = be64_to_cpu(*eablk); - error = gfs2_meta_read(ip->i_gl, bn, DIO_WAIT, 0, &eabh); + error = gfs2_meta_read(gl, bn, DIO_WAIT, 0, &eabh); if (error) break; error = ea_foreach_i(ip, eabh, ea_call, data); @@ -279,7 +280,7 @@ static int ea_dealloc_unstuffed(struct gfs2_inode *ip, struct buffer_head *bh, if (error) goto out_gunlock; - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gfs2_inode_glock(&ip->i_inode), bh); dataptrs = GFS2_EA2DATAPTRS(ea); for (x = 0; x < ea->ea_num_ptrs; x++, dataptrs++) { @@ -426,7 +427,8 @@ ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size) er.er_data_len = size; } - error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &i_gh); + error = gfs2_glock_nq_init(gfs2_inode_glock(&ip->i_inode), LM_ST_SHARED, + LM_FLAG_ANY, &i_gh); if (error) return error; @@ -457,6 +459,7 @@ ssize_t gfs2_listxattr(struct dentry *dentry, char *buffer, size_t size) static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, const char *din, char *dout) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head **bh; unsigned int amount = GFS2_EA_DATA_LEN(ea); @@ -472,7 +475,7 @@ static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, return -ENOMEM; for (x = 0; x < nptrs; x++) { - error = gfs2_meta_read(ip->i_gl, be64_to_cpu(*dataptrs), 0, 0, + error = gfs2_meta_read(gl, be64_to_cpu(*dataptrs), 0, 0, bh + x); if (error) { while (x--) @@ -505,7 +508,7 @@ static int gfs2_iter_unstuffed(struct gfs2_inode *ip, struct gfs2_ea_header *ea, } if (din) { - gfs2_trans_add_meta(ip->i_gl, bh[x]); + gfs2_trans_add_meta(gl, bh[x]); memcpy(pos, din, cp_size); din += sdp->sd_jbsize; } @@ -608,14 +611,14 @@ static int gfs2_xattr_get(const struct xattr_handler *handler, struct dentry *unused, struct inode *inode, const char *name, void *buffer, size_t size) { - struct gfs2_inode *ip = GFS2_I(inode); + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_holder gh; int ret; /* During lookup, SELinux calls this function with the glock locked. */ - if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); + if (!gfs2_glock_is_locked_by_me(gl)) { + ret = gfs2_glock_nq_init(gl, LM_ST_SHARED, LM_FLAG_ANY, &gh); if (ret) return ret; } else { @@ -637,6 +640,7 @@ static int gfs2_xattr_get(const struct xattr_handler *handler, static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_ea_header *ea; unsigned int n = 1; @@ -647,8 +651,8 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) if (error) return error; gfs2_trans_remove_revoke(sdp, block, 1); - *bhp = gfs2_meta_new(ip->i_gl, block); - gfs2_trans_add_meta(ip->i_gl, *bhp); + *bhp = gfs2_meta_new(gl, block); + gfs2_trans_add_meta(gl, *bhp); gfs2_metatype_set(*bhp, GFS2_METATYPE_EA, GFS2_FORMAT_EA); gfs2_buffer_clear_tail(*bhp, sizeof(struct gfs2_meta_header)); @@ -678,6 +682,7 @@ static int ea_alloc_blk(struct gfs2_inode *ip, struct buffer_head **bhp) static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, struct gfs2_ea_request *er) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); int error; @@ -709,8 +714,8 @@ static int ea_write(struct gfs2_inode *ip, struct gfs2_ea_header *ea, if (error) return error; gfs2_trans_remove_revoke(sdp, block, 1); - bh = gfs2_meta_new(ip->i_gl, block); - gfs2_trans_add_meta(ip->i_gl, bh); + bh = gfs2_meta_new(gl, block); + gfs2_trans_add_meta(gl, bh); gfs2_metatype_set(bh, GFS2_METATYPE_ED, GFS2_FORMAT_ED); gfs2_add_inode_blocks(&ip->i_inode, 1); @@ -841,11 +846,12 @@ static struct gfs2_ea_header *ea_split_ea(struct gfs2_ea_header *ea) static void ea_set_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_ea_header *ea = el->el_ea; struct gfs2_ea_header *prev = el->el_prev; u32 len; - gfs2_trans_add_meta(ip->i_gl, el->el_bh); + gfs2_trans_add_meta(gl, el->el_bh); if (!prev || !GFS2_EA_IS_STUFFED(ea)) { ea->ea_type = GFS2_EATYPE_UNUSED; @@ -875,6 +881,7 @@ struct ea_set { static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, struct gfs2_ea_header *ea, struct ea_set *es) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_ea_request *er = es->es_er; int error; @@ -882,7 +889,7 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, if (error) return error; - gfs2_trans_add_meta(ip->i_gl, bh); + gfs2_trans_add_meta(gl, bh); if (es->ea_split) ea = ea_split_ea(ea); @@ -902,11 +909,12 @@ static int ea_set_simple_noalloc(struct gfs2_inode *ip, struct buffer_head *bh, static int ea_set_simple_alloc(struct gfs2_inode *ip, struct gfs2_ea_request *er, void *private) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct ea_set *es = private; struct gfs2_ea_header *ea = es->es_ea; int error; - gfs2_trans_add_meta(ip->i_gl, es->es_bh); + gfs2_trans_add_meta(gl, es->es_bh); if (es->ea_split) ea = ea_split_ea(ea); @@ -971,6 +979,7 @@ static int ea_set_simple(struct gfs2_inode *ip, struct buffer_head *bh, static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, void *private) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct buffer_head *indbh, *newbh; __be64 *eablk; @@ -980,7 +989,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, if (ip->i_diskflags & GFS2_DIF_EA_INDIRECT) { __be64 *end; - error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0, + error = gfs2_meta_read(gl, ip->i_eattr, DIO_WAIT, 0, &indbh); if (error) return error; @@ -1002,7 +1011,7 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, goto out; } - gfs2_trans_add_meta(ip->i_gl, indbh); + gfs2_trans_add_meta(gl, indbh); } else { u64 blk; unsigned int n = 1; @@ -1010,8 +1019,8 @@ static int ea_set_block(struct gfs2_inode *ip, struct gfs2_ea_request *er, if (error) return error; gfs2_trans_remove_revoke(sdp, blk, 1); - indbh = gfs2_meta_new(ip->i_gl, blk); - gfs2_trans_add_meta(ip->i_gl, indbh); + indbh = gfs2_meta_new(gl, blk); + gfs2_trans_add_meta(gl, indbh); gfs2_metatype_set(indbh, GFS2_METATYPE_IN, GFS2_FORMAT_IN); gfs2_buffer_clear_tail(indbh, mh_size); @@ -1088,6 +1097,7 @@ static int ea_set_remove_unstuffed(struct gfs2_inode *ip, static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_ea_header *ea = el->el_ea; struct gfs2_ea_header *prev = el->el_prev; int error; @@ -1096,7 +1106,7 @@ static int ea_remove_stuffed(struct gfs2_inode *ip, struct gfs2_ea_location *el) if (error) return error; - gfs2_trans_add_meta(ip->i_gl, el->el_bh); + gfs2_trans_add_meta(gl, el->el_bh); if (prev) { u32 len; @@ -1234,6 +1244,7 @@ static int gfs2_xattr_set(const struct xattr_handler *handler, const char *name, const void *value, size_t size, int flags) { + struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_holder gh; int ret; @@ -1244,12 +1255,12 @@ static int gfs2_xattr_set(const struct xattr_handler *handler, /* May be called from gfs_setattr with the glock locked. */ - if (!gfs2_glock_is_locked_by_me(ip->i_gl)) { - ret = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh); + if (!gfs2_glock_is_locked_by_me(gl)) { + ret = gfs2_glock_nq_init(gl, LM_ST_EXCLUSIVE, 0, &gh); if (ret) goto out; } else { - if (WARN_ON_ONCE(ip->i_gl->gl_state != LM_ST_EXCLUSIVE)) { + if (WARN_ON_ONCE(gl->gl_state != LM_ST_EXCLUSIVE)) { ret = -EIO; goto out; } @@ -1265,6 +1276,7 @@ static int gfs2_xattr_set(const struct xattr_handler *handler, static int ea_dealloc_indirect(struct gfs2_inode *ip) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_rgrp_list rlist; struct gfs2_rgrpd *rgd; @@ -1283,7 +1295,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) memset(&rlist, 0, sizeof(struct gfs2_rgrp_list)); - error = gfs2_meta_read(ip->i_gl, ip->i_eattr, DIO_WAIT, 0, &indbh); + error = gfs2_meta_read(gl, ip->i_eattr, DIO_WAIT, 0, &indbh); if (error) return error; @@ -1333,7 +1345,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) if (error) goto out_gunlock; - gfs2_trans_add_meta(ip->i_gl, indbh); + gfs2_trans_add_meta(gl, indbh); eablk = (__be64 *)(indbh->b_data + sizeof(struct gfs2_meta_header)); bstart = 0; @@ -1367,7 +1379,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } @@ -1385,6 +1397,7 @@ static int ea_dealloc_indirect(struct gfs2_inode *ip) static int ea_dealloc_block(struct gfs2_inode *ip, bool initialized) { + struct gfs2_glock *gl = gfs2_inode_glock(&ip->i_inode); struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); struct gfs2_rgrpd *rgd; struct buffer_head *dibh; @@ -1419,7 +1432,7 @@ static int ea_dealloc_block(struct gfs2_inode *ip, bool initialized) if (initialized) { error = gfs2_meta_inode_buffer(ip, &dibh); if (!error) { - gfs2_trans_add_meta(ip->i_gl, dibh); + gfs2_trans_add_meta(gl, dibh); gfs2_dinode_out(ip, dibh->b_data); brelse(dibh); } From 51b812f668e252d19bc80b1956bdd796aef56121 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 16:00:56 +0200 Subject: [PATCH 05/19] gfs2: annotate i_gl with __rcu ip->i_gl is always set over the lifetime of a gfs2 inode; it is initialized at inode create time and torn down during evict. However, gfs2_permission() can be called on an inode in non-blocking mode, when the inode may already be undergoing evict. So far, to make that work, we have been using rcu_dereference_check() in gfs2_permission() and rcu_assign_pointer() in gfs2_evict_inode(). However, ip->i_gl wasn't marked as __rcu so far. rcu_dereference_check() and rcu_assign_pointer() expect __rcu pointer arguments, and sparse complains when regular pointers are passed to those functions: fs/gfs2/super.c:1516:17: error: incompatible types in comparison expression (different address spaces): fs/gfs2/super.c:1516:17: struct gfs2_glock [noderef] __rcu * fs/gfs2/super.c:1516:17: struct gfs2_glock * fs/gfs2/inode.c:1988:14: error: incompatible types in comparison expression (different address spaces): fs/gfs2/inode.c:1988:14: struct gfs2_glock [noderef] __rcu * fs/gfs2/inode.c:1988:14: struct gfs2_glock * To fix those errors, turn ip->i_gl into a __rcu variable. Use rcu_assign_pointer() to assign to it, and rcu_dereference_protected() to access it when the pointer is known to be valid. Make sure not to use gfs2_inode_glock() in gfs2_permission(). Based on a patch from Adrian Garcia Casado . Signed-off-by: Andreas Gruenbacher --- fs/gfs2/incore.h | 4 ++-- fs/gfs2/inode.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 3ae8e2be486c..0a48f8e8ed6c 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -391,7 +391,7 @@ struct gfs2_inode { u64 i_generation; u64 i_eattr; unsigned long i_flags; /* GIF_... */ - struct gfs2_glock *i_gl; + struct gfs2_glock __rcu *i_gl; struct gfs2_holder i_iopen_gh; struct gfs2_qadata *i_qadata; /* quota allocation data */ struct gfs2_holder i_rgd_gh; @@ -881,6 +881,6 @@ static inline unsigned gfs2_max_stuffed_size(const struct gfs2_inode *ip) static inline struct gfs2_glock *gfs2_inode_glock(struct inode *inode) { - return GFS2_I(inode)->i_gl; + return rcu_dereference_protected(GFS2_I(inode)->i_gl, 1); } #endif /* __INCORE_DOT_H__ */ diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 5aaed0018fb3..d4e1e443391e 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -151,7 +151,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, &gl); if (unlikely(error)) goto fail; - ip->i_gl = gl; + rcu_assign_pointer(ip->i_gl, gl); error = gfs2_glock_get(sdp, no_addr, &gfs2_iopen_glops, CREATE, &io_gl); @@ -244,7 +244,7 @@ struct inode *gfs2_inode_lookup(struct super_block *sb, unsigned int type, gfs2_glock_dq_uninit(&i_gh); if (gl) { gfs2_glock_put(gl); - ip->i_gl = NULL; + rcu_assign_pointer(ip->i_gl, NULL); } iget_failed(inode); return ERR_PTR(error); @@ -840,7 +840,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_inode_glops, CREATE, &gl); if (error) goto fail_dealloc_inode; - ip->i_gl = gl; + rcu_assign_pointer(ip->i_gl, gl); error = gfs2_glock_get(sdp, ip->i_no_addr, &gfs2_iopen_glops, CREATE, &io_gl); if (error) @@ -940,7 +940,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, fail_free_inode: if (gl) { gfs2_glock_put(gl); - ip->i_gl = NULL; + rcu_assign_pointer(ip->i_gl, NULL); } gfs2_rs_deltree(&ip->i_res); gfs2_qa_put(ip); From c4f01c85c8fe964a44f6967473a10f477c5f3cd0 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 15:15:35 +0200 Subject: [PATCH 06/19] gfs2: Silence sparse signedness warning Silence the following sparse warning: fs/gfs2/bmap.c:1718:42: warning: unsigned value that used to be signed checked against zero? fs/gfs2/bmap.c:2017:16: signed value source It's unclear to me what sparse is trying to tell me there, but making the height variables unsigned shuts it up. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index b5ddd936f489..3714364385c7 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1699,7 +1699,7 @@ enum dealloc_states { }; static inline void -metapointer_range(struct metapath *mp, int height, +metapointer_range(struct metapath *mp, unsigned int height, __u16 *start_list, unsigned int start_aligned, __u16 *end_list, unsigned int end_aligned, __be64 **start, __be64 **end) @@ -1770,7 +1770,7 @@ static int punch_hole(struct gfs2_inode *ip, u64 offset, u64 length) unsigned int strip_h = ip->i_height - 1; u32 btotal = 0; int ret, state; - int mp_h; /* metapath buffers are read in to this height */ + unsigned int mp_h; /* metapath buffers are read in to this height */ u64 prev_bnr = 0; __be64 *start, *end; From 26cb3a444d8ec1d15a3c951c30db1dc121e5e1a4 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 20 Aug 2026 23:39:40 +0200 Subject: [PATCH 07/19] gfs2: Improve resource group validation and error handling Validate the resource group boundaries, check against the device size, simplify the initialization logic, and check for resource group overlaps. Reported-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=9d20c3ad7d29227de28d Tested-by: syzbot+9d20c3ad7d29227de28d@syzkaller.appspotmail.com Signed-off-by: Andreas Gruenbacher --- fs/gfs2/rgrp.c | 125 ++++++++++++++++++++++++++----------------------- 1 file changed, 66 insertions(+), 59 deletions(-) diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index f6048a73e5c3..3ac751eea055 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -745,6 +745,7 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) /** * compute_bitstructs - Compute the bitmap sizes + * @sb: The superblock * @rgd: The resource group descriptor * * Calculates bitmap descriptors, one for each block that contains bitmap data @@ -752,84 +753,74 @@ void gfs2_clear_rgrpd(struct gfs2_sbd *sdp) * Returns: errno */ -static int compute_bitstructs(struct gfs2_rgrpd *rgd) +static int compute_bitstructs(struct super_block *sb, struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct gfs2_bitmap *bi; - u32 length = rgd->rd_length; /* # blocks in hdr & bitmap */ + u32 expected_length; u32 bytes_left, bytes; + u64 data_end; int x; - if (!length) - return -EINVAL; + /* + * The first resource group block has a gfs2_rgrp header; the remaining + * blocks have a gfs2_meta_header header. The rest of each block is + * filled with bitmap data. + */ - rgd->rd_bits = kzalloc_objs(struct gfs2_bitmap, length, GFP_NOFS); + if (rgd->rd_addr <= (GFS2_SB_ADDR >> sdp->sd_fsb2bb_shift)) { + gfs2_consist_rgrpd(rgd); + return -EIO; + } + if (check_add_overflow(rgd->rd_data0, rgd->rd_data, &data_end) || + rgd->rd_data == 0 || data_end > sb_bdev_nr_blocks(sb)) { + gfs2_consist_rgrpd(rgd); + return -EIO; + } + if (rgd->rd_bitbytes != DIV_ROUND_UP(rgd->rd_data, GFS2_NBBY)) { + gfs2_consist_rgrpd(rgd); + return -EIO; + } + expected_length = DIV_ROUND_UP(rgd->rd_bitbytes + + sizeof(struct gfs2_rgrp) - sizeof(struct gfs2_meta_header), + sdp->sd_sb.sb_bsize - sizeof(struct gfs2_meta_header)); + if (rgd->rd_length != expected_length) { + gfs2_consist_rgrpd(rgd); + return -EIO; + } + if (rgd->rd_data0 < rgd->rd_addr + rgd->rd_length) { + gfs2_consist_rgrpd(rgd); + return -EIO; + } + + rgd->rd_bits = kzalloc_objs(struct gfs2_bitmap, rgd->rd_length, GFP_NOFS); if (!rgd->rd_bits) return -ENOMEM; bytes_left = rgd->rd_bitbytes; - for (x = 0; x < length; x++) { + for (x = 0; x < rgd->rd_length; x++) { bi = rgd->rd_bits + x; bi->bi_flags = 0; - /* small rgrp; bitmap stored completely in header block */ - if (length == 1) { - bytes = bytes_left; - bi->bi_offset = sizeof(struct gfs2_rgrp); + if (x == 0) { + /* header block */ bi->bi_start = 0; - bi->bi_bytes = bytes; - bi->bi_blocks = bytes * GFS2_NBBY; - /* header block */ - } else if (x == 0) { - bytes = sdp->sd_sb.sb_bsize - sizeof(struct gfs2_rgrp); bi->bi_offset = sizeof(struct gfs2_rgrp); - bi->bi_start = 0; - bi->bi_bytes = bytes; - bi->bi_blocks = bytes * GFS2_NBBY; - /* last block */ - } else if (x + 1 == length) { - bytes = bytes_left; - bi->bi_offset = sizeof(struct gfs2_meta_header); - bi->bi_start = rgd->rd_bitbytes - bytes_left; - bi->bi_bytes = bytes; - bi->bi_blocks = bytes * GFS2_NBBY; - /* other blocks */ } else { - bytes = sdp->sd_sb.sb_bsize - - sizeof(struct gfs2_meta_header); - bi->bi_offset = sizeof(struct gfs2_meta_header); - bi->bi_start = rgd->rd_bitbytes - bytes_left; - bi->bi_bytes = bytes; - bi->bi_blocks = bytes * GFS2_NBBY; - } + /* bitmap-only block */ + struct gfs2_bitmap *prev = bi - 1; + bi->bi_start = prev->bi_start + prev->bi_bytes; + bi->bi_offset = sizeof(struct gfs2_meta_header); + } + bytes = sdp->sd_sb.sb_bsize - bi->bi_offset; + if (bytes > bytes_left) + bytes = bytes_left; + bi->bi_bytes = bytes; + bi->bi_blocks = bytes * GFS2_NBBY; bytes_left -= bytes; } - - if (bytes_left) { - gfs2_consist_rgrpd(rgd); - return -EIO; - } - bi = rgd->rd_bits + (length - 1); - if ((bi->bi_start + bi->bi_bytes) * GFS2_NBBY != rgd->rd_data) { - gfs2_lm(sdp, - "ri_addr=%llu " - "ri_length=%u " - "ri_data0=%llu " - "ri_data=%u " - "ri_bitbytes=%u " - "start=%u len=%u offset=%u\n", - (unsigned long long)rgd->rd_addr, - rgd->rd_length, - (unsigned long long)rgd->rd_data0, - rgd->rd_data, - rgd->rd_bitbytes, - bi->bi_start, bi->bi_bytes, bi->bi_offset); - gfs2_consist_rgrpd(rgd); - return -EIO; - } - return 0; } @@ -864,6 +855,7 @@ static int rgd_insert(struct gfs2_rgrpd *rgd) { struct gfs2_sbd *sdp = rgd->rd_sbd; struct rb_node **newn = &sdp->sd_rindex_tree.rb_node, *parent = NULL; + struct rb_node *prevn; /* Figure out where to put new node */ while (*newn) { @@ -882,6 +874,19 @@ static int rgd_insert(struct gfs2_rgrpd *rgd) rb_link_node(&rgd->rd_node, parent, newn); rb_insert_color(&rgd->rd_node, &sdp->sd_rindex_tree); sdp->sd_rgrps++; + + prevn = rb_prev(&rgd->rd_node); + if (prevn) { + struct gfs2_rgrpd *prev = + rb_entry(prevn, struct gfs2_rgrpd, rd_node); + + if (prev->rd_data0 + prev->rd_data > rgd->rd_addr) { + fs_err(sdp, "overlapping resource groups.\n"); + rb_erase(&rgd->rd_node, &sdp->sd_rindex_tree); + return -ENOENT; + } + } + return 0; } @@ -928,7 +933,7 @@ static int read_rindex_entry(struct gfs2_inode *ip) if (error) goto fail; - error = compute_bitstructs(rgd); + error = compute_bitstructs(sdp->sd_vfs, rgd); if (error) goto fail_glock; @@ -944,7 +949,9 @@ static int read_rindex_entry(struct gfs2_inode *ip) return 0; } - error = 0; /* someone else read in the rgrp; free it and ignore it */ + /* If someone else read in the rgrp, free it and ignore it. */ + if (error == -EEXIST) + error = 0; fail_glock: gfs2_glock_put(rgd->rd_gl); From 59932d7f7e48e2bd2017e8d4d9e1a3f2574436f1 Mon Sep 17 00:00:00 2001 From: Hongling Zeng Date: Tue, 25 Aug 2026 09:55:01 +0800 Subject: [PATCH 08/19] gfs2: move brelse() after buffer head accesses The brelse() call happens before all buffer head accesses are complete. While the reference counting prevents a real use-after-free in practice, this pattern is error-prone for future maintenance. Move the brelse() call to the end of the function to make the intent clearer and eliminate potential static analysis warnings. Suggested-by: Andreas Gruenbacher Suggested-by: Andrew Price Signed-off-by: Hongling Zeng Signed-off-by: Andreas Gruenbacher --- fs/gfs2/log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c index 78bba8cc10b8..a92c84146de9 100644 --- a/fs/gfs2/log.c +++ b/fs/gfs2/log.c @@ -1038,7 +1038,6 @@ void gfs2_remove_from_journal(struct buffer_head *bh, int meta) set_bit(TR_TOUCHED, &tr->tr_flags); } was_pinned = 1; - brelse(bh); } if (bd) { if (bd->bd_tr) { @@ -1056,6 +1055,8 @@ void gfs2_remove_from_journal(struct buffer_head *bh, int meta) } clear_buffer_dirty(bh); clear_buffer_uptodate(bh); + if (was_pinned) + brelse(bh); } /** From 0008baad6377c8195c63151f66cc01039919eab6 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Wed, 26 Aug 2026 12:41:28 +0200 Subject: [PATCH 09/19] gfs2: No quotas for meta inodes Inodes on the meta filesystem (mount -o meta) can never have quotas, so skip them entirely in the quota code. This avoids allocating ip->i_qadata unnecessarily. Without this fix, unlinking meta inodes like "statfs" on the meta filesystem will result in a NULL pointer dereference at unmount time: gfs2_evict_inode() -> gfs2_dinode_dealloc() -> gfs2_quota_hold() -> qdsb_get() -> slot_get() -> find_first_zero_bit(sd_quota_bitmap) Unlinking inodes on the meta filesystem isn't a useful operation, but it still shouldn't cause the kernel to misbehave. Reported-by: syzbot+cb79de2cc8b76fbf474f@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cb79de2cc8b76fbf474f Signed-off-by: Andreas Gruenbacher --- fs/gfs2/quota.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index b62431724eea..dbfc21693dd5 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -562,6 +562,8 @@ int gfs2_qa_get(struct gfs2_inode *ip) if (sdp->sd_args.ar_quota == GFS2_QUOTA_OFF) return 0; + if (ip->i_diskflags & GFS2_DIF_SYSTEM) + return 0; spin_lock(&inode->i_lock); if (ip->i_qadata == NULL) { @@ -605,7 +607,7 @@ int gfs2_quota_hold(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) return 0; error = gfs2_qa_get(ip); - if (error) + if (error || !ip->i_qadata) return error; qd = ip->i_qadata->qa_qd; From 33ed0a0567e0abe66ea65e89dad2e35082890fbe Mon Sep 17 00:00:00 2001 From: Jiaming Zhang Date: Mon, 31 Aug 2026 18:54:25 +0800 Subject: [PATCH 10/19] gfs2: reject invalid inode sizes A corrupted GFS2 image can store a dinode size that is larger than what VFS i_size can represent. gfs2_dinode_in() reads the on-disk di_size as a u64 and writes it directly into inode->i_size. If the value is larger than S64_MAX, the incore i_size becomes negative. That negative value can bypass the existing stuffed inode size check: inode->i_size > gfs2_max_stuffed_size(ip) Later, gfs2_quotad may try to sync the quota file and unstuff the quota inode. gfs2_unstuffer_folio() reads the negative i_size into an unsigned length and passes it to memcpy(), turning it into a huge copy size and triggering a out-of-bound issue. Reject dinodes whose size exceeds sb->s_maxbytes before storing the value in inode->i_size. Also make the stuffed inode check use the raw on-disk size while it is still unsigned. Fixes: 70376c7ff312 ("gfs2: Always check inode size of inline inodes") Closes: https://lore.kernel.org/lkml/CANypQFaF6bvORKKbRALvEL0k_epFaneFiOQqco4gjdmKVbdURg@mail.gmail.com/ Assisted-by: Codex:gpt-5.5-xhigh Cc: stable@vger.kernel.org Signed-off-by: Jiaming Zhang Signed-off-by: Andreas Gruenbacher --- fs/gfs2/glops.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index 662d033fd2ca..2597e1cf2315 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -393,6 +393,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) umode_t mode = be32_to_cpu(str->di_mode); struct inode *inode = &ip->i_inode; bool is_new = inode_state_read_once(inode) & I_NEW; + u64 size; if (unlikely(ip->i_no_addr != be64_to_cpu(str->di_num.no_addr))) { gfs2_consist_inode(ip); @@ -418,7 +419,12 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) i_uid_write(inode, be32_to_cpu(str->di_uid)); i_gid_write(inode, be32_to_cpu(str->di_gid)); set_nlink(inode, be32_to_cpu(str->di_nlink)); - i_size_write(inode, be64_to_cpu(str->di_size)); + size = be64_to_cpu(str->di_size); + if (unlikely(size > inode->i_sb->s_maxbytes)) { + gfs2_consist_inode(ip); + return -EIO; + } + i_size_write(inode, size); gfs2_set_inode_blocks(inode, be64_to_cpu(str->di_blocks)); atime.tv_sec = be64_to_cpu(str->di_atime); atime.tv_nsec = be32_to_cpu(str->di_atime_nsec); @@ -462,7 +468,7 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) return -EIO; } - if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) { + if (gfs2_is_stuffed(ip) && size > gfs2_max_stuffed_size(ip)) { gfs2_consist_inode(ip); return -EIO; } From a098f26d3b80e99740ea155a7012008d12a46010 Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Sun, 30 Aug 2026 16:36:37 +0200 Subject: [PATCH 11/19] gfs2: Get rid of sd_async_glock_wait Get rid of the per-superblock wait queue for asynchronous locking requests. Instead, wait for the specific events we are interested in. Use multiple wait queue entries when waiting for multiple events at once. Without this patch, the per-superblock wait queue for asynchronous locking requests can become a bottleneck when many inodes are deleted remotely: in that case, we schedule delayed work with gfs2_queue_verify_delete(). When that work later runs, we end up in delete_work_func() -> iput() -> gfs2_evict_inode() -> gfs2_upgrade_iopen_glock(), which uses asynchronous locking. Each completing locking asynchronous request will wake up sdp->sd_async_glock_wait, and all the waiters will compete with each other and waste resources. Avoid that by eliminating the per-superblock wait queue. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/glock.c | 56 ++++++++++++++++++++++++++++++-------------- fs/gfs2/incore.h | 1 - fs/gfs2/ops_fstype.c | 1 - fs/gfs2/super.c | 30 ++++++++++++++++++++---- 4 files changed, 63 insertions(+), 25 deletions(-) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index d0612014408e..d22a088c66cd 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -329,11 +329,6 @@ static void gfs2_holder_wake(struct gfs2_holder *gh) clear_bit(HIF_WAIT, &gh->gh_iflags); smp_mb__after_atomic(); wake_up_bit(&gh->gh_iflags, HIF_WAIT); - if (gh->gh_flags & GL_ASYNC) { - struct gfs2_sbd *sdp = glock_sbd(gh->gh_gl); - - wake_up(&sdp->sd_async_glock_wait); - } } /** @@ -512,11 +507,9 @@ static void state_change(struct gfs2_glock *gl, unsigned int new_state) static void gfs2_set_demote(int nr, struct gfs2_glock *gl) { - struct gfs2_sbd *sdp = glock_sbd(gl); - set_bit(nr, &gl->gl_flags); - smp_mb(); - wake_up(&sdp->sd_async_glock_wait); + smp_mb__after_atomic(); + wake_up_bit(&gl->gl_flags, GLF_DEMOTE); } static void gfs2_demote_wake(struct gfs2_glock *gl) @@ -1272,11 +1265,14 @@ static int glocks_pending(unsigned int num_gh, struct gfs2_holder *ghs) int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, unsigned int retries) { - struct gfs2_sbd *sdp = glock_sbd(ghs[0].gh_gl); unsigned long start_time = jiffies; - int i, ret = 0; - long timeout; + struct wait_queue_head *waitq[4]; + struct wait_queue_entry wait[4]; + long ret, timeout; + int i; + BUILD_BUG_ON(ARRAY_SIZE(waitq) != ARRAY_SIZE(wait)); + BUG_ON(num_gh > ARRAY_SIZE(wait)); might_sleep(); timeout = GL_GLOCK_MIN_HOLD; @@ -1294,14 +1290,38 @@ int gfs2_glock_async_wait(unsigned int num_gh, struct gfs2_holder *ghs, timeout += (incr / 3) + get_random_long() % (incr / 3); } - if (!wait_event_interruptible_timeout(sdp->sd_async_glock_wait, - !glocks_pending(num_gh, ghs), timeout)) { - ret = -ESTALE; /* request timed out. */ - goto out; + ret = timeout; + for (i = 0; i < num_gh; i++) { + waitq[i] = bit_waitqueue(&ghs[i].gh_iflags, HIF_WAIT); + init_wait(wait + i); } - if (signal_pending(current)) - goto interrupted; + for (;;) { + for (i = 0; i < num_gh; i++) + prepare_to_wait(waitq[i], wait + i, TASK_INTERRUPTIBLE); + if (!glocks_pending(num_gh, ghs)) + break; + if (signal_pending(current)) { + ret = -EINTR; + break; + } + ret = schedule_timeout(ret); + if (!glocks_pending(num_gh, ghs)) + break; + if (!ret) { + ret = -ESTALE; /* request timed out. */ + break; + } + if (signal_pending(current)) { + ret = -EINTR; + break; + } + } + for (i = 0; i < num_gh; i++) + finish_wait(waitq[i], wait + i); + if (ret < 0) + goto out; + ret = 0; for (i = 0; i < num_gh; i++) { struct gfs2_holder *gh = &ghs[i]; int ret2; diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h index 0a48f8e8ed6c..49cc232942a2 100644 --- a/fs/gfs2/incore.h +++ b/fs/gfs2/incore.h @@ -716,7 +716,6 @@ struct gfs2_sbd { struct work_struct sd_freeze_work; struct work_struct sd_withdraw_work; wait_queue_head_t sd_kill_wait; - wait_queue_head_t sd_async_glock_wait; atomic_t sd_glock_disposal; struct completion sd_locking_init; struct completion sd_withdraw_helper; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index 188b3e67f2d1..6ec47376aecf 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -90,7 +90,6 @@ static struct gfs2_sbd *init_sbd(struct super_block *sb) gfs2_tune_init(&sdp->sd_tune); init_waitqueue_head(&sdp->sd_kill_wait); - init_waitqueue_head(&sdp->sd_async_glock_wait); atomic_set(&sdp->sd_glock_disposal, 0); init_completion(&sdp->sd_locking_init); init_completion(&sdp->sd_withdraw_helper); diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index af8c71576833..04bb4cf787d4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -1180,8 +1180,10 @@ static enum evict_behavior gfs2_upgrade_iopen_glock(struct inode *inode) { struct gfs2_glock *gl = gfs2_inode_glock(inode); struct gfs2_inode *ip = GFS2_I(inode); - struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_holder *gh = &ip->i_iopen_gh; + struct wait_queue_head *holder_waitq, *glock_waitq; + struct wait_queue_entry holder_wait, glock_wait; + long ret = 5 * HZ; int error; gh->gh_flags |= GL_NOCACHE; @@ -1212,10 +1214,28 @@ static enum evict_behavior gfs2_upgrade_iopen_glock(struct inode *inode) if (error) return EVICT_SHOULD_SKIP_DELETE; - wait_event_interruptible_timeout(sdp->sd_async_glock_wait, - !test_bit(HIF_WAIT, &gh->gh_iflags) || - glock_needs_demote(gl), - 5 * HZ); + holder_waitq = bit_waitqueue(&gh->gh_iflags, HIF_WAIT); + glock_waitq = bit_waitqueue(&gl->gl_flags, GLF_DEMOTE); + init_wait(&holder_wait); + init_wait(&glock_wait); + for (;;) { + prepare_to_wait(holder_waitq, &holder_wait, TASK_INTERRUPTIBLE); + prepare_to_wait(glock_waitq, &glock_wait, TASK_INTERRUPTIBLE); + if (gfs2_glock_poll(gh) || glock_needs_demote(gl)) + break; + if (signal_pending(current)) + break; + ret = schedule_timeout(ret); + if (gfs2_glock_poll(gh) || glock_needs_demote(gl)) + break; + if (!ret) + break; + if (signal_pending(current)) + break; + } + finish_wait(holder_waitq, &holder_wait); + finish_wait(glock_waitq, &glock_wait); + if (!test_bit(HIF_HOLDER, &gh->gh_iflags)) { gfs2_glock_dq(gh); if (glock_needs_demote(gl)) From c6b4fcac9a4811032891904597590776fc4c81aa Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 1 Sep 2026 10:00:30 +0200 Subject: [PATCH 12/19] gfs2: missing whitespace in error message Add a missing whitespace in this error message in gfs2_quota_init(). Signed-off-by: Andreas Gruenbacher --- fs/gfs2/quota.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index dbfc21693dd5..52457f271f8b 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1477,7 +1477,7 @@ int gfs2_quota_init(struct gfs2_sbd *sdp) spin_lock_bucket(hash); old_qd = gfs2_qd_search_bucket_noref(hash, sdp, qc_id); if (old_qd) { - fs_err(sdp, "Corruption found in quota_change%u" + fs_err(sdp, "Corruption found in quota_change%u " "file: duplicate identifier in " "slot %u\n", sdp->sd_jdesc->jd_jid, slot); From a52652efd8f985397e87669f505af83f06e335cf Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Wed, 2 Sep 2026 16:36:57 +0200 Subject: [PATCH 13/19] gfs2: Fix journaled truncate range end offset The third argument to truncate_pagecache_range() is the inclusive end offset, but gfs2_journaled_truncate_range() passes the length of each chunk. A hole punch at an offset larger than its length therefore creates an inverted range. Commit 86066914edff ("gfs2: Don't support fallocate on jdata files") disables fallocate for jdata files. Otherwise, the following bug could occur: The MM truncation path then underflows the unsigned partial-folio length and passes an oversized range to folio_zero_range(), triggering a BUG. Pass the last byte of the chunk so page-cache invalidation covers the intended range. Fixes: 4e56a6411fbc ("gfs2: Implement fallocate(FALLOC_FL_PUNCH_HOLE)") Reported-by: VEGA Assisted-by: LLM Signed-off-by: Jan Kara Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index 3714364385c7..f0c4d054e5f0 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -2429,7 +2429,7 @@ static int gfs2_journaled_truncate_range(struct inode *inode, loff_t offset, if (offs && chunk > PAGE_SIZE) chunk = offs + ((chunk - offs) & PAGE_MASK); - truncate_pagecache_range(inode, offset, chunk); + truncate_pagecache_range(inode, offset, offset + chunk - 1); offset += chunk; length -= chunk; From 277536c882467e348173238e4ff701a4e4d2fb9e Mon Sep 17 00:00:00 2001 From: Hemanth Selam Date: Fri, 4 Sep 2026 16:54:27 +0530 Subject: [PATCH 14/19] gfs2: fix typos in comments Fix typos in comments, reported by scripts/checkpatch.pl using the misspelling list in scripts/spelling.txt. Only touches comments, no code changes. Assisted-by: Cursor:claude-opus-5 Signed-off-by: Hemanth Selam Signed-off-by: Andreas Gruenbacher --- fs/gfs2/bmap.c | 2 +- fs/gfs2/lock_dlm.c | 4 ++-- fs/gfs2/recovery.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index f0c4d054e5f0..264170f91c5d 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1217,7 +1217,7 @@ const struct iomap_ops gfs2_iomap_ops = { * @inode: The inode * @lblock: The logical block number * @bh_map: The bh to be mapped - * @create: True if its ok to alloc blocks to satify the request + * @create: True if its ok to alloc blocks to satisfy the request * * The size of the requested mapping is defined in bh_map->b_size. * diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index cef4bdee92a8..47eec0c13025 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -431,7 +431,7 @@ static void gdlm_cancel(struct gfs2_glock *gl) * 10. gfs2_control sets control_lock lvb = new gen + bits for failed jids * 12. gfs2_recover does journal recoveries for failed jids identified above * 14. gfs2_control clears control_lock lvb bits for recovered jids - * 15. gfs2_control checks if recover_block == recover_start (step 3 occured + * 15. gfs2_control checks if recover_block == recover_start (step 3 occurred * again) then do nothing, otherwise if recover_start > recover_block * then clear BLOCK_LOCKS. * @@ -809,7 +809,7 @@ static void gfs2_control_func(struct work_struct *work) /* * No more jid bits set in lvb, all recovery is done, unblock locks - * (unless a new recover_prep callback has occured blocking locks + * (unless a new recover_prep callback has occurred blocking locks * again while working above) */ diff --git a/fs/gfs2/recovery.c b/fs/gfs2/recovery.c index 5b1f494dc3c0..84db5bb7dc5c 100644 --- a/fs/gfs2/recovery.c +++ b/fs/gfs2/recovery.c @@ -156,7 +156,7 @@ int __get_log_header(struct gfs2_sbd *sdp, const struct gfs2_log_header *lh, * @blk: the block to look at * @head: the log header to return * - * Read the log header for a given segement in a given journal. Do a few + * Read the log header for a given segment in a given journal. Do a few * sanity checks on it. * * Returns: 0 on success, From 914141c17e08ecf4080ae0bd2fdedee0d8dedd18 Mon Sep 17 00:00:00 2001 From: ThangNN99 Date: Sun, 6 Sep 2026 15:08:21 +0700 Subject: [PATCH 15/19] gfs2: fix NULL deref in gfs2_quota_lock() for meta inodes gfs2_quota_hold() now treats a meta/system inode's NULL i_qadata as success, but gfs2_quota_lock() still dereferences it unconditionally afterwards. Bail out early when there is nothing to lock. Reported-by: syzbot+d84e35a320d14f8c270a@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=d84e35a320d14f8c270a Fixes: 0025112796287599dc79c822ed37124582a0d68a ("gfs2: No quotas for meta inodes") Signed-off-by: ThangNN99 Signed-off-by: Andreas Gruenbacher --- fs/gfs2/quota.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 52457f271f8b..b2984fb7b35c 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c @@ -1101,6 +1101,9 @@ int gfs2_quota_lock(struct gfs2_inode *ip, kuid_t uid, kgid_t gid) error = gfs2_quota_hold(ip, uid, gid); if (error) return error; + /* Meta inodes never get quota data (see gfs2_qa_get()); nothing to lock. */ + if (!ip->i_qadata) + return 0; sort(ip->i_qadata->qa_qd, ip->i_qadata->qa_qd_num, sizeof(struct gfs2_quota_data *), sort_qd, NULL); From 700a0a6892f7c0c541d5d23837cfab98cc744d17 Mon Sep 17 00:00:00 2001 From: Karl Mehltretter Date: Sat, 12 Sep 2026 08:26:14 +0200 Subject: [PATCH 16/19] gfs2: Fix the return value in gfs2_get_link() kernel-doc gfs2_get_link() returns the link target or an error pointer, but its kernel-doc still describes an integer status. The mismatch dates back to when gfs2_readlink() was replaced by generic_readlink() and persisted across the removal of nd_set_link(). Describe the returned pointer and error value. Fixes: c177c2ac8c5a ("Switch gfs2 to nd_set_link()") Assisted-by: LLM Signed-off-by: Karl Mehltretter Signed-off-by: Andreas Gruenbacher --- fs/gfs2/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index d4e1e443391e..2ec848b993d0 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -1910,7 +1910,7 @@ static int gfs2_rename2(struct mnt_idmap *idmap, struct inode *odir, * * This can handle symlinks of any size. * - * Returns: 0 on success or error code + * Returns: the link target on success, an ERR_PTR() on failure */ static const char *gfs2_get_link(struct dentry *dentry, From d0c4bce31a579216780b990a09250f15e00f38ff Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Tue, 22 Sep 2026 11:28:59 +0200 Subject: [PATCH 17/19] gfs2: gfs2_create_inode excl cleanup Function gfs2_create_inode() is used for creating different types of inodes. Regular inodes can be created exclusively or non-exclusively, while all other inode types are always created exclusively. Right now, gfs2_create_inode() checks the inode type to determine when creates should be exclusive; the excl argument is only set for regular files. Change that to set the excl argument correctly for all inode types; this saves the inode type check in gfs2_create_inode(). Suggested-by: NeilBrown Signed-off-by: Andreas Gruenbacher --- fs/gfs2/inode.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c index 2ec848b993d0..f748f8b3c73a 100644 --- a/fs/gfs2/inode.c +++ b/fs/gfs2/inode.c @@ -740,7 +740,7 @@ static int gfs2_create_inode(struct inode *dir, struct dentry *dentry, if (error) goto fail_gunlock; - inode = gfs2_dir_search(dir, &dentry->d_name, !S_ISREG(mode) || excl); + inode = gfs2_dir_search(dir, &dentry->d_name, excl); error = PTR_ERR(inode); if (!IS_ERR(inode)) { if (file && (file->f_flags & __O_REGULAR) && @@ -1338,7 +1338,7 @@ static int gfs2_symlink(struct mnt_idmap *idmap, struct inode *dir, if (size >= gfs2_max_stuffed_size(GFS2_I(dir))) return -ENAMETOOLONG; - return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 0); + return gfs2_create_inode(dir, dentry, NULL, S_IFLNK | S_IRWXUGO, 0, symname, size, 1); } /** @@ -1356,7 +1356,7 @@ static struct dentry *gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir, { unsigned dsize = gfs2_max_stuffed_size(GFS2_I(dir)); - return ERR_PTR(gfs2_create_inode(dir, dentry, NULL, mode, 0, NULL, dsize, 0)); + return ERR_PTR(gfs2_create_inode(dir, dentry, NULL, mode, 0, NULL, dsize, 1)); } /** @@ -1372,7 +1372,7 @@ static struct dentry *gfs2_mkdir(struct mnt_idmap *idmap, struct inode *dir, static int gfs2_mknod(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { - return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 0); + return gfs2_create_inode(dir, dentry, NULL, mode, dev, NULL, 0, 1); } /** From 1a4aeb6d6a08af1a2e2c52c84170561625819377 Mon Sep 17 00:00:00 2001 From: Tal Zussman Date: Wed, 14 Oct 2026 20:36:43 -0400 Subject: [PATCH 18/19] gfs2: fix the escaped block copy in gfs2_before_commit() Commit d68d0c6c3fc7 ("gfs2: Use memcpy_{from,to}_page where appropriate") made the escaped buffer copy read from the mempool page it had just allocated instead of from the buffer, so the block written to the log is whatever the pool page last held. If the journal is replayed after a crash, the block is restored from that and the file's data is corrupted. Only escaped buffers are affected: jdata blocks whose first four bytes match GFS2_MAGIC. Copy from the buffer's folio instead. Fixes: d68d0c6c3fc7 ("gfs2: Use memcpy_{from,to}_page where appropriate") Cc: stable@vger.kernel.org Signed-off-by: Tal Zussman Signed-off-by: Andreas Gruenbacher --- fs/gfs2/lops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/lops.c b/fs/gfs2/lops.c index 77ef22eab368..16fba2108a4f 100644 --- a/fs/gfs2/lops.c +++ b/fs/gfs2/lops.c @@ -689,7 +689,9 @@ static void gfs2_before_commit(struct gfs2_sbd *sdp, unsigned int limit, page = mempool_alloc(gfs2_page_pool, GFP_NOIO); p = page_address(page); - memcpy_from_page(p, page, bh_offset(bd2->bd_bh), bd2->bd_bh->b_size); + memcpy_from_folio(p, bd2->bd_bh->b_folio, + bh_offset(bd2->bd_bh), + bd2->bd_bh->b_size); *(__be32 *)p = 0; clear_buffer_escaped(bd2->bd_bh); unlock_buffer(bd2->bd_bh); From 2f9efb1efe4e026e44b7693e67f54344ae022deb Mon Sep 17 00:00:00 2001 From: Andreas Gruenbacher Date: Thu, 15 Oct 2026 16:37:25 +0200 Subject: [PATCH 19/19] gfs2: remove unnecessary check in gfs2_freeze_lock_shared gfs2_freeze_lock_shared() takes sdp->sd_freeze_gl without the LM_FLAG_TRY or LM_FLAG_TRY_1CB flags, so gfs2_glock_nq_init() will never return GLR_TRYFAILED. Signed-off-by: Andreas Gruenbacher --- fs/gfs2/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/gfs2/util.c b/fs/gfs2/util.c index 61b0668ecabc..529c3ec37a18 100644 --- a/fs/gfs2/util.c +++ b/fs/gfs2/util.c @@ -103,7 +103,7 @@ int gfs2_freeze_lock_shared(struct gfs2_sbd *sdp) error = gfs2_glock_nq_init(sdp->sd_freeze_gl, LM_ST_SHARED, flags, &sdp->sd_freeze_gh); - if (error && error != GLR_TRYFAILED) + if (error) fs_err(sdp, "can't lock the freeze glock: %d\n", error); return error; }