From: Andreas Gruenbacher Date: Thu, 26 Mar 2026 21:56:26 +0000 (+0100) Subject: gfs2: inode directory consistency checks X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b89e487bfcbc172e686a547fec4bc4072035a73b;p=thirdparty%2Fkernel%2Flinux.git gfs2: inode directory consistency checks In gfs2_dinode_in(), only allow directories to have the GFS2_DIF_EXHASH flag set. This will prevent other parts of the code from treating regular inodes as directories based on the presence of that flag. In sweep_bh_for_rgrps() and __gfs2_free_blocks(), check if the GFS2_DIF_EXHASH flag is set instead of checking if i_depth is non-zero. This matches what the directory code does. (The i_depth checks were introduced in commit 6d3117b412951 ("GFS2: Wipe directory hash table metadata when deallocating a directory").) Signed-off-by: Andreas Gruenbacher --- diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c index fdcac8e3f2ba2..89b043f706511 100644 --- a/fs/gfs2/bmap.c +++ b/fs/gfs2/bmap.c @@ -1539,7 +1539,7 @@ more_rgrps: revokes = jblocks_rqsted; if (meta) revokes += end - start; - else if (ip->i_depth) + else if (ip->i_diskflags & GFS2_DIF_EXHASH) revokes += sdp->sd_inptrs; ret = gfs2_trans_begin(sdp, jblocks_rqsted, revokes); if (ret) diff --git a/fs/gfs2/glops.c b/fs/gfs2/glops.c index aff7e890bf60a..28f32424ee64b 100644 --- a/fs/gfs2/glops.c +++ b/fs/gfs2/glops.c @@ -457,6 +457,11 @@ static int gfs2_dinode_in(struct gfs2_inode *ip, const void *buf) ip->i_depth = (u8)depth; ip->i_entries = be32_to_cpu(str->di_entries); + if (!S_ISDIR(inode->i_mode) && (ip->i_diskflags & GFS2_DIF_EXHASH)) { + gfs2_consist_inode(ip); + return -EIO; + } + if (gfs2_is_stuffed(ip) && inode->i_size > gfs2_max_stuffed_size(ip)) { gfs2_consist_inode(ip); return -EIO; diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 8a97ca734afc9..7ada7707e99af 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c @@ -2529,7 +2529,7 @@ void __gfs2_free_blocks(struct gfs2_inode *ip, struct gfs2_rgrpd *rgd, rgrp_unlock_local(rgd); /* Directories keep their data in the metadata address space */ - if (meta || ip->i_depth || gfs2_is_jdata(ip)) + if (meta || (ip->i_diskflags & GFS2_DIF_EXHASH) || gfs2_is_jdata(ip)) gfs2_journal_wipe(ip, bstart, blen); }